ppc patch queue 2018-06-12

Here's another batch of ppc patches towards the 3.0 release.  There's
 a fair bit here, because I've been working through my mail backlog
 after a holiday.  There's not much of a central theme, amongst other
 things we have:
     * ppc440 / sam460ex improvements
     * logging and error cleanups
     * 40p (PReP) bugfixes
     * Macintosh fixes and cleanups
     * Add emulation of the new POWER9 store-forwarding barrier
       instruction variant
     * Hotplug cleanups
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEdfRlhq5hpmzETofcbDjKyiDZs5IFAlsfa4kACgkQbDjKyiDZ
 s5IdhxAA1ZDgEMyQkMPlnjYBNSpw9ICo/v+Lj1ZvlVjIbtjP6ZWdmaNHbBLi1N/U
 jbY7Yb+a43xj96WigN2kxu16aL7AvgrGayscht+P+ZXGWaEAt0R1EhiqhheKjkOH
 n0gAxe5c9wN18tJ7ZMtq7HmWw/MyWVjPQ4Pr38npyDU037LG4xY55DigcFu9D/6N
 rSYtB3gWIEvbGhx2Sm+gzbkleKufUNhSJMJI9diRS2KvyocH8ENQUqcMqK//Y6w7
 /Lk/j+qcAOAfCS+QWH9/XQvYdOGR9Gaw4oWLViOCD+EpTJHAYFMzVsp5ZLZZByw/
 S51W3e9mfxzgtIjoDxaetrW95yx2bAcFekP+H8KQesWpydSprsnAlh3SE3dfO2Jp
 Z1yVPHZv2fYZQjNZ0t62Z248iJ4YiBDttDpQYzsiGTiGVfx1IKTNz+gfNwV78CCJ
 SkyIktky2TYAemAB+U90JL3gYSn0GHwgBFLTJ4Rrrf3kC0wNslgosGTEB9v3D+Mb
 zsWxaBftFwZsRnNggBtE2/35zccJ2YURASlDu9ccmczyCUrRZbKE57/GftRXdIcY
 Oqjf48/NSwBm98bIEQGTOw7H1NgWuTazAc2+VS4mAHtUEEYIunuRmC+eTKNM01Yu
 qSMCg6tPADEXwRg6z062sb6T0vvpicv+X1U++tbHNqV3gprOlts=
 =g3bP
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-3.0-20180612' into staging

ppc patch queue 2018-06-12

Here's another batch of ppc patches towards the 3.0 release.  There's
a fair bit here, because I've been working through my mail backlog
after a holiday.  There's not much of a central theme, amongst other
things we have:
    * ppc440 / sam460ex improvements
    * logging and error cleanups
    * 40p (PReP) bugfixes
    * Macintosh fixes and cleanups
    * Add emulation of the new POWER9 store-forwarding barrier
      instruction variant
    * Hotplug cleanups

# gpg: Signature made Tue 12 Jun 2018 07:43:21 BST
# gpg:                using RSA key 6C38CACA20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>"
# gpg:                 aka "David Gibson (Red Hat) <dgibson@redhat.com>"
# gpg:                 aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>"
# gpg:                 aka "David Gibson (kernel.org) <dwg@kernel.org>"
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E  87DC 6C38 CACA 20D9 B392

* remotes/dgibson/tags/ppc-for-3.0-20180612: (33 commits)
  spapr_pci: Remove unhelpful pagesize warning
  xics_kvm: use KVM helpers
  ppc/pnv: fix LPC HC firmware address space
  spapr: handle cpu core unplug via hotplug handler chain
  spapr: handle pc-dimm unplug via hotplug handler chain
  spapr: introduce machine unplug handler
  spapr: move memory hotplug support check into spapr_memory_pre_plug()
  spapr: move lookup of the node into spapr_memory_plug()
  spapr: no need to verify the node
  target/ppc: Allow PIR read in privileged mode
  ppc4xx_i2c: Clean up and improve error logging
  target/ppc: extend eieio for POWER9
  mos6522: convert VMSTATE_TIMER_PTR_TEST to VMSTATE_TIMER_PTR
  mos6522: move timer frequency initialisation to mos6522_reset
  cuda: embed mos6522_cuda device directly rather than using QOM object link
  mos6522: fix vmstate_mos6522_timer version in vmstate_mos6522
  ppc: add missing FW_CFG_PPC_NVRAM_FLAT definition
  ppc: remove obsolete macio_init() definition from mac.h
  ppc: remove obsolete pci_pmac_init() definitions from mac.h
  hw/misc/mos6522: Add trailing '\n' to qemu_log() calls
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2018-06-12 14:32:19 +01:00
commit 3b68de85b9
28 changed files with 304 additions and 255 deletions

View File

@ -766,8 +766,11 @@ F: hw/ppc/mac_newworld.c
F: hw/pci-host/uninorth.c F: hw/pci-host/uninorth.c
F: hw/pci-bridge/dec.[hc] F: hw/pci-bridge/dec.[hc]
F: hw/misc/macio/ F: hw/misc/macio/
F: include/hw/ppc/mac_dbdma.h F: hw/misc/mos6522.c
F: hw/nvram/mac_nvram.c F: hw/nvram/mac_nvram.c
F: include/hw/misc/macio/
F: include/hw/misc/mos6522.h
F: include/hw/ppc/mac_dbdma.h
Old World Old World
M: Alexander Graf <agraf@suse.de> M: Alexander Graf <agraf@suse.de>

View File

