[Qemu-devel] [PATCH 04/12] e500: additional CCSR registers
Add CCSRBAR to allow CCSR region to be relocated. Guest memory size introspection. Dummy RAM error controls. Guest clock introspection. Signed-off-by: Michael Davidsaver --- hw/ppc/e500.c | 2 ++ hw/ppc/e500.h | 1 + hw/ppc/e500_ccsr.c | 72 -- hw/ppc/e500plat.c | 1 + hw/ppc/mpc8544ds.c | 1 + 5 files changed, 75 insertions(+), 2 deletions(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 474a46a985..057be1751b 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -853,7 +853,9 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) dev = qdev_create(NULL, "e500-ccsr"); object_property_add_child(qdev_get_machine(), "e500-ccsr", OBJECT(dev), NULL); +qdev_prop_set_uint32(dev, "porpllsr", params->porpllsr); qdev_prop_set_uint32(dev, "base", params->ccsrbar_base); +qdev_prop_set_uint32(dev, "ram-size", ram_size); qdev_init_nofail(dev); ccsr_addr_space = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); diff --git a/hw/ppc/e500.h b/hw/ppc/e500.h index 40f72f2de2..1f39095dfa 100644 --- a/hw/ppc/e500.h +++ b/hw/ppc/e500.h @@ -22,6 +22,7 @@ typedef struct PPCE500Params { hwaddr pci_mmio_base; hwaddr pci_mmio_bus_base; hwaddr spin_base; +uint32_t porpllsr; /* value of PORPLLSR register */ uint32_t decrementor_freq; /* in Hz */ bool skip_load; bool tsec_nic; diff --git a/hw/ppc/e500_ccsr.c b/hw/ppc/e500_ccsr.c index 1b586c3f42..c58b17f06b 100644 --- a/hw/ppc/e500_ccsr.c +++ b/hw/ppc/e500_ccsr.c @@ -31,6 +31,16 @@ /* E500_ denotes registers common to all */ +#define E500_CCSRBAR (0) + +#define E500_CS0_BNDS(0x2000) + +#define E500_CS0_CONFIG (0x2080) + +#define E500_ERR_DETECT (0x2e40) +#define E500_ERR_DISABLE (0x2e44) + +#define E500_PORPLLSR(0xE) #define E500_PVR (0xE00A0) #define E500_SVR (0xE00A4) @@ -44,7 +54,11 @@ typedef struct { MemoryRegion iomem; -uint32_t defbase; +uint32_t defbase, base; +uint32_t ram_size; +uint32_t merrd; + +uint32_t porpllsr; } CCSRState; #define TYPE_E500_CCSR "e500-ccsr" @@ -53,10 +67,28 @@ typedef struct { static uint64_t e500_ccsr_read(void *opaque, hwaddr addr, unsigned size) { +CCSRState *ccsr = opaque; PowerPCCPU *cpu = POWERPC_CPU(current_cpu); CPUPPCState *env = &cpu->env; switch (addr) { +case E500_CCSRBAR: +return ccsr->base >> 12; +case E500_CS0_BNDS: +/* we model all RAM in a single chip with addresses [0, ram_size) */ +return (ccsr->ram_size - 1) >> 24; +case E500_CS0_CONFIG: +return 1 << 31; +case E500_ERR_DETECT: +return 0; /* (errors not modeled) */ +case E500_ERR_DISABLE: +return ccsr->merrd; +case E500_PORPLLSR: +if (!ccsr->porpllsr) { +qemu_log_mask(LOG_UNIMP, + "Machine does not provide valid PORPLLSR\n"); +} +return ccsr->porpllsr; case E500_PVR: return env->spr[SPR_PVR]; case E500_SVR: @@ -72,10 +104,22 @@ static uint64_t e500_ccsr_read(void *opaque, hwaddr addr, static void e500_ccsr_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { +CCSRState *ccsr = opaque; PowerPCCPU *cpu = POWERPC_CPU(current_cpu); CPUPPCState *env = &cpu->env; uint32_t svr = env->spr[SPR_E500_SVR] >> 16; +switch (addr) { +case E500_CCSRBAR: +value &= 0x000fff00; +ccsr->base = value << 12; +sysbus_mmio_map(SYS_BUS_DEVICE(ccsr), 0, ccsr->base); +return; +case E500_ERR_DISABLE: +ccsr->merrd = value & 0xd; +return; +} + switch (svr) { case 0: /* generic. assumed to be mpc8544ds or e500plat board */ case 0x8034: /* mpc8544 */ @@ -104,11 +148,20 @@ static const MemoryRegionOps e500_ccsr_ops = { } }; +static int e500_ccsr_post_load(void *opaque, int version_id) +{ +CCSRState *ccsr = opaque; + +sysbus_mmio_map(SYS_BUS_DEVICE(ccsr), 0, ccsr->base); +return 0; +} + static void e500_ccsr_reset(DeviceState *dev) { CCSRState *ccsr = E500_CCSR(dev); -sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, ccsr->defbase); +ccsr->base = ccsr->defbase; +e500_ccsr_post_load(ccsr, 1); } static void e500_ccsr_initfn(Object *obj) @@ -123,15 +176,30 @@ static void e500_ccsr_initfn(Object *obj) static Property e500_ccsr_props[] = { DEFINE_PROP_UINT32("base", CCSRState, defbase, 0xff70), +DEFINE_PROP_UINT32("ram-size", CCSRState, ram_size, 0), +DEFINE_PROP_UINT32("porpllsr", CCSRState, porpllsr, 0), DEFINE_PROP_END_OF_LIST() }; +static const VMStateDescription vmstate_e500_ccsr = { +.name = TYPE_E500_CCSR, +.version_id = 1, +.minimum_version_id = 1, +.post_load = e500_ccsr_post_load, +.fields = (VMStateField[]) { +VMSTATE_UI
Re: [Qemu-devel] [PATCH 04/12] e500: additional CCSR registers
On Sun, Nov 19, 2017 at 09:24:12PM -0600, Michael Davidsaver wrote: > Add CCSRBAR to allow CCSR region to be relocated. > Guest memory size introspection. > Dummy RAM error controls. > Guest clock introspection. > > Signed-off-by: Michael Davidsaver Looks fine from the POV of someone who doesn't know details about e500. Reviewed-by: David Gibson > --- > hw/ppc/e500.c | 2 ++ > hw/ppc/e500.h | 1 + > hw/ppc/e500_ccsr.c | 72 > -- > hw/ppc/e500plat.c | 1 + > hw/ppc/mpc8544ds.c | 1 + > 5 files changed, 75 insertions(+), 2 deletions(-) > > diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c > index 474a46a985..057be1751b 100644 > --- a/hw/ppc/e500.c > +++ b/hw/ppc/e500.c > @@ -853,7 +853,9 @@ void ppce500_init(MachineState *machine, PPCE500Params > *params) > dev = qdev_create(NULL, "e500-ccsr"); > object_property_add_child(qdev_get_machine(), "e500-ccsr", >OBJECT(dev), NULL); > +qdev_prop_set_uint32(dev, "porpllsr", params->porpllsr); > qdev_prop_set_uint32(dev, "base", params->ccsrbar_base); > +qdev_prop_set_uint32(dev, "ram-size", ram_size); > qdev_init_nofail(dev); > ccsr_addr_space = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); > > diff --git a/hw/ppc/e500.h b/hw/ppc/e500.h > index 40f72f2de2..1f39095dfa 100644 > --- a/hw/ppc/e500.h > +++ b/hw/ppc/e500.h > @@ -22,6 +22,7 @@ typedef struct PPCE500Params { > hwaddr pci_mmio_base; > hwaddr pci_mmio_bus_base; > hwaddr spin_base; > +uint32_t porpllsr; /* value of PORPLLSR register */ > uint32_t decrementor_freq; /* in Hz */ > bool skip_load; > bool tsec_nic; > diff --git a/hw/ppc/e500_ccsr.c b/hw/ppc/e500_ccsr.c > index 1b586c3f42..c58b17f06b 100644 > --- a/hw/ppc/e500_ccsr.c > +++ b/hw/ppc/e500_ccsr.c > @@ -31,6 +31,16 @@ > > /* E500_ denotes registers common to all */ > > +#define E500_CCSRBAR (0) > + > +#define E500_CS0_BNDS(0x2000) > + > +#define E500_CS0_CONFIG (0x2080) > + > +#define E500_ERR_DETECT (0x2e40) > +#define E500_ERR_DISABLE (0x2e44) > + > +#define E500_PORPLLSR(0xE) > #define E500_PVR (0xE00A0) > #define E500_SVR (0xE00A4) > > @@ -44,7 +54,11 @@ typedef struct { > > MemoryRegion iomem; > > -uint32_t defbase; > +uint32_t defbase, base; > +uint32_t ram_size; > +uint32_t merrd; > + > +uint32_t porpllsr; > } CCSRState; > > #define TYPE_E500_CCSR "e500-ccsr" > @@ -53,10 +67,28 @@ typedef struct { > static uint64_t e500_ccsr_read(void *opaque, hwaddr addr, >unsigned size) > { > +CCSRState *ccsr = opaque; > PowerPCCPU *cpu = POWERPC_CPU(current_cpu); > CPUPPCState *env = &cpu->env; > > switch (addr) { > +case E500_CCSRBAR: > +return ccsr->base >> 12; > +case E500_CS0_BNDS: > +/* we model all RAM in a single chip with addresses [0, ram_size) */ > +return (ccsr->ram_size - 1) >> 24; > +case E500_CS0_CONFIG: > +return 1 << 31; > +case E500_ERR_DETECT: > +return 0; /* (errors not modeled) */ > +case E500_ERR_DISABLE: > +return ccsr->merrd; > +case E500_PORPLLSR: > +if (!ccsr->porpllsr) { > +qemu_log_mask(LOG_UNIMP, > + "Machine does not provide valid PORPLLSR\n"); > +} > +return ccsr->porpllsr; > case E500_PVR: > return env->spr[SPR_PVR]; > case E500_SVR: > @@ -72,10 +104,22 @@ static uint64_t e500_ccsr_read(void *opaque, hwaddr addr, > static void e500_ccsr_write(void *opaque, hwaddr addr, > uint64_t value, unsigned size) > { > +CCSRState *ccsr = opaque; > PowerPCCPU *cpu = POWERPC_CPU(current_cpu); > CPUPPCState *env = &cpu->env; > uint32_t svr = env->spr[SPR_E500_SVR] >> 16; > > +switch (addr) { > +case E500_CCSRBAR: > +value &= 0x000fff00; > +ccsr->base = value << 12; > +sysbus_mmio_map(SYS_BUS_DEVICE(ccsr), 0, ccsr->base); > +return; > +case E500_ERR_DISABLE: > +ccsr->merrd = value & 0xd; > +return; > +} > + > switch (svr) { > case 0: /* generic. assumed to be mpc8544ds or e500plat board */ > case 0x8034: /* mpc8544 */ > @@ -104,11 +148,20 @@ static const MemoryRegionOps e500_ccsr_ops = { > } > }; > > +static int e500_ccsr_post_load(void *opaque, int version_id) > +{ > +CCSRState *ccsr = opaque; > + > +sysbus_mmio_map(SYS_BUS_DEVICE(ccsr), 0, ccsr->base); > +return 0; > +} > + > static void e500_ccsr_reset(DeviceState *dev) > { > CCSRState *ccsr = E500_CCSR(dev); > > -sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, ccsr->defbase); > +ccsr->base = ccsr->defbase; > +e500_ccsr_post_load(ccsr, 1); > } > > static void e500_ccsr_initfn(Object *obj) > @@ -123,15 +176,30 @@ static void e500_ccsr_initfn(Object *obj) > > static Proper