* [PATCH 1/5] target/ppc: Add POWER10 DD1.0 model information
2019-12-05 18:44 [PATCH 0/5] ppc/pnv: add a POWER10 PnvChip and a powernv10 machine Cédric Le Goater
@ 2019-12-05 18:44 ` Cédric Le Goater
2019-12-05 18:44 ` [PATCH 2/5] ppc/pnv: Introduce a POWER10 PnvChip and a powernv10 machine Cédric Le Goater
` (4 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Cédric Le Goater @ 2019-12-05 18:44 UTC (permalink / raw)
To: David Gibson; +Cc: Cédric Le Goater, qemu-ppc, Greg Kurz, qemu-devel
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
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/5] ppc/pnv: Introduce a POWER10 PnvChip and a powernv10 machine
2019-12-05 18:44 [PATCH 0/5] ppc/pnv: add a POWER10 PnvChip and a powernv10 machine Cédric Le Goater
2019-12-05 18:44 ` [PATCH 1/5] target/ppc: Add POWER10 DD1.0 model information Cédric Le Goater
@ 2019-12-05 18:44 ` Cédric Le Goater
2019-12-10 3:34 ` David Gibson
2019-12-05 18:44 ` [PATCH 3/5] ppc/psi: cleanup definitions Cédric Le Goater
` (3 subsequent siblings)
5 siblings, 1 reply; 10+ messages in thread
From: Cédric Le Goater @ 2019-12-05 18:44 UTC (permalink / raw)
To: David Gibson; +Cc: Cédric Le Goater, qemu-ppc, Greg Kurz, qemu-devel
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
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 2/5] ppc/pnv: Introduce a POWER10 PnvChip and a powernv10 machine
2019-12-05 18:44 ` [PATCH 2/5] ppc/pnv: Introduce a POWER10 PnvChip and a powernv10 machine Cédric Le Goater
@ 2019-12-10 3:34 ` David Gibson
2019-12-10 8:52 ` Cédric Le Goater
0 siblings, 1 reply; 10+ messages in thread
From: David Gibson @ 2019-12-10 3:34 UTC (permalink / raw)
To: Cédric Le Goater; +Cc: qemu-ppc, Greg Kurz, qemu-devel
[-- 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 --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/5] ppc/pnv: Introduce a POWER10 PnvChip and a powernv10 machine
2019-12-10 3:34 ` David Gibson
@ 2019-12-10 8:52 ` Cédric Le Goater
2019-12-10 23:42 ` David Gibson
0 siblings, 1 reply; 10+ messages in thread
From: Cédric Le Goater @ 2019-12-10 8:52 UTC (permalink / raw)
To: David Gibson; +Cc: qemu-ppc, Greg Kurz, qemu-devel
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.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/5] ppc/pnv: Introduce a POWER10 PnvChip and a powernv10 machine
2019-12-10 8:52 ` Cédric Le Goater
@ 2019-12-10 23:42 ` David Gibson
0 siblings, 0 replies; 10+ messages in thread
From: David Gibson @ 2019-12-10 23:42 UTC (permalink / raw)
To: Cédric Le Goater; +Cc: qemu-ppc, Greg Kurz, qemu-devel
[-- 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 --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 3/5] ppc/psi: cleanup definitions
2019-12-05 18:44 [PATCH 0/5] ppc/pnv: add a POWER10 PnvChip and a powernv10 machine Cédric Le Goater
2019-12-05 18:44 ` [PATCH 1/5] target/ppc: Add POWER10 DD1.0 model information Cédric Le Goater
2019-12-05 18:44 ` [PATCH 2/5] ppc/pnv: Introduce a POWER10 PnvChip and a powernv10 machine Cédric Le Goater
@ 2019-12-05 18:44 ` Cédric Le Goater
2019-12-05 18:44 ` [PATCH 4/5] ppc/pnv: add a PSI bridge model for POWER10 Cédric Le Goater
` (2 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Cédric Le Goater @ 2019-12-05 18:44 UTC (permalink / raw)
To: David Gibson; +Cc: Cédric Le Goater, qemu-ppc, Greg Kurz, qemu-devel
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
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/5] ppc/pnv: add a PSI bridge model for POWER10
2019-12-05 18:44 [PATCH 0/5] ppc/pnv: add a POWER10 PnvChip and a powernv10 machine Cédric Le Goater
` (2 preceding siblings ...)
2019-12-05 18:44 ` [PATCH 3/5] ppc/psi: cleanup definitions Cédric Le Goater
@ 2019-12-05 18:44 ` Cédric Le Goater
2019-12-05 18:44 ` [PATCH 5/5] ppc/pnv: add a LPC Controller " Cédric Le Goater
2019-12-10 3:33 ` [PATCH 0/5] ppc/pnv: add a POWER10 PnvChip and a powernv10 machine David Gibson
5 siblings, 0 replies; 10+ messages in thread
From: Cédric Le Goater @ 2019-12-05 18:44 UTC (permalink / raw)
To: David Gibson; +Cc: Cédric Le Goater, qemu-ppc, Greg Kurz, qemu-devel
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
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 5/5] ppc/pnv: add a LPC Controller model for POWER10
2019-12-05 18:44 [PATCH 0/5] ppc/pnv: add a POWER10 PnvChip and a powernv10 machine Cédric Le Goater
` (3 preceding siblings ...)
2019-12-05 18:44 ` [PATCH 4/5] ppc/pnv: add a PSI bridge model for POWER10 Cédric Le Goater
@ 2019-12-05 18:44 ` Cédric Le Goater
2019-12-10 3:33 ` [PATCH 0/5] ppc/pnv: add a POWER10 PnvChip and a powernv10 machine David Gibson
5 siblings, 0 replies; 10+ messages in thread
From: Cédric Le Goater @ 2019-12-05 18:44 UTC (permalink / raw)
To: David Gibson; +Cc: Cédric Le Goater, qemu-ppc, Greg Kurz, qemu-devel
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
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 0/5] ppc/pnv: add a POWER10 PnvChip and a powernv10 machine
2019-12-05 18:44 [PATCH 0/5] ppc/pnv: add a POWER10 PnvChip and a powernv10 machine Cédric Le Goater
` (4 preceding siblings ...)
2019-12-05 18:44 ` [PATCH 5/5] ppc/pnv: add a LPC Controller " Cédric Le Goater
@ 2019-12-10 3:33 ` David Gibson
5 siblings, 0 replies; 10+ messages in thread
From: David Gibson @ 2019-12-10 3:33 UTC (permalink / raw)
To: Cédric Le Goater; +Cc: qemu-ppc, Greg Kurz, qemu-devel
[-- 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 --]
^ permalink raw reply [flat|nested] 10+ messages in thread