Hello, The POWER10 and POWER9 processors are very similar and this series adds the basic framework for a POWER10 chip and a machine using this chip. The PSI and LPC models are provided first because there are no changes. XIVE needs some adaptation and will come later. Thanks, C. Cédric Le Goater (5): target/ppc: Add POWER10 DD1.0 model information ppc/pnv: Introduce a POWER10 PnvChip and a powernv10 machine ppc/psi: cleanup definitions ppc/pnv: add a PSI bridge model for POWER10 ppc/pnv: add a LPC Controller model for POWER10 include/hw/ppc/pnv.h | 46 +++++++ include/hw/ppc/pnv_lpc.h | 6 +- include/hw/ppc/pnv_psi.h | 2 + include/hw/ppc/pnv_xscom.h | 22 ++++ target/ppc/cpu-models.h | 3 + target/ppc/cpu.h | 1 + hw/ppc/pnv.c | 192 ++++++++++++++++++++++++++-- hw/ppc/pnv_core.c | 10 ++ hw/ppc/pnv_lpc.c | 30 +++-- hw/ppc/pnv_psi.c | 32 ++++- hw/ppc/pnv_xscom.c | 23 +++- target/ppc/compat.c | 21 +++- target/ppc/cpu-models.c | 3 + target/ppc/translate_init.inc.c | 215 ++++++++++++++++++++++++++++++++ 14 files changed, 576 insertions(+), 30 deletions(-) -- 2.21.0
This includes in QEMU a new CPU model for the POWER10 processor with the same capabilities of a POWER9 process. The model will be extended when support is completed. Signed-off-by: Cédric Le Goater <clg@kaod.org> --- target/ppc/cpu-models.h | 3 + target/ppc/cpu.h | 1 + target/ppc/compat.c | 21 +++- target/ppc/cpu-models.c | 3 + target/ppc/translate_init.inc.c | 215 ++++++++++++++++++++++++++++++++ 5 files changed, 237 insertions(+), 6 deletions(-) diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h index 4fdb73034dd0..ce750b2d55d2 100644 --- a/target/ppc/cpu-models.h +++ b/target/ppc/cpu-models.h @@ -373,6 +373,8 @@ enum { CPU_POWERPC_POWER9_BASE = 0x004E0000, CPU_POWERPC_POWER9_DD1 = 0x004E0100, CPU_POWERPC_POWER9_DD20 = 0x004E1200, + CPU_POWERPC_POWER10_BASE = 0x00800000, + CPU_POWERPC_POWER10_DD1 = 0x00800100, CPU_POWERPC_970_v22 = 0x00390202, CPU_POWERPC_970FX_v10 = 0x00391100, CPU_POWERPC_970FX_v20 = 0x003C0200, @@ -409,6 +411,7 @@ enum { CPU_POWERPC_LOGICAL_2_06_PLUS = 0x0F100003, CPU_POWERPC_LOGICAL_2_07 = 0x0F000004, CPU_POWERPC_LOGICAL_3_00 = 0x0F000005, + CPU_POWERPC_LOGICAL_3_10 = 0x0F000006, }; /* System version register (used on MPC 8xxx) */ diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index f9528fc29d98..0c5eb67245ef 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -2368,6 +2368,7 @@ enum { PCR_COMPAT_2_06 = PPC_BIT(61), PCR_COMPAT_2_07 = PPC_BIT(60), PCR_COMPAT_3_00 = PPC_BIT(59), + PCR_COMPAT_3_10 = PPC_BIT(58), PCR_VEC_DIS = PPC_BIT(0), /* Vec. disable (bit NA since POWER8) */ PCR_VSX_DIS = PPC_BIT(1), /* VSX disable (bit NA since POWER8) */ PCR_TM_DIS = PPC_BIT(2), /* Trans. memory disable (POWER8) */ diff --git a/target/ppc/compat.c b/target/ppc/compat.c index 7de4bf312285..f48df2594459 100644 --- a/target/ppc/compat.c +++ b/target/ppc/compat.c @@ -51,36 +51,38 @@ static const CompatInfo compat_table[] = { { /* POWER6, ISA2.05 */ .name = "power6", .pvr = CPU_POWERPC_LOGICAL_2_05, - .pcr = PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | - PCR_COMPAT_2_05 | PCR_TM_DIS | PCR_VSX_DIS, + .pcr = PCR_COMPAT_3_10 | PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | + PCR_COMPAT_2_06 | PCR_COMPAT_2_05 | PCR_TM_DIS | PCR_VSX_DIS, .pcr_level = PCR_COMPAT_2_05, .max_vthreads = 2, }, { /* POWER7, ISA2.06 */ .name = "power7", .pvr = CPU_POWERPC_LOGICAL_2_06, - .pcr = PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_TM_DIS, + .pcr = PCR_COMPAT_3_10 | PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | + PCR_COMPAT_2_06 | PCR_TM_DIS, .pcr_level = PCR_COMPAT_2_06, .max_vthreads = 4, }, { .name = "power7+", .pvr = CPU_POWERPC_LOGICAL_2_06_PLUS, - .pcr = PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_TM_DIS, + .pcr = PCR_COMPAT_3_10 | PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | + PCR_COMPAT_2_06 | PCR_TM_DIS, .pcr_level = PCR_COMPAT_2_06, .max_vthreads = 4, }, { /* POWER8, ISA2.07 */ .name = "power8", .pvr = CPU_POWERPC_LOGICAL_2_07, - .pcr = PCR_COMPAT_3_00 | PCR_COMPAT_2_07, + .pcr = PCR_COMPAT_3_10 | PCR_COMPAT_3_00 | PCR_COMPAT_2_07, .pcr_level = PCR_COMPAT_2_07, .max_vthreads = 8, }, { /* POWER9, ISA3.00 */ .name = "power9", .pvr = CPU_POWERPC_LOGICAL_3_00, - .pcr = PCR_COMPAT_3_00, + .pcr = PCR_COMPAT_3_10 | PCR_COMPAT_3_00, .pcr_level = PCR_COMPAT_3_00, /* * POWER9 hardware only supports 4 threads / core, but this @@ -91,6 +93,13 @@ static const CompatInfo compat_table[] = { */ .max_vthreads = 8, }, + { /* POWER10, ISA3.10 */ + .name = "power10", + .pvr = CPU_POWERPC_LOGICAL_3_10, + .pcr = PCR_COMPAT_3_10, + .pcr_level = PCR_COMPAT_3_10, + .max_vthreads = 8, + }, }; static const CompatInfo *compat_by_pvr(uint32_t pvr) diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c index 086548e9b965..4ad16863c0ce 100644 --- a/target/ppc/cpu-models.c +++ b/target/ppc/cpu-models.c @@ -774,6 +774,8 @@ "POWER9 v1.0") POWERPC_DEF("power9_v2.0", CPU_POWERPC_POWER9_DD20, POWER9, "POWER9 v2.0") + POWERPC_DEF("power10_v1.0", CPU_POWERPC_POWER10_DD1, POWER10, + "POWER10 v1.0") #endif /* defined (TARGET_PPC64) */ /***************************************************************************/ @@ -950,6 +952,7 @@ PowerPCCPUAlias ppc_cpu_aliases[] = { { "power8", "power8_v2.0" }, { "power8nvl", "power8nvl_v1.0" }, { "power9", "power9_v2.0" }, + { "power10", "power10_v1.0" }, #endif /* Generic PowerPCs */ diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c index 64a838095c7a..7364d36b07a8 100644 --- a/target/ppc/translate_init.inc.c +++ b/target/ppc/translate_init.inc.c @@ -3354,6 +3354,11 @@ static void init_excp_POWER9(CPUPPCState *env) #endif } +static void init_excp_POWER10(CPUPPCState *env) +{ + init_excp_POWER9(env); +} + #endif /*****************************************************************************/ @@ -8996,6 +9001,216 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data) pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE; } +#ifdef CONFIG_SOFTMMU +/* + * Radix pg sizes and AP encodings for dt node ibm,processor-radix-AP-encodings + * Encoded as array of int_32s in the form: + * 0bxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + * x -> AP encoding + * y -> radix mode supported page size (encoded as a shift) + */ +static struct ppc_radix_page_info POWER10_radix_page_info = { + .count = 4, + .entries = { + 0x0000000c, /* 4K - enc: 0x0 */ + 0xa0000010, /* 64K - enc: 0x5 */ + 0x20000015, /* 2M - enc: 0x1 */ + 0x4000001e /* 1G - enc: 0x2 */ + } +}; +#endif /* CONFIG_SOFTMMU */ + +static void init_proc_POWER10(CPUPPCState *env) +{ + /* Common Registers */ + init_proc_book3s_common(env); + gen_spr_book3s_207_dbg(env); + + /* POWER8 Specific Registers */ + gen_spr_book3s_ids(env); + gen_spr_amr(env); + gen_spr_iamr(env); + gen_spr_book3s_purr(env); + gen_spr_power5p_common(env); + gen_spr_power5p_lpar(env); + gen_spr_power5p_ear(env); + gen_spr_power6_common(env); + gen_spr_power6_dbg(env); + gen_spr_power8_tce_address_control(env); + gen_spr_power8_ids(env); + gen_spr_power8_ebb(env); + gen_spr_power8_fscr(env); + gen_spr_power8_pmu_sup(env); + gen_spr_power8_pmu_user(env); + gen_spr_power8_tm(env); + gen_spr_power8_pspb(env); + gen_spr_vtb(env); + gen_spr_power8_ic(env); + gen_spr_power8_book4(env); + gen_spr_power8_rpr(env); + gen_spr_power9_mmu(env); + + /* POWER9 Specific registers */ + spr_register_kvm(env, SPR_TIDR, "TIDR", NULL, NULL, + spr_read_generic, spr_write_generic, + KVM_REG_PPC_TIDR, 0); + + /* FIXME: Filter fields properly based on privilege level */ + spr_register_kvm_hv(env, SPR_PSSCR, "PSSCR", NULL, NULL, NULL, NULL, + spr_read_generic, spr_write_generic, + KVM_REG_PPC_PSSCR, 0); + + /* env variables */ + env->dcache_line_size = 128; + env->icache_line_size = 128; + + /* Allocate hardware IRQ controller */ + init_excp_POWER10(env); + ppcPOWER9_irq_init(env_archcpu(env)); +} + +static bool ppc_pvr_match_power10(PowerPCCPUClass *pcc, uint32_t pvr) +{ + if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER10_BASE) { + return true; + } + return false; +} + +static bool cpu_has_work_POWER10(CPUState *cs) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + + if (cs->halted) { + uint64_t psscr = env->spr[SPR_PSSCR]; + + if (!(cs->interrupt_request & CPU_INTERRUPT_HARD)) { + return false; + } + + /* If EC is clear, just return true on any pending interrupt */ + if (!(psscr & PSSCR_EC)) { + return true; + } + /* External Exception */ + if ((env->pending_interrupts & (1u << PPC_INTERRUPT_EXT)) && + (env->spr[SPR_LPCR] & LPCR_EEE)) { + bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); + if (heic == 0 || !msr_hv || msr_pr) { + return true; + } + } + /* Decrementer Exception */ + if ((env->pending_interrupts & (1u << PPC_INTERRUPT_DECR)) && + (env->spr[SPR_LPCR] & LPCR_DEE)) { + return true; + } + /* Machine Check or Hypervisor Maintenance Exception */ + if ((env->pending_interrupts & (1u << PPC_INTERRUPT_MCK | + 1u << PPC_INTERRUPT_HMI)) && (env->spr[SPR_LPCR] & LPCR_OEE)) { + return true; + } + /* Privileged Doorbell Exception */ + if ((env->pending_interrupts & (1u << PPC_INTERRUPT_DOORBELL)) && + (env->spr[SPR_LPCR] & LPCR_PDEE)) { + return true; + } + /* Hypervisor Doorbell Exception */ + if ((env->pending_interrupts & (1u << PPC_INTERRUPT_HDOORBELL)) && + (env->spr[SPR_LPCR] & LPCR_HDEE)) { + return true; + } + /* Hypervisor virtualization exception */ + if ((env->pending_interrupts & (1u << PPC_INTERRUPT_HVIRT)) && + (env->spr[SPR_LPCR] & LPCR_HVEE)) { + return true; + } + if (env->pending_interrupts & (1u << PPC_INTERRUPT_RESET)) { + return true; + } + return false; + } else { + return msr_ee && (cs->interrupt_request & CPU_INTERRUPT_HARD); + } +} + +POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); + CPUClass *cc = CPU_CLASS(oc); + + dc->fw_name = "PowerPC,POWER10"; + dc->desc = "POWER10"; + dc->props = powerpc_servercpu_properties; + pcc->pvr_match = ppc_pvr_match_power10; + pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06 | PCR_COMPAT_2_07 | + PCR_COMPAT_3_00; + pcc->pcr_supported = PCR_COMPAT_3_10 | PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | + PCR_COMPAT_2_06 | PCR_COMPAT_2_05; + pcc->init_proc = init_proc_POWER10; + pcc->check_pow = check_pow_nocheck; + cc->has_work = cpu_has_work_POWER10; + pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB | + PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES | + PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | + PPC_FLOAT_FRSQRTES | + PPC_FLOAT_STFIWX | + PPC_FLOAT_EXT | + PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ | + PPC_MEM_SYNC | PPC_MEM_EIEIO | + PPC_MEM_TLBSYNC | + PPC_64B | PPC_64H | PPC_64BX | PPC_ALTIVEC | + PPC_SEGMENT_64B | PPC_SLBI | + PPC_POPCNTB | PPC_POPCNTWD | + PPC_CILDST; + pcc->insns_flags2 = PPC2_VSX | PPC2_VSX207 | PPC2_DFP | PPC2_DBRX | + PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 | + PPC2_ATOMIC_ISA206 | PPC2_FP_CVT_ISA206 | + PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 | + PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 | + PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 | + PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL; + pcc->msr_mask = (1ull << MSR_SF) | + (1ull << MSR_SHV) | + (1ull << MSR_TM) | + (1ull << MSR_VR) | + (1ull << MSR_VSX) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); + pcc->mmu_model = POWERPC_MMU_3_00; +#if defined(CONFIG_SOFTMMU) + pcc->handle_mmu_fault = ppc64_v3_handle_mmu_fault; + /* segment page size remain the same */ + pcc->hash64_opts = &ppc_hash64_opts_POWER7; + pcc->radix_page_info = &POWER10_radix_page_info; + pcc->lrg_decr_bits = 56; +#endif + pcc->excp_model = POWERPC_EXCP_POWER9; + pcc->bus_model = PPC_FLAGS_INPUT_POWER9; + pcc->bfd_mach = bfd_mach_ppc64; + pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE | + POWERPC_FLAG_BE | POWERPC_FLAG_PMM | + POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR | + POWERPC_FLAG_VSX | POWERPC_FLAG_TM; + pcc->l1_dcache_size = 0x8000; + pcc->l1_icache_size = 0x8000; + pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr; + pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE; +} + #if !defined(CONFIG_USER_ONLY) void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp) { -- 2.21.0
This is an empty shell with the XSCOM bus and cores. The chip controllers will come later. Signed-off-by: Cédric Le Goater <clg@kaod.org> --- include/hw/ppc/pnv.h | 33 ++++++++ include/hw/ppc/pnv_xscom.h | 19 +++++ hw/ppc/pnv.c | 158 +++++++++++++++++++++++++++++++++++-- hw/ppc/pnv_core.c | 10 +++ hw/ppc/pnv_xscom.c | 23 ++++-- 5 files changed, 232 insertions(+), 11 deletions(-) diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index 3a7bc3c57e0d..bfa61edfbabd 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -43,6 +43,7 @@ typedef enum PnvChipType { PNV_CHIP_POWER8, /* AKA Venice */ PNV_CHIP_POWER8NVL, /* AKA Naples */ PNV_CHIP_POWER9, /* AKA Nimbus */ + PNV_CHIP_POWER10, /* AKA TBD */ } PnvChipType; typedef struct PnvChip { @@ -105,6 +106,14 @@ typedef struct Pnv9Chip { #define PNV9_PIR2FUSEDCORE(pir) (((pir) >> 3) & 0xf) #define PNV9_PIR2CHIP(pir) (((pir) >> 8) & 0x7f) +#define TYPE_PNV10_CHIP "pnv10-chip" +#define PNV10_CHIP(obj) OBJECT_CHECK(Pnv10Chip, (obj), TYPE_PNV10_CHIP) + +typedef struct Pnv10Chip { + /*< private >*/ + PnvChip parent_obj; +} Pnv10Chip; + typedef struct PnvChipClass { /*< private >*/ SysBusDeviceClass parent_class; @@ -144,6 +153,10 @@ typedef struct PnvChipClass { #define PNV_CHIP_POWER9(obj) \ OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER9) +#define TYPE_PNV_CHIP_POWER10 PNV_CHIP_TYPE_NAME("power10_v1.0") +#define PNV_CHIP_POWER10(obj) \ + OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER10) + /* * This generates a HW chip id depending on an index, as found on a * two socket system with dual chip modules : @@ -203,6 +216,16 @@ PnvChip *pnv_get_chip(uint32_t chip_id); #define PNV_FDT_ADDR 0x01000000 #define PNV_TIMEBASE_FREQ 512000000ULL +static inline bool pnv_chip_is_power10(const PnvChip *chip) +{ + return PNV_CHIP_GET_CLASS(chip)->chip_type == PNV_CHIP_POWER10; +} + +static inline bool pnv_is_power10(PnvMachineState *pnv) +{ + return pnv_chip_is_power10(pnv->chips[0]); +} + /* * BMC helpers */ @@ -293,4 +316,14 @@ IPMIBmc *pnv_bmc_create(void); #define PNV9_HOMER_SIZE 0x0000000000300000ull #define PNV9_HOMER_BASE(chip) \ (0x203ffd800000ull + ((uint64_t)PNV_CHIP_INDEX(chip)) * PNV9_HOMER_SIZE) + +/* + * POWER10 MMIO base addresses - 16TB stride per chip + */ +#define PNV10_CHIP_BASE(chip, base) \ + ((base) + ((uint64_t) (chip)->chip_id << 44)) + +#define PNV10_XSCOM_SIZE 0x0000000400000000ull +#define PNV10_XSCOM_BASE(chip) PNV10_CHIP_BASE(chip, 0x00603fc00000000ull) + #endif /* PPC_PNV_H */ diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h index 67641ed27800..790eb3d8f3b0 100644 --- a/include/hw/ppc/pnv_xscom.h +++ b/include/hw/ppc/pnv_xscom.h @@ -70,6 +70,9 @@ typedef struct PnvXScomInterfaceClass { #define PNV_XSCOM_OCC_BASE 0x0066000 #define PNV_XSCOM_OCC_SIZE 0x6000 +/* + * Layout of the XSCOM PCB addresses (POWER 9) + */ #define PNV9_XSCOM_EC_BASE(core) \ ((uint64_t)(((core) & 0x1F) + 0x20) << 24) #define PNV9_XSCOM_EC_SIZE 0x100000 @@ -87,6 +90,22 @@ typedef struct PnvXScomInterfaceClass { #define PNV9_XSCOM_XIVE_BASE 0x5013000 #define PNV9_XSCOM_XIVE_SIZE 0x300 +/* + * Layout of the XSCOM PCB addresses (POWER 10) + */ +#define PNV10_XSCOM_EQ_CHIPLET(core) (0x20 + ((core) >> 2)) +#define PNV10_XSCOM_EQ(chiplet) ((chiplet) << 24) +#define PNV10_XSCOM_EC(proc) \ + ((0x2 << 16) | ((1 << (3 - (proc))) << 12)) + +#define PNV10_XSCOM_EQ_BASE(core) \ + ((uint64_t) PNV10_XSCOM_EQ(PNV10_XSCOM_EQ_CHIPLET(core))) +#define PNV10_XSCOM_EQ_SIZE 0x100000 + +#define PNV10_XSCOM_EC_BASE(core) \ + ((uint64_t) PNV10_XSCOM_EQ_BASE(core) | PNV10_XSCOM_EC(core & 0x3)) +#define PNV10_XSCOM_EC_SIZE 0x100000 + extern void pnv_xscom_realize(PnvChip *chip, uint64_t size, Error **errp); extern int pnv_dt_xscom(PnvChip *chip, void *fdt, int offset); diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index fa656858b24a..d99cd72840be 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -317,6 +317,23 @@ static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt) pnv_dt_lpc(chip, fdt, 0); } +static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt) +{ + int i; + + pnv_dt_xscom(chip, fdt, 0); + + for (i = 0; i < chip->nr_cores; i++) { + PnvCore *pnv_core = chip->cores[i]; + + pnv_dt_core(chip, pnv_core, fdt); + } + + if (chip->ram_size) { + pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); + } +} + static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off) { uint32_t io_base = d->ioport_id; @@ -467,6 +484,7 @@ static void *pnv_dt_create(MachineState *machine) { const char plat_compat8[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv"; const char plat_compat9[] = "qemu,powernv9\0ibm,powernv"; + const char plat_compat10[] = "qemu,powernv10\0ibm,powernv"; PnvMachineState *pnv = PNV_MACHINE(machine); void *fdt; char *buf; @@ -484,7 +502,10 @@ static void *pnv_dt_create(MachineState *machine) _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2))); _FDT((fdt_setprop_string(fdt, 0, "model", "IBM PowerNV (emulated by qemu)"))); - if (pnv_is_power9(pnv)) { + if (pnv_is_power10(pnv)) { + _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat10, + sizeof(plat_compat10)))); + } else if (pnv_is_power9(pnv)) { _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat9, sizeof(plat_compat9)))); } else { @@ -528,8 +549,8 @@ static void *pnv_dt_create(MachineState *machine) pnv_dt_bmc_sensors(pnv->bmc, fdt); } - /* Create an extra node for power management on Power9 */ - if (pnv_is_power9(pnv)) { + /* Create an extra node for power management on Power9 and Power10 */ + if (pnv_is_power9(pnv) || pnv_is_power10(pnv)) { pnv_dt_power_mgt(fdt); } @@ -578,6 +599,12 @@ static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp) return pnv_lpc_isa_create(&chip9->lpc, false, errp); } +static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp) +{ + error_setg(errp, "No ISA bus!"); + return NULL; +} + static ISABus *pnv_isa_create(PnvChip *chip, Error **errp) { return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp); @@ -618,6 +645,13 @@ static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq) object_property_set_bool(obj, true, "realized", &error_fatal); } +static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon) +{ + /* + * No interrupt controller yet + */; +} + static void pnv_init(MachineState *machine) { PnvMachineState *pnv = PNV_MACHINE(machine); @@ -822,6 +856,11 @@ static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id) return (chip->chip_id << 8) | (core_id << 2); } +static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id) +{ + return (chip->chip_id << 8) | (core_id << 2); +} + static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu, Error **errp) { @@ -859,6 +898,27 @@ static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) pnv_cpu->intc = NULL; } +static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu, + Error **errp) +{ + PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); + + /* Will be defined when the interrupt controller is */ + pnv_cpu->intc = NULL; +} + +static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu) +{ + ; +} + +static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) +{ + PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); + + pnv_cpu->intc = NULL; +} + /* * Allowed core identifiers on a POWER8 Processor Chip : * @@ -886,6 +946,9 @@ static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) */ #define POWER9_CORE_MASK (0xffffffffffffffull) + +#define POWER10_CORE_MASK (0xffffffffffffffull) + static void pnv_chip_power8_instance_init(Object *obj) { Pnv8Chip *chip8 = PNV8_CHIP(obj); @@ -1246,6 +1309,56 @@ static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) &k->parent_realize); } +static void pnv_chip_power10_instance_init(Object *obj) +{ + /* + * No controllers yet + */ + ; +} + +static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) +{ + PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); + PnvChip *chip = PNV_CHIP(dev); + Error *local_err = NULL; + + /* XSCOM bridge is first */ + pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip)); + + pcc->parent_realize(dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } +} + +static void pnv_chip_power10_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PnvChipClass *k = PNV_CHIP_CLASS(klass); + + k->chip_type = PNV_CHIP_POWER10; + k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */ + k->cores_mask = POWER10_CORE_MASK; + k->core_pir = pnv_chip_core_pir_p10; + k->intc_create = pnv_chip_power10_intc_create; + k->intc_reset = pnv_chip_power10_intc_reset; + k->intc_destroy = pnv_chip_power10_intc_destroy; + k->isa_create = pnv_chip_power10_isa_create; + k->dt_populate = pnv_chip_power10_dt_populate; + k->pic_print_info = pnv_chip_power10_pic_print_info; + dc->desc = "PowerNV Chip POWER10"; + + device_class_set_parent_realize(dc, pnv_chip_power10_realize, + &k->parent_realize); +} + static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) { PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); @@ -1327,10 +1440,12 @@ static void pnv_chip_core_realize(PnvChip *chip, Error **errp) &error_fatal); /* Each core has an XSCOM MMIO region */ - if (!pnv_chip_is_power9(chip)) { - xscom_core_base = PNV_XSCOM_EX_BASE(core_hwid); - } else { + if (pnv_chip_is_power10(chip)) { + xscom_core_base = PNV10_XSCOM_EC_BASE(core_hwid); + } else if (pnv_chip_is_power9(chip)) { xscom_core_base = PNV9_XSCOM_EC_BASE(core_hwid); + } else { + xscom_core_base = PNV_XSCOM_EX_BASE(core_hwid); } pnv_xscom_add_subregion(chip, xscom_core_base, @@ -1558,6 +1673,14 @@ static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) mc->alias = "powernv"; } +static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; + mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v1.0"); +} + static void pnv_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -1595,7 +1718,19 @@ static void pnv_machine_class_init(ObjectClass *oc, void *data) .parent = TYPE_PNV9_CHIP, \ } +#define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \ + { \ + .name = type, \ + .class_init = class_initfn, \ + .parent = TYPE_PNV10_CHIP, \ + } + static const TypeInfo types[] = { + { + .name = MACHINE_TYPE_NAME("powernv10"), + .parent = TYPE_PNV_MACHINE, + .class_init = pnv_machine_power10_class_init, + }, { .name = MACHINE_TYPE_NAME("powernv9"), .parent = TYPE_PNV_MACHINE, @@ -1635,6 +1770,17 @@ static const TypeInfo types[] = { .abstract = true, }, + /* + * P10 chip and variants + */ + { + .name = TYPE_PNV10_CHIP, + .parent = TYPE_PNV_CHIP, + .instance_init = pnv_chip_power10_instance_init, + .instance_size = sizeof(Pnv10Chip), + }, + DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init), + /* * P9 chip and variants */ diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 5ab75bde6cc5..2651044278ed 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -247,6 +247,7 @@ static void pnv_core_realize(DeviceState *dev, Error **errp) } snprintf(name, sizeof(name), "xscom-core.%d", cc->core_id); + /* TODO: check PNV_XSCOM_EX_SIZE for p10 */ pnv_xscom_region_init(&pc->xscom_regs, OBJECT(dev), pcc->xscom_ops, pc, name, PNV_XSCOM_EX_SIZE); @@ -308,6 +309,14 @@ static void pnv_core_power9_class_init(ObjectClass *oc, void *data) pcc->xscom_ops = &pnv_core_power9_xscom_ops; } +static void pnv_core_power10_class_init(ObjectClass *oc, void *data) +{ + PnvCoreClass *pcc = PNV_CORE_CLASS(oc); + + /* TODO: Use the P9 XSCOMs for now on P10 */ + pcc->xscom_ops = &pnv_core_power9_xscom_ops; +} + static void pnv_core_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); @@ -337,6 +346,7 @@ static const TypeInfo pnv_core_infos[] = { DEFINE_PNV_CORE_TYPE(power8, "power8_v2.0"), DEFINE_PNV_CORE_TYPE(power8, "power8nvl_v1.0"), DEFINE_PNV_CORE_TYPE(power9, "power9_v2.0"), + DEFINE_PNV_CORE_TYPE(power10, "power10_v1.0"), }; DEFINE_TYPES(pnv_core_infos) diff --git a/hw/ppc/pnv_xscom.c b/hw/ppc/pnv_xscom.c index f01d788a6545..b3d3b6e3507d 100644 --- a/hw/ppc/pnv_xscom.c +++ b/hw/ppc/pnv_xscom.c @@ -69,10 +69,16 @@ static uint32_t pnv_xscom_pcba(PnvChip *chip, uint64_t addr) { addr &= (PNV_XSCOM_SIZE - 1); - if (pnv_chip_is_power9(chip)) { - return addr >> 3; - } else { + switch (PNV_CHIP_GET_CLASS(chip)->chip_type) { + case PNV_CHIP_POWER8E: + case PNV_CHIP_POWER8: + case PNV_CHIP_POWER8NVL: return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf); + case PNV_CHIP_POWER9: + case PNV_CHIP_POWER10: + return addr >> 3; + default: + g_assert_not_reached(); } } @@ -307,6 +313,7 @@ static int xscom_dt_child(Object *child, void *opaque) static const char compat_p8[] = "ibm,power8-xscom\0ibm,xscom"; static const char compat_p9[] = "ibm,power9-xscom\0ibm,xscom"; +static const char compat_p10[] = "ibm,power10-xscom\0ibm,xscom"; int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset) { @@ -315,7 +322,10 @@ int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset) ForeachPopulateArgs args; char *name; - if (pnv_chip_is_power9(chip)) { + if (pnv_chip_is_power10(chip)) { + reg[0] = cpu_to_be64(PNV10_XSCOM_BASE(chip)); + reg[1] = cpu_to_be64(PNV10_XSCOM_SIZE); + } else if (pnv_chip_is_power9(chip)) { reg[0] = cpu_to_be64(PNV9_XSCOM_BASE(chip)); reg[1] = cpu_to_be64(PNV9_XSCOM_SIZE); } else { @@ -332,7 +342,10 @@ int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset) _FDT((fdt_setprop_cell(fdt, xscom_offset, "#size-cells", 1))); _FDT((fdt_setprop(fdt, xscom_offset, "reg", reg, sizeof(reg)))); - if (pnv_chip_is_power9(chip)) { + if (pnv_chip_is_power10(chip)) { + _FDT((fdt_setprop(fdt, xscom_offset, "compatible", compat_p10, + sizeof(compat_p10)))); + } else if (pnv_chip_is_power9(chip)) { _FDT((fdt_setprop(fdt, xscom_offset, "compatible", compat_p9, sizeof(compat_p9)))); } else { -- 2.21.0
Signed-off-by: Cédric Le Goater <clg@kaod.org> --- hw/ppc/pnv_psi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c index a360515a86f8..f15aaa5c9cc0 100644 --- a/hw/ppc/pnv_psi.c +++ b/hw/ppc/pnv_psi.c @@ -609,9 +609,12 @@ static const TypeInfo pnv_psi_power8_info = { #define PSIHB9_IRQ_METHOD PPC_BIT(0) #define PSIHB9_IRQ_RESET PPC_BIT(1) #define PSIHB9_ESB_CI_BASE 0x60 -#define PSIHB9_ESB_CI_VALID 1 +#define PSIHB9_ESB_CI_64K PPC_BIT(1) +#define PSIHB9_ESB_CI_ADDR_MASK PPC_BITMASK(8, 47) +#define PSIHB9_ESB_CI_VALID PPC_BIT(63) #define PSIHB9_ESB_NOTIF_ADDR 0x68 -#define PSIHB9_ESB_NOTIF_VALID 1 +#define PSIHB9_ESB_NOTIF_ADDR_MASK PPC_BITMASK(8, 60) +#define PSIHB9_ESB_NOTIF_VALID PPC_BIT(63) #define PSIHB9_IVT_OFFSET 0x70 #define PSIHB9_IVT_OFF_SHIFT 32 -- 2.21.0
The POWER10 PSIHB controller is very similar to the one on POWER9. We should probably introduce a common PnvPsiXive object. The ESB page size should be changed to 64k when P10 support is ready. Signed-off-by: Cédric Le Goater <clg@kaod.org> --- include/hw/ppc/pnv.h | 9 +++++++++ include/hw/ppc/pnv_psi.h | 2 ++ include/hw/ppc/pnv_xscom.h | 3 +++ hw/ppc/pnv.c | 27 ++++++++++++++++++++------- hw/ppc/pnv_psi.c | 25 ++++++++++++++++++++++++- 5 files changed, 58 insertions(+), 8 deletions(-) diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index bfa61edfbabd..47b7370b27d8 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -112,6 +112,9 @@ typedef struct Pnv9Chip { typedef struct Pnv10Chip { /*< private >*/ PnvChip parent_obj; + + /*< public >*/ + Pnv9Psi psi; } Pnv10Chip; typedef struct PnvChipClass { @@ -326,4 +329,10 @@ IPMIBmc *pnv_bmc_create(void); #define PNV10_XSCOM_SIZE 0x0000000400000000ull #define PNV10_XSCOM_BASE(chip) PNV10_CHIP_BASE(chip, 0x00603fc00000000ull) +#define PNV10_PSIHB_ESB_SIZE 0x0000000000100000ull +#define PNV10_PSIHB_ESB_BASE(chip) PNV10_CHIP_BASE(chip, 0x0006030202000000ull) + +#define PNV10_PSIHB_SIZE 0x0000000000100000ull +#define PNV10_PSIHB_BASE(chip) PNV10_CHIP_BASE(chip, 0x0006030203000000ull) + #endif /* PPC_PNV_H */ diff --git a/include/hw/ppc/pnv_psi.h b/include/hw/ppc/pnv_psi.h index e82df9709fb8..a044aab304ae 100644 --- a/include/hw/ppc/pnv_psi.h +++ b/include/hw/ppc/pnv_psi.h @@ -69,6 +69,8 @@ typedef struct Pnv9Psi { XiveSource source; } Pnv9Psi; +#define TYPE_PNV10_PSI TYPE_PNV_PSI "-POWER10" + #define PNV_PSI_CLASS(klass) \ OBJECT_CLASS_CHECK(PnvPsiClass, (klass), TYPE_PNV_PSI) #define PNV_PSI_GET_CLASS(obj) \ diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h index 790eb3d8f3b0..a40d2a2a2a98 100644 --- a/include/hw/ppc/pnv_xscom.h +++ b/include/hw/ppc/pnv_xscom.h @@ -106,6 +106,9 @@ typedef struct PnvXScomInterfaceClass { ((uint64_t) PNV10_XSCOM_EQ_BASE(core) | PNV10_XSCOM_EC(core & 0x3)) #define PNV10_XSCOM_EC_SIZE 0x100000 +#define PNV10_XSCOM_PSIHB_BASE 0x3011D00 +#define PNV10_XSCOM_PSIHB_SIZE 0x100 + extern void pnv_xscom_realize(PnvChip *chip, uint64_t size, Error **errp); extern int pnv_dt_xscom(PnvChip *chip, void *fdt, int offset); diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index d99cd72840be..09263ab747d8 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -647,9 +647,9 @@ static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq) static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon) { - /* - * No interrupt controller yet - */; + Pnv10Chip *chip10 = PNV10_CHIP(chip); + + pnv_psi_pic_print_info(&chip10->psi, mon); } static void pnv_init(MachineState *machine) @@ -1311,16 +1311,17 @@ static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) static void pnv_chip_power10_instance_init(Object *obj) { - /* - * No controllers yet - */ - ; + Pnv10Chip *chip10 = PNV10_CHIP(obj); + + object_initialize_child(obj, "psi", &chip10->psi, sizeof(chip10->psi), + TYPE_PNV10_PSI, &error_abort, NULL); } static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) { PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); PnvChip *chip = PNV_CHIP(dev); + Pnv10Chip *chip10 = PNV10_CHIP(dev); Error *local_err = NULL; /* XSCOM bridge is first */ @@ -1336,6 +1337,18 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) error_propagate(errp, local_err); return; } + + /* Processor Service Interface (PSI) Host Bridge */ + object_property_set_int(OBJECT(&chip10->psi), PNV10_PSIHB_BASE(chip), + "bar", &error_fatal); + object_property_set_bool(OBJECT(&chip10->psi), true, "realized", + &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE, + &PNV_PSI(&chip10->psi)->xscom_regs); } static void pnv_chip_power10_class_init(ObjectClass *klass, void *data) diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c index f15aaa5c9cc0..32e4cbdb09bb 100644 --- a/hw/ppc/pnv_psi.c +++ b/hw/ppc/pnv_psi.c @@ -539,6 +539,7 @@ static void pnv_psi_power8_realize(DeviceState *dev, Error **errp) static const char compat_p8[] = "ibm,power8-psihb-x\0ibm,psihb-x"; static const char compat_p9[] = "ibm,power9-psihb-x\0ibm,psihb-x"; +static const char compat_p10[] = "ibm,power10-psihb-x\0ibm,psihb-x"; static int pnv_psi_dt_xscom(PnvXScomInterface *dev, void *fdt, int xscom_offset) { @@ -558,7 +559,10 @@ static int pnv_psi_dt_xscom(PnvXScomInterface *dev, void *fdt, int xscom_offset) _FDT(fdt_setprop(fdt, offset, "reg", reg, sizeof(reg))); _FDT(fdt_setprop_cell(fdt, offset, "#address-cells", 2)); _FDT(fdt_setprop_cell(fdt, offset, "#size-cells", 1)); - if (ppc->chip_type == PNV_CHIP_POWER9) { + if (ppc->chip_type == PNV_CHIP_POWER10) { + _FDT(fdt_setprop(fdt, offset, "compatible", compat_p10, + sizeof(compat_p10))); + } else if (ppc->chip_type == PNV_CHIP_POWER9) { _FDT(fdt_setprop(fdt, offset, "compatible", compat_p9, sizeof(compat_p9))); } else { @@ -910,6 +914,24 @@ static const TypeInfo pnv_psi_power9_info = { }, }; +static void pnv_psi_power10_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PnvPsiClass *ppc = PNV_PSI_CLASS(klass); + + dc->desc = "PowerNV PSI Controller POWER10"; + + ppc->chip_type = PNV_CHIP_POWER10; + ppc->xscom_pcba = PNV10_XSCOM_PSIHB_BASE; + ppc->xscom_size = PNV10_XSCOM_PSIHB_SIZE; +} + +static const TypeInfo pnv_psi_power10_info = { + .name = TYPE_PNV10_PSI, + .parent = TYPE_PNV9_PSI, + .class_init = pnv_psi_power10_class_init, +}; + static void pnv_psi_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -939,6 +961,7 @@ static void pnv_psi_register_types(void) type_register_static(&pnv_psi_info); type_register_static(&pnv_psi_power8_info); type_register_static(&pnv_psi_power9_info); + type_register_static(&pnv_psi_power10_info); } type_init(pnv_psi_register_types); -- 2.21.0
Same a POWER9, only the MMIO window changes. Signed-off-by: Cédric Le Goater <clg@kaod.org> --- include/hw/ppc/pnv.h | 4 ++++ include/hw/ppc/pnv_lpc.h | 6 +++++- hw/ppc/pnv.c | 25 ++++++++++++++++++++++--- hw/ppc/pnv_lpc.c | 30 ++++++++++++++++++++++-------- 4 files changed, 53 insertions(+), 12 deletions(-) diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index 47b7370b27d8..56d1161515dd 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -115,6 +115,7 @@ typedef struct Pnv10Chip { /*< public >*/ Pnv9Psi psi; + PnvLpcController lpc; } Pnv10Chip; typedef struct PnvChipClass { @@ -329,6 +330,9 @@ IPMIBmc *pnv_bmc_create(void); #define PNV10_XSCOM_SIZE 0x0000000400000000ull #define PNV10_XSCOM_BASE(chip) PNV10_CHIP_BASE(chip, 0x00603fc00000000ull) +#define PNV10_LPCM_SIZE 0x0000000100000000ull +#define PNV10_LPCM_BASE(chip) PNV10_CHIP_BASE(chip, 0x0006030000000000ull) + #define PNV10_PSIHB_ESB_SIZE 0x0000000000100000ull #define PNV10_PSIHB_ESB_BASE(chip) PNV10_CHIP_BASE(chip, 0x0006030202000000ull) diff --git a/include/hw/ppc/pnv_lpc.h b/include/hw/ppc/pnv_lpc.h index f659410716e1..c1ec85d5e2c5 100644 --- a/include/hw/ppc/pnv_lpc.h +++ b/include/hw/ppc/pnv_lpc.h @@ -31,6 +31,9 @@ #define TYPE_PNV9_LPC TYPE_PNV_LPC "-POWER9" #define PNV9_LPC(obj) OBJECT_CHECK(PnvLpcController, (obj), TYPE_PNV9_LPC) +#define TYPE_PNV10_LPC TYPE_PNV_LPC "-POWER10" +#define PNV10_LPC(obj) OBJECT_CHECK(PnvLpcController, (obj), TYPE_PNV10_LPC) + typedef struct PnvLpcController { DeviceState parent; @@ -97,6 +100,7 @@ typedef struct PnvLpcClass { struct PnvChip; ISABus *pnv_lpc_isa_create(PnvLpcController *lpc, bool use_cpld, Error **errp); -int pnv_dt_lpc(struct PnvChip *chip, void *fdt, int root_offset); +int pnv_dt_lpc(struct PnvChip *chip, void *fdt, int root_offset, + uint64_t lpcm_addr, uint64_t lpcm_size); #endif /* PPC_PNV_LPC_H */ diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 09263ab747d8..67d0ad55b870 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -314,7 +314,7 @@ static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt) pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); } - pnv_dt_lpc(chip, fdt, 0); + pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE); } static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt) @@ -332,6 +332,8 @@ static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt) if (chip->ram_size) { pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); } + + pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE); } static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off) @@ -601,8 +603,8 @@ static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp) static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp) { - error_setg(errp, "No ISA bus!"); - return NULL; + Pnv10Chip *chip10 = PNV10_CHIP(chip); + return pnv_lpc_isa_create(&chip10->lpc, false, errp); } static ISABus *pnv_isa_create(PnvChip *chip, Error **errp) @@ -1315,6 +1317,8 @@ static void pnv_chip_power10_instance_init(Object *obj) object_initialize_child(obj, "psi", &chip10->psi, sizeof(chip10->psi), TYPE_PNV10_PSI, &error_abort, NULL); + object_initialize_child(obj, "lpc", &chip10->lpc, sizeof(chip10->lpc), + TYPE_PNV10_LPC, &error_abort, NULL); } static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) @@ -1349,6 +1353,21 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) } pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE, &PNV_PSI(&chip10->psi)->xscom_regs); + + /* LPC */ + object_property_set_link(OBJECT(&chip10->lpc), OBJECT(&chip10->psi), "psi", + &error_abort); + object_property_set_bool(OBJECT(&chip10->lpc), true, "realized", + &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip), + &chip10->lpc.xscom_regs); + + chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", + (uint64_t) PNV10_LPCM_BASE(chip)); } static void pnv_chip_power10_class_init(ObjectClass *klass, void *data) diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c index dd5374c83899..18256d9ba399 100644 --- a/hw/ppc/pnv_lpc.c +++ b/hw/ppc/pnv_lpc.c @@ -122,26 +122,26 @@ static int pnv_lpc_dt_xscom(PnvXScomInterface *dev, void *fdt, int xscom_offset) } /* POWER9 only */ -int pnv_dt_lpc(PnvChip *chip, void *fdt, int root_offset) +int pnv_dt_lpc(PnvChip *chip, void *fdt, int root_offset, uint64_t lpcm_addr, + uint64_t lpcm_size) { const char compat[] = "ibm,power9-lpcm-opb\0simple-bus"; const char lpc_compat[] = "ibm,power9-lpc\0ibm,lpc"; char *name; int offset, lpcm_offset; - uint64_t lpcm_addr = PNV9_LPCM_BASE(chip); uint32_t opb_ranges[8] = { 0, cpu_to_be32(lpcm_addr >> 32), cpu_to_be32((uint32_t)lpcm_addr), - cpu_to_be32(PNV9_LPCM_SIZE / 2), - cpu_to_be32(PNV9_LPCM_SIZE / 2), + cpu_to_be32(lpcm_size / 2), + cpu_to_be32(lpcm_size / 2), cpu_to_be32(lpcm_addr >> 32), - cpu_to_be32(PNV9_LPCM_SIZE / 2), - cpu_to_be32(PNV9_LPCM_SIZE / 2), + cpu_to_be32(lpcm_size / 2), + cpu_to_be32(lpcm_size / 2), }; uint32_t opb_reg[4] = { cpu_to_be32(lpcm_addr >> 32), cpu_to_be32((uint32_t)lpcm_addr), - cpu_to_be32(PNV9_LPCM_SIZE >> 32), - cpu_to_be32((uint32_t)PNV9_LPCM_SIZE), + cpu_to_be32(lpcm_size >> 32), + cpu_to_be32((uint32_t)lpcm_size), }; uint32_t lpc_ranges[12] = { 0, 0, cpu_to_be32(LPC_MEM_OPB_ADDR), @@ -691,6 +691,19 @@ static const TypeInfo pnv_lpc_power9_info = { .class_init = pnv_lpc_power9_class_init, }; +static void pnv_lpc_power10_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "PowerNV LPC Controller POWER10"; +} + +static const TypeInfo pnv_lpc_power10_info = { + .name = TYPE_PNV10_LPC, + .parent = TYPE_PNV9_LPC, + .class_init = pnv_lpc_power10_class_init, +}; + static void pnv_lpc_realize(DeviceState *dev, Error **errp) { PnvLpcController *lpc = PNV_LPC(dev); @@ -764,6 +777,7 @@ static void pnv_lpc_register_types(void) type_register_static(&pnv_lpc_info); type_register_static(&pnv_lpc_power8_info); type_register_static(&pnv_lpc_power9_info); + type_register_static(&pnv_lpc_power10_info); } type_init(pnv_lpc_register_types) -- 2.21.0
[-- Attachment #1: Type: text/plain, Size: 1661 bytes --] On Thu, Dec 05, 2019 at 07:44:49PM +0100, Cédric Le Goater wrote: > Hello, > > The POWER10 and POWER9 processors are very similar and this series > adds the basic framework for a POWER10 chip and a machine using this > chip. The PSI and LPC models are provided first because there are no > changes. XIVE needs some adaptation and will come later. Applied to ppc-for-5.0, thanks. > > Thanks, > > C. > > Cédric Le Goater (5): > target/ppc: Add POWER10 DD1.0 model information > ppc/pnv: Introduce a POWER10 PnvChip and a powernv10 machine > ppc/psi: cleanup definitions > ppc/pnv: add a PSI bridge model for POWER10 > ppc/pnv: add a LPC Controller model for POWER10 > > include/hw/ppc/pnv.h | 46 +++++++ > include/hw/ppc/pnv_lpc.h | 6 +- > include/hw/ppc/pnv_psi.h | 2 + > include/hw/ppc/pnv_xscom.h | 22 ++++ > target/ppc/cpu-models.h | 3 + > target/ppc/cpu.h | 1 + > hw/ppc/pnv.c | 192 ++++++++++++++++++++++++++-- > hw/ppc/pnv_core.c | 10 ++ > hw/ppc/pnv_lpc.c | 30 +++-- > hw/ppc/pnv_psi.c | 32 ++++- > hw/ppc/pnv_xscom.c | 23 +++- > target/ppc/compat.c | 21 +++- > target/ppc/cpu-models.c | 3 + > target/ppc/translate_init.inc.c | 215 ++++++++++++++++++++++++++++++++ > 14 files changed, 576 insertions(+), 30 deletions(-) > -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --]
[-- Attachment #1: Type: text/plain, Size: 17902 bytes --] On Thu, Dec 05, 2019 at 07:44:51PM +0100, Cédric Le Goater wrote: > This is an empty shell with the XSCOM bus and cores. The chip controllers > will come later. > > Signed-off-by: Cédric Le Goater <clg@kaod.org> > --- > include/hw/ppc/pnv.h | 33 ++++++++ > include/hw/ppc/pnv_xscom.h | 19 +++++ > hw/ppc/pnv.c | 158 +++++++++++++++++++++++++++++++++++-- > hw/ppc/pnv_core.c | 10 +++ > hw/ppc/pnv_xscom.c | 23 ++++-- > 5 files changed, 232 insertions(+), 11 deletions(-) > > diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h > index 3a7bc3c57e0d..bfa61edfbabd 100644 > --- a/include/hw/ppc/pnv.h > +++ b/include/hw/ppc/pnv.h > @@ -43,6 +43,7 @@ typedef enum PnvChipType { > PNV_CHIP_POWER8, /* AKA Venice */ > PNV_CHIP_POWER8NVL, /* AKA Naples */ > PNV_CHIP_POWER9, /* AKA Nimbus */ > + PNV_CHIP_POWER10, /* AKA TBD */ > } PnvChipType; > > typedef struct PnvChip { > @@ -105,6 +106,14 @@ typedef struct Pnv9Chip { > #define PNV9_PIR2FUSEDCORE(pir) (((pir) >> 3) & 0xf) > #define PNV9_PIR2CHIP(pir) (((pir) >> 8) & 0x7f) > > +#define TYPE_PNV10_CHIP "pnv10-chip" > +#define PNV10_CHIP(obj) OBJECT_CHECK(Pnv10Chip, (obj), TYPE_PNV10_CHIP) > + > +typedef struct Pnv10Chip { > + /*< private >*/ > + PnvChip parent_obj; > +} Pnv10Chip; > + > typedef struct PnvChipClass { > /*< private >*/ > SysBusDeviceClass parent_class; > @@ -144,6 +153,10 @@ typedef struct PnvChipClass { > #define PNV_CHIP_POWER9(obj) \ > OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER9) > > +#define TYPE_PNV_CHIP_POWER10 PNV_CHIP_TYPE_NAME("power10_v1.0") > +#define PNV_CHIP_POWER10(obj) \ > + OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP_POWER10) > + > /* > * This generates a HW chip id depending on an index, as found on a > * two socket system with dual chip modules : > @@ -203,6 +216,16 @@ PnvChip *pnv_get_chip(uint32_t chip_id); > #define PNV_FDT_ADDR 0x01000000 > #define PNV_TIMEBASE_FREQ 512000000ULL > > +static inline bool pnv_chip_is_power10(const PnvChip *chip) > +{ > + return PNV_CHIP_GET_CLASS(chip)->chip_type == PNV_CHIP_POWER10; > +} > + > +static inline bool pnv_is_power10(PnvMachineState *pnv) > +{ > + return pnv_chip_is_power10(pnv->chips[0]); > +} It's not in scope for this series, but now that we have P8/9/10 specific chip object types and powernv8/powernv9, we should be able to remove the ugly chip_type field, and just do object class checks on the chip and or machine objects themselves. > + > /* > * BMC helpers > */ > @@ -293,4 +316,14 @@ IPMIBmc *pnv_bmc_create(void); > #define PNV9_HOMER_SIZE 0x0000000000300000ull > #define PNV9_HOMER_BASE(chip) \ > (0x203ffd800000ull + ((uint64_t)PNV_CHIP_INDEX(chip)) * PNV9_HOMER_SIZE) > + > +/* > + * POWER10 MMIO base addresses - 16TB stride per chip > + */ > +#define PNV10_CHIP_BASE(chip, base) \ > + ((base) + ((uint64_t) (chip)->chip_id << 44)) > + > +#define PNV10_XSCOM_SIZE 0x0000000400000000ull > +#define PNV10_XSCOM_BASE(chip) PNV10_CHIP_BASE(chip, 0x00603fc00000000ull) > + > #endif /* PPC_PNV_H */ > diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h > index 67641ed27800..790eb3d8f3b0 100644 > --- a/include/hw/ppc/pnv_xscom.h > +++ b/include/hw/ppc/pnv_xscom.h > @@ -70,6 +70,9 @@ typedef struct PnvXScomInterfaceClass { > #define PNV_XSCOM_OCC_BASE 0x0066000 > #define PNV_XSCOM_OCC_SIZE 0x6000 > > +/* > + * Layout of the XSCOM PCB addresses (POWER 9) > + */ > #define PNV9_XSCOM_EC_BASE(core) \ > ((uint64_t)(((core) & 0x1F) + 0x20) << 24) > #define PNV9_XSCOM_EC_SIZE 0x100000 > @@ -87,6 +90,22 @@ typedef struct PnvXScomInterfaceClass { > #define PNV9_XSCOM_XIVE_BASE 0x5013000 > #define PNV9_XSCOM_XIVE_SIZE 0x300 > > +/* > + * Layout of the XSCOM PCB addresses (POWER 10) > + */ > +#define PNV10_XSCOM_EQ_CHIPLET(core) (0x20 + ((core) >> 2)) > +#define PNV10_XSCOM_EQ(chiplet) ((chiplet) << 24) > +#define PNV10_XSCOM_EC(proc) \ > + ((0x2 << 16) | ((1 << (3 - (proc))) << 12)) > + > +#define PNV10_XSCOM_EQ_BASE(core) \ > + ((uint64_t) PNV10_XSCOM_EQ(PNV10_XSCOM_EQ_CHIPLET(core))) > +#define PNV10_XSCOM_EQ_SIZE 0x100000 > + > +#define PNV10_XSCOM_EC_BASE(core) \ > + ((uint64_t) PNV10_XSCOM_EQ_BASE(core) | PNV10_XSCOM_EC(core & 0x3)) > +#define PNV10_XSCOM_EC_SIZE 0x100000 > + > extern void pnv_xscom_realize(PnvChip *chip, uint64_t size, Error **errp); > extern int pnv_dt_xscom(PnvChip *chip, void *fdt, int offset); > > diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c > index fa656858b24a..d99cd72840be 100644 > --- a/hw/ppc/pnv.c > +++ b/hw/ppc/pnv.c > @@ -317,6 +317,23 @@ static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt) > pnv_dt_lpc(chip, fdt, 0); > } > > +static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt) > +{ > + int i; > + > + pnv_dt_xscom(chip, fdt, 0); > + > + for (i = 0; i < chip->nr_cores; i++) { > + PnvCore *pnv_core = chip->cores[i]; > + > + pnv_dt_core(chip, pnv_core, fdt); > + } > + > + if (chip->ram_size) { > + pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); > + } > +} > + > static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off) > { > uint32_t io_base = d->ioport_id; > @@ -467,6 +484,7 @@ static void *pnv_dt_create(MachineState *machine) > { > const char plat_compat8[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv"; > const char plat_compat9[] = "qemu,powernv9\0ibm,powernv"; > + const char plat_compat10[] = "qemu,powernv10\0ibm,powernv"; > PnvMachineState *pnv = PNV_MACHINE(machine); > void *fdt; > char *buf; > @@ -484,7 +502,10 @@ static void *pnv_dt_create(MachineState *machine) > _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2))); > _FDT((fdt_setprop_string(fdt, 0, "model", > "IBM PowerNV (emulated by qemu)"))); > - if (pnv_is_power9(pnv)) { > + if (pnv_is_power10(pnv)) { > + _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat10, > + sizeof(plat_compat10)))); > + } else if (pnv_is_power9(pnv)) { > _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat9, > sizeof(plat_compat9)))); > } else { > @@ -528,8 +549,8 @@ static void *pnv_dt_create(MachineState *machine) > pnv_dt_bmc_sensors(pnv->bmc, fdt); > } > > - /* Create an extra node for power management on Power9 */ > - if (pnv_is_power9(pnv)) { > + /* Create an extra node for power management on Power9 and Power10 */ > + if (pnv_is_power9(pnv) || pnv_is_power10(pnv)) { > pnv_dt_power_mgt(fdt); > } > > @@ -578,6 +599,12 @@ static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp) > return pnv_lpc_isa_create(&chip9->lpc, false, errp); > } > > +static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp) > +{ > + error_setg(errp, "No ISA bus!"); > + return NULL; > +} > + > static ISABus *pnv_isa_create(PnvChip *chip, Error **errp) > { > return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp); > @@ -618,6 +645,13 @@ static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq) > object_property_set_bool(obj, true, "realized", &error_fatal); > } > > +static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon) > +{ > + /* > + * No interrupt controller yet > + */; > +} > + > static void pnv_init(MachineState *machine) > { > PnvMachineState *pnv = PNV_MACHINE(machine); > @@ -822,6 +856,11 @@ static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id) > return (chip->chip_id << 8) | (core_id << 2); > } > > +static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id) > +{ > + return (chip->chip_id << 8) | (core_id << 2); > +} > + > static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu, > Error **errp) > { > @@ -859,6 +898,27 @@ static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) > pnv_cpu->intc = NULL; > } > > +static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu, > + Error **errp) > +{ > + PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); > + > + /* Will be defined when the interrupt controller is */ > + pnv_cpu->intc = NULL; > +} > + > +static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu) > +{ > + ; > +} > + > +static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) > +{ > + PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); > + > + pnv_cpu->intc = NULL; > +} > + > /* > * Allowed core identifiers on a POWER8 Processor Chip : > * > @@ -886,6 +946,9 @@ static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) > */ > #define POWER9_CORE_MASK (0xffffffffffffffull) > > + > +#define POWER10_CORE_MASK (0xffffffffffffffull) > + > static void pnv_chip_power8_instance_init(Object *obj) > { > Pnv8Chip *chip8 = PNV8_CHIP(obj); > @@ -1246,6 +1309,56 @@ static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) > &k->parent_realize); > } > > +static void pnv_chip_power10_instance_init(Object *obj) > +{ > + /* > + * No controllers yet > + */ > + ; > +} > + > +static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) > +{ > + PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); > + PnvChip *chip = PNV_CHIP(dev); > + Error *local_err = NULL; > + > + /* XSCOM bridge is first */ > + pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err); > + if (local_err) { > + error_propagate(errp, local_err); > + return; > + } > + sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip)); > + > + pcc->parent_realize(dev, &local_err); > + if (local_err) { > + error_propagate(errp, local_err); > + return; > + } > +} > + > +static void pnv_chip_power10_class_init(ObjectClass *klass, void *data) > +{ > + DeviceClass *dc = DEVICE_CLASS(klass); > + PnvChipClass *k = PNV_CHIP_CLASS(klass); > + > + k->chip_type = PNV_CHIP_POWER10; > + k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */ > + k->cores_mask = POWER10_CORE_MASK; > + k->core_pir = pnv_chip_core_pir_p10; > + k->intc_create = pnv_chip_power10_intc_create; > + k->intc_reset = pnv_chip_power10_intc_reset; > + k->intc_destroy = pnv_chip_power10_intc_destroy; > + k->isa_create = pnv_chip_power10_isa_create; > + k->dt_populate = pnv_chip_power10_dt_populate; > + k->pic_print_info = pnv_chip_power10_pic_print_info; > + dc->desc = "PowerNV Chip POWER10"; > + > + device_class_set_parent_realize(dc, pnv_chip_power10_realize, > + &k->parent_realize); > +} > + > static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) > { > PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); > @@ -1327,10 +1440,12 @@ static void pnv_chip_core_realize(PnvChip *chip, Error **errp) > &error_fatal); > > /* Each core has an XSCOM MMIO region */ > - if (!pnv_chip_is_power9(chip)) { > - xscom_core_base = PNV_XSCOM_EX_BASE(core_hwid); > - } else { > + if (pnv_chip_is_power10(chip)) { > + xscom_core_base = PNV10_XSCOM_EC_BASE(core_hwid); > + } else if (pnv_chip_is_power9(chip)) { > xscom_core_base = PNV9_XSCOM_EC_BASE(core_hwid); > + } else { > + xscom_core_base = PNV_XSCOM_EX_BASE(core_hwid); > } > > pnv_xscom_add_subregion(chip, xscom_core_base, > @@ -1558,6 +1673,14 @@ static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) > mc->alias = "powernv"; > } > > +static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) > +{ > + MachineClass *mc = MACHINE_CLASS(oc); > + > + mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; > + mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v1.0"); > +} > + > static void pnv_machine_class_init(ObjectClass *oc, void *data) > { > MachineClass *mc = MACHINE_CLASS(oc); > @@ -1595,7 +1718,19 @@ static void pnv_machine_class_init(ObjectClass *oc, void *data) > .parent = TYPE_PNV9_CHIP, \ > } > > +#define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \ > + { \ > + .name = type, \ > + .class_init = class_initfn, \ > + .parent = TYPE_PNV10_CHIP, \ > + } > + > static const TypeInfo types[] = { > + { > + .name = MACHINE_TYPE_NAME("powernv10"), > + .parent = TYPE_PNV_MACHINE, > + .class_init = pnv_machine_power10_class_init, > + }, > { > .name = MACHINE_TYPE_NAME("powernv9"), > .parent = TYPE_PNV_MACHINE, > @@ -1635,6 +1770,17 @@ static const TypeInfo types[] = { > .abstract = true, > }, > > + /* > + * P10 chip and variants > + */ > + { > + .name = TYPE_PNV10_CHIP, > + .parent = TYPE_PNV_CHIP, > + .instance_init = pnv_chip_power10_instance_init, > + .instance_size = sizeof(Pnv10Chip), > + }, > + DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init), > + > /* > * P9 chip and variants > */ > diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c > index 5ab75bde6cc5..2651044278ed 100644 > --- a/hw/ppc/pnv_core.c > +++ b/hw/ppc/pnv_core.c > @@ -247,6 +247,7 @@ static void pnv_core_realize(DeviceState *dev, Error **errp) > } > > snprintf(name, sizeof(name), "xscom-core.%d", cc->core_id); > + /* TODO: check PNV_XSCOM_EX_SIZE for p10 */ > pnv_xscom_region_init(&pc->xscom_regs, OBJECT(dev), pcc->xscom_ops, > pc, name, PNV_XSCOM_EX_SIZE); > > @@ -308,6 +309,14 @@ static void pnv_core_power9_class_init(ObjectClass *oc, void *data) > pcc->xscom_ops = &pnv_core_power9_xscom_ops; > } > > +static void pnv_core_power10_class_init(ObjectClass *oc, void *data) > +{ > + PnvCoreClass *pcc = PNV_CORE_CLASS(oc); > + > + /* TODO: Use the P9 XSCOMs for now on P10 */ > + pcc->xscom_ops = &pnv_core_power9_xscom_ops; > +} > + > static void pnv_core_class_init(ObjectClass *oc, void *data) > { > DeviceClass *dc = DEVICE_CLASS(oc); > @@ -337,6 +346,7 @@ static const TypeInfo pnv_core_infos[] = { > DEFINE_PNV_CORE_TYPE(power8, "power8_v2.0"), > DEFINE_PNV_CORE_TYPE(power8, "power8nvl_v1.0"), > DEFINE_PNV_CORE_TYPE(power9, "power9_v2.0"), > + DEFINE_PNV_CORE_TYPE(power10, "power10_v1.0"), > }; > > DEFINE_TYPES(pnv_core_infos) > diff --git a/hw/ppc/pnv_xscom.c b/hw/ppc/pnv_xscom.c > index f01d788a6545..b3d3b6e3507d 100644 > --- a/hw/ppc/pnv_xscom.c > +++ b/hw/ppc/pnv_xscom.c > @@ -69,10 +69,16 @@ static uint32_t pnv_xscom_pcba(PnvChip *chip, uint64_t addr) > { > addr &= (PNV_XSCOM_SIZE - 1); > > - if (pnv_chip_is_power9(chip)) { > - return addr >> 3; > - } else { > + switch (PNV_CHIP_GET_CLASS(chip)->chip_type) { > + case PNV_CHIP_POWER8E: > + case PNV_CHIP_POWER8: > + case PNV_CHIP_POWER8NVL: > return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf); > + case PNV_CHIP_POWER9: > + case PNV_CHIP_POWER10: > + return addr >> 3; > + default: > + g_assert_not_reached(); > } > } > > @@ -307,6 +313,7 @@ static int xscom_dt_child(Object *child, void *opaque) > > static const char compat_p8[] = "ibm,power8-xscom\0ibm,xscom"; > static const char compat_p9[] = "ibm,power9-xscom\0ibm,xscom"; > +static const char compat_p10[] = "ibm,power10-xscom\0ibm,xscom"; > > int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset) > { > @@ -315,7 +322,10 @@ int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset) > ForeachPopulateArgs args; > char *name; > > - if (pnv_chip_is_power9(chip)) { > + if (pnv_chip_is_power10(chip)) { > + reg[0] = cpu_to_be64(PNV10_XSCOM_BASE(chip)); > + reg[1] = cpu_to_be64(PNV10_XSCOM_SIZE); > + } else if (pnv_chip_is_power9(chip)) { > reg[0] = cpu_to_be64(PNV9_XSCOM_BASE(chip)); > reg[1] = cpu_to_be64(PNV9_XSCOM_SIZE); > } else { > @@ -332,7 +342,10 @@ int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset) > _FDT((fdt_setprop_cell(fdt, xscom_offset, "#size-cells", 1))); > _FDT((fdt_setprop(fdt, xscom_offset, "reg", reg, sizeof(reg)))); > > - if (pnv_chip_is_power9(chip)) { > + if (pnv_chip_is_power10(chip)) { > + _FDT((fdt_setprop(fdt, xscom_offset, "compatible", compat_p10, > + sizeof(compat_p10)))); > + } else if (pnv_chip_is_power9(chip)) { > _FDT((fdt_setprop(fdt, xscom_offset, "compatible", compat_p9, > sizeof(compat_p9)))); > } else { -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --]
On 10/12/2019 04:34, David Gibson wrote: >> +static inline bool pnv_chip_is_power10(const PnvChip *chip) >> +{ >> + return PNV_CHIP_GET_CLASS(chip)->chip_type == PNV_CHIP_POWER10; >> +} >> + >> +static inline bool pnv_is_power10(PnvMachineState *pnv) >> +{ >> + return pnv_chip_is_power10(pnv->chips[0]); >> +} > I agree this is starting to be ugly. > It's not in scope for this series, but now that we have P8/9/10 > specific chip object types and powernv8/powernv9, we should be able to > remove the ugly chip_type field, and just do object class checks on > the chip and or machine objects themselves. So we would use object_class_dynamic_cast() instead of field chip_type ? C.
[-- Attachment #1: Type: text/plain, Size: 1122 bytes --] On Tue, Dec 10, 2019 at 09:52:05AM +0100, Cédric Le Goater wrote: > On 10/12/2019 04:34, David Gibson wrote: > >> +static inline bool pnv_chip_is_power10(const PnvChip *chip) > >> +{ > >> + return PNV_CHIP_GET_CLASS(chip)->chip_type == PNV_CHIP_POWER10; > >> +} > >> + > >> +static inline bool pnv_is_power10(PnvMachineState *pnv) > >> +{ > >> + return pnv_chip_is_power10(pnv->chips[0]); > >> +} > > > > I agree this is starting to be ugly. > > > It's not in scope for this series, but now that we have P8/9/10 > > specific chip object types and powernv8/powernv9, we should be able to > > remove the ugly chip_type field, and just do object class checks on > > the chip and or machine objects themselves. > > > So we would use object_class_dynamic_cast() instead of field > chip_type ? Just object_dynamic_cast() should suffice, since you have access to the chip and machine instances. -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --]