diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 23740f9d07..eb54f93986 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1685,6 +1685,9 @@ static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp) pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id), &eq->xscom_regs); + + pnv_xscom_add_subregion(chip, PNV10_XSCOM_QME_BASE(eq->quad_id), + &eq->xscom_qme_regs); } } diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 9e7cf341dc..9b39d527de 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -496,7 +496,54 @@ static const MemoryRegionOps pnv_quad_power10_xscom_ops = { .endianness = DEVICE_BIG_ENDIAN, }; -static void pnv_quad_realize(DeviceState *dev, Error **errp) +#define P10_QME_SPWU_HYP 0x83c +#define P10_QME_SSH_HYP 0x82c + +static uint64_t pnv_qme_power10_xscom_read(void *opaque, hwaddr addr, + unsigned int width) +{ + uint32_t offset = addr >> 3; + uint64_t val = -1; + + /* + * Forth nibble selects the core within a quad, mask it to process read + * for any core. + */ + switch (offset & ~0xf000) { + case P10_QME_SPWU_HYP: + case P10_QME_SSH_HYP: + return 0; + default: + qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, + offset); + } + + return val; +} + +static void pnv_qme_power10_xscom_write(void *opaque, hwaddr addr, + uint64_t val, unsigned int width) +{ + uint32_t offset = addr >> 3; + + switch (offset) { + default: + qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, + offset); + } +} + +static const MemoryRegionOps pnv_qme_power10_xscom_ops = { + .read = pnv_qme_power10_xscom_read, + .write = pnv_qme_power10_xscom_write, + .valid.min_access_size = 8, + .valid.max_access_size = 8, + .impl.min_access_size = 8, + .impl.max_access_size = 8, + .endianness = DEVICE_BIG_ENDIAN, +}; + +static void pnv_quad_power9_realize(DeviceState *dev, Error **errp) { PnvQuad *eq = PNV_QUAD(dev); PnvQuadClass *pqc = PNV_QUAD_GET_CLASS(eq); @@ -509,6 +556,25 @@ static void pnv_quad_realize(DeviceState *dev, Error **errp) pqc->xscom_size); } +static void pnv_quad_power10_realize(DeviceState *dev, Error **errp) +{ + PnvQuad *eq = PNV_QUAD(dev); + PnvQuadClass *pqc = PNV_QUAD_GET_CLASS(eq); + char name[32]; + + snprintf(name, sizeof(name), "xscom-quad.%d", eq->quad_id); + pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev), + pqc->xscom_ops, + eq, name, + pqc->xscom_size); + + snprintf(name, sizeof(name), "xscom-qme.%d", eq->quad_id); + pnv_xscom_region_init(&eq->xscom_qme_regs, OBJECT(dev), + pqc->xscom_qme_ops, + eq, name, + pqc->xscom_qme_size); +} + static Property pnv_quad_properties[] = { DEFINE_PROP_UINT32("quad-id", PnvQuad, quad_id, 0), DEFINE_PROP_END_OF_LIST(), @@ -517,6 +583,9 @@ static Property pnv_quad_properties[] = { static void pnv_quad_power9_class_init(ObjectClass *oc, void *data) { PnvQuadClass *pqc = PNV_QUAD_CLASS(oc); + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = pnv_quad_power9_realize; pqc->xscom_ops = &pnv_quad_power9_xscom_ops; pqc->xscom_size = PNV9_XSCOM_EQ_SIZE; @@ -525,16 +594,21 @@ static void pnv_quad_power9_class_init(ObjectClass *oc, void *data) static void pnv_quad_power10_class_init(ObjectClass *oc, void *data) { PnvQuadClass *pqc = PNV_QUAD_CLASS(oc); + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = pnv_quad_power10_realize; pqc->xscom_ops = &pnv_quad_power10_xscom_ops; pqc->xscom_size = PNV10_XSCOM_EQ_SIZE; + + pqc->xscom_qme_ops = &pnv_qme_power10_xscom_ops; + pqc->xscom_qme_size = PNV10_XSCOM_QME_SIZE; } static void pnv_quad_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); - dc->realize = pnv_quad_realize; device_class_set_props(dc, pnv_quad_properties); dc->user_creatable = false; } diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h index aa5ca281fc..4db21229a6 100644 --- a/include/hw/ppc/pnv_core.h +++ b/include/hw/ppc/pnv_core.h @@ -66,6 +66,9 @@ struct PnvQuadClass { const MemoryRegionOps *xscom_ops; uint64_t xscom_size; + + const MemoryRegionOps *xscom_qme_ops; + uint64_t xscom_qme_size; }; #define TYPE_PNV_QUAD "powernv-cpu-quad" @@ -80,5 +83,6 @@ struct PnvQuad { uint32_t quad_id; MemoryRegion xscom_regs; + MemoryRegion xscom_qme_regs; }; #endif /* PPC_PNV_CORE_H */ diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h index a4c9d95dc5..9bc6463547 100644 --- a/include/hw/ppc/pnv_xscom.h +++ b/include/hw/ppc/pnv_xscom.h @@ -127,6 +127,17 @@ struct PnvXScomInterfaceClass { #define PNV10_XSCOM_EC(proc) \ ((0x2 << 16) | ((1 << (3 - (proc))) << 12)) +#define PNV10_XSCOM_QME(chiplet) \ + (PNV10_XSCOM_EQ(chiplet) | (0xE << 16)) + +/* + * Make the region larger by 0x1000 (instead of starting at an offset) so the + * modelled addresses start from 0 + */ +#define PNV10_XSCOM_QME_BASE(core) \ + ((uint64_t) PNV10_XSCOM_QME(PNV10_XSCOM_EQ_CHIPLET(core))) +#define PNV10_XSCOM_QME_SIZE (0x8000 + 0x1000) + #define PNV10_XSCOM_EQ_BASE(core) \ ((uint64_t) PNV10_XSCOM_EQ(PNV10_XSCOM_EQ_CHIPLET(core))) #define PNV10_XSCOM_EQ_SIZE 0x20000