@ -31,7 +31,7 @@
#include "hw/hw.h" #include "hw/hw.h"
#include "hw/i2c/ppc4xx_i2c.h" #include "hw/i2c/ppc4xx_i2c.h"
#define PPC4xx_I2C_MEM_SIZE 0x12 #define PPC4xx_I2C_MEM_SIZE 18
#define IIC_CNTL_PT (1 << 0) #define IIC_CNTL_PT (1 << 0)
#define IIC_CNTL_READ (1 << 1) #define IIC_CNTL_READ (1 << 1)
@ -70,7 +70,7 @@ static void ppc4xx_i2c_reset(DeviceState *s)
i2c->intrmsk = 0; i2c->intrmsk = 0;
i2c->xfrcnt = 0; i2c->xfrcnt = 0;
i2c->xtcntlss = 0; i2c->xtcntlss = 0;
i2c->directcntl = 0x0f; i2c->directcntl = 0xf;
i2c->intr = 0; i2c->intr = 0;
} }
@ -85,7 +85,7 @@ static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int size)
uint64_t ret; uint64_t ret;
switch (addr) { switch (addr) {
case 0x00: case 0:
ret = i2c->mdata; ret = i2c->mdata;
if (ppc4xx_i2c_is_master(i2c)) { if (ppc4xx_i2c_is_master(i2c)) {
ret = 0xff; ret = 0xff;
@ -139,58 +139,62 @@ static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int size)
TYPE_PPC4xx_I2C, __func__); TYPE_PPC4xx_I2C, __func__);
} }
break; break;
case 0x02: case 2:
ret = i2c->sdata; ret = i2c->sdata;
break; break;
case 0x04: case 4:
ret = i2c->lmadr; ret = i2c->lmadr;
break; break;
case 0x05: case 5:
ret = i2c->hmadr; ret = i2c->hmadr;
break; break;
case 0x06: case 6:
ret = i2c->cntl; ret = i2c->cntl;
break; break;
case 0x07: case 7:
ret = i2c->mdcntl; ret = i2c->mdcntl;
break; break;
case 0x08: case 8:
ret = i2c->sts; ret = i2c->sts;
break; break;
case 0x09: case 9:
ret = i2c->extsts; ret = i2c->extsts;
break; break;
case 0x0A: case 10:
ret = i2c->lsadr; ret = i2c->lsadr;
break; break;
case 0x0B: case 11:
ret = i2c->hsadr; ret = i2c->hsadr;
break; break;
case 0x0C: case 12:
ret = i2c->clkdiv; ret = i2c->clkdiv;
break; break;
case 0x0D: case 13:
ret = i2c->intrmsk; ret = i2c->intrmsk;
break; break;
case 0x0E: case 14:
ret = i2c->xfrcnt; ret = i2c->xfrcnt;
break; break;
case 0x0F: case 15:
ret = i2c->xtcntlss; ret = i2c->xtcntlss;
break; break;
case 0x10: case 16:
ret = i2c->directcntl; ret = i2c->directcntl;
break; break;
case 0x11: case 17:
ret = i2c->intr; ret = i2c->intr;
break; break;
default: default:
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%" if (addr < PPC4xx_I2C_MEM_SIZE) {
HWADDR_PRIx "\n", TYPE_PPC4xx_I2C, __func__, addr); qemu_log_mask(LOG_UNIMP, "%s: Unimplemented register 0x%"
HWADDR_PRIx "\n", __func__, addr);
} else {
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address 0x%"
HWADDR_PRIx "\n", __func__, addr);
}
ret = 0; ret = 0;
break; break;
} }
return ret; return ret;
} }
@ -200,7 +204,7 @@ static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value,
PPC4xxI2CState *i2c = opaque; PPC4xxI2CState *i2c = opaque;
switch (addr) { switch (addr) {
case 0x00: case 0:
i2c->mdata = value; i2c->mdata = value;
if (!i2c_bus_busy(i2c->bus)) { if (!i2c_bus_busy(i2c->bus)) {
/* assume we start a write transfer */ /* assume we start a write transfer */
@ -225,19 +229,19 @@ static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value,
} }
} }
break; break;
case 0x02: case 2:
i2c->sdata = value; i2c->sdata = value;
break; break;
case 0x04: case 4:
i2c->lmadr = value; i2c->lmadr = value;
if (i2c_bus_busy(i2c->bus)) { if (i2c_bus_busy(i2c->bus)) {
i2c_end_transfer(i2c->bus); i2c_end_transfer(i2c->bus);
} }
break; break;
case 0x05: case 5:
i2c->hmadr = value; i2c->hmadr = value;
break; break;
case 0x06: case 6:
i2c->cntl = value; i2c->cntl = value;
if (i2c->cntl & IIC_CNTL_PT) { if (i2c->cntl & IIC_CNTL_PT) {
if (i2c->cntl & IIC_CNTL_READ) { if (i2c->cntl & IIC_CNTL_READ) {
@ -263,32 +267,31 @@ static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value,
} }
} }
break; break;
case 0x07: case 7:
i2c->mdcntl = value & 0xDF; i2c->mdcntl = value & 0xdf;
break; break;
case 0x08: case 8:
i2c->sts &= ~(value & 0x0A); i2c->sts &= ~(value & 0xa);
break; break;
case 0x09: case 9:
i2c->extsts &= ~(value & 0x8F); i2c->extsts &= ~(value & 0x8f);
break; break;
case 0x0A: case 10:
i2c->lsadr = value; i2c->lsadr = value;
/*i2c_set_slave_address(i2c->bus, i2c->lsadr);*/
break; break;
case 0x0B: case 11:
i2c->hsadr = value; i2c->hsadr = value;
break; break;
case 0x0C: case 12:
i2c->clkdiv = value; i2c->clkdiv = value;
break; break;
case 0x0D: case 13:
i2c->intrmsk = value; i2c->intrmsk = value;
break; break;
case 0x0E: case 14:
i2c->xfrcnt = value & 0x77; i2c->xfrcnt = value & 0x77;
break; break;
case 0x0F: case 15:
if (value & IIC_XTCNTLSS_SRST) { if (value & IIC_XTCNTLSS_SRST) {
/* Is it actually a full reset? U-Boot sets some regs before */ /* Is it actually a full reset? U-Boot sets some regs before */
ppc4xx_i2c_reset(DEVICE(i2c)); ppc4xx_i2c_reset(DEVICE(i2c));
@ -296,15 +299,20 @@ static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value,
} }
i2c->xtcntlss = value; i2c->xtcntlss = value;
break; break;
case 0x10: case 16:
i2c->directcntl = value & 0x7; i2c->directcntl = value & 0x7;
break; break;
case 0x11: case 17:
i2c->intr = value; i2c->intr = value;
break; break;
default: default:
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%" if (addr < PPC4xx_I2C_MEM_SIZE) {
HWADDR_PRIx "\n", TYPE_PPC4xx_I2C, __func__, addr); qemu_log_mask(LOG_UNIMP, "%s: Unimplemented register 0x%"
HWADDR_PRIx "\n", __func__, addr);
} else {
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address 0x%"
HWADDR_PRIx "\n", __func__, addr);
}
break; break;
} }
} }

View File

