mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/agraf/tags/signed-ppc-for-upstream' into staging
Patch queue for ppc - 2015-03-09 This is my current patch queue for 2.3. Highlights include: * pseries: 2.3 machine * pseries: Export RTC via QOM * pseries: EEH support * mac: save/restore support * fix POWER5 hosts * random bug fixes # gpg: Signature made Mon Mar 9 14:00:53 2015 GMT using RSA key ID 03FEDC60 # gpg: Good signature from "Alexander Graf <agraf@suse.de>" # gpg: aka "Alexander Graf <alex@csgraf.de>" * remotes/agraf/tags/signed-ppc-for-upstream: (38 commits) target-ppc: Fix warnings from Sparse sPAPR: Implement sPAPRPHBClass EEH callbacks sPAPR: Implement EEH RTAS calls target-ppc: Add versions to server CPU descriptions PPC: Introduce the Virtual Time Base (VTB) SPR register PPC: Remove duplicate OPENPIC defines in default-configs ppc64-softmmu: Remove duplicated OPENPIC from config Revert "default-configs/ppc64: add all components of i82378 SuperIO chip used by prep" spapr_vio: Convert to realize() openpic: convert to vmstate openpic: switch IRQQueue queue from inline to bitmap openpic: fix up loadvm under -M mac99 openpic: fix segfault on -M mac99 savevm target-ppc: force update of msr bits in cpu_post_load target-ppc: move sdr1 value change detection logic to helper_store_sdr1() cuda.c: include adb_poll_timer in VMStateDescription adb.c: include ADBDevice parent state in KBDState and MouseState macio.c: include parent PCIDevice state in VMStateDescription display cpu id dump state Openpic: check that cpu id is within the number of cpus ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -38,7 +38,6 @@ CONFIG_PTIMER=y
|
||||
CONFIG_I8259=y
|
||||
CONFIG_XILINX=y
|
||||
CONFIG_XILINX_ETHLITE=y
|
||||
CONFIG_OPENPIC=y
|
||||
CONFIG_PREP=y
|
||||
CONFIG_MAC=y
|
||||
CONFIG_E500=y
|
||||
|
||||
@@ -38,7 +38,6 @@ CONFIG_PTIMER=y
|
||||
CONFIG_I8259=y
|
||||
CONFIG_XILINX=y
|
||||
CONFIG_XILINX_ETHLITE=y
|
||||
CONFIG_OPENPIC=y
|
||||
CONFIG_PSERIES=y
|
||||
CONFIG_PREP=y
|
||||
CONFIG_MAC=y
|
||||
@@ -51,11 +50,5 @@ CONFIG_LIBDECNUMBER=y
|
||||
CONFIG_XICS=$(CONFIG_PSERIES)
|
||||
CONFIG_XICS_KVM=$(and $(CONFIG_PSERIES),$(CONFIG_KVM))
|
||||
# For PReP
|
||||
CONFIG_I82378=y
|
||||
CONFIG_I8259=y
|
||||
CONFIG_I8254=y
|
||||
CONFIG_PCSPK=y
|
||||
CONFIG_I82374=y
|
||||
CONFIG_I8257=y
|
||||
CONFIG_MC146818RTC=y
|
||||
CONFIG_ISA_TESTDEV=y
|
||||
|
||||
@@ -13,5 +13,4 @@ CONFIG_PTIMER=y
|
||||
CONFIG_I8259=y
|
||||
CONFIG_XILINX=y
|
||||
CONFIG_XILINX_ETHLITE=y
|
||||
CONFIG_OPENPIC=y
|
||||
CONFIG_LIBDECNUMBER=y
|
||||
|
||||
+4
-6
@@ -60,19 +60,17 @@ void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
|
||||
qemu_chr_fe_write(dev->chardev, buf, len);
|
||||
}
|
||||
|
||||
static int spapr_vty_init(VIOsPAPRDevice *sdev)
|
||||
static void spapr_vty_realize(VIOsPAPRDevice *sdev, Error **errp)
|
||||
{
|
||||
VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev);
|
||||
|
||||
if (!dev->chardev) {
|
||||
fprintf(stderr, "spapr-vty: Can't create vty without a chardev!\n");
|
||||
exit(1);
|
||||
error_setg(errp, "chardev property not set");
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_chr_add_handlers(dev->chardev, vty_can_receive,
|
||||
vty_receive, NULL, dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Forward declaration */
|
||||
@@ -163,7 +161,7 @@ static void spapr_vty_class_init(ObjectClass *klass, void *data)
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
|
||||
|
||||
k->init = spapr_vty_init;
|
||||
k->realize = spapr_vty_realize;
|
||||
k->dt_name = "vty";
|
||||
k->dt_type = "serial";
|
||||
k->dt_compatible = "hvterm1";
|
||||
|
||||
@@ -181,6 +181,20 @@ static void pci_vga_qext_write(void *ptr, hwaddr addr,
|
||||
}
|
||||
}
|
||||
|
||||
static bool vga_get_big_endian_fb(Object *obj, Error **errp)
|
||||
{
|
||||
PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, PCI_DEVICE(obj));
|
||||
|
||||
return d->vga.big_endian_fb;
|
||||
}
|
||||
|
||||
static void vga_set_big_endian_fb(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, PCI_DEVICE(obj));
|
||||
|
||||
d->vga.big_endian_fb = value;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps pci_vga_qext_ops = {
|
||||
.read = pci_vga_qext_read,
|
||||
.write = pci_vga_qext_write,
|
||||
@@ -234,6 +248,13 @@ static void pci_std_vga_realize(PCIDevice *dev, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
static void pci_std_vga_init(Object *obj)
|
||||
{
|
||||
/* Expose framebuffer byteorder via QOM */
|
||||
object_property_add_bool(obj, "big-endian-framebuffer",
|
||||
vga_get_big_endian_fb, vga_set_big_endian_fb, NULL);
|
||||
}
|
||||
|
||||
static void pci_secondary_vga_realize(PCIDevice *dev, Error **errp)
|
||||
{
|
||||
PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
|
||||
@@ -265,7 +286,13 @@ static void pci_secondary_vga_realize(PCIDevice *dev, Error **errp)
|
||||
|
||||
pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
|
||||
pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
|
||||
}
|
||||
|
||||
static void pci_secondary_vga_init(Object *obj)
|
||||
{
|
||||
/* Expose framebuffer byteorder via QOM */
|
||||
object_property_add_bool(obj, "big-endian-framebuffer",
|
||||
vga_get_big_endian_fb, vga_set_big_endian_fb, NULL);
|
||||
}
|
||||
|
||||
static void pci_secondary_vga_reset(DeviceState *dev)
|
||||
@@ -324,6 +351,7 @@ static void secondary_class_init(ObjectClass *klass, void *data)
|
||||
static const TypeInfo vga_info = {
|
||||
.name = "VGA",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_init = pci_std_vga_init,
|
||||
.instance_size = sizeof(PCIVGAState),
|
||||
.class_init = vga_class_init,
|
||||
};
|
||||
@@ -331,6 +359,7 @@ static const TypeInfo vga_info = {
|
||||
static const TypeInfo secondary_info = {
|
||||
.name = "secondary-vga",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_init = pci_secondary_vga_init,
|
||||
.instance_size = sizeof(PCIVGAState),
|
||||
.class_init = secondary_class_init,
|
||||
};
|
||||
|
||||
+18
-4
@@ -118,6 +118,17 @@ static const TypeInfo adb_bus_type_info = {
|
||||
.instance_size = sizeof(ADBBusState),
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_adb_device = {
|
||||
.name = "adb_device",
|
||||
.version_id = 0,
|
||||
.minimum_version_id = 0,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_INT32(devaddr, ADBDevice),
|
||||
VMSTATE_INT32(handler, ADBDevice),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static void adb_device_realizefn(DeviceState *dev, Error **errp)
|
||||
{
|
||||
ADBDevice *d = ADB_DEVICE(dev);
|
||||
@@ -301,9 +312,10 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
|
||||
|
||||
static const VMStateDescription vmstate_adb_kbd = {
|
||||
.name = "adb_kbd",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_STRUCT(parent_obj, KBDState, 0, vmstate_adb_device, ADBDevice),
|
||||
VMSTATE_BUFFER(data, KBDState),
|
||||
VMSTATE_INT32(rptr, KBDState),
|
||||
VMSTATE_INT32(wptr, KBDState),
|
||||
@@ -515,9 +527,11 @@ static void adb_mouse_reset(DeviceState *dev)
|
||||
|
||||
static const VMStateDescription vmstate_adb_mouse = {
|
||||
.name = "adb_mouse",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_STRUCT(parent_obj, MouseState, 0, vmstate_adb_device,
|
||||
ADBDevice),
|
||||
VMSTATE_INT32(buttons_state, MouseState),
|
||||
VMSTATE_INT32(last_buttons_state, MouseState),
|
||||
VMSTATE_INT32(dx, MouseState),
|
||||
|
||||
+135
-145
@@ -200,11 +200,14 @@ typedef enum IRQType {
|
||||
IRQ_TYPE_FSLSPECIAL, /* FSL timer/IPI interrupt, edge, no polarity */
|
||||
} IRQType;
|
||||
|
||||
/* Round up to the nearest 64 IRQs so that the queue length
|
||||
* won't change when moving between 32 and 64 bit hosts.
|
||||
*/
|
||||
#define IRQQUEUE_SIZE_BITS ((OPENPIC_MAX_IRQ + 63) & ~63)
|
||||
|
||||
typedef struct IRQQueue {
|
||||
/* Round up to the nearest 64 IRQs so that the queue length
|
||||
* won't change when moving between 32 and 64 bit hosts.
|
||||
*/
|
||||
unsigned long queue[BITS_TO_LONGS((OPENPIC_MAX_IRQ + 63) & ~63)];
|
||||
unsigned long *queue;
|
||||
int32_t queue_size; /* Only used for VMSTATE_BITMAP */
|
||||
int next;
|
||||
int priority;
|
||||
} IRQQueue;
|
||||
@@ -240,6 +243,15 @@ typedef struct IRQSource {
|
||||
#define IDR_EP 0x80000000 /* external pin */
|
||||
#define IDR_CI 0x40000000 /* critical interrupt */
|
||||
|
||||
typedef struct OpenPICTimer {
|
||||
uint32_t tccr; /* Global timer current count register */
|
||||
uint32_t tbcr; /* Global timer base count register */
|
||||
} OpenPICTimer;
|
||||
|
||||
typedef struct OpenPICMSI {
|
||||
uint32_t msir; /* Shared Message Signaled Interrupt Register */
|
||||
} OpenPICMSI;
|
||||
|
||||
typedef struct IRQDest {
|
||||
int32_t ctpr; /* CPU current task priority */
|
||||
IRQQueue raised;
|
||||
@@ -288,14 +300,9 @@ typedef struct OpenPICState {
|
||||
IRQDest dst[MAX_CPU];
|
||||
uint32_t nb_cpus;
|
||||
/* Timer registers */
|
||||
struct {
|
||||
uint32_t tccr; /* Global timer current count register */
|
||||
uint32_t tbcr; /* Global timer base count register */
|
||||
} timers[OPENPIC_MAX_TMR];
|
||||
OpenPICTimer timers[OPENPIC_MAX_TMR];
|
||||
/* Shared MSI registers */
|
||||
struct {
|
||||
uint32_t msir; /* Shared Message Signaled Interrupt Register */
|
||||
} msi[MAX_MSI];
|
||||
OpenPICMSI msi[MAX_MSI];
|
||||
uint32_t max_irq;
|
||||
uint32_t irq_ipi0;
|
||||
uint32_t irq_tim0;
|
||||
@@ -1013,7 +1020,7 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
|
||||
DPRINTF("%s: cpu %d addr %#" HWADDR_PRIx " <= 0x%08x\n", __func__, idx,
|
||||
addr, val);
|
||||
|
||||
if (idx < 0) {
|
||||
if (idx < 0 || idx >= opp->nb_cpus) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1152,7 +1159,7 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
|
||||
DPRINTF("%s: cpu %d addr %#" HWADDR_PRIx "\n", __func__, idx, addr);
|
||||
retval = 0xFFFFFFFF;
|
||||
|
||||
if (idx < 0) {
|
||||
if (idx < 0 || idx >= opp->nb_cpus) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -1287,132 +1294,6 @@ static const MemoryRegionOps openpic_summary_ops_be = {
|
||||
},
|
||||
};
|
||||
|
||||
static void openpic_save_IRQ_queue(QEMUFile* f, IRQQueue *q)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(q->queue); i++) {
|
||||
/* Always put the lower half of a 64-bit long first, in case we
|
||||
* restore on a 32-bit host. The least significant bits correspond
|
||||
* to lower IRQ numbers in the bitmap.
|
||||
*/
|
||||
qemu_put_be32(f, (uint32_t)q->queue[i]);
|
||||
#if LONG_MAX > 0x7FFFFFFF
|
||||
qemu_put_be32(f, (uint32_t)(q->queue[i] >> 32));
|
||||
#endif
|
||||
}
|
||||
|
||||
qemu_put_sbe32s(f, &q->next);
|
||||
qemu_put_sbe32s(f, &q->priority);
|
||||
}
|
||||
|
||||
static void openpic_save(QEMUFile* f, void *opaque)
|
||||
{
|
||||
OpenPICState *opp = (OpenPICState *)opaque;
|
||||
unsigned int i;
|
||||
|
||||
qemu_put_be32s(f, &opp->gcr);
|
||||
qemu_put_be32s(f, &opp->vir);
|
||||
qemu_put_be32s(f, &opp->pir);
|
||||
qemu_put_be32s(f, &opp->spve);
|
||||
qemu_put_be32s(f, &opp->tfrr);
|
||||
|
||||
qemu_put_be32s(f, &opp->nb_cpus);
|
||||
|
||||
for (i = 0; i < opp->nb_cpus; i++) {
|
||||
qemu_put_sbe32s(f, &opp->dst[i].ctpr);
|
||||
openpic_save_IRQ_queue(f, &opp->dst[i].raised);
|
||||
openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
|
||||
qemu_put_buffer(f, (uint8_t *)&opp->dst[i].outputs_active,
|
||||
sizeof(opp->dst[i].outputs_active));
|
||||
}
|
||||
|
||||
for (i = 0; i < OPENPIC_MAX_TMR; i++) {
|
||||
qemu_put_be32s(f, &opp->timers[i].tccr);
|
||||
qemu_put_be32s(f, &opp->timers[i].tbcr);
|
||||
}
|
||||
|
||||
for (i = 0; i < opp->max_irq; i++) {
|
||||
qemu_put_be32s(f, &opp->src[i].ivpr);
|
||||
qemu_put_be32s(f, &opp->src[i].idr);
|
||||
qemu_get_be32s(f, &opp->src[i].destmask);
|
||||
qemu_put_sbe32s(f, &opp->src[i].last_cpu);
|
||||
qemu_put_sbe32s(f, &opp->src[i].pending);
|
||||
}
|
||||
}
|
||||
|
||||
static void openpic_load_IRQ_queue(QEMUFile* f, IRQQueue *q)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(q->queue); i++) {
|
||||
unsigned long val;
|
||||
|
||||
val = qemu_get_be32(f);
|
||||
#if LONG_MAX > 0x7FFFFFFF
|
||||
val <<= 32;
|
||||
val |= qemu_get_be32(f);
|
||||
#endif
|
||||
|
||||
q->queue[i] = val;
|
||||
}
|
||||
|
||||
qemu_get_sbe32s(f, &q->next);
|
||||
qemu_get_sbe32s(f, &q->priority);
|
||||
}
|
||||
|
||||
static int openpic_load(QEMUFile* f, void *opaque, int version_id)
|
||||
{
|
||||
OpenPICState *opp = (OpenPICState *)opaque;
|
||||
unsigned int i, nb_cpus;
|
||||
|
||||
if (version_id != 1) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qemu_get_be32s(f, &opp->gcr);
|
||||
qemu_get_be32s(f, &opp->vir);
|
||||
qemu_get_be32s(f, &opp->pir);
|
||||
qemu_get_be32s(f, &opp->spve);
|
||||
qemu_get_be32s(f, &opp->tfrr);
|
||||
|
||||
qemu_get_be32s(f, &nb_cpus);
|
||||
if (opp->nb_cpus != nb_cpus) {
|
||||
return -EINVAL;
|
||||
}
|
||||
assert(nb_cpus > 0 && nb_cpus <= MAX_CPU);
|
||||
|
||||
for (i = 0; i < opp->nb_cpus; i++) {
|
||||
qemu_get_sbe32s(f, &opp->dst[i].ctpr);
|
||||
openpic_load_IRQ_queue(f, &opp->dst[i].raised);
|
||||
openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
|
||||
qemu_get_buffer(f, (uint8_t *)&opp->dst[i].outputs_active,
|
||||
sizeof(opp->dst[i].outputs_active));
|
||||
}
|
||||
|
||||
for (i = 0; i < OPENPIC_MAX_TMR; i++) {
|
||||
qemu_get_be32s(f, &opp->timers[i].tccr);
|
||||
qemu_get_be32s(f, &opp->timers[i].tbcr);
|
||||
}
|
||||
|
||||
for (i = 0; i < opp->max_irq; i++) {
|
||||
uint32_t val;
|
||||
|
||||
val = qemu_get_be32(f);
|
||||
write_IRQreg_idr(opp, i, val);
|
||||
val = qemu_get_be32(f);
|
||||
write_IRQreg_ivpr(opp, i, val);
|
||||
|
||||
qemu_get_be32s(f, &opp->src[i].ivpr);
|
||||
qemu_get_be32s(f, &opp->src[i].idr);
|
||||
qemu_get_be32s(f, &opp->src[i].destmask);
|
||||
qemu_get_sbe32s(f, &opp->src[i].last_cpu);
|
||||
qemu_get_sbe32s(f, &opp->src[i].pending);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void openpic_reset(DeviceState *d)
|
||||
{
|
||||
OpenPICState *opp = OPENPIC(d);
|
||||
@@ -1446,12 +1327,14 @@ static void openpic_reset(DeviceState *d)
|
||||
write_IRQreg_idr(opp, i, opp->idr_reset);
|
||||
}
|
||||
/* Initialise IRQ destinations */
|
||||
for (i = 0; i < MAX_CPU; i++) {
|
||||
for (i = 0; i < opp->nb_cpus; i++) {
|
||||
opp->dst[i].ctpr = 15;
|
||||
memset(&opp->dst[i].raised, 0, sizeof(IRQQueue));
|
||||
opp->dst[i].raised.next = -1;
|
||||
memset(&opp->dst[i].servicing, 0, sizeof(IRQQueue));
|
||||
opp->dst[i].raised.priority = 0;
|
||||
bitmap_clear(opp->dst[i].raised.queue, 0, IRQQUEUE_SIZE_BITS);
|
||||
opp->dst[i].servicing.next = -1;
|
||||
opp->dst[i].servicing.priority = 0;
|
||||
bitmap_clear(opp->dst[i].servicing.queue, 0, IRQQUEUE_SIZE_BITS);
|
||||
}
|
||||
/* Initialise timers */
|
||||
for (i = 0; i < OPENPIC_MAX_TMR; i++) {
|
||||
@@ -1525,6 +1408,110 @@ static void map_list(OpenPICState *opp, const MemReg *list, int *count)
|
||||
}
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_openpic_irq_queue = {
|
||||
.name = "openpic_irq_queue",
|
||||
.version_id = 0,
|
||||
.minimum_version_id = 0,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_BITMAP(queue, IRQQueue, 0, queue_size),
|
||||
VMSTATE_INT32(next, IRQQueue),
|
||||
VMSTATE_INT32(priority, IRQQueue),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_openpic_irqdest = {
|
||||
.name = "openpic_irqdest",
|
||||
.version_id = 0,
|
||||
.minimum_version_id = 0,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_INT32(ctpr, IRQDest),
|
||||
VMSTATE_STRUCT(raised, IRQDest, 0, vmstate_openpic_irq_queue,
|
||||
IRQQueue),
|
||||
VMSTATE_STRUCT(servicing, IRQDest, 0, vmstate_openpic_irq_queue,
|
||||
IRQQueue),
|
||||
VMSTATE_UINT32_ARRAY(outputs_active, IRQDest, OPENPIC_OUTPUT_NB),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_openpic_irqsource = {
|
||||
.name = "openpic_irqsource",
|
||||
.version_id = 0,
|
||||
.minimum_version_id = 0,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32(ivpr, IRQSource),
|
||||
VMSTATE_UINT32(idr, IRQSource),
|
||||
VMSTATE_UINT32(destmask, IRQSource),
|
||||
VMSTATE_INT32(last_cpu, IRQSource),
|
||||
VMSTATE_INT32(pending, IRQSource),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_openpic_timer = {
|
||||
.name = "openpic_timer",
|
||||
.version_id = 0,
|
||||
.minimum_version_id = 0,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32(tccr, OpenPICTimer),
|
||||
VMSTATE_UINT32(tbcr, OpenPICTimer),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_openpic_msi = {
|
||||
.name = "openpic_msi",
|
||||
.version_id = 0,
|
||||
.minimum_version_id = 0,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32(msir, OpenPICMSI),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static int openpic_post_load(void *opaque, int version_id)
|
||||
{
|
||||
OpenPICState *opp = (OpenPICState *)opaque;
|
||||
int i;
|
||||
|
||||
/* Update internal ivpr and idr variables */
|
||||
for (i = 0; i < opp->max_irq; i++) {
|
||||
write_IRQreg_idr(opp, i, opp->src[i].idr);
|
||||
write_IRQreg_ivpr(opp, i, opp->src[i].ivpr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_openpic = {
|
||||
.name = "openpic",
|
||||
.version_id = 3,
|
||||
.minimum_version_id = 3,
|
||||
.post_load = openpic_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32(gcr, OpenPICState),
|
||||
VMSTATE_UINT32(vir, OpenPICState),
|
||||
VMSTATE_UINT32(pir, OpenPICState),
|
||||
VMSTATE_UINT32(spve, OpenPICState),
|
||||
VMSTATE_UINT32(tfrr, OpenPICState),
|
||||
VMSTATE_UINT32(max_irq, OpenPICState),
|
||||
VMSTATE_STRUCT_VARRAY_UINT32(src, OpenPICState, max_irq, 0,
|
||||
vmstate_openpic_irqsource, IRQSource),
|
||||
VMSTATE_UINT32_EQUAL(nb_cpus, OpenPICState),
|
||||
VMSTATE_STRUCT_VARRAY_UINT32(dst, OpenPICState, nb_cpus, 0,
|
||||
vmstate_openpic_irqdest, IRQDest),
|
||||
VMSTATE_STRUCT_ARRAY(timers, OpenPICState, OPENPIC_MAX_TMR, 0,
|
||||
vmstate_openpic_timer, OpenPICTimer),
|
||||
VMSTATE_STRUCT_ARRAY(msi, OpenPICState, MAX_MSI, 0,
|
||||
vmstate_openpic_msi, OpenPICMSI),
|
||||
VMSTATE_UINT32(irq_ipi0, OpenPICState),
|
||||
VMSTATE_UINT32(irq_tim0, OpenPICState),
|
||||
VMSTATE_UINT32(irq_msi, OpenPICState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static void openpic_init(Object *obj)
|
||||
{
|
||||
OpenPICState *opp = OPENPIC(obj);
|
||||
@@ -1631,10 +1618,12 @@ static void openpic_realize(DeviceState *dev, Error **errp)
|
||||
for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
|
||||
sysbus_init_irq(d, &opp->dst[i].irqs[j]);
|
||||
}
|
||||
}
|
||||
|
||||
register_savevm(dev, "openpic", 0, 2,
|
||||
openpic_save, openpic_load, opp);
|
||||
opp->dst[i].raised.queue_size = IRQQUEUE_SIZE_BITS;
|
||||
opp->dst[i].raised.queue = bitmap_new(IRQQUEUE_SIZE_BITS);
|
||||
opp->dst[i].servicing.queue_size = IRQQUEUE_SIZE_BITS;
|
||||
opp->dst[i].servicing.queue = bitmap_new(IRQQUEUE_SIZE_BITS);
|
||||
}
|
||||
|
||||
sysbus_init_mmio(d, &opp->mem);
|
||||
qdev_init_gpio_in(dev, openpic_set_irq, opp->max_irq);
|
||||
@@ -1653,6 +1642,7 @@ static void openpic_class_init(ObjectClass *oc, void *data)
|
||||
dc->realize = openpic_realize;
|
||||
dc->props = openpic_properties;
|
||||
dc->reset = openpic_reset;
|
||||
dc->vmsd = &vmstate_openpic;
|
||||
}
|
||||
|
||||
static const TypeInfo openpic_info = {
|
||||
|
||||
@@ -638,8 +638,8 @@ static const VMStateDescription vmstate_cuda_timer = {
|
||||
|
||||
static const VMStateDescription vmstate_cuda = {
|
||||
.name = "cuda",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT8(a, CUDAState),
|
||||
VMSTATE_UINT8(b, CUDAState),
|
||||
@@ -660,6 +660,7 @@ static const VMStateDescription vmstate_cuda = {
|
||||
VMSTATE_UINT32(tick_offset, CUDAState),
|
||||
VMSTATE_STRUCT_ARRAY(timers, CUDAState, 2, 1,
|
||||
vmstate_cuda_timer, CUDATimer),
|
||||
VMSTATE_TIMER_PTR(adb_poll_timer, CUDAState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
@@ -336,20 +336,44 @@ static void macio_instance_init(Object *obj)
|
||||
memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_macio_oldworld = {
|
||||
.name = "macio-oldworld",
|
||||
.version_id = 0,
|
||||
.minimum_version_id = 0,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_PCI_DEVICE(parent_obj.parent, OldWorldMacIOState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static void macio_oldworld_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc);
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
pdc->init = macio_oldworld_initfn;
|
||||
pdc->device_id = PCI_DEVICE_ID_APPLE_343S1201;
|
||||
dc->vmsd = &vmstate_macio_oldworld;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_macio_newworld = {
|
||||
.name = "macio-newworld",
|
||||
.version_id = 0,
|
||||
.minimum_version_id = 0,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_PCI_DEVICE(parent_obj.parent, NewWorldMacIOState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static void macio_newworld_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc);
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
pdc->init = macio_newworld_initfn;
|
||||
pdc->device_id = PCI_DEVICE_ID_APPLE_UNI_N_KEYL;
|
||||
dc->vmsd = &vmstate_macio_newworld;
|
||||
}
|
||||
|
||||
static Property macio_properties[] = {
|
||||
|
||||
+2
-4
@@ -203,7 +203,7 @@ static void spapr_vlan_reset(VIOsPAPRDevice *sdev)
|
||||
dev->isopen = 0;
|
||||
}
|
||||
|
||||
static int spapr_vlan_init(VIOsPAPRDevice *sdev)
|
||||
static void spapr_vlan_realize(VIOsPAPRDevice *sdev, Error **errp)
|
||||
{
|
||||
VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
|
||||
|
||||
@@ -212,8 +212,6 @@ static int spapr_vlan_init(VIOsPAPRDevice *sdev)
|
||||
dev->nic = qemu_new_nic(&net_spapr_vlan_info, &dev->nicconf,
|
||||
object_get_typename(OBJECT(sdev)), sdev->qdev.id, dev);
|
||||
qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void spapr_vlan_instance_init(Object *obj)
|
||||
@@ -534,7 +532,7 @@ static void spapr_vlan_class_init(ObjectClass *klass, void *data)
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
|
||||
|
||||
k->init = spapr_vlan_init;
|
||||
k->realize = spapr_vlan_realize;
|
||||
k->reset = spapr_vlan_reset;
|
||||
k->devnode = spapr_vlan_devnode;
|
||||
k->dt_name = "l-lan";
|
||||
|
||||
@@ -132,7 +132,7 @@ static void rtas_nvram_store(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||
rtas_st(rets, 1, (alen < 0) ? 0 : alen);
|
||||
}
|
||||
|
||||
static int spapr_nvram_init(VIOsPAPRDevice *dev)
|
||||
static void spapr_nvram_realize(VIOsPAPRDevice *dev, Error **errp)
|
||||
{
|
||||
sPAPRNVRAM *nvram = VIO_SPAPR_NVRAM(dev);
|
||||
|
||||
@@ -145,23 +145,22 @@ static int spapr_nvram_init(VIOsPAPRDevice *dev)
|
||||
nvram->buf = g_malloc0(nvram->size);
|
||||
|
||||
if ((nvram->size < MIN_NVRAM_SIZE) || (nvram->size > MAX_NVRAM_SIZE)) {
|
||||
fprintf(stderr, "spapr-nvram must be between %d and %d bytes in size\n",
|
||||
MIN_NVRAM_SIZE, MAX_NVRAM_SIZE);
|
||||
return -1;
|
||||
error_setg(errp, "spapr-nvram must be between %d and %d bytes in size",
|
||||
MIN_NVRAM_SIZE, MAX_NVRAM_SIZE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nvram->blk) {
|
||||
int alen = blk_pread(nvram->blk, 0, nvram->buf, nvram->size);
|
||||
|
||||
if (alen != nvram->size) {
|
||||
return -1;
|
||||
error_setg(errp, "can't read spapr-nvram contents");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
spapr_rtas_register(RTAS_NVRAM_FETCH, "nvram-fetch", rtas_nvram_fetch);
|
||||
spapr_rtas_register(RTAS_NVRAM_STORE, "nvram-store", rtas_nvram_store);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spapr_nvram_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off)
|
||||
@@ -224,7 +223,7 @@ static void spapr_nvram_class_init(ObjectClass *klass, void *data)
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
|
||||
|
||||
k->init = spapr_nvram_init;
|
||||
k->realize = spapr_nvram_realize;
|
||||
k->devnode = spapr_nvram_devnode;
|
||||
k->dt_name = "nvram";
|
||||
k->dt_type = "nvram";
|
||||
|
||||
@@ -3,7 +3,7 @@ obj-y += ppc.o ppc_booke.o
|
||||
# IBM pSeries (sPAPR)
|
||||
obj-$(CONFIG_PSERIES) += spapr.o spapr_vio.o spapr_events.o
|
||||
obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
|
||||
obj-$(CONFIG_PSERIES) += spapr_pci.o
|
||||
obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o
|
||||
ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy)
|
||||
obj-y += spapr_pci_vfio.o
|
||||
endif
|
||||
|
||||
+11
-9
@@ -706,17 +706,19 @@ static DeviceState *ppce500_init_mpic_qemu(PPCE500Params *params,
|
||||
}
|
||||
|
||||
static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params,
|
||||
qemu_irq **irqs)
|
||||
qemu_irq **irqs, Error **errp)
|
||||
{
|
||||
Error *err = NULL;
|
||||
DeviceState *dev;
|
||||
CPUState *cs;
|
||||
int r;
|
||||
|
||||
dev = qdev_create(NULL, TYPE_KVM_OPENPIC);
|
||||
qdev_prop_set_uint32(dev, "model", params->mpic_version);
|
||||
|
||||
r = qdev_init(dev);
|
||||
if (r) {
|
||||
object_property_set_bool(OBJECT(dev), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
object_unparent(OBJECT(dev));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -747,15 +749,15 @@ static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr,
|
||||
"kernel_irqchip", true);
|
||||
bool irqchip_required = qemu_opt_get_bool(machine_opts,
|
||||
"kernel_irqchip", false);
|
||||
Error *err = NULL;
|
||||
|
||||
if (irqchip_allowed) {
|
||||
dev = ppce500_init_mpic_kvm(params, irqs);
|
||||
dev = ppce500_init_mpic_kvm(params, irqs, &err);
|
||||
}
|
||||
|
||||
if (irqchip_required && !dev) {
|
||||
fprintf(stderr, "%s: irqchip requested but unavailable\n",
|
||||
__func__);
|
||||
abort();
|
||||
error_report("kernel_irqchip requested but unavailable: %s",
|
||||
error_get_pretty(err));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+86
-18
@@ -110,17 +110,20 @@ struct sPAPRMachineState {
|
||||
sPAPREnvironment *spapr;
|
||||
|
||||
static XICSState *try_create_xics(const char *type, int nr_servers,
|
||||
int nr_irqs)
|
||||
int nr_irqs, Error **errp)
|
||||
{
|
||||
Error *err = NULL;
|
||||
DeviceState *dev;
|
||||
|
||||
dev = qdev_create(NULL, type);
|
||||
qdev_prop_set_uint32(dev, "nr_servers", nr_servers);
|
||||
qdev_prop_set_uint32(dev, "nr_irqs", nr_irqs);
|
||||
if (qdev_init(dev) < 0) {
|
||||
object_property_set_bool(OBJECT(dev), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
object_unparent(OBJECT(dev));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return XICS_COMMON(dev);
|
||||
}
|
||||
|
||||
@@ -134,23 +137,19 @@ static XICSState *xics_system_init(int nr_servers, int nr_irqs)
|
||||
"kernel_irqchip", true);
|
||||
bool irqchip_required = qemu_opt_get_bool(machine_opts,
|
||||
"kernel_irqchip", false);
|
||||
Error *err = NULL;
|
||||
|
||||
if (irqchip_allowed) {
|
||||
icp = try_create_xics(TYPE_KVM_XICS, nr_servers, nr_irqs);
|
||||
icp = try_create_xics(TYPE_KVM_XICS, nr_servers, nr_irqs, &err);
|
||||
}
|
||||
|
||||
if (irqchip_required && !icp) {
|
||||
perror("Failed to create in-kernel XICS\n");
|
||||
abort();
|
||||
error_report("kernel_irqchip requested but unavailable: %s",
|
||||
error_get_pretty(err));
|
||||
}
|
||||
}
|
||||
|
||||
if (!icp) {
|
||||
icp = try_create_xics(TYPE_XICS, nr_servers, nr_irqs);
|
||||
}
|
||||
|
||||
if (!icp) {
|
||||
perror("Failed to create XICS\n");
|
||||
abort();
|
||||
icp = try_create_xics(TYPE_XICS, nr_servers, nr_irqs, &error_abort);
|
||||
}
|
||||
|
||||
return icp;
|
||||
@@ -994,6 +993,17 @@ static void spapr_create_nvram(sPAPREnvironment *spapr)
|
||||
spapr->nvram = (struct sPAPRNVRAM *)dev;
|
||||
}
|
||||
|
||||
static void spapr_rtc_create(sPAPREnvironment *spapr)
|
||||
{
|
||||
DeviceState *dev = qdev_create(NULL, TYPE_SPAPR_RTC);
|
||||
|
||||
qdev_init_nofail(dev);
|
||||
spapr->rtc = dev;
|
||||
|
||||
object_property_add_alias(qdev_get_machine(), "rtc-time",
|
||||
OBJECT(spapr->rtc), "date", NULL);
|
||||
}
|
||||
|
||||
/* Returns whether we want to use VGA or not */
|
||||
static int spapr_vga_init(PCIBus *pci_bus)
|
||||
{
|
||||
@@ -1011,15 +1021,39 @@ static int spapr_vga_init(PCIBus *pci_bus)
|
||||
}
|
||||
}
|
||||
|
||||
static int spapr_post_load(void *opaque, int version_id)
|
||||
{
|
||||
sPAPREnvironment *spapr = (sPAPREnvironment *)opaque;
|
||||
int err = 0;
|
||||
|
||||
/* In earlier versions, there was no seperate qdev for the PAPR
|
||||
* RTC, so the RTC offset was stored directly in sPAPREnvironment.
|
||||
* So when migrating from those versions, poke the incoming offset
|
||||
* value into the RTC device */
|
||||
if (version_id < 3) {
|
||||
err = spapr_rtc_import_offset(spapr->rtc, spapr->rtc_offset);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static bool version_before_3(void *opaque, int version_id)
|
||||
{
|
||||
return version_id < 3;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_spapr = {
|
||||
.name = "spapr",
|
||||
.version_id = 2,
|
||||
.version_id = 3,
|
||||
.minimum_version_id = 1,
|
||||
.post_load = spapr_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UNUSED(4), /* used to be @next_irq */
|
||||
/* used to be @next_irq */
|
||||
VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4),
|
||||
|
||||
/* RTC offset */
|
||||
VMSTATE_UINT64(rtc_offset, sPAPREnvironment),
|
||||
VMSTATE_UINT64_TEST(rtc_offset, sPAPREnvironment, version_before_3),
|
||||
|
||||
VMSTATE_PPC_TIMEBASE_V(tb, sPAPREnvironment, 2),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
@@ -1491,6 +1525,9 @@ static void ppc_spapr_init(MachineState *machine)
|
||||
/* Set up EPOW events infrastructure */
|
||||
spapr_events_init(spapr);
|
||||
|
||||
/* Set up the RTC RTAS interfaces */
|
||||
spapr_rtc_create(spapr);
|
||||
|
||||
/* Set up VIO bus */
|
||||
spapr->vio_bus = spapr_vio_bus_init();
|
||||
|
||||
@@ -1759,11 +1796,22 @@ static const TypeInfo spapr_machine_info = {
|
||||
},
|
||||
};
|
||||
|
||||
#define SPAPR_COMPAT_2_2 \
|
||||
{\
|
||||
.driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\
|
||||
.property = "mem_win_size",\
|
||||
.value = "0x20000000",\
|
||||
}
|
||||
|
||||
#define SPAPR_COMPAT_2_1 \
|
||||
SPAPR_COMPAT_2_2
|
||||
|
||||
static void spapr_machine_2_1_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
static GlobalProperty compat_props[] = {
|
||||
HW_COMPAT_2_1,
|
||||
SPAPR_COMPAT_2_1,
|
||||
{ /* end of list */ }
|
||||
};
|
||||
|
||||
@@ -1780,12 +1828,15 @@ static const TypeInfo spapr_machine_2_1_info = {
|
||||
|
||||
static void spapr_machine_2_2_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
static GlobalProperty compat_props[] = {
|
||||
SPAPR_COMPAT_2_2,
|
||||
{ /* end of list */ }
|
||||
};
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
|
||||
mc->name = "pseries-2.2";
|
||||
mc->desc = "pSeries Logical Partition (PAPR compliant) v2.2";
|
||||
mc->alias = "pseries";
|
||||
mc->is_default = 1;
|
||||
mc->compat_props = compat_props;
|
||||
}
|
||||
|
||||
static const TypeInfo spapr_machine_2_2_info = {
|
||||
@@ -1794,11 +1845,28 @@ static const TypeInfo spapr_machine_2_2_info = {
|
||||
.class_init = spapr_machine_2_2_class_init,
|
||||
};
|
||||
|
||||
static void spapr_machine_2_3_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
|
||||
mc->name = "pseries-2.3";
|
||||
mc->desc = "pSeries Logical Partition (PAPR compliant) v2.3";
|
||||
mc->alias = "pseries";
|
||||
mc->is_default = 1;
|
||||
}
|
||||
|
||||
static const TypeInfo spapr_machine_2_3_info = {
|
||||
.name = TYPE_SPAPR_MACHINE "2.3",
|
||||
.parent = TYPE_SPAPR_MACHINE,
|
||||
.class_init = spapr_machine_2_3_class_init,
|
||||
};
|
||||
|
||||
static void spapr_machine_register_types(void)
|
||||
{
|
||||
type_register_static(&spapr_machine_info);
|
||||
type_register_static(&spapr_machine_2_1_info);
|
||||
type_register_static(&spapr_machine_2_2_info);
|
||||
type_register_static(&spapr_machine_2_3_info);
|
||||
}
|
||||
|
||||
type_init(spapr_machine_register_types)
|
||||
|
||||
@@ -246,7 +246,7 @@ static void spapr_powerdown_req(Notifier *n, void *opaque)
|
||||
maina->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINA);
|
||||
maina->hdr.section_length = cpu_to_be16(sizeof(*maina));
|
||||
/* FIXME: section version, subtype and creator id? */
|
||||
qemu_get_timedate(&tm, spapr->rtc_offset);
|
||||
spapr_rtc_read(spapr->rtc, &tm, NULL);
|
||||
year = tm.tm_year + 1900;
|
||||
maina->creation_date = cpu_to_be32((to_bcd(year / 100) << 24)
|
||||
| (to_bcd(year % 100) << 16)
|
||||
|
||||
@@ -731,12 +731,14 @@ static target_ulong h_set_mode_resource_le(PowerPCCPU *cpu,
|
||||
CPU_FOREACH(cs) {
|
||||
set_spr(cs, SPR_LPCR, 0, LPCR_ILE);
|
||||
}
|
||||
spapr_pci_switch_vga(true);
|
||||
return H_SUCCESS;
|
||||
|
||||
case H_SET_MODE_ENDIAN_LITTLE:
|
||||
CPU_FOREACH(cs) {
|
||||
set_spr(cs, SPR_LPCR, LPCR_ILE, LPCR_ILE);
|
||||
}
|
||||
spapr_pci_switch_vga(false);
|
||||
return H_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
+16
-10
@@ -25,6 +25,7 @@
|
||||
#include "trace.h"
|
||||
|
||||
#include "hw/ppc/spapr.h"
|
||||
#include "hw/ppc/spapr_vio.h"
|
||||
|
||||
#include <libfdt.h>
|
||||
|
||||
@@ -73,9 +74,7 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr,
|
||||
.perm = IOMMU_NONE,
|
||||
};
|
||||
|
||||
if (tcet->bypass) {
|
||||
ret.perm = IOMMU_RW;
|
||||
} else if ((addr >> tcet->page_shift) < tcet->nb_table) {
|
||||
if ((addr >> tcet->page_shift) < tcet->nb_table) {
|
||||
/* Check if we are in bound */
|
||||
hwaddr page_mask = IOMMU_PAGE_MASK(tcet->page_shift);
|
||||
|
||||
@@ -91,10 +90,22 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int spapr_tce_table_post_load(void *opaque, int version_id)
|
||||
{
|
||||
sPAPRTCETable *tcet = SPAPR_TCE_TABLE(opaque);
|
||||
|
||||
if (tcet->vdev) {
|
||||
spapr_vio_set_bypass(tcet->vdev, tcet->bypass);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_spapr_tce_table = {
|
||||
.name = "spapr_iommu",
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.post_load = spapr_tce_table_post_load,
|
||||
.fields = (VMStateField []) {
|
||||
/* Sanity check */
|
||||
VMSTATE_UINT32_EQUAL(liobn, sPAPRTCETable),
|
||||
@@ -132,7 +143,8 @@ static int spapr_tce_table_realize(DeviceState *dev)
|
||||
trace_spapr_iommu_new_table(tcet->liobn, tcet, tcet->table, tcet->fd);
|
||||
|
||||
memory_region_init_iommu(&tcet->iommu, OBJECT(dev), &spapr_iommu_ops,
|
||||
"iommu-spapr", ram_size);
|
||||
"iommu-spapr",
|
||||
(uint64_t)tcet->nb_table << tcet->page_shift);
|
||||
|
||||
QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
|
||||
|
||||
@@ -192,17 +204,11 @@ MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet)
|
||||
return &tcet->iommu;
|
||||
}
|
||||
|
||||
void spapr_tce_set_bypass(sPAPRTCETable *tcet, bool bypass)
|
||||
{
|
||||
tcet->bypass = bypass;
|
||||
}
|
||||
|
||||
static void spapr_tce_reset(DeviceState *dev)
|
||||
{
|
||||
sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
|
||||
size_t table_size = tcet->nb_table * sizeof(uint64_t);
|
||||
|
||||
tcet->bypass = false;
|
||||
memset(tcet->table, 0, table_size);
|
||||
}
|
||||
|
||||
|
||||
+318
-3
@@ -406,6 +406,258 @@ static void rtas_ibm_query_interrupt_source_number(PowerPCCPU *cpu,
|
||||
rtas_st(rets, 2, 1);/* 0 == level; 1 == edge */
|
||||
}
|
||||
|
||||
static void rtas_ibm_set_eeh_option(PowerPCCPU *cpu,
|
||||
sPAPREnvironment *spapr,
|
||||
uint32_t token, uint32_t nargs,
|
||||
target_ulong args, uint32_t nret,
|
||||
target_ulong rets)
|
||||
{
|
||||
sPAPRPHBState *sphb;
|
||||
sPAPRPHBClass *spc;
|
||||
uint32_t addr, option;
|
||||
uint64_t buid;
|
||||
int ret;
|
||||
|
||||
if ((nargs != 4) || (nret != 1)) {
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
|
||||
addr = rtas_ld(args, 0);
|
||||
option = rtas_ld(args, 3);
|
||||
|
||||
sphb = find_phb(spapr, buid);
|
||||
if (!sphb) {
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb);
|
||||
if (!spc->eeh_set_option) {
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
ret = spc->eeh_set_option(sphb, addr, option);
|
||||
rtas_st(rets, 0, ret);
|
||||
return;
|
||||
|
||||
param_error_exit:
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
}
|
||||
|
||||
static void rtas_ibm_get_config_addr_info2(PowerPCCPU *cpu,
|
||||
sPAPREnvironment *spapr,
|
||||
uint32_t token, uint32_t nargs,
|
||||
target_ulong args, uint32_t nret,
|
||||
target_ulong rets)
|
||||
{
|
||||
sPAPRPHBState *sphb;
|
||||
sPAPRPHBClass *spc;
|
||||
PCIDevice *pdev;
|
||||
uint32_t addr, option;
|
||||
uint64_t buid;
|
||||
|
||||
if ((nargs != 4) || (nret != 2)) {
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
|
||||
sphb = find_phb(spapr, buid);
|
||||
if (!sphb) {
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb);
|
||||
if (!spc->eeh_set_option) {
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* We always have PE address of form "00BB0001". "BB"
|
||||
* represents the bus number of PE's primary bus.
|
||||
*/
|
||||
option = rtas_ld(args, 3);
|
||||
switch (option) {
|
||||
case RTAS_GET_PE_ADDR:
|
||||
addr = rtas_ld(args, 0);
|
||||
pdev = find_dev(spapr, buid, addr);
|
||||
if (!pdev) {
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
rtas_st(rets, 1, (pci_bus_num(pdev->bus) << 16) + 1);
|
||||
break;
|
||||
case RTAS_GET_PE_MODE:
|
||||
rtas_st(rets, 1, RTAS_PE_MODE_SHARED);
|
||||
break;
|
||||
default:
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
|
||||
return;
|
||||
|
||||
param_error_exit:
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
}
|
||||
|
||||
static void rtas_ibm_read_slot_reset_state2(PowerPCCPU *cpu,
|
||||
sPAPREnvironment *spapr,
|
||||
uint32_t token, uint32_t nargs,
|
||||
target_ulong args, uint32_t nret,
|
||||
target_ulong rets)
|
||||
{
|
||||
sPAPRPHBState *sphb;
|
||||
sPAPRPHBClass *spc;
|
||||
uint64_t buid;
|
||||
int state, ret;
|
||||
|
||||
if ((nargs != 3) || (nret != 4 && nret != 5)) {
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
|
||||
sphb = find_phb(spapr, buid);
|
||||
if (!sphb) {
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb);
|
||||
if (!spc->eeh_get_state) {
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
ret = spc->eeh_get_state(sphb, &state);
|
||||
rtas_st(rets, 0, ret);
|
||||
if (ret != RTAS_OUT_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
rtas_st(rets, 1, state);
|
||||
rtas_st(rets, 2, RTAS_EEH_SUPPORT);
|
||||
rtas_st(rets, 3, RTAS_EEH_PE_UNAVAIL_INFO);
|
||||
if (nret >= 5) {
|
||||
rtas_st(rets, 4, RTAS_EEH_PE_RECOVER_INFO);
|
||||
}
|
||||
return;
|
||||
|
||||
param_error_exit:
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
}
|
||||
|
||||
static void rtas_ibm_set_slot_reset(PowerPCCPU *cpu,
|
||||
sPAPREnvironment *spapr,
|
||||
uint32_t token, uint32_t nargs,
|
||||
target_ulong args, uint32_t nret,
|
||||
target_ulong rets)
|
||||
{
|
||||
sPAPRPHBState *sphb;
|
||||
sPAPRPHBClass *spc;
|
||||
uint32_t option;
|
||||
uint64_t buid;
|
||||
int ret;
|
||||
|
||||
if ((nargs != 4) || (nret != 1)) {
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
|
||||
option = rtas_ld(args, 3);
|
||||
sphb = find_phb(spapr, buid);
|
||||
if (!sphb) {
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb);
|
||||
if (!spc->eeh_reset) {
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
ret = spc->eeh_reset(sphb, option);
|
||||
rtas_st(rets, 0, ret);
|
||||
return;
|
||||
|
||||
param_error_exit:
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
}
|
||||
|
||||
static void rtas_ibm_configure_pe(PowerPCCPU *cpu,
|
||||
sPAPREnvironment *spapr,
|
||||
uint32_t token, uint32_t nargs,
|
||||
target_ulong args, uint32_t nret,
|
||||
target_ulong rets)
|
||||
{
|
||||
sPAPRPHBState *sphb;
|
||||
sPAPRPHBClass *spc;
|
||||
uint64_t buid;
|
||||
int ret;
|
||||
|
||||
if ((nargs != 3) || (nret != 1)) {
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
|
||||
sphb = find_phb(spapr, buid);
|
||||
if (!sphb) {
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb);
|
||||
if (!spc->eeh_configure) {
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
ret = spc->eeh_configure(sphb);
|
||||
rtas_st(rets, 0, ret);
|
||||
return;
|
||||
|
||||
param_error_exit:
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
}
|
||||
|
||||
/* To support it later */
|
||||
static void rtas_ibm_slot_error_detail(PowerPCCPU *cpu,
|
||||
sPAPREnvironment *spapr,
|
||||
uint32_t token, uint32_t nargs,
|
||||
target_ulong args, uint32_t nret,
|
||||
target_ulong rets)
|
||||
{
|
||||
sPAPRPHBState *sphb;
|
||||
sPAPRPHBClass *spc;
|
||||
int option;
|
||||
uint64_t buid;
|
||||
|
||||
if ((nargs != 8) || (nret != 1)) {
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
|
||||
sphb = find_phb(spapr, buid);
|
||||
if (!sphb) {
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb);
|
||||
if (!spc->eeh_set_option) {
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
option = rtas_ld(args, 7);
|
||||
switch (option) {
|
||||
case RTAS_SLOT_TEMP_ERR_LOG:
|
||||
case RTAS_SLOT_PERM_ERR_LOG:
|
||||
break;
|
||||
default:
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
/* We don't have error log yet */
|
||||
rtas_st(rets, 0, RTAS_OUT_NO_ERRORS_FOUND);
|
||||
return;
|
||||
|
||||
param_error_exit:
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
}
|
||||
|
||||
static int pci_spapr_swizzle(int slot, int pin)
|
||||
{
|
||||
return (slot + pin) % PCI_NUM_PINS;
|
||||
@@ -501,6 +753,12 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
if (sphb->index > SPAPR_PCI_MAX_INDEX) {
|
||||
error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)",
|
||||
SPAPR_PCI_MAX_INDEX);
|
||||
return;
|
||||
}
|
||||
|
||||
sphb->buid = SPAPR_PCI_BASE_BUID + sphb->index;
|
||||
sphb->dma_liobn = SPAPR_PCI_BASE_LIOBN + sphb->index;
|
||||
|
||||
@@ -669,7 +927,7 @@ static void spapr_phb_reset(DeviceState *qdev)
|
||||
}
|
||||
|
||||
static Property spapr_phb_properties[] = {
|
||||
DEFINE_PROP_INT32("index", sPAPRPHBState, index, -1),
|
||||
DEFINE_PROP_UINT32("index", sPAPRPHBState, index, -1),
|
||||
DEFINE_PROP_UINT64("buid", sPAPRPHBState, buid, -1),
|
||||
DEFINE_PROP_UINT32("liobn", sPAPRPHBState, dma_liobn, -1),
|
||||
DEFINE_PROP_UINT64("mem_win_addr", sPAPRPHBState, mem_win_addr, -1),
|
||||
@@ -862,6 +1120,10 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
|
||||
int bus_off, i, j;
|
||||
char nodename[256];
|
||||
uint32_t bus_range[] = { cpu_to_be32(0), cpu_to_be32(0xff) };
|
||||
const uint64_t mmiosize = memory_region_size(&phb->memwindow);
|
||||
const uint64_t w32max = (1ULL << 32) - SPAPR_PCI_MEM_WIN_BUS_OFFSET;
|
||||
const uint64_t w32size = MIN(w32max, mmiosize);
|
||||
const uint64_t w64size = (mmiosize > w32size) ? (mmiosize - w32size) : 0;
|
||||
struct {
|
||||
uint32_t hi;
|
||||
uint64_t child;
|
||||
@@ -876,9 +1138,15 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
|
||||
{
|
||||
cpu_to_be32(b_ss(2)), cpu_to_be64(SPAPR_PCI_MEM_WIN_BUS_OFFSET),
|
||||
cpu_to_be64(phb->mem_win_addr),
|
||||
cpu_to_be64(memory_region_size(&phb->memwindow)),
|
||||
cpu_to_be64(w32size),
|
||||
},
|
||||
{
|
||||
cpu_to_be32(b_ss(3)), cpu_to_be64(1ULL << 32),
|
||||
cpu_to_be64(phb->mem_win_addr + w32size),
|
||||
cpu_to_be64(w64size)
|
||||
},
|
||||
};
|
||||
const unsigned sizeof_ranges = (w64size ? 3 : 2) * sizeof(ranges[0]);
|
||||
uint64_t bus_reg[] = { cpu_to_be64(phb->buid), 0 };
|
||||
uint32_t interrupt_map_mask[] = {
|
||||
cpu_to_be32(b_ddddd(-1)|b_fff(0)), 0x0, 0x0, cpu_to_be32(-1)};
|
||||
@@ -907,7 +1175,7 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
|
||||
_FDT(fdt_setprop_cell(fdt, bus_off, "#interrupt-cells", 0x1));
|
||||
_FDT(fdt_setprop(fdt, bus_off, "used-by-rtas", NULL, 0));
|
||||
_FDT(fdt_setprop(fdt, bus_off, "bus-range", &bus_range, sizeof(bus_range)));
|
||||
_FDT(fdt_setprop(fdt, bus_off, "ranges", &ranges, sizeof(ranges)));
|
||||
_FDT(fdt_setprop(fdt, bus_off, "ranges", &ranges, sizeof_ranges));
|
||||
_FDT(fdt_setprop(fdt, bus_off, "reg", &bus_reg, sizeof(bus_reg)));
|
||||
_FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pci-config-space-type", 0x1));
|
||||
_FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pe-total-#msi", XICS_IRQS));
|
||||
@@ -958,6 +1226,25 @@ void spapr_pci_rtas_init(void)
|
||||
spapr_rtas_register(RTAS_IBM_CHANGE_MSI, "ibm,change-msi",
|
||||
rtas_ibm_change_msi);
|
||||
}
|
||||
|
||||
spapr_rtas_register(RTAS_IBM_SET_EEH_OPTION,
|
||||
"ibm,set-eeh-option",
|
||||
rtas_ibm_set_eeh_option);
|
||||
spapr_rtas_register(RTAS_IBM_GET_CONFIG_ADDR_INFO2,
|
||||
"ibm,get-config-addr-info2",
|
||||
rtas_ibm_get_config_addr_info2);
|
||||
spapr_rtas_register(RTAS_IBM_READ_SLOT_RESET_STATE2,
|
||||
"ibm,read-slot-reset-state2",
|
||||
rtas_ibm_read_slot_reset_state2);
|
||||
spapr_rtas_register(RTAS_IBM_SET_SLOT_RESET,
|
||||
"ibm,set-slot-reset",
|
||||
rtas_ibm_set_slot_reset);
|
||||
spapr_rtas_register(RTAS_IBM_CONFIGURE_PE,
|
||||
"ibm,configure-pe",
|
||||
rtas_ibm_configure_pe);
|
||||
spapr_rtas_register(RTAS_IBM_SLOT_ERROR_DETAIL,
|
||||
"ibm,slot-error-detail",
|
||||
rtas_ibm_slot_error_detail);
|
||||
}
|
||||
|
||||
static void spapr_pci_register_types(void)
|
||||
@@ -966,3 +1253,31 @@ static void spapr_pci_register_types(void)
|
||||
}
|
||||
|
||||
type_init(spapr_pci_register_types)
|
||||
|
||||
static int spapr_switch_one_vga(DeviceState *dev, void *opaque)
|
||||
{
|
||||
bool be = *(bool *)opaque;
|
||||
|
||||
if (object_dynamic_cast(OBJECT(dev), "VGA")
|
||||
|| object_dynamic_cast(OBJECT(dev), "secondary-vga")) {
|
||||
object_property_set_bool(OBJECT(dev), be, "big-endian-framebuffer",
|
||||
&error_abort);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void spapr_pci_switch_vga(bool big_endian)
|
||||
{
|
||||
sPAPRPHBState *sphb;
|
||||
|
||||
/*
|
||||
* For backward compatibility with existing guests, we switch
|
||||
* the endianness of the VGA controller when changing the guest
|
||||
* interrupt mode
|
||||
*/
|
||||
QLIST_FOREACH(sphb, &spapr->phbs, list) {
|
||||
BusState *bus = &PCI_HOST_BRIDGE(sphb)->bus->qbus;
|
||||
qbus_walk_children(bus, spapr_switch_one_vga, NULL, NULL, NULL,
|
||||
&big_endian);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +76,117 @@ static void spapr_phb_vfio_reset(DeviceState *qdev)
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
static int spapr_phb_vfio_eeh_set_option(sPAPRPHBState *sphb,
|
||||
unsigned int addr, int option)
|
||||
{
|
||||
sPAPRPHBVFIOState *svphb = SPAPR_PCI_VFIO_HOST_BRIDGE(sphb);
|
||||
struct vfio_eeh_pe_op op = { .argsz = sizeof(op) };
|
||||
int ret;
|
||||
|
||||
switch (option) {
|
||||
case RTAS_EEH_DISABLE:
|
||||
op.op = VFIO_EEH_PE_DISABLE;
|
||||
break;
|
||||
case RTAS_EEH_ENABLE: {
|
||||
PCIHostState *phb;
|
||||
PCIDevice *pdev;
|
||||
|
||||
/*
|
||||
* The EEH functionality is enabled on basis of PCI device,
|
||||
* instead of PE. We need check the validity of the PCI
|
||||
* device address.
|
||||
*/
|
||||
phb = PCI_HOST_BRIDGE(sphb);
|
||||
pdev = pci_find_device(phb->bus,
|
||||
(addr >> 16) & 0xFF, (addr >> 8) & 0xFF);
|
||||
if (!pdev) {
|
||||
return RTAS_OUT_PARAM_ERROR;
|
||||
}
|
||||
|
||||
op.op = VFIO_EEH_PE_ENABLE;
|
||||
break;
|
||||
}
|
||||
case RTAS_EEH_THAW_IO:
|
||||
op.op = VFIO_EEH_PE_UNFREEZE_IO;
|
||||
break;
|
||||
case RTAS_EEH_THAW_DMA:
|
||||
op.op = VFIO_EEH_PE_UNFREEZE_DMA;
|
||||
break;
|
||||
default:
|
||||
return RTAS_OUT_PARAM_ERROR;
|
||||
}
|
||||
|
||||
ret = vfio_container_ioctl(&svphb->phb.iommu_as, svphb->iommugroupid,
|
||||
VFIO_EEH_PE_OP, &op);
|
||||
if (ret < 0) {
|
||||
return RTAS_OUT_HW_ERROR;
|
||||
}
|
||||
|
||||
return RTAS_OUT_SUCCESS;
|
||||
}
|
||||
|
||||
static int spapr_phb_vfio_eeh_get_state(sPAPRPHBState *sphb, int *state)
|
||||
{
|
||||
sPAPRPHBVFIOState *svphb = SPAPR_PCI_VFIO_HOST_BRIDGE(sphb);
|
||||
struct vfio_eeh_pe_op op = { .argsz = sizeof(op) };
|
||||
int ret;
|
||||
|
||||
op.op = VFIO_EEH_PE_GET_STATE;
|
||||
ret = vfio_container_ioctl(&svphb->phb.iommu_as, svphb->iommugroupid,
|
||||
VFIO_EEH_PE_OP, &op);
|
||||
if (ret < 0) {
|
||||
return RTAS_OUT_PARAM_ERROR;
|
||||
}
|
||||
|
||||
*state = ret;
|
||||
return RTAS_OUT_SUCCESS;
|
||||
}
|
||||
|
||||
static int spapr_phb_vfio_eeh_reset(sPAPRPHBState *sphb, int option)
|
||||
{
|
||||
sPAPRPHBVFIOState *svphb = SPAPR_PCI_VFIO_HOST_BRIDGE(sphb);
|
||||
struct vfio_eeh_pe_op op = { .argsz = sizeof(op) };
|
||||
int ret;
|
||||
|
||||
switch (option) {
|
||||
case RTAS_SLOT_RESET_DEACTIVATE:
|
||||
op.op = VFIO_EEH_PE_RESET_DEACTIVATE;
|
||||
break;
|
||||
case RTAS_SLOT_RESET_HOT:
|
||||
op.op = VFIO_EEH_PE_RESET_HOT;
|
||||
break;
|
||||
case RTAS_SLOT_RESET_FUNDAMENTAL:
|
||||
op.op = VFIO_EEH_PE_RESET_FUNDAMENTAL;
|
||||
break;
|
||||
default:
|
||||
return RTAS_OUT_PARAM_ERROR;
|
||||
}
|
||||
|
||||
ret = vfio_container_ioctl(&svphb->phb.iommu_as, svphb->iommugroupid,
|
||||
VFIO_EEH_PE_OP, &op);
|
||||
if (ret < 0) {
|
||||
return RTAS_OUT_HW_ERROR;
|
||||
}
|
||||
|
||||
return RTAS_OUT_SUCCESS;
|
||||
}
|
||||
|
||||
static int spapr_phb_vfio_eeh_configure(sPAPRPHBState *sphb)
|
||||
{
|
||||
sPAPRPHBVFIOState *svphb = SPAPR_PCI_VFIO_HOST_BRIDGE(sphb);
|
||||
struct vfio_eeh_pe_op op = { .argsz = sizeof(op) };
|
||||
int ret;
|
||||
|
||||
op.op = VFIO_EEH_PE_CONFIGURE;
|
||||
ret = vfio_container_ioctl(&svphb->phb.iommu_as, svphb->iommugroupid,
|
||||
VFIO_EEH_PE_OP, &op);
|
||||
if (ret < 0) {
|
||||
return RTAS_OUT_PARAM_ERROR;
|
||||
}
|
||||
|
||||
return RTAS_OUT_SUCCESS;
|
||||
}
|
||||
|
||||
static void spapr_phb_vfio_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
@@ -84,6 +195,10 @@ static void spapr_phb_vfio_class_init(ObjectClass *klass, void *data)
|
||||
dc->props = spapr_phb_vfio_properties;
|
||||
dc->reset = spapr_phb_vfio_reset;
|
||||
spc->finish_realize = spapr_phb_vfio_finish_realize;
|
||||
spc->eeh_set_option = spapr_phb_vfio_eeh_set_option;
|
||||
spc->eeh_get_state = spapr_phb_vfio_eeh_get_state;
|
||||
spc->eeh_reset = spapr_phb_vfio_eeh_reset;
|
||||
spc->eeh_configure = spapr_phb_vfio_eeh_configure;
|
||||
}
|
||||
|
||||
static const TypeInfo spapr_phb_vfio_info = {
|
||||
|
||||
@@ -52,51 +52,6 @@ static void rtas_display_character(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||
}
|
||||
}
|
||||
|
||||
static void rtas_get_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||
uint32_t token, uint32_t nargs,
|
||||
target_ulong args,
|
||||
uint32_t nret, target_ulong rets)
|
||||
{
|
||||
struct tm tm;
|
||||
|
||||
if (nret != 8) {
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_get_timedate(&tm, spapr->rtc_offset);
|
||||
|
||||
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
|
||||
rtas_st(rets, 1, tm.tm_year + 1900);
|
||||
rtas_st(rets, 2, tm.tm_mon + 1);
|
||||
rtas_st(rets, 3, tm.tm_mday);
|
||||
rtas_st(rets, 4, tm.tm_hour);
|
||||
rtas_st(rets, 5, tm.tm_min);
|
||||
rtas_st(rets, 6, tm.tm_sec);
|
||||
rtas_st(rets, 7, 0); /* we don't do nanoseconds */
|
||||
}
|
||||
|
||||
static void rtas_set_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||
uint32_t token, uint32_t nargs,
|
||||
target_ulong args,
|
||||
uint32_t nret, target_ulong rets)
|
||||
{
|
||||
struct tm tm;
|
||||
|
||||
tm.tm_year = rtas_ld(args, 0) - 1900;
|
||||
tm.tm_mon = rtas_ld(args, 1) - 1;
|
||||
tm.tm_mday = rtas_ld(args, 2);
|
||||
tm.tm_hour = rtas_ld(args, 3);
|
||||
tm.tm_min = rtas_ld(args, 4);
|
||||
tm.tm_sec = rtas_ld(args, 5);
|
||||
|
||||
/* Just generate a monitor event for the change */
|
||||
qapi_event_send_rtc_change(qemu_timedate_diff(&tm), &error_abort);
|
||||
spapr->rtc_offset = qemu_timedate_diff(&tm);
|
||||
|
||||
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
|
||||
}
|
||||
|
||||
static void rtas_power_off(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||
uint32_t token, uint32_t nargs, target_ulong args,
|
||||
uint32_t nret, target_ulong rets)
|
||||
@@ -400,10 +355,6 @@ static void core_rtas_register_types(void)
|
||||
{
|
||||
spapr_rtas_register(RTAS_DISPLAY_CHARACTER, "display-character",
|
||||
rtas_display_character);
|
||||
spapr_rtas_register(RTAS_GET_TIME_OF_DAY, "get-time-of-day",
|
||||
rtas_get_time_of_day);
|
||||
spapr_rtas_register(RTAS_SET_TIME_OF_DAY, "set-time-of-day",
|
||||
rtas_set_time_of_day);
|
||||
spapr_rtas_register(RTAS_POWER_OFF, "power-off", rtas_power_off);
|
||||
spapr_rtas_register(RTAS_SYSTEM_REBOOT, "system-reboot",
|
||||
rtas_system_reboot);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user