diff options
author | Cédric Le Goater <clg@kaod.org> | 2022-03-02 06:51:38 +0100 |
---|---|---|
committer | Cédric Le Goater <clg@kaod.org> | 2022-03-02 06:51:38 +0100 |
commit | da71b7e3ed454bd9200367e09bf75160f8f097a9 (patch) | |
tree | 080b731b03e515a542cd72883616d09c6878c305 /hw/ppc/pnv.c | |
parent | 09a67f3d0e2cb9e66b2ba438de09789527ccb9fe (diff) | |
download | qemu-da71b7e3ed454bd9200367e09bf75160f8f097a9.zip qemu-da71b7e3ed454bd9200367e09bf75160f8f097a9.tar.gz qemu-da71b7e3ed454bd9200367e09bf75160f8f097a9.tar.bz2 |
ppc/pnv: Add a XIVE2 controller to the POWER10 chip
The XIVE2 interrupt controller of the POWER10 processor follows the
same logic than on POWER9 but the HW interface has been largely
reviewed. It has a new register interface, different BARs, extra
VSDs, new layout for the XIVE2 structures, and a set of new features
which are described below.
This is a model of the POWER10 XIVE2 interrupt controller for the
PowerNV machine. It focuses primarily on the needs of the skiboot
firmware but some initial hypervisor support is implemented for KVM
use (escalation).
Support for new features will be implemented in time and will require
new support from the OS.
* XIVE2 BARS
The interrupt controller BARs have a different layout outlined below.
Each sub-engine has now own its range and the indirect TIMA access was
replaced with a set of pages, one per CPU, under the IC BAR:
- IC BAR (Interrupt Controller)
. 4 pages, one per sub-engine
. 128 indirect TIMA pages
- TM BAR (Thread Interrupt Management Area)
. 4 pages
- ESB BAR (ESB pages for IPIs)
. up to 1TB
- END BAR (ESB pages for ENDs)
. up to 2TB
- NVC BAR (Notification Virtual Crowd)
. up to 128
- NVPG BAR (Notification Virtual Process and Group)
. up to 1TB
- Direct mapped Thread Context Area (reads & writes)
OPAL does not use the grouping and crowd capability.
* Virtual Structure Tables
XIVE2 adds new tables types and also changes the field layout of the END
and NVP Virtualization Structure Descriptors.
- EAS
- END new layout
- NVT was splitted in :
. NVP (Processor), 32B
. NVG (Group), 32B
. NVC (Crowd == P9 block group) 32B
- IC for remote configuration
- SYNC for cache injection
- ERQ for event input queue
The setup is slighly different on XIVE2 because the indexing has changed
for some of the tables, block ID or the chip topology ID can be used.
* XIVE2 features
SCOM and MMIO registers have a new layout and XIVE2 adds a new global
capability and configuration registers.
The lowlevel hardware offers a set of new features among which :
- a configurable number of priorities : 1 - 8
- StoreEOI with load-after-store ordering is activated by default
- Gen2 TIMA layout
- A P9-compat mode, or Gen1, TIMA toggle bit for SW compatibility
- increase to 24bit for VP number
Other features will have some impact on the Hypervisor and guest OS
when activated, but this is not required for initial support of the
controller.
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Diffstat (limited to 'hw/ppc/pnv.c')
-rw-r--r-- | hw/ppc/pnv.c | 85 |
1 files changed, 82 insertions, 3 deletions
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 441bf95..f486fdf 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -725,6 +725,7 @@ static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon) { Pnv10Chip *chip10 = PNV10_CHIP(chip); + pnv_xive2_pic_print_info(&chip10->xive, mon); pnv_psi_pic_print_info(&chip10->psi, mon); } @@ -1047,27 +1048,45 @@ static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu, Error **errp) { + Pnv10Chip *chip10 = PNV10_CHIP(chip); + Error *local_err = NULL; + Object *obj; PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); - /* Will be defined when the interrupt controller is */ - pnv_cpu->intc = NULL; + /* + * The core creates its interrupt presenter but the XIVE2 interrupt + * controller object is initialized afterwards. Hopefully, it's + * only used at runtime. + */ + obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip10->xive), + &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + pnv_cpu->intc = obj; } static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu) { - ; + PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); + + xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc)); } static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) { PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); + xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc)); pnv_cpu->intc = NULL; } static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, Monitor *mon) { + xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); } /* @@ -1558,6 +1577,9 @@ static void pnv_chip_power10_instance_init(Object *obj) { Pnv10Chip *chip10 = PNV10_CHIP(obj); + object_initialize_child(obj, "xive", &chip10->xive, TYPE_PNV_XIVE2); + object_property_add_alias(obj, "xive-fabric", OBJECT(&chip10->xive), + "xive-fabric"); object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI); object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC); } @@ -1583,6 +1605,27 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) return; } + /* XIVE2 interrupt controller (POWER10) */ + object_property_set_int(OBJECT(&chip10->xive), "ic-bar", + PNV10_XIVE2_IC_BASE(chip), &error_fatal); + object_property_set_int(OBJECT(&chip10->xive), "esb-bar", + PNV10_XIVE2_ESB_BASE(chip), &error_fatal); + object_property_set_int(OBJECT(&chip10->xive), "end-bar", + PNV10_XIVE2_END_BASE(chip), &error_fatal); + object_property_set_int(OBJECT(&chip10->xive), "nvpg-bar", + PNV10_XIVE2_NVPG_BASE(chip), &error_fatal); + object_property_set_int(OBJECT(&chip10->xive), "nvc-bar", + PNV10_XIVE2_NVC_BASE(chip), &error_fatal); + object_property_set_int(OBJECT(&chip10->xive), "tm-bar", + PNV10_XIVE2_TM_BASE(chip), &error_fatal); + object_property_set_link(OBJECT(&chip10->xive), "chip", OBJECT(chip), + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&chip10->xive), errp)) { + return; + } + pnv_xscom_add_subregion(chip, PNV10_XSCOM_XIVE2_BASE, + &chip10->xive.xscom_regs); + /* Processor Service Interface (PSI) Host Bridge */ object_property_set_int(OBJECT(&chip10->psi), "bar", PNV10_PSIHB_BASE(chip), &error_fatal); @@ -1927,6 +1970,35 @@ static int pnv_match_nvt(XiveFabric *xfb, uint8_t format, return total_count; } +static int pnv10_xive_match_nvt(XiveFabric *xfb, uint8_t format, + uint8_t nvt_blk, uint32_t nvt_idx, + bool cam_ignore, uint8_t priority, + uint32_t logic_serv, + XiveTCTXMatch *match) +{ + PnvMachineState *pnv = PNV_MACHINE(xfb); + int total_count = 0; + int i; + + for (i = 0; i < pnv->num_chips; i++) { + Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]); + XivePresenter *xptr = XIVE_PRESENTER(&chip10->xive); + XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); + int count; + + count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, + priority, logic_serv, match); + + if (count < 0) { + return count; + } + + total_count += count; + } + + return total_count; +} + static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -1971,6 +2043,7 @@ static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); + XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); static const char compat[] = "qemu,powernv10\0ibm,powernv"; mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; @@ -1979,6 +2052,8 @@ static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) pmc->compat = compat; pmc->compat_size = sizeof(compat); pmc->dt_power_mgt = pnv_dt_power_mgt; + + xfc->match_nvt = pnv10_xive_match_nvt; } static bool pnv_machine_get_hb(Object *obj, Error **errp) @@ -2090,6 +2165,10 @@ static const TypeInfo types[] = { .name = MACHINE_TYPE_NAME("powernv10"), .parent = TYPE_PNV_MACHINE, .class_init = pnv_machine_power10_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_XIVE_FABRIC }, + { }, + }, }, { .name = MACHINE_TYPE_NAME("powernv9"), |