@ -56,10 +56,6 @@ static QLIST_HEAD(, KVMEnabledICP)
static void icp_get_kvm_state(ICPState *icp) static void icp_get_kvm_state(ICPState *icp)
{ {
uint64_t state; uint64_t state;
struct kvm_one_reg reg = {
.id = KVM_REG_PPC_ICP_STATE,
.addr = (uintptr_t)&state,
};
int ret; int ret;
/* ICP for this CPU thread is not in use, exiting */ /* ICP for this CPU thread is not in use, exiting */
@ -67,7 +63,7 @@ static void icp_get_kvm_state(ICPState *icp)
return; return;
} }
ret = kvm_vcpu_ioctl(icp->cs, KVM_GET_ONE_REG, &reg); ret = kvm_get_one_reg(icp->cs, KVM_REG_PPC_ICP_STATE, &state);
if (ret != 0) { if (ret != 0) {
error_report("Unable to retrieve KVM interrupt controller state" error_report("Unable to retrieve KVM interrupt controller state"
" for CPU %ld: %s", kvm_arch_vcpu_id(icp->cs), strerror(errno)); " for CPU %ld: %s", kvm_arch_vcpu_id(icp->cs), strerror(errno));
@ -96,10 +92,6 @@ static void icp_synchronize_state(ICPState *icp)
static int icp_set_kvm_state(ICPState *icp, int version_id) static int icp_set_kvm_state(ICPState *icp, int version_id)
{ {
uint64_t state; uint64_t state;
struct kvm_one_reg reg = {
.id = KVM_REG_PPC_ICP_STATE,
.addr = (uintptr_t)&state,
};
int ret; int ret;
/* ICP for this CPU thread is not in use, exiting */ /* ICP for this CPU thread is not in use, exiting */
@ -111,7 +103,7 @@ static int icp_set_kvm_state(ICPState *icp, int version_id)
| ((uint64_t)icp->mfrr << KVM_REG_PPC_ICP_MFRR_SHIFT) | ((uint64_t)icp->mfrr << KVM_REG_PPC_ICP_MFRR_SHIFT)
| ((uint64_t)icp->pending_priority << KVM_REG_PPC_ICP_PPRI_SHIFT); | ((uint64_t)icp->pending_priority << KVM_REG_PPC_ICP_PPRI_SHIFT);
ret = kvm_vcpu_ioctl(icp->cs, KVM_SET_ONE_REG, &reg); ret = kvm_set_one_reg(icp->cs, KVM_REG_PPC_ICP_STATE, &state);
if (ret != 0) { if (ret != 0) {
error_report("Unable to restore KVM interrupt controller state (0x%" error_report("Unable to restore KVM interrupt controller state (0x%"
PRIx64 ") for CPU %ld: %s", state, kvm_arch_vcpu_id(icp->cs), PRIx64 ") for CPU %ld: %s", state, kvm_arch_vcpu_id(icp->cs),
@ -185,21 +177,15 @@ static const TypeInfo icp_kvm_info = {
static void ics_get_kvm_state(ICSState *ics) static void ics_get_kvm_state(ICSState *ics)
{ {
uint64_t state; uint64_t state;
struct kvm_device_attr attr = {
.flags = 0,
.group = KVM_DEV_XICS_GRP_SOURCES,
.addr = (uint64_t)(uintptr_t)&state,
};
int i; int i;
Error *local_err = NULL;
for (i = 0; i < ics->nr_irqs; i++) { for (i = 0; i < ics->nr_irqs; i++) {
ICSIRQState *irq = &ics->irqs[i]; ICSIRQState *irq = &ics->irqs[i];
int ret;
attr.attr = i + ics->offset; kvm_device_access(kernel_xics_fd, KVM_DEV_XICS_GRP_SOURCES,
i + ics->offset, &state, false, &local_err);
ret = ioctl(kernel_xics_fd, KVM_GET_DEVICE_ATTR, &attr); if (local_err) {
if (ret != 0) {
error_report("Unable to retrieve KVM interrupt controller state" error_report("Unable to retrieve KVM interrupt controller state"
" for IRQ %d: %s", i + ics->offset, strerror(errno)); " for IRQ %d: %s", i + ics->offset, strerror(errno));
exit(1); exit(1);
@ -255,19 +241,13 @@ static void ics_synchronize_state(ICSState *ics)
static int ics_set_kvm_state(ICSState *ics, int version_id) static int ics_set_kvm_state(ICSState *ics, int version_id)
{ {
uint64_t state; uint64_t state;
struct kvm_device_attr attr = {
.flags = 0,
.group = KVM_DEV_XICS_GRP_SOURCES,
.addr = (uint64_t)(uintptr_t)&state,
};
int i; int i;
Error *local_err = NULL;
for (i = 0; i < ics->nr_irqs; i++) { for (i = 0; i < ics->nr_irqs; i++) {
ICSIRQState *irq = &ics->irqs[i]; ICSIRQState *irq = &ics->irqs[i];
int ret; int ret;
attr.attr = i + ics->offset;
state = irq->server; state = irq->server;
state |= (uint64_t)(irq->saved_priority & KVM_XICS_PRIORITY_MASK) state |= (uint64_t)(irq->saved_priority & KVM_XICS_PRIORITY_MASK)
<< KVM_XICS_PRIORITY_SHIFT; << KVM_XICS_PRIORITY_SHIFT;
@ -293,8 +273,9 @@ static int ics_set_kvm_state(ICSState *ics, int version_id)
state |= KVM_XICS_QUEUED; state |= KVM_XICS_QUEUED;
} }
ret = ioctl(kernel_xics_fd, KVM_SET_DEVICE_ATTR, &attr); kvm_device_access(kernel_xics_fd, KVM_DEV_XICS_GRP_SOURCES,
if (ret != 0) { i + ics->offset, &state, true, &local_err);
if (local_err) {
error_report("Unable to restore KVM interrupt controller state" error_report("Unable to restore KVM interrupt controller state"
" for IRQs %d: %s", i + ics->offset, strerror(errno)); " for IRQs %d: %s", i + ics->offset, strerror(errno));
return ret; return ret;
@ -391,10 +372,6 @@ static void rtas_dummy(PowerPCCPU *cpu, sPAPRMachineState *spapr,
int xics_kvm_init(sPAPRMachineState *spapr, Error **errp) int xics_kvm_init(sPAPRMachineState *spapr, Error **errp)
{ {
int rc; int rc;
struct kvm_create_device xics_create_device = {
.type = KVM_DEV_TYPE_XICS,
.flags = 0,
};
if (!kvm_enabled() || !kvm_check_extension(kvm_state, KVM_CAP_IRQ_XICS)) { if (!kvm_enabled() || !kvm_check_extension(kvm_state, KVM_CAP_IRQ_XICS)) {
error_setg(errp, error_setg(errp,
@ -431,20 +408,19 @@ int xics_kvm_init(sPAPRMachineState *spapr, Error **errp)
goto fail; goto fail;
} }
/* Create the kernel ICP */ /* Create the KVM XICS device */
rc = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &xics_create_device); rc = kvm_create_device(kvm_state, KVM_DEV_TYPE_XICS, false);
if (rc < 0) { if (rc < 0) {
error_setg_errno(errp, -rc, "Error on KVM_CREATE_DEVICE for XICS"); error_setg_errno(errp, -rc, "Error on KVM_CREATE_DEVICE for XICS");
goto fail; goto fail;
} }
kernel_xics_fd = xics_create_device.fd; kernel_xics_fd = rc;
kvm_kernel_irqchip = true; kvm_kernel_irqchip = true;
kvm_msi_via_irqfd_allowed = true; kvm_msi_via_irqfd_allowed = true;
kvm_gsi_direct_mapping = true; kvm_gsi_direct_mapping = true;
return rc; return 0;
fail: fail:
kvmppc_define_rtas_kernel_token(0, "ibm,set-xive"); kvmppc_define_rtas_kernel_token(0, "ibm,set-xive");

View File

@ -65,7 +65,7 @@ static void cuda_receive_packet_from_host(CUDAState *s,
static uint64_t cuda_get_counter_value(MOS6522State *s, MOS6522Timer *ti) static uint64_t cuda_get_counter_value(MOS6522State *s, MOS6522Timer *ti)
{ {
MOS6522CUDAState *mcs = container_of(s, MOS6522CUDAState, parent_obj); MOS6522CUDAState *mcs = container_of(s, MOS6522CUDAState, parent_obj);
CUDAState *cs = mcs->cuda; CUDAState *cs = container_of(mcs, CUDAState, mos6522_cuda);
/* Reverse of the tb calculation algorithm that Mac OS X uses on bootup */ /* Reverse of the tb calculation algorithm that Mac OS X uses on bootup */
uint64_t tb_diff = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), uint64_t tb_diff = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
@ -78,7 +78,7 @@ static uint64_t cuda_get_counter_value(MOS6522State *s, MOS6522Timer *ti)
static uint64_t cuda_get_load_time(MOS6522State *s, MOS6522Timer *ti) static uint64_t cuda_get_load_time(MOS6522State *s, MOS6522Timer *ti)
{ {
MOS6522CUDAState *mcs = container_of(s, MOS6522CUDAState, parent_obj); MOS6522CUDAState *mcs = container_of(s, MOS6522CUDAState, parent_obj);
CUDAState *cs = mcs->cuda; CUDAState *cs = container_of(mcs, CUDAState, mos6522_cuda);
uint64_t load_time = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), uint64_t load_time = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
cs->tb_frequency, NANOSECONDS_PER_SECOND); cs->tb_frequency, NANOSECONDS_PER_SECOND);
@ -88,7 +88,7 @@ static uint64_t cuda_get_load_time(MOS6522State *s, MOS6522Timer *ti)
static void cuda_set_sr_int(void *opaque) static void cuda_set_sr_int(void *opaque)
{ {
CUDAState *s = opaque; CUDAState *s = opaque;
MOS6522CUDAState *mcs = s->mos6522_cuda; MOS6522CUDAState *mcs = &s->mos6522_cuda;
MOS6522State *ms = MOS6522(mcs); MOS6522State *ms = MOS6522(mcs);
MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms); MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms);
@ -97,7 +97,7 @@ static void cuda_set_sr_int(void *opaque)
static void cuda_delay_set_sr_int(CUDAState *s) static void cuda_delay_set_sr_int(CUDAState *s)
{ {
MOS6522CUDAState *mcs = s->mos6522_cuda; MOS6522CUDAState *mcs = &s->mos6522_cuda;
MOS6522State *ms = MOS6522(mcs); MOS6522State *ms = MOS6522(mcs);
MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms); MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms);
int64_t expire; int64_t expire;
@ -117,7 +117,7 @@ static void cuda_delay_set_sr_int(CUDAState *s)
/* NOTE: TIP and TREQ are negated */ /* NOTE: TIP and TREQ are negated */
static void cuda_update(CUDAState *s) static void cuda_update(CUDAState *s)
{ {
MOS6522CUDAState *mcs = s->mos6522_cuda; MOS6522CUDAState *mcs = &s->mos6522_cuda;
MOS6522State *ms = MOS6522(mcs); MOS6522State *ms = MOS6522(mcs);
int packet_received, len; int packet_received, len;
@ -462,7 +462,7 @@ static void cuda_receive_packet_from_host(CUDAState *s,
static uint64_t mos6522_cuda_read(void *opaque, hwaddr addr, unsigned size) static uint64_t mos6522_cuda_read(void *opaque, hwaddr addr, unsigned size)
{ {
CUDAState *s = opaque; CUDAState *s = opaque;
MOS6522CUDAState *mcs = s->mos6522_cuda; MOS6522CUDAState *mcs = &s->mos6522_cuda;
MOS6522State *ms = MOS6522(mcs); MOS6522State *ms = MOS6522(mcs);
addr = (addr >> 9) & 0xf; addr = (addr >> 9) & 0xf;
@ -473,7 +473,7 @@ static void mos6522_cuda_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size) unsigned size)
{ {
CUDAState *s = opaque; CUDAState *s = opaque;
MOS6522CUDAState *mcs = s->mos6522_cuda; MOS6522CUDAState *mcs = &s->mos6522_cuda;
MOS6522State *ms = MOS6522(mcs); MOS6522State *ms = MOS6522(mcs);
addr = (addr >> 9) & 0xf; addr = (addr >> 9) & 0xf;
@ -492,9 +492,11 @@ static const MemoryRegionOps mos6522_cuda_ops = {
static const VMStateDescription vmstate_cuda = { static const VMStateDescription vmstate_cuda = {
.name = "cuda", .name = "cuda",
.version_id = 4, .version_id = 5,
.minimum_version_id = 4, .minimum_version_id = 5,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_STRUCT(mos6522_cuda.parent_obj, CUDAState, 0, vmstate_mos6522,
MOS6522State),
VMSTATE_UINT8(last_b, CUDAState), VMSTATE_UINT8(last_b, CUDAState),
VMSTATE_UINT8(last_acr, CUDAState), VMSTATE_UINT8(last_acr, CUDAState),
VMSTATE_INT32(data_in_size, CUDAState), VMSTATE_INT32(data_in_size, CUDAState),
@ -530,12 +532,8 @@ static void cuda_realize(DeviceState *dev, Error **errp)
DeviceState *d; DeviceState *d;
struct tm tm; struct tm tm;
d = qdev_create(NULL, TYPE_MOS6522_CUDA);
object_property_set_link(OBJECT(d), OBJECT(s), "cuda", errp);
qdev_init_nofail(d);
s->mos6522_cuda = MOS6522_CUDA(d);
/* Pass IRQ from 6522 */ /* Pass IRQ from 6522 */
d = DEVICE(&s->mos6522_cuda);
ms = MOS6522(d); ms = MOS6522(d);
sbd = SYS_BUS_DEVICE(s); sbd = SYS_BUS_DEVICE(s);
sysbus_pass_irq(sbd, SYS_BUS_DEVICE(ms)); sysbus_pass_irq(sbd, SYS_BUS_DEVICE(ms));
@ -556,6 +554,10 @@ static void cuda_init(Object *obj)
CUDAState *s = CUDA(obj); CUDAState *s = CUDA(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
object_initialize(&s->mos6522_cuda, sizeof(s->mos6522_cuda),
TYPE_MOS6522_CUDA);
qdev_set_parent_bus(DEVICE(&s->mos6522_cuda), sysbus_get_default());
memory_region_init_io(&s->mem, obj, &mos6522_cuda_ops, s, "cuda", 0x2000); memory_region_init_io(&s->mem, obj, &mos6522_cuda_ops, s, "cuda", 0x2000);
sysbus_init_mmio(sbd, &s->mem); sysbus_init_mmio(sbd, &s->mem);
@ -590,37 +592,28 @@ static const TypeInfo cuda_type_info = {
static void mos6522_cuda_portB_write(MOS6522State *s) static void mos6522_cuda_portB_write(MOS6522State *s)
{ {
MOS6522CUDAState *mcs = container_of(s, MOS6522CUDAState, parent_obj); MOS6522CUDAState *mcs = container_of(s, MOS6522CUDAState, parent_obj);
CUDAState *cs = container_of(mcs, CUDAState, mos6522_cuda);
cuda_update(mcs->cuda); cuda_update(cs);
} }
static void mos6522_cuda_realize(DeviceState *dev, Error **errp) static void mos6522_cuda_reset(DeviceState *dev)
{ {
MOS6522State *ms = MOS6522(dev); MOS6522State *ms = MOS6522(dev);
MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms); MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms);
mdc->parent_realize(dev, errp); mdc->parent_reset(dev);
ms->timers[0].frequency = CUDA_TIMER_FREQ; ms->timers[0].frequency = CUDA_TIMER_FREQ;
ms->timers[1].frequency = (SCALE_US * 6000) / 4700; ms->timers[1].frequency = (SCALE_US * 6000) / 4700;
} }
static void mos6522_cuda_init(Object *obj)
{
MOS6522CUDAState *s = MOS6522_CUDA(obj);
object_property_add_link(obj, "cuda", TYPE_CUDA,
(Object **) &s->cuda,
qdev_prop_allow_set_link_before_realize,
0, NULL);
}
static void mos6522_cuda_class_init(ObjectClass *oc, void *data) static void mos6522_cuda_class_init(ObjectClass *oc, void *data)
{ {
DeviceClass *dc = DEVICE_CLASS(oc); DeviceClass *dc = DEVICE_CLASS(oc);
MOS6522DeviceClass *mdc = MOS6522_DEVICE_CLASS(oc); MOS6522DeviceClass *mdc = MOS6522_DEVICE_CLASS(oc);
dc->realize = mos6522_cuda_realize; dc->reset = mos6522_cuda_reset;
mdc->portB_write = mos6522_cuda_portB_write; mdc->portB_write = mos6522_cuda_portB_write;
mdc->get_timer1_counter_value = cuda_get_counter_value; mdc->get_timer1_counter_value = cuda_get_counter_value;
mdc->get_timer2_counter_value = cuda_get_counter_value; mdc->get_timer2_counter_value = cuda_get_counter_value;
@ -632,7 +625,6 @@ static const TypeInfo mos6522_cuda_type_info = {
.name = TYPE_MOS6522_CUDA, .name = TYPE_MOS6522_CUDA,
.parent = TYPE_MOS6522, .parent = TYPE_MOS6522,
.instance_size = sizeof(MOS6522CUDAState), .instance_size = sizeof(MOS6522CUDAState),
.instance_init = mos6522_cuda_init,
.class_init = mos6522_cuda_class_init, .class_init = mos6522_cuda_class_init,
}; };

View File

@ -32,6 +32,7 @@
#include "hw/char/escc.h" #include "hw/char/escc.h"
#include "hw/misc/macio/macio.h" #include "hw/misc/macio/macio.h"
#include "hw/intc/heathrow_pic.h" #include "hw/intc/heathrow_pic.h"
#include "trace.h"
/* Note: this code is strongly inspirated from the corresponding code /* Note: this code is strongly inspirated from the corresponding code
* in PearPC */ * in PearPC */
@ -246,6 +247,7 @@ static void macio_oldworld_init(Object *obj)
static void timer_write(void *opaque, hwaddr addr, uint64_t value, static void timer_write(void *opaque, hwaddr addr, uint64_t value,
unsigned size) unsigned size)
{ {
trace_macio_timer_write(addr, size, value);
} }
static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size) static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size)
@ -266,6 +268,7 @@ static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size)
break; break;
} }
trace_macio_timer_read(addr, size, value);
return value; return value;
} }

View File

@ -9,3 +9,7 @@ cuda_packet_receive(int len) "length %d"
cuda_packet_receive_data(int i, const uint8_t data) "[%d] 0x%02x" cuda_packet_receive_data(int i, const uint8_t data) "[%d] 0x%02x"
cuda_packet_send(int len) "length %d" cuda_packet_send(int len) "length %d"
cuda_packet_send_data(int i, const uint8_t data) "[%d] 0x%02x" cuda_packet_send_data(int i, const uint8_t data) "[%d] 0x%02x"
# hw/misc/macio/macio.c
macio_timer_write(uint64_t addr, unsigned len, uint64_t val) "write addr 0x%"PRIx64 " len %d val 0x%"PRIx64
macio_timer_read(uint64_t addr, unsigned len, uint32_t val) "read addr 0x%"PRIx64 " len %d val 0x%"PRIx32

View File

@ -189,12 +189,12 @@ static uint64_t mos6522_get_load_time(MOS6522State *s, MOS6522Timer *ti)
static void mos6522_portA_write(MOS6522State *s) static void mos6522_portA_write(MOS6522State *s)
{ {
qemu_log_mask(LOG_UNIMP, "portA_write unimplemented"); qemu_log_mask(LOG_UNIMP, "portA_write unimplemented\n");
} }
static void mos6522_portB_write(MOS6522State *s) static void mos6522_portB_write(MOS6522State *s)
{ {
qemu_log_mask(LOG_UNIMP, "portB_write unimplemented"); qemu_log_mask(LOG_UNIMP, "portB_write unimplemented\n");
} }
uint64_t mos6522_read(void *opaque, hwaddr addr, unsigned size) uint64_t mos6522_read(void *opaque, hwaddr addr, unsigned size)
@ -369,13 +369,6 @@ static const MemoryRegionOps mos6522_ops = {
}, },
}; };
static bool mos6522_timer_exist(void *opaque, int version_id)
{
MOS6522Timer *s = opaque;
return s->timer != NULL;
}
static const VMStateDescription vmstate_mos6522_timer = { static const VMStateDescription vmstate_mos6522_timer = {
.name = "mos6522_timer", .name = "mos6522_timer",
.version_id = 0, .version_id = 0,
@ -385,12 +378,12 @@ static const VMStateDescription vmstate_mos6522_timer = {
VMSTATE_UINT16(counter_value, MOS6522Timer), VMSTATE_UINT16(counter_value, MOS6522Timer),
VMSTATE_INT64(load_time, MOS6522Timer), VMSTATE_INT64(load_time, MOS6522Timer),
VMSTATE_INT64(next_irq_time, MOS6522Timer), VMSTATE_INT64(next_irq_time, MOS6522Timer),
VMSTATE_TIMER_PTR_TEST(timer, MOS6522Timer, mos6522_timer_exist), VMSTATE_TIMER_PTR(timer, MOS6522Timer),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
} }
}; };
static const VMStateDescription vmstate_mos6522 = { const VMStateDescription vmstate_mos6522 = {
.name = "mos6522", .name = "mos6522",
.version_id = 0, .version_id = 0,
.minimum_version_id = 0, .minimum_version_id = 0,
@ -405,7 +398,7 @@ static const VMStateDescription vmstate_mos6522 = {
VMSTATE_UINT8(ifr, MOS6522State), VMSTATE_UINT8(ifr, MOS6522State),
VMSTATE_UINT8(ier, MOS6522State), VMSTATE_UINT8(ier, MOS6522State),
VMSTATE_UINT8(anh, MOS6522State), VMSTATE_UINT8(anh, MOS6522State),
VMSTATE_STRUCT_ARRAY(timers, MOS6522State, 2, 1, VMSTATE_STRUCT_ARRAY(timers, MOS6522State, 2, 0,
vmstate_mos6522_timer, MOS6522Timer), vmstate_mos6522_timer, MOS6522Timer),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
} }
@ -427,18 +420,12 @@ static void mos6522_reset(DeviceState *dev)
/* s->ier = T1_INT | SR_INT; */ /* s->ier = T1_INT | SR_INT; */
s->anh = 0; s->anh = 0;
s->timers[0].frequency = s->frequency;
s->timers[0].latch = 0xffff; s->timers[0].latch = 0xffff;
set_counter(s, &s->timers[0], 0xffff); set_counter(s, &s->timers[0], 0xffff);
s->timers[1].latch = 0xffff;
}
static void mos6522_realize(DeviceState *dev, Error **errp)
{
MOS6522State *s = MOS6522(dev);
s->timers[0].frequency = s->frequency;
s->timers[1].frequency = s->frequency; s->timers[1].frequency = s->frequency;
s->timers[1].latch = 0xffff;
} }
static void mos6522_init(Object *obj) static void mos6522_init(Object *obj)
@ -469,11 +456,10 @@ static void mos6522_class_init(ObjectClass *oc, void *data)
DeviceClass *dc = DEVICE_CLASS(oc); DeviceClass *dc = DEVICE_CLASS(oc);
MOS6522DeviceClass *mdc = MOS6522_DEVICE_CLASS(oc); MOS6522DeviceClass *mdc = MOS6522_DEVICE_CLASS(oc);
dc->realize = mos6522_realize;
dc->reset = mos6522_reset; dc->reset = mos6522_reset;
dc->vmsd = &vmstate_mos6522; dc->vmsd = &vmstate_mos6522;
dc->props = mos6522_properties; dc->props = mos6522_properties;
mdc->parent_realize = dc->realize; mdc->parent_reset = dc->reset;
mdc->set_sr_int = mos6522_set_sr_int; mdc->set_sr_int = mos6522_set_sr_int;
mdc->portB_write = mos6522_portB_write; mdc->portB_write = mos6522_portB_write;
mdc->portA_write = mos6522_portA_write; mdc->portA_write = mos6522_portA_write;

View File

@ -524,19 +524,18 @@ static void unin_write(void *opaque, hwaddr addr, uint64_t value,
unsigned size) unsigned size)
{ {
trace_unin_write(addr, value); trace_unin_write(addr, value);
if (addr == 0x0) {
*(int *)opaque = value;
}
} }
static uint64_t unin_read(void *opaque, hwaddr addr, unsigned size) static uint64_t unin_read(void *opaque, hwaddr addr, unsigned size)
{ {
uint32_t value; uint32_t value;
value = 0;
switch (addr) { switch (addr) {
case 0: case 0:
value = *(int *)opaque; value = UNINORTH_VERSION_10A;
break;
default:
value = 0;
} }
trace_unin_read(addr, value); trace_unin_read(addr, value);
@ -555,7 +554,7 @@ static void unin_init(Object *obj)
UNINState *s = UNI_NORTH(obj); UNINState *s = UNI_NORTH(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
memory_region_init_io(&s->mem, obj, &unin_ops, &s->token, "unin", 0x1000); memory_region_init_io(&s->mem, obj, &unin_ops, s, "unin", 0x1000);
sysbus_init_mmio(sbd, &s->mem); sysbus_init_mmio(sbd, &s->mem);
} }

View File

@ -91,18 +91,9 @@ typedef struct MACIOIDEState {
void macio_ide_init_drives(MACIOIDEState *ide, DriveInfo **hd_table); void macio_ide_init_drives(MACIOIDEState *ide, DriveInfo **hd_table);
void macio_ide_register_dma(MACIOIDEState *ide); void macio_ide_register_dma(MACIOIDEState *ide);
void macio_init(PCIDevice *dev,
MemoryRegion *pic_mem);
/* Grackle PCI */ /* Grackle PCI */
#define TYPE_GRACKLE_PCI_HOST_BRIDGE "grackle-pcihost" #define TYPE_GRACKLE_PCI_HOST_BRIDGE "grackle-pcihost"
/* UniNorth PCI */
UNINHostState *pci_pmac_init(qemu_irq *pic,
MemoryRegion *address_space_mem);
UNINHostState *pci_pmac_u3_init(qemu_irq *pic,
MemoryRegion *address_space_mem);
/* Mac NVRAM */ /* Mac NVRAM */
#define TYPE_MACIO_NVRAM "macio-nvram" #define TYPE_MACIO_NVRAM "macio-nvram"
#define MACIO_NVRAM(obj) \ #define MACIO_NVRAM(obj) \

View File

@ -79,6 +79,7 @@ enum {
#define ISA_IO_SIZE 0x00010000 #define ISA_IO_SIZE 0x00010000
#define ISA_MEM_SIZE 0x10000000 #define ISA_MEM_SIZE 0x10000000
#define ISA_FW_SIZE 0x10000000
#define LPC_IO_OPB_ADDR 0xd0010000 #define LPC_IO_OPB_ADDR 0xd0010000
#define LPC_IO_OPB_SIZE 0x00010000 #define LPC_IO_OPB_SIZE 0x00010000
#define LPC_MEM_OPB_ADDR 0xe0010000 #define LPC_MEM_OPB_ADDR 0xe0010000
@ -429,6 +430,7 @@ static void pnv_lpc_realize(DeviceState *dev, Error **errp)
*/ */
memory_region_init(&lpc->isa_io, OBJECT(dev), "isa-io", ISA_IO_SIZE); memory_region_init(&lpc->isa_io, OBJECT(dev), "isa-io", ISA_IO_SIZE);
memory_region_init(&lpc->isa_mem, OBJECT(dev), "isa-mem", ISA_MEM_SIZE); memory_region_init(&lpc->isa_mem, OBJECT(dev), "isa-mem", ISA_MEM_SIZE);
memory_region_init(&lpc->isa_fw, OBJECT(dev), "isa-fw", ISA_FW_SIZE);
/* Create windows from the OPB space to the ISA space */ /* Create windows from the OPB space to the ISA space */
memory_region_init_alias(&lpc->opb_isa_io, OBJECT(dev), "lpc-isa-io", memory_region_init_alias(&lpc->opb_isa_io, OBJECT(dev), "lpc-isa-io",
@ -440,7 +442,7 @@ static void pnv_lpc_realize(DeviceState *dev, Error **errp)
memory_region_add_subregion(&lpc->opb_mr, LPC_MEM_OPB_ADDR, memory_region_add_subregion(&lpc->opb_mr, LPC_MEM_OPB_ADDR,
&lpc->opb_isa_mem); &lpc->opb_isa_mem);
memory_region_init_alias(&lpc->opb_isa_fw, OBJECT(dev), "lpc-isa-fw", memory_region_init_alias(&lpc->opb_isa_fw, OBJECT(dev), "lpc-isa-fw",
&lpc->isa_mem, 0, LPC_FW_OPB_SIZE); &lpc->isa_fw, 0, LPC_FW_OPB_SIZE);
memory_region_add_subregion(&lpc->opb_mr, LPC_FW_OPB_ADDR, memory_region_add_subregion(&lpc->opb_mr, LPC_FW_OPB_ADDR,
&lpc->opb_isa_fw); &lpc->opb_isa_fw);

View File

@ -257,7 +257,7 @@ static void ppc440_pcix_reg_write4(void *opaque, hwaddr addr,
break; break;
case PCIX0_PIM2SAL: case PCIX0_PIM2SAL:
s->pim[2].sa &= 0xffffffff00000000ULL; s->pim[2].sa &= 0xffffffff00000000ULL;
s->pim[2].sa = val; s->pim[2].sa |= val;
ppc440_pcix_update_pim(s, 2); ppc440_pcix_update_pim(s, 2);
break; break;
case PCIX0_PIM2LAL: case PCIX0_PIM2LAL:

View File

@ -770,7 +770,6 @@ static void ibm_40p_init(MachineState *machine)
/* add some more devices */ /* add some more devices */
if (defaults_enabled()) { if (defaults_enabled()) {
isa_create_simple(isa_bus, TYPE_I8042);
m48t59 = NVRAM(isa_create_simple(isa_bus, "isa-m48t59")); m48t59 = NVRAM(isa_create_simple(isa_bus, "isa-m48t59"));
dev = DEVICE(isa_create(isa_bus, "cs4231a")); dev = DEVICE(isa_create(isa_bus, "cs4231a"));
@ -885,7 +884,6 @@ static void ibm_40p_machine_init(MachineClass *mc)
mc->desc = "IBM RS/6000 7020 (40p)", mc->desc = "IBM RS/6000 7020 (40p)",
mc->init = ibm_40p_init; mc->init = ibm_40p_init;
mc->max_cpus = 1; mc->max_cpus = 1;
mc->pci_allow_0_address = true;
mc->default_ram_size = 128 * M_BYTE; mc->default_ram_size = 128 * M_BYTE;
mc->block_default_type = IF_SCSI; mc->block_default_type = IF_SCSI;
mc->default_boot_order = "c"; mc->default_boot_order = "c";

View File

@ -3136,7 +3136,7 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,
} }
static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
uint32_t node, Error **errp) Error **errp)
{ {
Error *local_err = NULL; Error *local_err = NULL;
sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev); sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev);
@ -3144,6 +3144,7 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
MemoryRegion *mr; MemoryRegion *mr;
uint64_t align, size, addr; uint64_t align, size, addr;
uint32_t node;
mr = ddc->get_memory_region(dimm, &local_err); mr = ddc->get_memory_region(dimm, &local_err);
if (local_err) { if (local_err) {
@ -3163,6 +3164,8 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
goto out_unplug; goto out_unplug;
} }
node = object_property_get_uint(OBJECT(dev), PC_DIMM_NODE_PROP,
&error_abort);
spapr_add_lmbs(dev, addr, size, node, spapr_add_lmbs(dev, addr, size, node,
spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT), spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT),
&local_err); &local_err);
@ -3181,12 +3184,18 @@ out:
static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp) Error **errp)
{ {
const sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(hotplug_dev);
PCDIMMDevice *dimm = PC_DIMM(dev); PCDIMMDevice *dimm = PC_DIMM(dev);
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
MemoryRegion *mr; MemoryRegion *mr;
uint64_t size; uint64_t size;
char *mem_dev; char *mem_dev;
if (!smc->dr_lmb_enabled) {
error_setg(errp, "Memory hotplug not supported for this machine");
return;
}
mr = ddc->get_memory_region(dimm, errp); mr = ddc->get_memory_region(dimm, errp);
if (!mr) { if (!mr) {
return; return;
@ -3290,7 +3299,8 @@ static sPAPRDIMMState *spapr_recover_pending_dimm_state(sPAPRMachineState *ms,
/* Callback to be called during DRC release. */ /* Callback to be called during DRC release. */
void spapr_lmb_release(DeviceState *dev) void spapr_lmb_release(DeviceState *dev)
{ {
sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_hotplug_handler(dev)); HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
sPAPRMachineState *spapr = SPAPR_MACHINE(hotplug_ctrl);
sPAPRDIMMState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); sPAPRDIMMState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev));
/* This information will get lost if a migration occurs /* This information will get lost if a migration occurs
@ -3308,9 +3318,17 @@ void spapr_lmb_release(DeviceState *dev)
/* /*
* Now that all the LMBs have been removed by the guest, call the * Now that all the LMBs have been removed by the guest, call the
* pc-dimm unplug handler to cleanup up the pc-dimm device. * unplug handler chain. This can never fail.
*/ */
pc_dimm_memory_unplug(dev, MACHINE(spapr)); hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
}
static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
{
sPAPRMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
sPAPRDIMMState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev));
pc_dimm_memory_unplug(dev, MACHINE(hotplug_dev));
object_unparent(OBJECT(dev)); object_unparent(OBJECT(dev));
spapr_pending_dimm_unplugs_remove(spapr, ds); spapr_pending_dimm_unplugs_remove(spapr, ds);
} }
@ -3398,7 +3416,15 @@ static void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset,
/* Callback to be called during DRC release. */ /* Callback to be called during DRC release. */
void spapr_core_release(DeviceState *dev) void spapr_core_release(DeviceState *dev)
{ {
MachineState *ms = MACHINE(qdev_get_hotplug_handler(dev)); HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
/* Call the unplug handler chain. This can never fail. */
hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
}
static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
{
MachineState *ms = MACHINE(hotplug_dev);
sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms); sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms);
CPUCore *cc = CPU_CORE(dev); CPUCore *cc = CPU_CORE(dev);
CPUArchId *core_slot = spapr_find_cpu_slot(ms, cc->core_id, NULL); CPUArchId *core_slot = spapr_find_cpu_slot(ms, cc->core_id, NULL);
@ -3568,31 +3594,23 @@ out:
static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp) DeviceState *dev, Error **errp)
{ {
MachineState *ms = MACHINE(hotplug_dev);
sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms);
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
int node; spapr_memory_plug(hotplug_dev, dev, errp);
if (!smc->dr_lmb_enabled) {
error_setg(errp, "Memory hotplug not supported for this machine");
return;
}
node = object_property_get_uint(OBJECT(dev), PC_DIMM_NODE_PROP, errp);
if (*errp) {
return;
}
if (node < 0 || node >= MAX_NODES) {
error_setg(errp, "Invaild node %d", node);
return;
}
spapr_memory_plug(hotplug_dev, dev, node, errp);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
spapr_core_plug(hotplug_dev, dev, errp); spapr_core_plug(hotplug_dev, dev, errp);
} }
} }
static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
spapr_memory_unplug(hotplug_dev, dev);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
spapr_core_unplug(hotplug_dev, dev);
}
}
static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev, static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp) DeviceState *dev, Error **errp)
{ {
@ -3987,6 +4005,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
mc->get_default_cpu_node_id = spapr_get_default_cpu_node_id; mc->get_default_cpu_node_id = spapr_get_default_cpu_node_id;
mc->possible_cpu_arch_ids = spapr_possible_cpu_arch_ids; mc->possible_cpu_arch_ids = spapr_possible_cpu_arch_ids;
hc->unplug_request = spapr_machine_device_unplug_request; hc->unplug_request = spapr_machine_device_unplug_request;
hc->unplug = spapr_machine_device_unplug;
smc->dr_lmb_enabled = true; smc->dr_lmb_enabled = true;
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");

View File

@ -366,7 +366,8 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name,
break; break;
} }
default: default:
error_setg(&error_abort, "device FDT in unexpected state: %d", tag); error_report("device FDT in unexpected state: %d", tag);
abort();
} }
fdt_offset = fdt_offset_next; fdt_offset = fdt_offset_next;
} while (fdt_depth != 0); } while (fdt_depth != 0);

View File

@ -1717,13 +1717,6 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
} }
/* DMA setup */ /* DMA setup */
if (((sphb->page_size_mask & qemu_getrampagesize()) == 0)
&& kvm_enabled()) {
warn_report("System page size 0x%lx is not enabled in page_size_mask "
"(0x%"PRIx64"). Performance may be slow",
qemu_getrampagesize(), sphb->page_size_mask);
}
for (i = 0; i < windows_supported; ++i) { for (i = 0; i < windows_supported; ++i) {
tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn[i]); tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn[i]);
if (!tcet) { if (!tcet) {

View File

@ -22,6 +22,7 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "qapi/visitor.h"
#include "hw/hw.h" #include "hw/hw.h"
#include "qemu/log.h" #include "qemu/log.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
@ -32,6 +33,7 @@
#include "sysemu/kvm.h" #include "sysemu/kvm.h"
#include "sysemu/device_tree.h" #include "sysemu/device_tree.h"
#include "kvm_ppc.h" #include "kvm_ppc.h"
#include "sysemu/qtest.h"
#include "hw/ppc/spapr.h" #include "hw/ppc/spapr.h"
#include "hw/ppc/spapr_vio.h" #include "hw/ppc/spapr_vio.h"
@ -41,8 +43,26 @@
#include <libfdt.h> #include <libfdt.h>
static void spapr_vio_getset_irq(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
Property *prop = opaque;
uint32_t *ptr = qdev_get_prop_ptr(DEVICE(obj), prop);
if (!qtest_enabled()) {
warn_report(TYPE_VIO_SPAPR_DEVICE " '%s' property is deprecated", name);
}
visit_type_uint32(v, name, ptr, errp);
}
static const PropertyInfo spapr_vio_irq_propinfo = {
.name = "irq",
.get = spapr_vio_getset_irq,
.set = spapr_vio_getset_irq,
};
static Property spapr_vio_props[] = { static Property spapr_vio_props[] = {
DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, irq, 0), \ DEFINE_PROP("irq", VIOsPAPRDevice, irq, spapr_vio_irq_propinfo, uint32_t),
DEFINE_PROP_END_OF_LIST(), DEFINE_PROP_END_OF_LIST(),
}; };

View File

@ -54,12 +54,21 @@
#define CUDA_TIMER_TICKLE 0x24 #define CUDA_TIMER_TICKLE 0x24
#define CUDA_COMBINED_FORMAT_IIC 0x25 #define CUDA_COMBINED_FORMAT_IIC 0x25
/* MOS6522 CUDA */
typedef struct MOS6522CUDAState {
/*< private >*/
MOS6522State parent_obj;
} MOS6522CUDAState;
#define TYPE_MOS6522_CUDA "mos6522-cuda"
#define MOS6522_CUDA(obj) OBJECT_CHECK(MOS6522CUDAState, (obj), \
TYPE_MOS6522_CUDA)
/* Cuda */ /* Cuda */
#define TYPE_CUDA "cuda" #define TYPE_CUDA "cuda"
#define CUDA(obj) OBJECT_CHECK(CUDAState, (obj), TYPE_CUDA) #define CUDA(obj) OBJECT_CHECK(CUDAState, (obj), TYPE_CUDA)
typedef struct MOS6522CUDAState MOS6522CUDAState;
typedef struct CUDAState { typedef struct CUDAState {
/*< private >*/ /*< private >*/
SysBusDevice parent_obj; SysBusDevice parent_obj;
@ -67,7 +76,7 @@ typedef struct CUDAState {
MemoryRegion mem; MemoryRegion mem;
ADBBusState adb_bus; ADBBusState adb_bus;
MOS6522CUDAState *mos6522_cuda; MOS6522CUDAState mos6522_cuda;
uint32_t tick_offset; uint32_t tick_offset;
uint64_t tb_frequency; uint64_t tb_frequency;
@ -92,16 +101,4 @@ typedef struct CUDAState {
QEMUTimer *adb_poll_timer; QEMUTimer *adb_poll_timer;
} CUDAState; } CUDAState;
/* MOS6522 CUDA */
struct MOS6522CUDAState {
/*< private >*/
MOS6522State parent_obj;
CUDAState *cuda;
};
#define TYPE_MOS6522_CUDA "mos6522-cuda"
#define MOS6522_CUDA(obj) OBJECT_CHECK(MOS6522CUDAState, (obj), \
TYPE_MOS6522_CUDA)
#endif /* CUDA_H */ #endif /* CUDA_H */

View File

@ -130,7 +130,7 @@ typedef struct MOS6522State {
typedef struct MOS6522DeviceClass { typedef struct MOS6522DeviceClass {
DeviceClass parent_class; DeviceClass parent_class;
DeviceRealize parent_realize; DeviceReset parent_reset;
void (*set_sr_int)(MOS6522State *dev); void (*set_sr_int)(MOS6522State *dev);
void (*portB_write)(MOS6522State *dev); void (*portB_write)(MOS6522State *dev);
void (*portA_write)(MOS6522State *dev); void (*portA_write)(MOS6522State *dev);
@ -146,6 +146,8 @@ typedef struct MOS6522DeviceClass {
#define MOS6522_DEVICE_GET_CLASS(obj) \ #define MOS6522_DEVICE_GET_CLASS(obj) \
OBJECT_GET_CLASS(MOS6522DeviceClass, (obj), TYPE_MOS6522) OBJECT_GET_CLASS(MOS6522DeviceClass, (obj), TYPE_MOS6522)
extern const VMStateDescription vmstate_mos6522;
uint64_t mos6522_read(void *opaque, hwaddr addr, unsigned size); uint64_t mos6522_read(void *opaque, hwaddr addr, unsigned size);
void mos6522_write(void *opaque, hwaddr addr, uint64_t val, unsigned size); void mos6522_write(void *opaque, hwaddr addr, uint64_t val, unsigned size);

View File

@ -29,6 +29,9 @@
#include "hw/ppc/openpic.h" #include "hw/ppc/openpic.h"
/* UniNorth version */
#define UNINORTH_VERSION_10A 0x7
#define TYPE_UNI_NORTH_PCI_HOST_BRIDGE "uni-north-pci-pcihost" #define TYPE_UNI_NORTH_PCI_HOST_BRIDGE "uni-north-pci-pcihost"
#define TYPE_UNI_NORTH_AGP_HOST_BRIDGE "uni-north-agp-pcihost" #define TYPE_UNI_NORTH_AGP_HOST_BRIDGE "uni-north-agp-pcihost"
#define TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE "uni-north-internal-pci-pcihost" #define TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE "uni-north-internal-pci-pcihost"
@ -57,7 +60,6 @@ typedef struct UNINState {
SysBusDevice parent_obj; SysBusDevice parent_obj;
MemoryRegion mem; MemoryRegion mem;
int token[1];
} UNINState; } UNINState;
#define TYPE_UNI_NORTH "uni-north" #define TYPE_UNI_NORTH "uni-north"

View File

@ -38,6 +38,7 @@ typedef struct PnvLpcController {
/* ISA IO and Memory space */ /* ISA IO and Memory space */
MemoryRegion isa_io; MemoryRegion isa_io;
MemoryRegion isa_mem; MemoryRegion isa_mem;
MemoryRegion isa_fw;
/* Windows from OPB to ISA (aliases) */ /* Windows from OPB to ISA (aliases) */
MemoryRegion opb_isa_io; MemoryRegion opb_isa_io;

View File

@ -100,6 +100,7 @@ enum {
#define FW_CFG_PPC_KVM_PID (FW_CFG_ARCH_LOCAL + 0x07) #define FW_CFG_PPC_KVM_PID (FW_CFG_ARCH_LOCAL + 0x07)
#define FW_CFG_PPC_NVRAM_ADDR (FW_CFG_ARCH_LOCAL + 0x08) #define FW_CFG_PPC_NVRAM_ADDR (FW_CFG_ARCH_LOCAL + 0x08)
#define FW_CFG_PPC_BUSFREQ (FW_CFG_ARCH_LOCAL + 0x09) #define FW_CFG_PPC_BUSFREQ (FW_CFG_ARCH_LOCAL + 0x09)
#define FW_CFG_PPC_NVRAM_FLAT (FW_CFG_ARCH_LOCAL + 0x0a)
#define PPC_SERIAL_MM_BAUDBASE 399193 #define PPC_SERIAL_MM_BAUDBASE 399193

View File

@ -367,7 +367,8 @@ void qemu_anon_ram_free(void *ptr, size_t size);
#endif #endif
#if defined(__linux__) && \ #if defined(__linux__) && \
(defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)) (defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) \
|| defined(__powerpc64__))
/* Use 2 MiB alignment so transparent hugepages can be used by KVM. /* Use 2 MiB alignment so transparent hugepages can be used by KVM.
Valgrind does not support alignments larger than 1 MiB, Valgrind does not support alignments larger than 1 MiB,
therefore we need special code which handles running on Valgrind. */ therefore we need special code which handles running on Valgrind. */

View File

@ -2958,13 +2958,21 @@ support page sizes < 4096 any longer.
@section System emulator machines @section System emulator machines
@section Block device options @section Device options
@subsection "backing": "" (since 2.12.0) @subsection Block device options
@subsubsection "backing": "" (since 2.12.0)
In order to prevent QEMU from automatically opening an image's backing In order to prevent QEMU from automatically opening an image's backing
chain, use ``"backing": null'' instead. chain, use ``"backing": null'' instead.
@subsection vio-spapr-device device options
@subsubsection "irq": "" (since 3.0.0)
The ``irq'' property is obsoleted.
@node Supported build platforms @node Supported build platforms
@appendix Supported build platforms @appendix Supported build platforms

View File

@ -17,6 +17,7 @@ DEF_HELPER_2(pminsn, void, env, i32)
DEF_HELPER_1(rfid, void, env) DEF_HELPER_1(rfid, void, env)
DEF_HELPER_1(hrfid, void, env) DEF_HELPER_1(hrfid, void, env)
DEF_HELPER_2(store_lpcr, void, env, tl) DEF_HELPER_2(store_lpcr, void, env, tl)
DEF_HELPER_2(store_pcr, void, env, tl)
#endif #endif
DEF_HELPER_1(check_tlb_flush_local, void, env) DEF_HELPER_1(check_tlb_flush_local, void, env)
DEF_HELPER_1(check_tlb_flush_global, void, env) DEF_HELPER_1(check_tlb_flush_global, void, env)

View File

@ -2412,6 +2412,41 @@ bool kvmppc_has_cap_mmu_hash_v3(void)
return cap_mmu_hash_v3; return cap_mmu_hash_v3;
} }
static int parse_cap_ppc_safe_cache(struct kvm_ppc_cpu_char c)
{
if (~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_L1D_FLUSH_PR) {
return 2;
} else if ((c.character & c.character_mask & H_CPU_CHAR_L1D_THREAD_PRIV) &&
(c.character & c.character_mask
& (H_CPU_CHAR_L1D_FLUSH_ORI30 | H_CPU_CHAR_L1D_FLUSH_TRIG2))) {
return 1;
}
return 0;
}
static int parse_cap_ppc_safe_bounds_check(struct kvm_ppc_cpu_char c)
{
if (~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_BNDS_CHK_SPEC_BAR) {
return 2;
} else if (c.character & c.character_mask & H_CPU_CHAR_SPEC_BAR_ORI31) {
return 1;
}
return 0;
}
static int parse_cap_ppc_safe_indirect_branch(struct kvm_ppc_cpu_char c)
{
if (c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) {
return SPAPR_CAP_FIXED_CCD;
} else if (c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED) {
return SPAPR_CAP_FIXED_IBS;
}
return 0;
}
static void kvmppc_get_cpu_characteristics(KVMState *s) static void kvmppc_get_cpu_characteristics(KVMState *s)
{ {
struct kvm_ppc_cpu_char c; struct kvm_ppc_cpu_char c;
@ -2430,26 +2465,10 @@ static void kvmppc_get_cpu_characteristics(KVMState *s)
if (ret < 0) { if (ret < 0) {
return; return;
} }
/* Parse and set cap_ppc_safe_cache */
if (~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_L1D_FLUSH_PR) { cap_ppc_safe_cache = parse_cap_ppc_safe_cache(c);
cap_ppc_safe_cache = 2; cap_ppc_safe_bounds_check = parse_cap_ppc_safe_bounds_check(c);
} else if ((c.character & c.character_mask & H_CPU_CHAR_L1D_THREAD_PRIV) && cap_ppc_safe_indirect_branch = parse_cap_ppc_safe_indirect_branch(c);
(c.character & c.character_mask
& (H_CPU_CHAR_L1D_FLUSH_ORI30 | H_CPU_CHAR_L1D_FLUSH_TRIG2))) {
cap_ppc_safe_cache = 1;
}
/* Parse and set cap_ppc_safe_bounds_check */
if (~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_BNDS_CHK_SPEC_BAR) {
cap_ppc_safe_bounds_check = 2;
} else if (c.character & c.character_mask & H_CPU_CHAR_SPEC_BAR_ORI31) {
cap_ppc_safe_bounds_check = 1;
}
/* Parse and set cap_ppc_safe_indirect_branch */
if (c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) {
cap_ppc_safe_indirect_branch = SPAPR_CAP_FIXED_CCD;
} else if (c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED) {
cap_ppc_safe_indirect_branch = SPAPR_CAP_FIXED_IBS;
}
} }
int kvmppc_get_cap_safe_cache(void) int kvmppc_get_cap_safe_cache(void)

View File

@ -20,6 +20,7 @@
#include "cpu.h" #include "cpu.h"
#include "exec/exec-all.h" #include "exec/exec-all.h"
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "qemu/error-report.h"
#include "helper_regs.h" #include "helper_regs.h"
@ -98,6 +99,14 @@ void helper_store_ptcr(CPUPPCState *env, target_ulong val)
tlb_flush(CPU(cpu)); tlb_flush(CPU(cpu));
} }
} }
void helper_store_pcr(CPUPPCState *env, target_ulong value)
{
PowerPCCPU *cpu = ppc_env_get_cpu(env);
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
env->spr[SPR_PCR] = value & pcc->pcr_mask;
}
#endif /* defined(TARGET_PPC64) */ #endif /* defined(TARGET_PPC64) */
void helper_store_pidr(CPUPPCState *env, target_ulong val) void helper_store_pidr(CPUPPCState *env, target_ulong val)

View File

@ -2967,7 +2967,28 @@ static void gen_stswx(DisasContext *ctx)
/* eieio */ /* eieio */
static void gen_eieio(DisasContext *ctx) static void gen_eieio(DisasContext *ctx)
{ {
tcg_gen_mb(TCG_MO_LD_ST | TCG_BAR_SC); TCGBar bar = TCG_MO_LD_ST;
/*
* POWER9 has a eieio instruction variant using bit 6 as a hint to
* tell the CPU it is a store-forwarding barrier.
*/
if (ctx->opcode & 0x2000000) {
/*
* ISA says that "Reserved fields in instructions are ignored
* by the processor". So ignore the bit 6 on non-POWER9 CPU but
* as this is not an instruction software should be using,
* complain to the user.
*/
if (!(ctx->insns_flags2 & PPC2_ISA300)) {
qemu_log_mask(LOG_GUEST_ERROR, "invalid eieio using bit 6 at @"
TARGET_FMT_lx "\n", ctx->base.pc_next - 4);
} else {
bar = TCG_MO_ST_LD;
}
}
tcg_gen_mb(bar | TCG_BAR_SC);
} }
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)
@ -3933,14 +3954,10 @@ static inline void gen_op_mfspr(DisasContext *ctx)
* allowing userland application to read the PVR * allowing userland application to read the PVR
*/ */
if (sprn != SPR_PVR) { if (sprn != SPR_PVR) {
fprintf(stderr, "Trying to read privileged spr %d (0x%03x) at " qemu_log_mask(LOG_GUEST_ERROR, "Trying to read privileged spr "
TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4); "%d (0x%03x) at " TARGET_FMT_lx "\n", sprn, sprn,
if (qemu_log_separate()) {
qemu_log("Trying to read privileged spr %d (0x%03x) at "
TARGET_FMT_lx "\n", sprn, sprn,
ctx->base.pc_next - 4); ctx->base.pc_next - 4);
} }
}
gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG); gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
} }
} else { } else {
@ -3951,12 +3968,9 @@ static inline void gen_op_mfspr(DisasContext *ctx)
return; return;
} }
/* Not defined */ /* Not defined */
fprintf(stderr, "Trying to read invalid spr %d (0x%03x) at " qemu_log_mask(LOG_GUEST_ERROR,
"Trying to read invalid spr %d (0x%03x) at "
TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4); TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4);
if (qemu_log_separate()) {
qemu_log("Trying to read invalid spr %d (0x%03x) at "
TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4);
}
/* The behaviour depends on MSR:PR and SPR# bit 0x10, /* The behaviour depends on MSR:PR and SPR# bit 0x10,
* it can generate a priv, a hv emu or a no-op * it can generate a priv, a hv emu or a no-op
@ -4097,12 +4111,9 @@ static void gen_mtspr(DisasContext *ctx)
(*write_cb)(ctx, sprn, rS(ctx->opcode)); (*write_cb)(ctx, sprn, rS(ctx->opcode));
} else { } else {
/* Privilege exception */ /* Privilege exception */
fprintf(stderr, "Trying to write privileged spr %d (0x%03x) at " qemu_log_mask(LOG_GUEST_ERROR, "Trying to write privileged spr "
TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4); "%d (0x%03x) at " TARGET_FMT_lx "\n", sprn, sprn,
if (qemu_log_separate()) { ctx->base.pc_next - 4);
qemu_log("Trying to write privileged spr %d (0x%03x) at "
TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4);
}
gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG); gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
} }
} else { } else {
@ -4114,11 +4125,8 @@ static void gen_mtspr(DisasContext *ctx)
} }
/* Not defined */ /* Not defined */
if (qemu_log_separate()) { qemu_log_mask(LOG_GUEST_ERROR,
qemu_log("Trying to write invalid spr %d (0x%03x) at " "Trying to write invalid spr %d (0x%03x) at "
TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4);
}
fprintf(stderr, "Trying to write invalid spr %d (0x%03x) at "
TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4); TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4);
@ -6496,7 +6504,7 @@ GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING),
GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING), GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING),
GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING), GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING),
GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING), GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING),
GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO), GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x01FFF801, PPC_MEM_EIEIO),
GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM), GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM),
GEN_HANDLER_E(lbarx, 0x1F, 0x14, 0x01, 0, PPC_NONE, PPC2_ATOMIC_ISA206), GEN_HANDLER_E(lbarx, 0x1F, 0x14, 0x01, 0, PPC_NONE, PPC2_ATOMIC_ISA206),
GEN_HANDLER_E(lharx, 0x1F, 0x14, 0x03, 0, PPC_NONE, PPC2_ATOMIC_ISA206), GEN_HANDLER_E(lharx, 0x1F, 0x14, 0x03, 0, PPC_NONE, PPC2_ATOMIC_ISA206),

View File

@ -424,6 +424,10 @@ static void spr_write_ptcr(DisasContext *ctx, int sprn, int gprn)
gen_helper_store_ptcr(cpu_env, cpu_gpr[gprn]); gen_helper_store_ptcr(cpu_env, cpu_gpr[gprn]);
} }
static void spr_write_pcr(DisasContext *ctx, int sprn, int gprn)
{
gen_helper_store_pcr(cpu_env, cpu_gpr[gprn]);
}
#endif #endif
#endif #endif
@ -7815,7 +7819,7 @@ static void gen_spr_book3s_ids(CPUPPCState *env)
/* Processor identification */ /* Processor identification */
spr_register_hv(env, SPR_PIR, "PIR", spr_register_hv(env, SPR_PIR, "PIR",
SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, SPR_NOACCESS,
&spr_read_generic, NULL, &spr_read_generic, NULL,
0x00000000); 0x00000000);
spr_register_hv(env, SPR_HID0, "HID0", spr_register_hv(env, SPR_HID0, "HID0",
@ -7957,11 +7961,12 @@ static void gen_spr_power6_common(CPUPPCState *env)
#endif #endif
/* /*
* Register PCR to report POWERPC_EXCP_PRIV_REG instead of * Register PCR to report POWERPC_EXCP_PRIV_REG instead of
* POWERPC_EXCP_INVAL_SPR. * POWERPC_EXCP_INVAL_SPR in userspace. Permit hypervisor access.
*/ */
spr_register(env, SPR_PCR, "PCR", spr_register_hv(env, SPR_PCR, "PCR",
SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_pcr,
0x00000000); 0x00000000);
} }