From b5ea6754e8f913c82197dc26973d7d7ee4aef91f Mon Sep 17 00:00:00 2001 From: Frederic Barrat Date: Fri, 30 Jun 2023 12:26:09 +0200 Subject: [PATCH 01/59] pnv/psi: Allow access to PSI registers through xscom MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit skiboot only uses mmio to access the PSI registers (once the BAR is set) but we don't have any reason to block the accesses through xscom. This patch enables xscom access to the PSI registers. It converts the xscom addresses to mmio addresses, which requires a bit of care for the PSIHB, then reuse the existing mmio ops. Signed-off-by: Frederic Barrat Reviewed-by: Cédric Le Goater Message-ID: <20230630102609.193214-1-fbarrat@linux.ibm.com> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/pnv_psi.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c index 8aa09ab26b..46da58dff8 100644 --- a/hw/ppc/pnv_psi.c +++ b/hw/ppc/pnv_psi.c @@ -121,8 +121,12 @@ #define PSIHB9_BAR_MASK 0x00fffffffff00000ull #define PSIHB9_FSPBAR_MASK 0x00ffffff00000000ull +/* mmio address to xscom address */ #define PSIHB_REG(addr) (((addr) >> 3) + PSIHB_XSCOM_BAR) +/* xscom address to mmio address */ +#define PSIHB_MMIO(reg) ((reg - PSIHB_XSCOM_BAR) << 3) + static void pnv_psi_set_bar(PnvPsi *psi, uint64_t bar) { PnvPsiClass *ppc = PNV_PSI_GET_CLASS(psi); @@ -769,24 +773,31 @@ static const MemoryRegionOps pnv_psi_p9_mmio_ops = { static uint64_t pnv_psi_p9_xscom_read(void *opaque, hwaddr addr, unsigned size) { - /* No read are expected */ - qemu_log_mask(LOG_GUEST_ERROR, "PSI: xscom read at 0x%" PRIx64 "\n", addr); - return -1; + uint32_t reg = addr >> 3; + uint64_t val = -1; + + if (reg < PSIHB_XSCOM_BAR) { + /* FIR, not modeled */ + qemu_log_mask(LOG_UNIMP, "PSI: xscom read at 0x%08x\n", reg); + } else { + val = pnv_psi_p9_mmio_read(opaque, PSIHB_MMIO(reg), size); + } + return val; } static void pnv_psi_p9_xscom_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { PnvPsi *psi = PNV_PSI(opaque); + uint32_t reg = addr >> 3; - /* XSCOM is only used to set the PSIHB MMIO region */ - switch (addr >> 3) { - case PSIHB_XSCOM_BAR: + if (reg < PSIHB_XSCOM_BAR) { + /* FIR, not modeled */ + qemu_log_mask(LOG_UNIMP, "PSI: xscom write at 0x%08x\n", reg); + } else if (reg == PSIHB_XSCOM_BAR) { pnv_psi_set_bar(psi, val); - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, "PSI: xscom write at 0x%" PRIx64 "\n", - addr); + } else { + pnv_psi_p9_mmio_write(opaque, PSIHB_MMIO(reg), val, size); } } From a5ff7875a9e50180c354471f931f863a26283ce1 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Sun, 25 Jun 2023 22:20:45 +1000 Subject: [PATCH 02/59] target/ppc: Make HDECR underflow edge triggered MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HDEC interrupts are edge-triggered on HDECR underflow (notably different from DEC which is level-triggered). HDEC interrupts already clear the irq on delivery so that does not need to be changed. Signed-off-by: Nicholas Piggin Reviewed-by: Cédric Le Goater Message-ID: <20230625122045.15544-1-npiggin@gmail.com> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index 82e4408c5c..0fc82bb175 100644 --- a/hw/ppc/ppc.c +++ b/hw/ppc/ppc.c @@ -788,8 +788,8 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp, QEMUTimer *timer, void (*raise_excp)(void *), void (*lower_excp)(PowerPCCPU *), - target_ulong decr, target_ulong value, - int nr_bits) + uint32_t flags, target_ulong decr, + target_ulong value, int nr_bits) { CPUPPCState *env = &cpu->env; ppc_tb_t *tb_env = env->tb_env; @@ -819,15 +819,15 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp, * On MSB edge based DEC implementations the MSB going from 0 -> 1 triggers * an edge interrupt, so raise it here too. */ - if (((tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL) && signed_value < 0) || - ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED) && signed_value < 0 + if (((flags & PPC_DECR_UNDERFLOW_LEVEL) && signed_value < 0) || + ((flags & PPC_DECR_UNDERFLOW_TRIGGERED) && signed_value < 0 && signed_decr >= 0)) { (*raise_excp)(cpu); return; } /* On MSB level based systems a 0 for the MSB stops interrupt delivery */ - if (signed_value >= 0 && (tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL)) { + if (signed_value >= 0 && (flags & PPC_DECR_UNDERFLOW_LEVEL)) { (*lower_excp)(cpu); } @@ -846,8 +846,8 @@ static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, target_ulong decr, ppc_tb_t *tb_env = cpu->env.tb_env; __cpu_ppc_store_decr(cpu, &tb_env->decr_next, tb_env->decr_timer, - tb_env->decr_timer->cb, &cpu_ppc_decr_lower, decr, - value, nr_bits); + tb_env->decr_timer->cb, &cpu_ppc_decr_lower, + tb_env->flags, decr, value, nr_bits); } void cpu_ppc_store_decr(CPUPPCState *env, target_ulong value) @@ -876,8 +876,10 @@ static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, target_ulong hdecr, ppc_tb_t *tb_env = cpu->env.tb_env; if (tb_env->hdecr_timer != NULL) { + /* HDECR (Book3S 64bit) is edge-based, not level like DECR */ __cpu_ppc_store_decr(cpu, &tb_env->hdecr_next, tb_env->hdecr_timer, tb_env->hdecr_timer->cb, &cpu_ppc_hdecr_lower, + PPC_DECR_UNDERFLOW_TRIGGERED, hdecr, value, nr_bits); } } From 2ad2e113deb5663e69a05dd6922cbfc6d7ea34d3 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Thu, 29 Jun 2023 12:07:13 +1000 Subject: [PATCH 03/59] hw/ppc: Fix clock update drift MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The clock update logic reads the clock twice to compute the new clock value, with a value derived from the later time subtracted from a value derived from the earlier time. The delta causes time to be lost. This can ultimately result in time becoming unsynchronized between CPUs and that can cause OS lockups, timeouts, watchdogs, etc. This can be seen running a KVM guest (that causes lots of TB updates) on a powernv SMP machine. Fix this by reading the clock once. Cc: qemu-stable@nongnu.org Fixes: dbdd25065e90 ("Implement time-base start/stop helpers.") Signed-off-by: Nicholas Piggin Reviewed-by: Cédric Le Goater Reviewed-by: Frederic Barrat Message-ID: <20230629020713.327745-1-npiggin@gmail.com> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index 0fc82bb175..0e0a3d93c3 100644 --- a/hw/ppc/ppc.c +++ b/hw/ppc/ppc.c @@ -535,23 +535,24 @@ static inline void cpu_ppc_store_tb(ppc_tb_t *tb_env, uint64_t vmclk, void cpu_ppc_store_tbl (CPUPPCState *env, uint32_t value) { ppc_tb_t *tb_env = env->tb_env; + int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); uint64_t tb; - tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->tb_offset); + tb = cpu_ppc_get_tb(tb_env, clock, tb_env->tb_offset); tb &= 0xFFFFFFFF00000000ULL; - cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - &tb_env->tb_offset, tb | (uint64_t)value); + cpu_ppc_store_tb(tb_env, clock, &tb_env->tb_offset, tb | (uint64_t)value); } static inline void _cpu_ppc_store_tbu(CPUPPCState *env, uint32_t value) { ppc_tb_t *tb_env = env->tb_env; + int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); uint64_t tb; - tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->tb_offset); + tb = cpu_ppc_get_tb(tb_env, clock, tb_env->tb_offset); tb &= 0x00000000FFFFFFFFULL; - cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - &tb_env->tb_offset, ((uint64_t)value << 32) | tb); + cpu_ppc_store_tb(tb_env, clock, &tb_env->tb_offset, + ((uint64_t)value << 32) | tb); } void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value) @@ -584,23 +585,24 @@ uint32_t cpu_ppc_load_atbu (CPUPPCState *env) void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value) { ppc_tb_t *tb_env = env->tb_env; + int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); uint64_t tb; - tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->atb_offset); + tb = cpu_ppc_get_tb(tb_env, clock, tb_env->atb_offset); tb &= 0xFFFFFFFF00000000ULL; - cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - &tb_env->atb_offset, tb | (uint64_t)value); + cpu_ppc_store_tb(tb_env, clock, &tb_env->atb_offset, tb | (uint64_t)value); } void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value) { ppc_tb_t *tb_env = env->tb_env; + int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); uint64_t tb; - tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->atb_offset); + tb = cpu_ppc_get_tb(tb_env, clock, tb_env->atb_offset); tb &= 0x00000000FFFFFFFFULL; - cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - &tb_env->atb_offset, ((uint64_t)value << 32) | tb); + cpu_ppc_store_tb(tb_env, clock, &tb_env->atb_offset, + ((uint64_t)value << 32) | tb); } uint64_t cpu_ppc_load_vtb(CPUPPCState *env) @@ -622,14 +624,13 @@ void cpu_ppc_store_vtb(CPUPPCState *env, uint64_t value) void cpu_ppc_store_tbu40(CPUPPCState *env, uint64_t value) { ppc_tb_t *tb_env = env->tb_env; + int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); uint64_t tb; - tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - tb_env->tb_offset); + tb = cpu_ppc_get_tb(tb_env, clock, tb_env->tb_offset); tb &= 0xFFFFFFUL; tb |= (value & ~0xFFFFFFUL); - cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - &tb_env->tb_offset, tb); + cpu_ppc_store_tb(tb_env, clock, &tb_env->tb_offset, tb); } static void cpu_ppc_tb_stop (CPUPPCState *env) From 28eafc1270c5878a2f2538b8050443f88c5c9282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 26 Jun 2023 16:01:00 +0200 Subject: [PATCH 04/59] target/ppc: Only generate decodetree files when TCG is enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to generate TCG-specific decodetree files when TCG is disabled. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Greg Kurz Reviewed-by: Richard Henderson Message-ID: <20230626140100.67941-1-philmd@linaro.org> Signed-off-by: Daniel Henrique Barboza --- target/ppc/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/ppc/meson.build b/target/ppc/meson.build index a69f174f41..4c2635039e 100644 --- a/target/ppc/meson.build +++ b/target/ppc/meson.build @@ -28,7 +28,7 @@ gen = [ extra_args: ['--static-decode=decode_insn64', '--insnwidth=64']), ] -ppc_ss.add(gen) +ppc_ss.add(when: 'CONFIG_TCG', if_true: gen) ppc_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: files('kvm-stub.c')) ppc_ss.add(when: 'CONFIG_USER_ONLY', if_true: files('user_only_helper.c')) From 32be62a3d811fa9f389ff791ac6c5cecf69b2109 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Mon, 5 Jun 2023 23:51:45 +0200 Subject: [PATCH 05/59] mv64361: Add dummy gigabit ethernet PHY access registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't emulate the gigabit ethernet part of the chip but the MorphOS driver accesses these and expects to get some valid looking result otherwise it hangs. Add some minimal dummy implementation to avoid rhis. Signed-off-by: BALATON Zoltan Acked-by: Cédric Le Goater Message-ID: <20230605215145.29458746335@zero.eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/pci-host/mv64361.c | 6 ++++++ hw/pci-host/mv643xx.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/hw/pci-host/mv64361.c b/hw/pci-host/mv64361.c index 19e8031a3f..01bd8c887f 100644 --- a/hw/pci-host/mv64361.c +++ b/hw/pci-host/mv64361.c @@ -541,6 +541,12 @@ static uint64_t mv64361_read(void *opaque, hwaddr addr, unsigned int size) } } break; + case MV64340_ETH_PHY_ADDR: + ret = 0x98; + break; + case MV64340_ETH_SMI: + ret = BIT(27); + break; case MV64340_CUNIT_ARBITER_CONTROL_REG: ret = 0x11ff0000 | (s->gpp_int_level << 10); break; diff --git a/hw/pci-host/mv643xx.h b/hw/pci-host/mv643xx.h index cd26a43f18..f2e1baea88 100644 --- a/hw/pci-host/mv643xx.h +++ b/hw/pci-host/mv643xx.h @@ -656,6 +656,9 @@ /* Ethernet Unit Registers */ /****************************************/ +#define MV64340_ETH_PHY_ADDR 0x2000 +#define MV64340_ETH_SMI 0x2004 + /*******************************************/ /* CUNIT Registers */ /*******************************************/ From 6f967f4f7869cd393585946ed43427c626a15d40 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Sun, 25 Jun 2023 22:03:16 +1000 Subject: [PATCH 06/59] target/ppc: Tidy POWER book4 SPR registration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit POWER book4 (implementation-specific) SPRs are sometimes in their own functions, but in other cases are mixed with architected SPRs. Do some spring cleaning on these. Reviewed-by: Cédric Le Goater Signed-off-by: Nicholas Piggin Message-ID: <20230625120317.13877-2-npiggin@gmail.com> Signed-off-by: Daniel Henrique Barboza --- target/ppc/cpu_init.c | 82 +++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 27 deletions(-) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index aeff71d063..dc93581dd3 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -5370,31 +5370,6 @@ static void register_book3s_ids_sprs(CPUPPCState *env) &spr_read_generic, SPR_NOACCESS, &spr_read_generic, NULL, 0x00000000); - spr_register_hv(env, SPR_HID0, "HID0", - SPR_NOACCESS, SPR_NOACCESS, - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - spr_register_hv(env, SPR_TSCR, "TSCR", - SPR_NOACCESS, SPR_NOACCESS, - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic32, - 0x00000000); - spr_register_hv(env, SPR_HMER, "HMER", - SPR_NOACCESS, SPR_NOACCESS, - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_hmer, - 0x00000000); - spr_register_hv(env, SPR_HMEER, "HMEER", - SPR_NOACCESS, SPR_NOACCESS, - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - spr_register_hv(env, SPR_TFMR, "TFMR", - SPR_NOACCESS, SPR_NOACCESS, - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); spr_register_hv(env, SPR_LPIDR, "LPIDR", SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, @@ -5656,14 +5631,60 @@ static void register_power8_ic_sprs(CPUPPCState *env) #endif } +/* SPRs specific to IBM POWER CPUs */ +static void register_power_common_book4_sprs(CPUPPCState *env) +{ +#if !defined(CONFIG_USER_ONLY) + spr_register_hv(env, SPR_HID0, "HID0", + SPR_NOACCESS, SPR_NOACCESS, + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + spr_register_hv(env, SPR_TSCR, "TSCR", + SPR_NOACCESS, SPR_NOACCESS, + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic32, + 0x00000000); + spr_register_hv(env, SPR_HMER, "HMER", + SPR_NOACCESS, SPR_NOACCESS, + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_hmer, + 0x00000000); + spr_register_hv(env, SPR_HMEER, "HMEER", + SPR_NOACCESS, SPR_NOACCESS, + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + spr_register_hv(env, SPR_TFMR, "TFMR", + SPR_NOACCESS, SPR_NOACCESS, + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); +#endif +} + +static void register_power9_book4_sprs(CPUPPCState *env) +{ + /* Add a number of P9 book4 registers */ + register_power_common_book4_sprs(env); +#if !defined(CONFIG_USER_ONLY) + spr_register_kvm(env, SPR_WORT, "WORT", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + KVM_REG_PPC_WORT, 0); +#endif +} + static void register_power8_book4_sprs(CPUPPCState *env) { /* Add a number of P8 book4 registers */ + register_power_common_book4_sprs(env); #if !defined(CONFIG_USER_ONLY) spr_register_kvm(env, SPR_ACOP, "ACOP", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, KVM_REG_PPC_ACOP, 0); + /* PID is only in BookE in ISA v2.07 */ spr_register_kvm(env, SPR_BOOKS_PID, "PID", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_pidr, @@ -5679,10 +5700,12 @@ static void register_power7_book4_sprs(CPUPPCState *env) { /* Add a number of P7 book4 registers */ #if !defined(CONFIG_USER_ONLY) + register_power_common_book4_sprs(env); spr_register_kvm(env, SPR_ACOP, "ACOP", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, KVM_REG_PPC_ACOP, 0); + /* PID is only in BookE in ISA v2.06 */ spr_register_kvm(env, SPR_BOOKS_PID, "PID", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic32, @@ -5716,6 +5739,11 @@ static void register_power9_mmu_sprs(CPUPPCState *env) SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, 0x0000000000000000); + /* PID is part of the BookS ISA from v3.0 */ + spr_register_kvm(env, SPR_BOOKS_PID, "PID", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_pidr, + KVM_REG_PPC_PID, 0); #endif } @@ -6269,7 +6297,7 @@ static void init_proc_POWER9(CPUPPCState *env) register_power8_dpdes_sprs(env); register_vtb_sprs(env); register_power8_ic_sprs(env); - register_power8_book4_sprs(env); + register_power9_book4_sprs(env); register_power8_rpr_sprs(env); register_power9_mmu_sprs(env); @@ -6462,7 +6490,7 @@ static void init_proc_POWER10(CPUPPCState *env) register_power8_dpdes_sprs(env); register_vtb_sprs(env); register_power8_ic_sprs(env); - register_power8_book4_sprs(env); + register_power9_book4_sprs(env); register_power8_rpr_sprs(env); register_power9_mmu_sprs(env); register_power10_hash_sprs(env); From b25f2ffa19c0f4a79de0315d4eade36ce76b031c Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Sun, 25 Jun 2023 22:03:17 +1000 Subject: [PATCH 07/59] target/ppc: Add TFMR SPR implementation with read and write helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TFMR is the Time Facility Management Register which is specific to POWER CPUs, and used for the purpose of timebase management (generally by firmware, not the OS). Add helpers for the TFMR register, which will form part of the core timebase facility model in future but for now behaviour is unchanged. Reviewed-by: Cédric Le Goater Signed-off-by: Nicholas Piggin Message-ID: <20230625120317.13877-3-npiggin@gmail.com> Signed-off-by: Daniel Henrique Barboza --- target/ppc/cpu_init.c | 2 +- target/ppc/helper.h | 2 ++ target/ppc/spr_common.h | 2 ++ target/ppc/timebase_helper.c | 13 +++++++++++++ target/ppc/translate.c | 10 ++++++++++ 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index dc93581dd3..5f4969664e 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -5658,7 +5658,7 @@ static void register_power_common_book4_sprs(CPUPPCState *env) spr_register_hv(env, SPR_TFMR, "TFMR", SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, + &spr_read_tfmr, &spr_write_tfmr, 0x00000000); #endif } diff --git a/target/ppc/helper.h b/target/ppc/helper.h index fda40b8a60..828f7844c8 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -722,6 +722,8 @@ DEF_HELPER_FLAGS_1(load_dpdes, TCG_CALL_NO_RWG, tl, env) DEF_HELPER_FLAGS_2(store_dpdes, TCG_CALL_NO_RWG, void, env, tl) DEF_HELPER_2(book3s_msgsndp, void, env, tl) DEF_HELPER_2(book3s_msgclrp, void, env, tl) +DEF_HELPER_1(load_tfmr, tl, env) +DEF_HELPER_2(store_tfmr, void, env, tl) #endif DEF_HELPER_2(store_sdr1, void, env, tl) DEF_HELPER_2(store_pidr, void, env, tl) diff --git a/target/ppc/spr_common.h b/target/ppc/spr_common.h index 4c0f2bed77..fbf52123b5 100644 --- a/target/ppc/spr_common.h +++ b/target/ppc/spr_common.h @@ -194,6 +194,8 @@ void spr_write_ebb(DisasContext *ctx, int sprn, int gprn); void spr_read_ebb_upper32(DisasContext *ctx, int gprn, int sprn); void spr_write_ebb_upper32(DisasContext *ctx, int sprn, int gprn); void spr_write_hmer(DisasContext *ctx, int sprn, int gprn); +void spr_read_tfmr(DisasContext *ctx, int gprn, int sprn); +void spr_write_tfmr(DisasContext *ctx, int sprn, int gprn); void spr_write_lpcr(DisasContext *ctx, int sprn, int gprn); void spr_read_dexcr_ureg(DisasContext *ctx, int gprn, int sprn); #endif diff --git a/target/ppc/timebase_helper.c b/target/ppc/timebase_helper.c index b80f56af7e..08a6b47ee0 100644 --- a/target/ppc/timebase_helper.c +++ b/target/ppc/timebase_helper.c @@ -144,6 +144,19 @@ void helper_store_booke_tsr(CPUPPCState *env, target_ulong val) store_booke_tsr(env, val); } +#if defined(TARGET_PPC64) +/* POWER processor Timebase Facility */ +target_ulong helper_load_tfmr(CPUPPCState *env) +{ + return env->spr[SPR_TFMR]; +} + +void helper_store_tfmr(CPUPPCState *env, target_ulong val) +{ + env->spr[SPR_TFMR] = val; +} +#endif + /*****************************************************************************/ /* Embedded PowerPC specific helpers */ diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 372ee600b2..599bd4b4f9 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -1175,6 +1175,16 @@ void spr_write_hmer(DisasContext *ctx, int sprn, int gprn) spr_store_dump_spr(sprn); } +void spr_read_tfmr(DisasContext *ctx, int gprn, int sprn) +{ + gen_helper_load_tfmr(cpu_gpr[gprn], cpu_env); +} + +void spr_write_tfmr(DisasContext *ctx, int sprn, int gprn) +{ + gen_helper_store_tfmr(cpu_env, cpu_gpr[gprn]); +} + void spr_write_lpcr(DisasContext *ctx, int sprn, int gprn) { gen_helper_store_lpcr(cpu_env, cpu_gpr[gprn]); From bc65beb3a412b3d6d7e16d9f11a9712a086aae02 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Mon, 26 Jun 2023 06:16:28 +1000 Subject: [PATCH 08/59] sungem: Add WOL MMIO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apple sungem devices are expected to have WOL MMIO registers. Add a region to prevent transaction failures, and implement the WOL-disable CSR write because the Linux driver reset writes this. Signed-off-by: Nicholas Piggin Reviewed-by: Cédric Le Goater Reviewed-by: Joel Stanley Message-ID: <20230625201628.65231-1-npiggin@gmail.com> Signed-off-by: Daniel Henrique Barboza --- hw/net/sungem.c | 52 +++++++++++++++++++++++++++++++++++++++++++++ hw/net/trace-events | 2 ++ 2 files changed, 54 insertions(+) diff --git a/hw/net/sungem.c b/hw/net/sungem.c index eb01520790..e0e8e5ae41 100644 --- a/hw/net/sungem.c +++ b/hw/net/sungem.c @@ -107,6 +107,15 @@ OBJECT_DECLARE_SIMPLE_TYPE(SunGEMState, SUNGEM) #define RXDMA_FTAG 0x0110UL /* RX FIFO Tag */ #define RXDMA_FSZ 0x0120UL /* RX FIFO Size */ +/* WOL Registers */ +#define SUNGEM_MMIO_WOL_SIZE 0x14 + +#define WOL_MATCH0 0x0000UL +#define WOL_MATCH1 0x0004UL +#define WOL_MATCH2 0x0008UL +#define WOL_MCOUNT 0x000CUL +#define WOL_WAKECSR 0x0010UL + /* MAC Registers */ #define SUNGEM_MMIO_MAC_SIZE 0x200 @@ -168,6 +177,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(SunGEMState, SUNGEM) #define SUNGEM_MMIO_PCS_SIZE 0x60 #define PCS_MIISTAT 0x0004UL /* PCS MII Status Register */ #define PCS_ISTAT 0x0018UL /* PCS Interrupt Status Reg */ + #define PCS_SSTATE 0x005CUL /* Serialink State Register */ /* Descriptors */ @@ -200,6 +210,7 @@ struct SunGEMState { MemoryRegion greg; MemoryRegion txdma; MemoryRegion rxdma; + MemoryRegion wol; MemoryRegion mac; MemoryRegion mif; MemoryRegion pcs; @@ -1076,6 +1087,43 @@ static const MemoryRegionOps sungem_mmio_rxdma_ops = { }, }; +static void sungem_mmio_wol_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) +{ + trace_sungem_mmio_wol_write(addr, val); + + switch (addr) { + case WOL_WAKECSR: + if (val != 0) { + qemu_log_mask(LOG_UNIMP, "sungem: WOL not supported\n"); + } + break; + default: + qemu_log_mask(LOG_UNIMP, "sungem: WOL not supported\n"); + } +} + +static uint64_t sungem_mmio_wol_read(void *opaque, hwaddr addr, unsigned size) +{ + uint32_t val = -1; + + qemu_log_mask(LOG_UNIMP, "sungem: WOL not supported\n"); + + trace_sungem_mmio_wol_read(addr, val); + + return val; +} + +static const MemoryRegionOps sungem_mmio_wol_ops = { + .read = sungem_mmio_wol_read, + .write = sungem_mmio_wol_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + static void sungem_mmio_mac_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { @@ -1344,6 +1392,10 @@ static void sungem_realize(PCIDevice *pci_dev, Error **errp) "sungem.rxdma", SUNGEM_MMIO_RXDMA_SIZE); memory_region_add_subregion(&s->sungem, 0x4000, &s->rxdma); + memory_region_init_io(&s->wol, OBJECT(s), &sungem_mmio_wol_ops, s, + "sungem.wol", SUNGEM_MMIO_WOL_SIZE); + memory_region_add_subregion(&s->sungem, 0x3000, &s->wol); + memory_region_init_io(&s->mac, OBJECT(s), &sungem_mmio_mac_ops, s, "sungem.mac", SUNGEM_MMIO_MAC_SIZE); memory_region_add_subregion(&s->sungem, 0x6000, &s->mac); diff --git a/hw/net/trace-events b/hw/net/trace-events index e4a98b2c7d..930e5b4293 100644 --- a/hw/net/trace-events +++ b/hw/net/trace-events @@ -350,6 +350,8 @@ sungem_mmio_txdma_write(uint64_t addr, uint64_t val) "MMIO txdma write to 0x%"PR sungem_mmio_txdma_read(uint64_t addr, uint64_t val) "MMIO txdma read from 0x%"PRIx64" val=0x%"PRIx64 sungem_mmio_rxdma_write(uint64_t addr, uint64_t val) "MMIO rxdma write to 0x%"PRIx64" val=0x%"PRIx64 sungem_mmio_rxdma_read(uint64_t addr, uint64_t val) "MMIO rxdma read from 0x%"PRIx64" val=0x%"PRIx64 +sungem_mmio_wol_write(uint64_t addr, uint64_t val) "MMIO wol write to 0x%"PRIx64" val=0x%"PRIx64 +sungem_mmio_wol_read(uint64_t addr, uint64_t val) "MMIO wol read from 0x%"PRIx64" val=0x%"PRIx64 sungem_mmio_mac_write(uint64_t addr, uint64_t val) "MMIO mac write to 0x%"PRIx64" val=0x%"PRIx64 sungem_mmio_mac_read(uint64_t addr, uint64_t val) "MMIO mac read from 0x%"PRIx64" val=0x%"PRIx64 sungem_mmio_mif_write(uint64_t addr, uint64_t val) "MMIO mif write to 0x%"PRIx64" val=0x%"PRIx64 From c32654af150191e376d2d89dba4afbb31c8e9958 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Sun, 25 Jun 2023 20:36:59 +1000 Subject: [PATCH 09/59] target/ppc: Fix icount access for some hypervisor instructions Several instructions and register access require icount reads and are missing translator_io_start(). Signed-off-by: Nicholas Piggin Acked-by: Richard Henderson Message-ID: <20230625103700.8992-1-npiggin@gmail.com> Signed-off-by: Daniel Henrique Barboza --- target/ppc/translate.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 599bd4b4f9..4766240927 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -1187,6 +1187,7 @@ void spr_write_tfmr(DisasContext *ctx, int sprn, int gprn) void spr_write_lpcr(DisasContext *ctx, int sprn, int gprn) { + translator_io_start(&ctx->base); gen_helper_store_lpcr(cpu_env, cpu_gpr[gprn]); } #endif /* !defined(CONFIG_USER_ONLY) */ @@ -4012,6 +4013,7 @@ static void gen_doze(DisasContext *ctx) TCGv_i32 t; CHK_HV(ctx); + translator_io_start(&ctx->base); t = tcg_constant_i32(PPC_PM_DOZE); gen_helper_pminsn(cpu_env, t); /* Stop translation, as the CPU is supposed to sleep from now */ @@ -4027,6 +4029,7 @@ static void gen_nap(DisasContext *ctx) TCGv_i32 t; CHK_HV(ctx); + translator_io_start(&ctx->base); t = tcg_constant_i32(PPC_PM_NAP); gen_helper_pminsn(cpu_env, t); /* Stop translation, as the CPU is supposed to sleep from now */ @@ -4042,6 +4045,7 @@ static void gen_stop(DisasContext *ctx) TCGv_i32 t; CHK_HV(ctx); + translator_io_start(&ctx->base); t = tcg_constant_i32(PPC_PM_STOP); gen_helper_pminsn(cpu_env, t); /* Stop translation, as the CPU is supposed to sleep from now */ @@ -4057,6 +4061,7 @@ static void gen_sleep(DisasContext *ctx) TCGv_i32 t; CHK_HV(ctx); + translator_io_start(&ctx->base); t = tcg_constant_i32(PPC_PM_SLEEP); gen_helper_pminsn(cpu_env, t); /* Stop translation, as the CPU is supposed to sleep from now */ @@ -4072,6 +4077,7 @@ static void gen_rvwinkle(DisasContext *ctx) TCGv_i32 t; CHK_HV(ctx); + translator_io_start(&ctx->base); t = tcg_constant_i32(PPC_PM_RVWINKLE); gen_helper_pminsn(cpu_env, t); /* Stop translation, as the CPU is supposed to sleep from now */ @@ -4468,6 +4474,7 @@ static void gen_hrfid(DisasContext *ctx) #else /* Restore CPU state */ CHK_HV(ctx); + translator_io_start(&ctx->base); gen_helper_hrfid(cpu_env); ctx->base.is_jmp = DISAS_EXIT; #endif From d2b4e29768d783a85a3756bf349ca33f63688ba1 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Sun, 25 Jun 2023 20:37:00 +1000 Subject: [PATCH 10/59] tests/avocado: record_replay test for ppc powernv machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The powernv machine can boot Linux to VFS mount with icount enabled. Add a test case for it. Signed-off-by: Nicholas Piggin Reviewed-by: Cédric Le Goater Message-ID: <20230625103700.8992-2-npiggin@gmail.com> Signed-off-by: Daniel Henrique Barboza --- tests/avocado/replay_kernel.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/avocado/replay_kernel.py b/tests/avocado/replay_kernel.py index fe1e901f4b..79c607b0e7 100644 --- a/tests/avocado/replay_kernel.py +++ b/tests/avocado/replay_kernel.py @@ -259,6 +259,23 @@ class ReplayKernelNormal(ReplayKernelBase): console_pattern = 'Kernel command line: %s' % kernel_command_line self.run_rr(kernel_path, kernel_command_line, console_pattern) + def test_ppc64_powernv(self): + """ + :avocado: tags=arch:ppc64 + :avocado: tags=machine:powernv + :avocado: tags=accel:tcg + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive' + '/fedora-secondary/releases/29/Everything/ppc64le/os' + '/ppc/ppc64/vmlinuz') + kernel_hash = '3fe04abfc852b66653b8c3c897a59a689270bc77' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + \ + 'console=tty0 console=hvc0' + console_pattern = 'VFS: Cannot open root device' + self.run_rr(kernel_path, kernel_command_line, console_pattern) + def test_m68k_q800(self): """ :avocado: tags=arch:m68k From d73a17515035a006eb09272b8d554833e11140bb Mon Sep 17 00:00:00 2001 From: Frederic Barrat Date: Mon, 26 Jun 2023 11:40:57 +0200 Subject: [PATCH 11/59] pnv/xive2: Allow indirect TIMA accesses of all sizes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Booting linux on the powernv10 machine logs a few errors like: Invalid read at addr 0x38, size 1, region 'xive-ic-tm-indirect', reason: invalid size (min:8 max:8) Invalid write at addr 0x38, size 1, region 'xive-ic-tm-indirect', reason: invalid size (min:8 max:8) Invalid read at addr 0x38, size 1, region 'xive-ic-tm-indirect', reason: invalid size (min:8 max:8) Those errors happen when linux is resetting XIVE. We're trying to read/write the enablement bit for the hardware context and qemu doesn't allow indirect TIMA accesses of less than 8 bytes. Direct TIMA access can go through though, as well as indirect TIMA accesses on P9. So even though there are some restrictions regarding the address/size combinations for TIMA access, the example above is perfectly valid. This patch lets indirect TIMA accesses of all sizes go through. The special operations will be intercepted and the default "raw" handlers will pick up all other requests and complain about invalid sizes as appropriate. Tested-by: Nicholas Piggin Signed-off-by: Frederic Barrat Reviewed-by: Cédric Le Goater Message-ID: <20230626094057.1192473-1-fbarrat@linux.ibm.com> Signed-off-by: Daniel Henrique Barboza --- hw/intc/pnv_xive2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c index ed438a20ed..e8ab176de6 100644 --- a/hw/intc/pnv_xive2.c +++ b/hw/intc/pnv_xive2.c @@ -1644,11 +1644,11 @@ static const MemoryRegionOps pnv_xive2_ic_tm_indirect_ops = { .write = pnv_xive2_ic_tm_indirect_write, .endianness = DEVICE_BIG_ENDIAN, .valid = { - .min_access_size = 8, + .min_access_size = 1, .max_access_size = 8, }, .impl = { - .min_access_size = 8, + .min_access_size = 1, .max_access_size = 8, }, }; From 2306c60633f8f2811e5f42666b8155a8d2065154 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Fri, 16 Jun 2023 01:03:10 +0200 Subject: [PATCH 12/59] target/ppc: Remove some superfluous parentheses Signed-off-by: BALATON Zoltan Acked-by: Nicholas Piggin Message-ID: <8384ed0f7335093012bbd3d28fb2a543a2e7346c.1686868895.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- target/ppc/excp_helper.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 2158390e27..f51a8db075 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -1030,7 +1030,7 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) { int lev = env->error_code; - if ((lev == 1) && cpu->vhyp) { + if (lev == 1 && cpu->vhyp) { dump_hcall(env); } else { dump_syscall(env); @@ -1048,7 +1048,7 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) * uses VOF and the 74xx CPUs, so although the 74xx don't have * HV mode, we need to keep hypercall support. */ - if ((lev == 1) && cpu->vhyp) { + if (lev == 1 && cpu->vhyp) { PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); vhc->hypercall(cpu->vhyp, cpu); @@ -1572,7 +1572,7 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) case POWERPC_EXCP_SYSCALL: /* System call exception */ lev = env->error_code; - if ((lev == 1) && cpu->vhyp) { + if (lev == 1 && cpu->vhyp) { dump_hcall(env); } else { dump_syscall(env); @@ -1585,7 +1585,7 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) env->nip += 4; /* "PAPR mode" built-in hypercall emulation */ - if ((lev == 1) && books_vhyp_handles_hcall(cpu)) { + if (lev == 1 && books_vhyp_handles_hcall(cpu)) { PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); vhc->hypercall(cpu->vhyp, cpu); From 3f88a89d10b2391a6cce1d3e1c77bafc586f215d Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Fri, 16 Jun 2023 01:03:11 +0200 Subject: [PATCH 13/59] target/ppc: Remove unneeded parameter from powerpc_reset_wakeup() CPUState is rarely needed by this function (only for logging a fatal error) and it's easy to get from the env parameter so passing it separately is not necessary. Signed-off-by: BALATON Zoltan Acked-by: Nicholas Piggin Message-ID: Signed-off-by: Daniel Henrique Barboza --- target/ppc/excp_helper.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index f51a8db075..3ddec06f65 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -187,8 +187,7 @@ static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp) } #if defined(TARGET_PPC64) -static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, - target_ulong *msr) +static int powerpc_reset_wakeup(CPUPPCState *env, int excp, target_ulong *msr) { /* We no longer are in a PM state */ env->resume_as_sreset = false; @@ -223,8 +222,8 @@ static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, *msr |= SRR1_WAKEHVI; break; default: - cpu_abort(cs, "Unsupported exception %d in Power Save mode\n", - excp); + cpu_abort(env_cpu(env), + "Unsupported exception %d in Power Save mode\n", excp); } return POWERPC_EXCP_RESET; } @@ -1440,7 +1439,7 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) * P7/P8/P9 */ if (env->resume_as_sreset) { - excp = powerpc_reset_wakeup(cs, env, excp, &msr); + excp = powerpc_reset_wakeup(env, excp, &msr); } /* From 819b31b0b43813a32c91bebf8c8dce82a9bff389 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Fri, 16 Jun 2023 01:03:12 +0200 Subject: [PATCH 14/59] target/ppc: Move common check in exception handlers to a function All powerpc exception handlers share some code when handling machine check exceptions. Move this to a common function. Signed-off-by: BALATON Zoltan Reviewed-by: Nicholas Piggin Message-ID: <9cfffaa35aa894086dd092af6b0b26f2d62ff3de.1686868895.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- target/ppc/excp_helper.c | 114 +++++++++------------------------------ 1 file changed, 25 insertions(+), 89 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 3ddec06f65..d1d3d089a6 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -424,6 +424,25 @@ static void powerpc_set_excp_state(PowerPCCPU *cpu, target_ulong vector, env->reserve_addr = -1; } +static void powerpc_mcheck_checkstop(CPUPPCState *env) +{ + CPUState *cs = env_cpu(env); + + if (FIELD_EX64(env->msr, MSR, ME)) { + return; + } + + /* Machine check exception is not enabled. Enter checkstop state. */ + fprintf(stderr, "Machine check while not allowed. " + "Entering checkstop state\n"); + if (qemu_log_separate()) { + qemu_log("Machine check while not allowed. " + "Entering checkstop state\n"); + } + cs->halted = 1; + cpu_interrupt_exittb(cs); +} + static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) { CPUState *cs = CPU(cpu); @@ -466,21 +485,7 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) srr1 = SPR_40x_SRR3; break; case POWERPC_EXCP_MCHECK: /* Machine check exception */ - if (!FIELD_EX64(env->msr, MSR, ME)) { - /* - * Machine check exception is not enabled. Enter - * checkstop state. - */ - fprintf(stderr, "Machine check while not allowed. " - "Entering checkstop state\n"); - if (qemu_log_separate()) { - qemu_log("Machine check while not allowed. " - "Entering checkstop state\n"); - } - cs->halted = 1; - cpu_interrupt_exittb(cs); - } - + powerpc_mcheck_checkstop(env); /* machine check exceptions don't have ME set */ new_msr &= ~((target_ulong)1 << MSR_ME); @@ -597,21 +602,7 @@ static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp) case POWERPC_EXCP_CRITICAL: /* Critical input */ break; case POWERPC_EXCP_MCHECK: /* Machine check exception */ - if (!FIELD_EX64(env->msr, MSR, ME)) { - /* - * Machine check exception is not enabled. Enter - * checkstop state. - */ - fprintf(stderr, "Machine check while not allowed. " - "Entering checkstop state\n"); - if (qemu_log_separate()) { - qemu_log("Machine check while not allowed. " - "Entering checkstop state\n"); - } - cs->halted = 1; - cpu_interrupt_exittb(cs); - } - + powerpc_mcheck_checkstop(env); /* machine check exceptions don't have ME set */ new_msr &= ~((target_ulong)1 << MSR_ME); @@ -770,21 +761,7 @@ static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp) switch (excp) { case POWERPC_EXCP_MCHECK: /* Machine check exception */ - if (!FIELD_EX64(env->msr, MSR, ME)) { - /* - * Machine check exception is not enabled. Enter - * checkstop state. - */ - fprintf(stderr, "Machine check while not allowed. " - "Entering checkstop state\n"); - if (qemu_log_separate()) { - qemu_log("Machine check while not allowed. " - "Entering checkstop state\n"); - } - cs->halted = 1; - cpu_interrupt_exittb(cs); - } - + powerpc_mcheck_checkstop(env); /* machine check exceptions don't have ME set */ new_msr &= ~((target_ulong)1 << MSR_ME); @@ -955,21 +932,7 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) switch (excp) { case POWERPC_EXCP_MCHECK: /* Machine check exception */ - if (!FIELD_EX64(env->msr, MSR, ME)) { - /* - * Machine check exception is not enabled. Enter - * checkstop state. - */ - fprintf(stderr, "Machine check while not allowed. " - "Entering checkstop state\n"); - if (qemu_log_separate()) { - qemu_log("Machine check while not allowed. " - "Entering checkstop state\n"); - } - cs->halted = 1; - cpu_interrupt_exittb(cs); - } - + powerpc_mcheck_checkstop(env); /* machine check exceptions don't have ME set */ new_msr &= ~((target_ulong)1 << MSR_ME); @@ -1150,21 +1113,7 @@ static void powerpc_excp_booke(PowerPCCPU *cpu, int excp) srr1 = SPR_BOOKE_CSRR1; break; case POWERPC_EXCP_MCHECK: /* Machine check exception */ - if (!FIELD_EX64(env->msr, MSR, ME)) { - /* - * Machine check exception is not enabled. Enter - * checkstop state. - */ - fprintf(stderr, "Machine check while not allowed. " - "Entering checkstop state\n"); - if (qemu_log_separate()) { - qemu_log("Machine check while not allowed. " - "Entering checkstop state\n"); - } - cs->halted = 1; - cpu_interrupt_exittb(cs); - } - + powerpc_mcheck_checkstop(env); /* machine check exceptions don't have ME set */ new_msr &= ~((target_ulong)1 << MSR_ME); @@ -1467,20 +1416,7 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) switch (excp) { case POWERPC_EXCP_MCHECK: /* Machine check exception */ - if (!FIELD_EX64(env->msr, MSR, ME)) { - /* - * Machine check exception is not enabled. Enter - * checkstop state. - */ - fprintf(stderr, "Machine check while not allowed. " - "Entering checkstop state\n"); - if (qemu_log_separate()) { - qemu_log("Machine check while not allowed. " - "Entering checkstop state\n"); - } - cs->halted = 1; - cpu_interrupt_exittb(cs); - } + powerpc_mcheck_checkstop(env); if (env->msr_mask & MSR_HVB) { /* * ISA specifies HV, but can be delivered to guest with HV From 0661329a356c17bb1fabef99a45b21b52a43fb08 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Fri, 16 Jun 2023 01:03:14 +0200 Subject: [PATCH 15/59] target/ppc: Remove some more local CPUState variables only used once Some helpers only have a CPUState local to call cpu_interrupt_exittb() but we can use env_cpu for that and remove the local. Signed-off-by: BALATON Zoltan Acked-by: Nicholas Piggin Message-ID: Signed-off-by: Daniel Henrique Barboza --- target/ppc/excp_helper.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index d1d3d089a6..b2cff4e7eb 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -2653,8 +2653,7 @@ void helper_store_msr(CPUPPCState *env, target_ulong val) uint32_t excp = hreg_store_msr(env, val, 0); if (excp != 0) { - CPUState *cs = env_cpu(env); - cpu_interrupt_exittb(cs); + cpu_interrupt_exittb(env_cpu(env)); raise_exception(env, excp); } } @@ -2691,8 +2690,6 @@ void helper_pminsn(CPUPPCState *env, uint32_t insn) static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr) { - CPUState *cs = env_cpu(env); - /* MSR:POW cannot be set by any form of rfi */ msr &= ~(1ULL << MSR_POW); @@ -2716,7 +2713,7 @@ static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr) * No need to raise an exception here, as rfi is always the last * insn of a TB */ - cpu_interrupt_exittb(cs); + cpu_interrupt_exittb(env_cpu(env)); /* Reset the reservation */ env->reserve_addr = -1; From 08d7cfd04c3e90b0e904918cd785352e50bc17e1 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Fri, 16 Jun 2023 01:03:16 +0200 Subject: [PATCH 16/59] target/ppd: Remove unused define MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 7a3fe174b12d removed usage of POWERPC_SYSCALL_VECTORED, drop the unused define as well. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Nicholas Piggin Message-ID: <50adc24f9d408882128e896d8a81a1a059c41836.1686868895.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- target/ppc/translate.c | 1 - 1 file changed, 1 deletion(-) diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 4766240927..db0ba49bdc 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -4486,7 +4486,6 @@ static void gen_hrfid(DisasContext *ctx) #define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER #else #define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL -#define POWERPC_SYSCALL_VECTORED POWERPC_EXCP_SYSCALL_VECTORED #endif static void gen_sc(DisasContext *ctx) { From 4e6b7db2c3331ccc2cae24443950a501181a9a0c Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Fri, 16 Jun 2023 01:03:21 +0200 Subject: [PATCH 17/59] target/ppc: Get CPUState in one step We can get CPUState from env with env_cpu without going through PowerPCCPU and casting that. Signed-off-by: BALATON Zoltan Acked-by: Nicholas Piggin Message-ID: <28424220f37f51ce97f24cadc7538a9c0d16cb45.1686868895.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- target/ppc/excp_helper.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index b2cff4e7eb..354392668e 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -1770,8 +1770,8 @@ static int p7_interrupt_powersave(CPUPPCState *env) static int p7_next_unmasked_interrupt(CPUPPCState *env) { - PowerPCCPU *cpu = env_archcpu(env); - CPUState *cs = CPU(cpu); + CPUState *cs = env_cpu(env); + /* Ignore MSR[EE] when coming out of some power management states */ bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset; @@ -1860,8 +1860,8 @@ static int p8_interrupt_powersave(CPUPPCState *env) static int p8_next_unmasked_interrupt(CPUPPCState *env) { - PowerPCCPU *cpu = env_archcpu(env); - CPUState *cs = CPU(cpu); + CPUState *cs = env_cpu(env); + /* Ignore MSR[EE] when coming out of some power management states */ bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset; @@ -1981,8 +1981,8 @@ static int p9_interrupt_powersave(CPUPPCState *env) static int p9_next_unmasked_interrupt(CPUPPCState *env) { - PowerPCCPU *cpu = env_archcpu(env); - CPUState *cs = CPU(cpu); + CPUState *cs = env_cpu(env); + /* Ignore MSR[EE] when coming out of some power management states */ bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset; @@ -2675,9 +2675,8 @@ void helper_scv(CPUPPCState *env, uint32_t lev) void helper_pminsn(CPUPPCState *env, uint32_t insn) { - CPUState *cs; + CPUState *cs = env_cpu(env); - cs = env_cpu(env); cs->halted = 1; /* Condition for waking up at 0x100 */ From 93c691a003193a8bc4db54f4e544e19d6b1016fc Mon Sep 17 00:00:00 2001 From: Narayana Murty N Date: Fri, 23 Jun 2023 03:25:06 -0400 Subject: [PATCH 18/59] target: ppc: Use MSR_HVB bit to get the target endianness for memory dump Currently on PPC64 qemu always dumps the guest memory in Big Endian (BE) format even though the guest running in Little Endian (LE) mode. So crash tool fails to load the dump as illustrated below: Log : $ virsh dump DOMAIN --memory-only dump.file Domain 'DOMAIN' dumped to dump.file $ crash vmlinux dump.file crash 8.0.2-1.el9 WARNING: endian mismatch: crash utility: little-endian dump.file: big-endian WARNING: machine type mismatch: crash utility: PPC64 dump.file: (unknown) crash: dump.file: not a supported file format This happens because cpu_get_dump_info() passes cpu->env->has_hv_mode to function ppc_interrupts_little_endian(), the cpu->env->has_hv_mode always set for powerNV even though the guest is not running in hv mode. The hv mode should be taken from msr_mask MSR_HVB bit (cpu->env.msr_mask & MSR_HVB). This patch fixes the issue by passing MSR_HVB value to ppc_interrupts_little_endian() in order to determine the guest endianness. The crash tool also expects guest kernel endianness should match the endianness of the dump. The patch was tested on POWER9 box booted with Linux as host in following cases: Host-Endianess Qemu-Target-Machine Qemu-Generated-Guest Memory-Dump-Format BE powernv(OPAL/PowerNV) LE BE powernv(OPAL/PowerNV) BE LE powernv(OPAL/PowerNV) LE LE powernv(OPAL/PowerNV) BE LE pseries(OPAL/PowerNV/pSeries) KVMHV LE LE pseries TCG LE Fixes: 5609400a4228 ("target/ppc: Set the correct endianness for powernv memory dumps") Signed-off-by: Narayana Murty N Reviewed-by: Nicholas Piggin Reviewed-by: Greg Kurz Reviewed-by: Vaibhav Jain Message-ID: <20230623072506.34713-1-nnmlinux@linux.ibm.com> Signed-off-by: Daniel Henrique Barboza --- target/ppc/arch_dump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/ppc/arch_dump.c b/target/ppc/arch_dump.c index f58e6359d5..a8315659d9 100644 --- a/target/ppc/arch_dump.c +++ b/target/ppc/arch_dump.c @@ -237,7 +237,7 @@ int cpu_get_dump_info(ArchDumpInfo *info, info->d_machine = PPC_ELF_MACHINE; info->d_class = ELFCLASS; - if (ppc_interrupts_little_endian(cpu, cpu->env.has_hv_mode)) { + if (ppc_interrupts_little_endian(cpu, !!(cpu->env.msr_mask & MSR_HVB))) { info->d_endian = ELFDATA2LSB; } else { info->d_endian = ELFDATA2MSB; From 694d3cb2ef2d7355ddaf413614f325f17da9716b Mon Sep 17 00:00:00 2001 From: Frederic Barrat Date: Mon, 3 Jul 2023 10:08:58 +0200 Subject: [PATCH 19/59] pnv/xive2: Fix TIMA offset for indirect access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Direct TIMA operations can be done through 4 pages, each with a different privilege level dictating what fields can be accessed. On the other hand, indirect TIMA accesses on P10 are done through a single page, which is the equivalent of the most privileged page of direct TIMA accesses. The offset in the IC bar of an indirect access specifies what hw thread is targeted (page shift bits) and the offset in the TIMA being accessed (the page offset bits). When the indirect access is calling the underlying direct access functions, it is therefore important to clearly separate the 2, as the direct functions assume any page shift bits define the privilege ring level. For indirect accesses, those bits must be 0. This patch fixes the offset passed to direct TIMA functions. It didn't matter for SMT1, as the 2 least significant bits of the page shift are part of the hw thread ID and always 0, so the direct TIMA functions were accessing the privilege ring 0 page. With SMT4/8, it is no longer true. The fix is specific to P10, as indirect TIMA access on P9 was handled differently. Signed-off-by: Frederic Barrat Reviewed-by: Cédric Le Goater Message-ID: <20230703080858.54060-1-fbarrat@linux.ibm.com> Signed-off-by: Daniel Henrique Barboza --- hw/intc/pnv_xive2.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c index e8ab176de6..82fcd3ea22 100644 --- a/hw/intc/pnv_xive2.c +++ b/hw/intc/pnv_xive2.c @@ -1590,6 +1590,18 @@ static uint32_t pnv_xive2_ic_tm_get_pir(PnvXive2 *xive, hwaddr offset) return xive->chip->chip_id << 8 | offset >> xive->ic_shift; } +static uint32_t pnv_xive2_ic_tm_get_hw_page_offset(PnvXive2 *xive, + hwaddr offset) +{ + /* + * Indirect TIMA accesses are similar to direct accesses for + * privilege ring 0. So remove any traces of the hw thread ID from + * the offset in the IC BAR as it could be interpreted as the ring + * privilege when calling the underlying direct access functions. + */ + return offset & ((1ull << xive->ic_shift) - 1); +} + static XiveTCTX *pnv_xive2_get_indirect_tctx(PnvXive2 *xive, uint32_t pir) { PnvChip *chip = xive->chip; @@ -1612,14 +1624,16 @@ static uint64_t pnv_xive2_ic_tm_indirect_read(void *opaque, hwaddr offset, unsigned size) { PnvXive2 *xive = PNV_XIVE2(opaque); + hwaddr hw_page_offset; uint32_t pir; XiveTCTX *tctx; uint64_t val = -1; pir = pnv_xive2_ic_tm_get_pir(xive, offset); + hw_page_offset = pnv_xive2_ic_tm_get_hw_page_offset(xive, offset); tctx = pnv_xive2_get_indirect_tctx(xive, pir); if (tctx) { - val = xive_tctx_tm_read(NULL, tctx, offset, size); + val = xive_tctx_tm_read(NULL, tctx, hw_page_offset, size); } return val; @@ -1629,13 +1643,15 @@ static void pnv_xive2_ic_tm_indirect_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) { PnvXive2 *xive = PNV_XIVE2(opaque); + hwaddr hw_page_offset; uint32_t pir; XiveTCTX *tctx; pir = pnv_xive2_ic_tm_get_pir(xive, offset); + hw_page_offset = pnv_xive2_ic_tm_get_hw_page_offset(xive, offset); tctx = pnv_xive2_get_indirect_tctx(xive, pir); if (tctx) { - xive_tctx_tm_write(NULL, tctx, offset, val, size); + xive_tctx_tm_write(NULL, tctx, hw_page_offset, val, size); } } From a8da2e1424c2f716222582a4706117d2ca845fe1 Mon Sep 17 00:00:00 2001 From: Frederic Barrat Date: Mon, 3 Jul 2023 10:12:14 +0200 Subject: [PATCH 20/59] pnv/xive: Add property on xive sources to define PQ state on reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PQ state of a xive interrupt is always initialized to Q=1, which means the interrupt is disabled. Since a xive source can be embedded in many objects, this patch adds a property to allow that behavior to be refined if needed. Signed-off-by: Frederic Barrat Reviewed-by: Cédric Le Goater Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20230703081215.55252-2-fbarrat@linux.ibm.com> Signed-off-by: Daniel Henrique Barboza --- hw/intc/xive.c | 8 ++++++-- include/hw/ppc/xive.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 84c079b034..f60c878345 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -1232,8 +1232,7 @@ static void xive_source_reset(void *dev) /* Do not clear the LSI bitmap */ - /* PQs are initialized to 0b01 (Q=1) which corresponds to "ints off" */ - memset(xsrc->status, XIVE_ESB_OFF, xsrc->nr_irqs); + memset(xsrc->status, xsrc->reset_pq, xsrc->nr_irqs); } static void xive_source_realize(DeviceState *dev, Error **errp) @@ -1287,6 +1286,11 @@ static Property xive_source_properties[] = { DEFINE_PROP_UINT64("flags", XiveSource, esb_flags, 0), DEFINE_PROP_UINT32("nr-irqs", XiveSource, nr_irqs, 0), DEFINE_PROP_UINT32("shift", XiveSource, esb_shift, XIVE_ESB_64K_2PAGE), + /* + * By default, PQs are initialized to 0b01 (Q=1) which corresponds + * to "ints off" + */ + DEFINE_PROP_UINT8("reset-pq", XiveSource, reset_pq, XIVE_ESB_OFF), DEFINE_PROP_LINK("xive", XiveSource, xive, TYPE_XIVE_NOTIFIER, XiveNotifier *), DEFINE_PROP_END_OF_LIST(), diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h index 3dfb06e002..9f580a2699 100644 --- a/include/hw/ppc/xive.h +++ b/include/hw/ppc/xive.h @@ -187,6 +187,7 @@ struct XiveSource { /* PQ bits and LSI assertion bit */ uint8_t *status; + uint8_t reset_pq; /* PQ state on reset */ /* ESB memory region */ uint64_t esb_flags; From 4a1e9449e8d55c173f3eddd94ae363c2c2938fda Mon Sep 17 00:00:00 2001 From: Frederic Barrat Date: Mon, 3 Jul 2023 10:12:15 +0200 Subject: [PATCH 21/59] pnv/psi: Initialize the PSIHB interrupts to match hardware MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On the powernv9 and powernv10 machines, the PSIHB interrupts are currently initialized with a PQ state of 0b01, i.e. interrupts are disabled. However real hardware initializes them to 0b00 for the PSIHB. This patch updates it, in case an hypervisor is in the mood of checking it. Signed-off-by: Frederic Barrat Reviewed-by: Cédric Le Goater Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20230703081215.55252-3-fbarrat@linux.ibm.com> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/pnv_psi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c index 46da58dff8..daaa2f0575 100644 --- a/hw/ppc/pnv_psi.c +++ b/hw/ppc/pnv_psi.c @@ -863,6 +863,8 @@ static void pnv_psi_power9_realize(DeviceState *dev, Error **errp) object_property_set_int(OBJECT(xsrc), "nr-irqs", PSIHB9_NUM_IRQS, &error_fatal); object_property_set_link(OBJECT(xsrc), "xive", OBJECT(psi), &error_abort); + object_property_set_int(OBJECT(xsrc), "reset-pq", XIVE_ESB_RESET, + &error_abort); if (!qdev_realize(DEVICE(xsrc), NULL, errp)) { return; } From 19d197f5d1e12717310110389267f16986763e9a Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Tue, 4 Jul 2023 15:12:00 +0930 Subject: [PATCH 22/59] ppc/pnv: quad xscom callbacks are P9 specific MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename the functions to include P9 in the name in preparation for adding P10 versions. Correct the unimp read message while we're changing the function. Reviewed-by: Cédric Le Goater Signed-off-by: Joel Stanley Reviewed-by: Frederic Barrat Message-ID: <20230704054204.168547-2-joel@jms.id.au> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/pnv_core.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 0bc3ad41c8..0f451b3b6e 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -360,8 +360,8 @@ DEFINE_TYPES(pnv_core_infos) #define P9X_EX_NCU_SPEC_BAR 0x11010 -static uint64_t pnv_quad_xscom_read(void *opaque, hwaddr addr, - unsigned int width) +static uint64_t pnv_quad_power9_xscom_read(void *opaque, hwaddr addr, + unsigned int width) { uint32_t offset = addr >> 3; uint64_t val = -1; @@ -372,15 +372,15 @@ static uint64_t pnv_quad_xscom_read(void *opaque, hwaddr addr, val = 0; break; default: - qemu_log_mask(LOG_UNIMP, "%s: writing @0x%08x\n", __func__, + qemu_log_mask(LOG_UNIMP, "%s: reading @0x%08x\n", __func__, offset); } return val; } -static void pnv_quad_xscom_write(void *opaque, hwaddr addr, uint64_t val, - unsigned int width) +static void pnv_quad_power9_xscom_write(void *opaque, hwaddr addr, uint64_t val, + unsigned int width) { uint32_t offset = addr >> 3; @@ -394,9 +394,9 @@ static void pnv_quad_xscom_write(void *opaque, hwaddr addr, uint64_t val, } } -static const MemoryRegionOps pnv_quad_xscom_ops = { - .read = pnv_quad_xscom_read, - .write = pnv_quad_xscom_write, +static const MemoryRegionOps pnv_quad_power9_xscom_ops = { + .read = pnv_quad_power9_xscom_read, + .write = pnv_quad_power9_xscom_write, .valid.min_access_size = 8, .valid.max_access_size = 8, .impl.min_access_size = 8, @@ -410,7 +410,8 @@ static void pnv_quad_realize(DeviceState *dev, Error **errp) char name[32]; snprintf(name, sizeof(name), "xscom-quad.%d", eq->quad_id); - pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev), &pnv_quad_xscom_ops, + pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev), + &pnv_quad_power9_xscom_ops, eq, name, PNV9_XSCOM_EQ_SIZE); } From fdc2b46abaa81415a8e6d8439bdd0c3d1b930373 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Tue, 4 Jul 2023 15:12:01 +0930 Subject: [PATCH 23/59] ppc/pnv: Subclass quad xscom callbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the existing pnv_quad_xscom_read/write be P9 specific, in preparation for a different P10 callback. Reviewed-by: Cédric Le Goater Signed-off-by: Joel Stanley Reviewed-by: Frederic Barrat Message-ID: <20230704054204.168547-3-joel@jms.id.au> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/pnv.c | 11 +++++++---- hw/ppc/pnv_core.c | 40 ++++++++++++++++++++++++++------------- include/hw/ppc/pnv_core.h | 13 ++++++++++++- 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index fc083173f3..c77fdb6747 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1429,14 +1429,15 @@ static void pnv_chip_power9_instance_init(Object *obj) } static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq, - PnvCore *pnv_core) + PnvCore *pnv_core, + const char *type) { char eq_name[32]; int core_id = CPU_CORE(pnv_core)->core_id; snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); object_initialize_child_with_props(OBJECT(chip), eq_name, eq, - sizeof(*eq), TYPE_PNV_QUAD, + sizeof(*eq), type, &error_fatal, NULL); object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal); @@ -1454,7 +1455,8 @@ static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) for (i = 0; i < chip9->nr_quads; i++) { PnvQuad *eq = &chip9->quads[i]; - pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]); + pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4], + PNV_QUAD_TYPE_NAME("power9")); pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id), &eq->xscom_regs); @@ -1666,7 +1668,8 @@ static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp) for (i = 0; i < chip10->nr_quads; i++) { PnvQuad *eq = &chip10->quads[i]; - pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]); + pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4], + PNV_QUAD_TYPE_NAME("power9")); pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id), &eq->xscom_regs); diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 0f451b3b6e..73d25409c9 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -407,12 +407,14 @@ static const MemoryRegionOps pnv_quad_power9_xscom_ops = { static void pnv_quad_realize(DeviceState *dev, Error **errp) { PnvQuad *eq = PNV_QUAD(dev); + PnvQuadClass *pqc = PNV_QUAD_GET_CLASS(eq); char name[32]; snprintf(name, sizeof(name), "xscom-quad.%d", eq->quad_id); pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev), - &pnv_quad_power9_xscom_ops, - eq, name, PNV9_XSCOM_EQ_SIZE); + pqc->xscom_ops, + eq, name, + pqc->xscom_size); } static Property pnv_quad_properties[] = { @@ -420,6 +422,14 @@ static Property pnv_quad_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +static void pnv_quad_power9_class_init(ObjectClass *oc, void *data) +{ + PnvQuadClass *pqc = PNV_QUAD_CLASS(oc); + + pqc->xscom_ops = &pnv_quad_power9_xscom_ops; + pqc->xscom_size = PNV9_XSCOM_EQ_SIZE; +} + static void pnv_quad_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); @@ -429,16 +439,20 @@ static void pnv_quad_class_init(ObjectClass *oc, void *data) dc->user_creatable = false; } -static const TypeInfo pnv_quad_info = { - .name = TYPE_PNV_QUAD, - .parent = TYPE_DEVICE, - .instance_size = sizeof(PnvQuad), - .class_init = pnv_quad_class_init, +static const TypeInfo pnv_quad_infos[] = { + { + .name = TYPE_PNV_QUAD, + .parent = TYPE_DEVICE, + .instance_size = sizeof(PnvQuad), + .class_size = sizeof(PnvQuadClass), + .class_init = pnv_quad_class_init, + .abstract = true, + }, + { + .parent = TYPE_PNV_QUAD, + .name = PNV_QUAD_TYPE_NAME("power9"), + .class_init = pnv_quad_power9_class_init, + }, }; -static void pnv_core_register_types(void) -{ - type_register_static(&pnv_quad_info); -} - -type_init(pnv_core_register_types) +DEFINE_TYPES(pnv_quad_infos); diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h index 3d75706e95..77ef00f47a 100644 --- a/include/hw/ppc/pnv_core.h +++ b/include/hw/ppc/pnv_core.h @@ -60,8 +60,19 @@ static inline PnvCPUState *pnv_cpu_state(PowerPCCPU *cpu) return (PnvCPUState *)cpu->machine_data; } +struct PnvQuadClass { + DeviceClass parent_class; + + const MemoryRegionOps *xscom_ops; + uint64_t xscom_size; +}; + #define TYPE_PNV_QUAD "powernv-cpu-quad" -OBJECT_DECLARE_SIMPLE_TYPE(PnvQuad, PNV_QUAD) + +#define PNV_QUAD_TYPE_SUFFIX "-" TYPE_PNV_QUAD +#define PNV_QUAD_TYPE_NAME(cpu_model) cpu_model PNV_QUAD_TYPE_SUFFIX + +OBJECT_DECLARE_TYPE(PnvQuad, PnvQuadClass, PNV_QUAD) struct PnvQuad { DeviceState parent_obj; From a1d64b9efc8173e4e90aef5f48e89364c43118a5 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Tue, 4 Jul 2023 15:12:02 +0930 Subject: [PATCH 24/59] ppc/pnv: Add P10 quad xscom model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a PnvQuad class for the P10 powernv machine. No xscoms are implemented yet, but this allows them to be added. The size is reduced to avoid the quad region from overlapping with the core region. address-space: xscom-0 0000000000000000-00000003ffffffff (prio 0, i/o): xscom-0 0000000100000000-00000001000fffff (prio 0, i/o): xscom-quad.0 0000000100108000-0000000100907fff (prio 0, i/o): xscom-core.3 0000000100110000-000000010090ffff (prio 0, i/o): xscom-core.2 0000000100120000-000000010091ffff (prio 0, i/o): xscom-core.1 0000000100140000-000000010093ffff (prio 0, i/o): xscom-core.0 Signed-off-by: Joel Stanley Reviewed-by: Cédric Le Goater Reviewed-by: Frederic Barrat Message-ID: <20230704054204.168547-4-joel@jms.id.au> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/pnv.c | 2 +- hw/ppc/pnv_core.c | 54 ++++++++++++++++++++++++++++++++++++++ include/hw/ppc/pnv_xscom.h | 2 +- 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index c77fdb6747..5f25fe985a 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1669,7 +1669,7 @@ static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp) PnvQuad *eq = &chip10->quads[i]; pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4], - PNV_QUAD_TYPE_NAME("power9")); + PNV_QUAD_TYPE_NAME("power10")); pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id), &eq->xscom_regs); diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 73d25409c9..e4df435b15 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -404,6 +404,47 @@ static const MemoryRegionOps pnv_quad_power9_xscom_ops = { .endianness = DEVICE_BIG_ENDIAN, }; +/* + * POWER10 Quads + */ + +static uint64_t pnv_quad_power10_xscom_read(void *opaque, hwaddr addr, + unsigned int width) +{ + uint32_t offset = addr >> 3; + uint64_t val = -1; + + switch (offset) { + default: + qemu_log_mask(LOG_UNIMP, "%s: reading @0x%08x\n", __func__, + offset); + } + + return val; +} + +static void pnv_quad_power10_xscom_write(void *opaque, hwaddr addr, + uint64_t val, unsigned int width) +{ + uint32_t offset = addr >> 3; + + switch (offset) { + default: + qemu_log_mask(LOG_UNIMP, "%s: writing @0x%08x\n", __func__, + offset); + } +} + +static const MemoryRegionOps pnv_quad_power10_xscom_ops = { + .read = pnv_quad_power10_xscom_read, + .write = pnv_quad_power10_xscom_write, + .valid.min_access_size = 8, + .valid.max_access_size = 8, + .impl.min_access_size = 8, + .impl.max_access_size = 8, + .endianness = DEVICE_BIG_ENDIAN, +}; + static void pnv_quad_realize(DeviceState *dev, Error **errp) { PnvQuad *eq = PNV_QUAD(dev); @@ -430,6 +471,14 @@ static void pnv_quad_power9_class_init(ObjectClass *oc, void *data) pqc->xscom_size = PNV9_XSCOM_EQ_SIZE; } +static void pnv_quad_power10_class_init(ObjectClass *oc, void *data) +{ + PnvQuadClass *pqc = PNV_QUAD_CLASS(oc); + + pqc->xscom_ops = &pnv_quad_power10_xscom_ops; + pqc->xscom_size = PNV10_XSCOM_EQ_SIZE; +} + static void pnv_quad_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); @@ -453,6 +502,11 @@ static const TypeInfo pnv_quad_infos[] = { .name = PNV_QUAD_TYPE_NAME("power9"), .class_init = pnv_quad_power9_class_init, }, + { + .parent = TYPE_PNV_QUAD, + .name = PNV_QUAD_TYPE_NAME("power10"), + .class_init = pnv_quad_power10_class_init, + }, }; DEFINE_TYPES(pnv_quad_infos); diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h index cbe848d27b..f7da9a1dc6 100644 --- a/include/hw/ppc/pnv_xscom.h +++ b/include/hw/ppc/pnv_xscom.h @@ -129,7 +129,7 @@ struct PnvXScomInterfaceClass { #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_EQ_SIZE 0x20000 #define PNV10_XSCOM_EC_BASE(core) \ ((uint64_t) PNV10_XSCOM_EQ_BASE(core) | PNV10_XSCOM_EC(core & 0x3)) From 9a3942179d395d223531530d6ff71df25b00d064 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Tue, 4 Jul 2023 15:12:03 +0930 Subject: [PATCH 25/59] ppc/pnv: Add P10 core xscom model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Like the quad xscoms, add a core model for P10 to allow future differentiation from P9. Signed-off-by: Joel Stanley Reviewed-by: Cédric Le Goater Reviewed-by: Frederic Barrat Message-ID: <20230704054204.168547-5-joel@jms.id.au> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/pnv_core.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index e4df435b15..1eec28c88c 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -167,6 +167,47 @@ static const MemoryRegionOps pnv_core_power9_xscom_ops = { .endianness = DEVICE_BIG_ENDIAN, }; +/* + * POWER10 core controls + */ + +static uint64_t pnv_core_power10_xscom_read(void *opaque, hwaddr addr, + unsigned int width) +{ + uint32_t offset = addr >> 3; + uint64_t val = 0; + + switch (offset) { + default: + qemu_log_mask(LOG_UNIMP, "Warning: reading reg=0x%" HWADDR_PRIx "\n", + addr); + } + + return val; +} + +static void pnv_core_power10_xscom_write(void *opaque, hwaddr addr, + uint64_t val, unsigned int width) +{ + uint32_t offset = addr >> 3; + + switch (offset) { + default: + qemu_log_mask(LOG_UNIMP, "Warning: writing to reg=0x%" HWADDR_PRIx "\n", + addr); + } +} + +static const MemoryRegionOps pnv_core_power10_xscom_ops = { + .read = pnv_core_power10_xscom_read, + .write = pnv_core_power10_xscom_write, + .valid.min_access_size = 8, + .valid.max_access_size = 8, + .impl.min_access_size = 8, + .impl.max_access_size = 8, + .endianness = DEVICE_BIG_ENDIAN, +}; + static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp) { CPUPPCState *env = &cpu->env; @@ -315,8 +356,7 @@ 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; + pcc->xscom_ops = &pnv_core_power10_xscom_ops; } static void pnv_core_class_init(ObjectClass *oc, void *data) From 53658074955efc7b4329999577464bd763ef4cbd Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Tue, 4 Jul 2023 15:12:04 +0930 Subject: [PATCH 26/59] ppc/pnv: Return zero for core thread state xscom MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Firmware now warns if booting in LPAR per core mode (PPC bit 62). So this warning doesn't trigger, report the core thread state is 0. Reviewed-by: Cédric Le Goater Signed-off-by: Joel Stanley Reviewed-by: Frederic Barrat Message-ID: <20230704054204.168547-6-joel@jms.id.au> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/pnv_core.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 1eec28c88c..b7223bb445 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -116,6 +116,8 @@ static const MemoryRegionOps pnv_core_power8_xscom_ops = { #define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP 0xf010d #define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR 0xf010a +#define PNV9_XSCOM_EC_CORE_THREAD_STATE 0x10ab3 + static uint64_t pnv_core_power9_xscom_read(void *opaque, hwaddr addr, unsigned int width) { @@ -134,6 +136,9 @@ static uint64_t pnv_core_power9_xscom_read(void *opaque, hwaddr addr, case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR: val = 0x0; break; + case PNV9_XSCOM_EC_CORE_THREAD_STATE: + val = 0; + break; default: qemu_log_mask(LOG_UNIMP, "Warning: reading reg=0x%" HWADDR_PRIx "\n", addr); @@ -171,6 +176,8 @@ static const MemoryRegionOps pnv_core_power9_xscom_ops = { * POWER10 core controls */ +#define PNV10_XSCOM_EC_CORE_THREAD_STATE 0x412 + static uint64_t pnv_core_power10_xscom_read(void *opaque, hwaddr addr, unsigned int width) { @@ -178,6 +185,9 @@ static uint64_t pnv_core_power10_xscom_read(void *opaque, hwaddr addr, uint64_t val = 0; switch (offset) { + case PNV10_XSCOM_EC_CORE_THREAD_STATE: + val = 0; + break; default: qemu_log_mask(LOG_UNIMP, "Warning: reading reg=0x%" HWADDR_PRIx "\n", addr); From 053075097a053f7f9d8ce01f40ae1b1ad1845fea Mon Sep 17 00:00:00 2001 From: Frederic Barrat Date: Tue, 4 Jul 2023 16:48:48 +0200 Subject: [PATCH 27/59] pnv/xive: Allow mmio operations of any size on the ESB CI pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We currently only allow 64-bit operations on the ESB CI pages. There's no real reason for that limitation, skiboot/linux didn't need more. However the hardware supports any size, so this patch relaxes that restriction. It impacts both the ESB pages for "normal" interrupts as well as the ESB pages for escalation interrupts defined for the ENDs. Signed-off-by: Frederic Barrat Reviewed-by: Cédric Le Goater Message-ID: <20230704144848.164287-1-fbarrat@linux.ibm.com> Signed-off-by: Daniel Henrique Barboza --- hw/intc/xive.c | 8 ++++---- hw/intc/xive2.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/intc/xive.c b/hw/intc/xive.c index f60c878345..c014e961a4 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -1175,11 +1175,11 @@ static const MemoryRegionOps xive_source_esb_ops = { .write = xive_source_esb_write, .endianness = DEVICE_BIG_ENDIAN, .valid = { - .min_access_size = 8, + .min_access_size = 1, .max_access_size = 8, }, .impl = { - .min_access_size = 8, + .min_access_size = 1, .max_access_size = 8, }, }; @@ -2006,11 +2006,11 @@ static const MemoryRegionOps xive_end_source_ops = { .write = xive_end_source_write, .endianness = DEVICE_BIG_ENDIAN, .valid = { - .min_access_size = 8, + .min_access_size = 1, .max_access_size = 8, }, .impl = { - .min_access_size = 8, + .min_access_size = 1, .max_access_size = 8, }, }; diff --git a/hw/intc/xive2.c b/hw/intc/xive2.c index 4d9ff41956..c37ef25d44 100644 --- a/hw/intc/xive2.c +++ b/hw/intc/xive2.c @@ -954,11 +954,11 @@ static const MemoryRegionOps xive2_end_source_ops = { .write = xive2_end_source_write, .endianness = DEVICE_BIG_ENDIAN, .valid = { - .min_access_size = 8, + .min_access_size = 1, .max_access_size = 8, }, .impl = { - .min_access_size = 8, + .min_access_size = 1, .max_access_size = 8, }, }; From ebe0e9bbcbe432cd9fbcfbb4e2e9be86761ee606 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Tue, 4 Jul 2023 20:19:20 +0200 Subject: [PATCH 28/59] ppc/pegasos2: Add support for -initrd command line option This also changes type of sz local variable to ssize_t because it is used to store return value of load_elf() and load_image_targphys() that return ssize_t. Signed-off-by: BALATON Zoltan Reviewed-by: Daniel Henrique Barboza Message-ID: <20230704181920.27B58746335@zero.eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/pegasos2.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c index af5489de26..9c9944188b 100644 --- a/hw/ppc/pegasos2.c +++ b/hw/ppc/pegasos2.c @@ -44,6 +44,8 @@ #define PROM_ADDR 0xfff00000 #define PROM_SIZE 0x80000 +#define INITRD_MIN_ADDR 0x600000 + #define KVMPPC_HCALL_BASE 0xf000 #define KVMPPC_H_RTAS (KVMPPC_HCALL_BASE + 0x0) #define KVMPPC_H_VOF_CLIENT (KVMPPC_HCALL_BASE + 0x5) @@ -80,6 +82,8 @@ struct Pegasos2MachineState { uint64_t kernel_addr; uint64_t kernel_entry; uint64_t kernel_size; + uint64_t initrd_addr; + uint64_t initrd_size; }; static void *build_fdt(MachineState *machine, int *fdt_size); @@ -117,7 +121,8 @@ static void pegasos2_init(MachineState *machine) I2CBus *i2c_bus; const char *fwname = machine->firmware ?: PROM_FILENAME; char *filename; - int i, sz; + int i; + ssize_t sz; uint8_t *spd_data; /* init CPU */ @@ -213,6 +218,20 @@ static void pegasos2_init(MachineState *machine) warn_report("Using Virtual OpenFirmware but no -kernel option."); } + if (machine->initrd_filename) { + pm->initrd_addr = pm->kernel_addr + pm->kernel_size + 64 * KiB; + pm->initrd_addr = ROUND_UP(pm->initrd_addr, 4); + pm->initrd_addr = MAX(pm->initrd_addr, INITRD_MIN_ADDR); + sz = load_image_targphys(machine->initrd_filename, pm->initrd_addr, + machine->ram_size - pm->initrd_addr); + if (sz <= 0) { + error_report("Could not load initrd '%s'", + machine->initrd_filename); + exit(1); + } + pm->initrd_size = sz; + } + if (!pm->vof && machine->kernel_cmdline && machine->kernel_cmdline[0]) { warn_report("Option -append may be ineffective with -bios."); } @@ -335,6 +354,11 @@ static void pegasos2_machine_reset(MachineState *machine, ShutdownCause reason) error_report("Memory for kernel is in use"); exit(1); } + if (pm->initrd_size && + vof_claim(pm->vof, pm->initrd_addr, pm->initrd_size, 0) == -1) { + error_report("Memory for initrd is in use"); + exit(1); + } fdt = build_fdt(machine, &sz); /* FIXME: VOF assumes entry is same as load address */ d[0] = cpu_to_be64(pm->kernel_entry); @@ -966,6 +990,12 @@ static void *build_fdt(MachineState *machine, int *fdt_size) qemu_fdt_setprop_string(fdt, "/memory@0", "name", "memory"); qemu_fdt_add_subnode(fdt, "/chosen"); + if (pm->initrd_addr && pm->initrd_size) { + qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", + pm->initrd_addr + pm->initrd_size); + qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", + pm->initrd_addr); + } qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", machine->kernel_cmdline ?: ""); qemu_fdt_setprop_string(fdt, "/chosen", "name", "chosen"); From ff349cce8923d3c1713a6d58eb98ff692e6637f6 Mon Sep 17 00:00:00 2001 From: Frederic Barrat Date: Wed, 5 Jul 2023 13:00:39 +0200 Subject: [PATCH 29/59] pnv/xive: Print CPU target in all TIMA traces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the CPU target in the trace when reading/writing the TIMA space. It was already done for other TIMA ops (notify, accept, ...), only missing for those 2. Useful for debug and even more now that we experiment with SMT. Signed-off-by: Frederic Barrat Reviewed-by: Cédric Le Goater Message-ID: <20230705110039.231148-1-fbarrat@linux.ibm.com> Signed-off-by: Daniel Henrique Barboza --- hw/intc/trace-events | 4 ++-- hw/intc/xive.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/intc/trace-events b/hw/intc/trace-events index 5c6094c457..36ff71f947 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -265,8 +265,8 @@ xive_source_esb_read(uint64_t addr, uint32_t srcno, uint64_t value) "@0x%"PRIx64 xive_source_esb_write(uint64_t addr, uint32_t srcno, uint64_t value) "@0x%"PRIx64" IRQ 0x%x val=0x%"PRIx64 xive_router_end_notify(uint8_t end_blk, uint32_t end_idx, uint32_t end_data) "END 0x%02x/0x%04x -> enqueue 0x%08x" xive_router_end_escalate(uint8_t end_blk, uint32_t end_idx, uint8_t esc_blk, uint32_t esc_idx, uint32_t end_data) "END 0x%02x/0x%04x -> escalate END 0x%02x/0x%04x data 0x%08x" -xive_tctx_tm_write(uint64_t offset, unsigned int size, uint64_t value) "@0x%"PRIx64" sz=%d val=0x%" PRIx64 -xive_tctx_tm_read(uint64_t offset, unsigned int size, uint64_t value) "@0x%"PRIx64" sz=%d val=0x%" PRIx64 +xive_tctx_tm_write(uint32_t index, uint64_t offset, unsigned int size, uint64_t value) "target=%d @0x%"PRIx64" sz=%d val=0x%" PRIx64 +xive_tctx_tm_read(uint32_t index, uint64_t offset, unsigned int size, uint64_t value) "target=%d @0x%"PRIx64" sz=%d val=0x%" PRIx64 xive_presenter_notify(uint8_t nvt_blk, uint32_t nvt_idx, uint8_t ring) "found NVT 0x%x/0x%x ring=0x%x" xive_end_source_read(uint8_t end_blk, uint32_t end_idx, uint64_t addr) "END 0x%x/0x%x @0x%"PRIx64 diff --git a/hw/intc/xive.c b/hw/intc/xive.c index c014e961a4..56670b2cac 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -566,7 +566,7 @@ void xive_tctx_tm_write(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, { const XiveTmOp *xto; - trace_xive_tctx_tm_write(offset, size, value); + trace_xive_tctx_tm_write(tctx->cs->cpu_index, offset, size, value); /* * TODO: check V bit in Q[0-3]W2 @@ -639,7 +639,7 @@ uint64_t xive_tctx_tm_read(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, */ ret = xive_tm_raw_read(tctx, offset, size); out: - trace_xive_tctx_tm_read(offset, size, ret); + trace_xive_tctx_tm_read(tctx->cs->cpu_index, offset, size, ret); return ret; } From ed75a123579d56b5523f74868bb2c5877dc2c119 Mon Sep 17 00:00:00 2001 From: Frederic Barrat Date: Wed, 5 Jul 2023 10:14:00 +0200 Subject: [PATCH 30/59] pnv/xive2: Always pass a presenter object when accessing the TIMA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The low-level functions to access the TIMA take a presenter object as a first argument. When accessing the TIMA from the IC BAR, i.e. indirect calls, we currently pass a NULL pointer for the presenter argument. While it appears ok with the current usage, it's dangerous. And it's pretty easy to figure out the presenter in that context, so this patch fixes it. Signed-off-by: Frederic Barrat Reviewed-by: Cédric Le Goater Message-ID: <20230705081400.218408-1-fbarrat@linux.ibm.com> Signed-off-by: Daniel Henrique Barboza --- hw/intc/pnv_xive2.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c index 82fcd3ea22..bbb44a533c 100644 --- a/hw/intc/pnv_xive2.c +++ b/hw/intc/pnv_xive2.c @@ -1624,6 +1624,7 @@ static uint64_t pnv_xive2_ic_tm_indirect_read(void *opaque, hwaddr offset, unsigned size) { PnvXive2 *xive = PNV_XIVE2(opaque); + XivePresenter *xptr = XIVE_PRESENTER(xive); hwaddr hw_page_offset; uint32_t pir; XiveTCTX *tctx; @@ -1633,7 +1634,7 @@ static uint64_t pnv_xive2_ic_tm_indirect_read(void *opaque, hwaddr offset, hw_page_offset = pnv_xive2_ic_tm_get_hw_page_offset(xive, offset); tctx = pnv_xive2_get_indirect_tctx(xive, pir); if (tctx) { - val = xive_tctx_tm_read(NULL, tctx, hw_page_offset, size); + val = xive_tctx_tm_read(xptr, tctx, hw_page_offset, size); } return val; @@ -1643,6 +1644,7 @@ static void pnv_xive2_ic_tm_indirect_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) { PnvXive2 *xive = PNV_XIVE2(opaque); + XivePresenter *xptr = XIVE_PRESENTER(xive); hwaddr hw_page_offset; uint32_t pir; XiveTCTX *tctx; @@ -1651,7 +1653,7 @@ static void pnv_xive2_ic_tm_indirect_write(void *opaque, hwaddr offset, hw_page_offset = pnv_xive2_ic_tm_get_hw_page_offset(xive, offset); tctx = pnv_xive2_get_indirect_tctx(xive, pir); if (tctx) { - xive_tctx_tm_write(NULL, tctx, hw_page_offset, val, size); + xive_tctx_tm_write(xptr, tctx, hw_page_offset, val, size); } } From 3401ea3cfe06ab5ab059ae19b662270e1357545e Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Wed, 5 Jul 2023 22:06:28 +1000 Subject: [PATCH 31/59] target/ppc: Add LPAR-per-core vs per-thread mode flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Power ISA has the concept of sub-processors: Hardware is allowed to sub-divide a multi-threaded processor into "sub-processors" that appear to privileged programs as multi-threaded processors with fewer threads. POWER9 and POWER10 have two modes, either every thread is a sub-processor or all threads appear as one multi-threaded processor. In the user manuals these are known as "LPAR per thread" / "Thread LPAR", and "LPAR per core" / "1 LPAR", respectively. The practical difference is: in thread LPAR mode, non-hypervisor SPRs are not shared between threads and msgsndp can not be used to message siblings. In 1 LPAR mode, some SPRs are shared and msgsndp is usable. Thrad LPAR allows multiple partitions to run concurrently on the same core, and is a requirement for KVM to run on POWER9/10 (which does not gang-schedule an LPAR on all threads of a core like POWER8 KVM). Traditionally, SMT in PAPR environments including PowerVM and the pseries QEMU machine with KVM acceleration behaves as in 1 LPAR mode. In OPAL systems, Thread LPAR is used. When adding SMT to the powernv machine, it is therefore preferable to emulate Thread LPAR. To account for this difference between pseries and powernv, an LPAR mode flag is added such that SPRs can be implemented as per-LPAR shared, and that becomes either per-thread or per-core depending on the flag. Reviewed-by: Joel Stanley Reviewed-by: Cédric Le Goater Tested-by: Cédric Le Goater Signed-off-by: Nicholas Piggin Message-ID: <20230705120631.27670-2-npiggin@gmail.com> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/spapr_cpu_core.c | 2 ++ target/ppc/cpu.h | 3 +++ target/ppc/cpu_init.c | 12 ++++++++++++ target/ppc/excp_helper.c | 4 ++++ target/ppc/misc_helper.c | 8 ++++++++ target/ppc/translate.c | 11 ++++++----- 6 files changed, 35 insertions(+), 5 deletions(-) diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index a4e3c2fadd..b482d9754a 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -270,6 +270,8 @@ static bool spapr_realize_vcpu(PowerPCCPU *cpu, SpaprMachineState *spapr, env->spr_cb[SPR_PIR].default_value = cs->cpu_index; env->spr_cb[SPR_TIR].default_value = thread_index; + cpu_ppc_set_1lpar(cpu); + /* Set time-base frequency to 512 MHz. vhyp must be set first. */ cpu_ppc_tb_init(env, SPAPR_TIMEBASE_FREQ); diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index af12c93ebc..b269b0d090 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -674,6 +674,8 @@ enum { POWERPC_FLAG_SCV = 0x00200000, /* Has >1 thread per core */ POWERPC_FLAG_SMT = 0x00400000, + /* Using "LPAR per core" mode (as opposed to per-thread) */ + POWERPC_FLAG_SMT_1LPAR = 0x00800000, }; /* @@ -1437,6 +1439,7 @@ void store_booke_tsr(CPUPPCState *env, target_ulong val); void ppc_tlb_invalidate_all(CPUPPCState *env); void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr); void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp); +void cpu_ppc_set_1lpar(PowerPCCPU *cpu); int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb, hwaddr *raddrp, target_ulong address, uint32_t pid); int ppcemb_tlb_search(CPUPPCState *env, target_ulong address, uint32_t pid); diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 5f4969664e..905a59aea9 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -6629,6 +6629,18 @@ void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp) env->msr_mask &= ~MSR_HVB; } +void cpu_ppc_set_1lpar(PowerPCCPU *cpu) +{ + CPUPPCState *env = &cpu->env; + + /* + * pseries SMT means "LPAR per core" mode, e.g., msgsndp is usable + * between threads. + */ + if (env->flags & POWERPC_FLAG_SMT) { + env->flags |= POWERPC_FLAG_SMT_1LPAR; + } +} #endif /* !defined(CONFIG_USER_ONLY) */ #endif /* defined(TARGET_PPC64) */ diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 354392668e..7683ea0fc9 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -3130,6 +3130,10 @@ void helper_book3s_msgsndp(CPUPPCState *env, target_ulong rb) helper_hfscr_facility_check(env, HFSCR_MSGP, "msgsndp", HFSCR_IC_MSGP); + if (!(env->flags & POWERPC_FLAG_SMT_1LPAR)) { + nr_threads = 1; /* msgsndp behaves as 1-thread in LPAR-per-thread mode*/ + } + if (!dbell_type_server(rb) || ttir >= nr_threads) { return; } diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c index 1f1af21f33..26e546cc9c 100644 --- a/target/ppc/misc_helper.c +++ b/target/ppc/misc_helper.c @@ -191,6 +191,10 @@ target_ulong helper_load_dpdes(CPUPPCState *env) helper_hfscr_facility_check(env, HFSCR_MSGP, "load DPDES", HFSCR_IC_MSGP); + if (!(env->flags & POWERPC_FLAG_SMT_1LPAR)) { + nr_threads = 1; /* DPDES behaves as 1-thread in LPAR-per-thread mode */ + } + if (nr_threads == 1) { if (env->pending_interrupts & PPC_INTERRUPT_DOORBELL) { dpdes = 1; @@ -222,6 +226,10 @@ void helper_store_dpdes(CPUPPCState *env, target_ulong val) helper_hfscr_facility_check(env, HFSCR_MSGP, "store DPDES", HFSCR_IC_MSGP); + if (!(env->flags & POWERPC_FLAG_SMT_1LPAR)) { + nr_threads = 1; /* DPDES behaves as 1-thread in LPAR-per-thread mode */ + } + if (val & ~(nr_threads - 1)) { qemu_log_mask(LOG_GUEST_ERROR, "Invalid DPDES register value " TARGET_FMT_lx"\n", val); diff --git a/target/ppc/translate.c b/target/ppc/translate.c index db0ba49bdc..4556297ab5 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -246,9 +246,9 @@ static inline bool gen_serialize(DisasContext *ctx) } #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) -static inline bool gen_serialize_core(DisasContext *ctx) +static inline bool gen_serialize_core_lpar(DisasContext *ctx) { - if (ctx->flags & POWERPC_FLAG_SMT) { + if (ctx->flags & POWERPC_FLAG_SMT_1LPAR) { return gen_serialize(ctx); } @@ -451,7 +451,8 @@ static void spr_write_CTRL_ST(DisasContext *ctx, int sprn, int gprn) void spr_write_CTRL(DisasContext *ctx, int sprn, int gprn) { - if (!(ctx->flags & POWERPC_FLAG_SMT)) { + if (!(ctx->flags & POWERPC_FLAG_SMT_1LPAR)) { + /* CTRL behaves as 1-thread in LPAR-per-thread mode */ spr_write_CTRL_ST(ctx, sprn, gprn); goto out; } @@ -815,7 +816,7 @@ void spr_write_pcr(DisasContext *ctx, int sprn, int gprn) /* DPDES */ void spr_read_dpdes(DisasContext *ctx, int gprn, int sprn) { - if (!gen_serialize_core(ctx)) { + if (!gen_serialize_core_lpar(ctx)) { return; } @@ -824,7 +825,7 @@ void spr_read_dpdes(DisasContext *ctx, int gprn, int sprn) void spr_write_dpdes(DisasContext *ctx, int sprn, int gprn) { - if (!gen_serialize_core(ctx)) { + if (!gen_serialize_core_lpar(ctx)) { return; } From 9cdfd1b9f7eb5ecd1267bbd68330a11dcb8aa8f2 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Wed, 5 Jul 2023 22:06:29 +1000 Subject: [PATCH 32/59] target/ppc: SMT support for the HID SPR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HID is a per-core shared register, skiboot sets this (e.g., setting HILE) on one thread and that must affect all threads of the core. Reviewed-by: Cédric Le Goater Tested-by: Cédric Le Goater Signed-off-by: Nicholas Piggin Message-ID: <20230705120631.27670-3-npiggin@gmail.com> Signed-off-by: Daniel Henrique Barboza --- target/ppc/cpu_init.c | 2 +- target/ppc/helper.h | 1 + target/ppc/misc_helper.c | 21 +++++++++++++++++++++ target/ppc/spr_common.h | 1 + target/ppc/translate.c | 16 ++++++++++++++++ 5 files changed, 40 insertions(+), 1 deletion(-) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 905a59aea9..720aad9e05 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -5638,7 +5638,7 @@ static void register_power_common_book4_sprs(CPUPPCState *env) spr_register_hv(env, SPR_HID0, "HID0", SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, + &spr_read_generic, &spr_core_write_generic, 0x00000000); spr_register_hv(env, SPR_TSCR, "TSCR", SPR_NOACCESS, SPR_NOACCESS, diff --git a/target/ppc/helper.h b/target/ppc/helper.h index 828f7844c8..abec6fe341 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -704,6 +704,7 @@ DEF_HELPER_3(store_dcr, void, env, tl, tl) DEF_HELPER_2(load_dump_spr, void, env, i32) DEF_HELPER_2(store_dump_spr, void, env, i32) +DEF_HELPER_3(spr_core_write_generic, void, env, i32, tl) DEF_HELPER_3(spr_write_CTRL, void, env, i32, tl) DEF_HELPER_4(fscr_facility_check, void, env, i32, i32, i32) diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c index 26e546cc9c..692d058665 100644 --- a/target/ppc/misc_helper.c +++ b/target/ppc/misc_helper.c @@ -43,6 +43,27 @@ void helper_store_dump_spr(CPUPPCState *env, uint32_t sprn) env->spr[sprn]); } +void helper_spr_core_write_generic(CPUPPCState *env, uint32_t sprn, + target_ulong val) +{ + CPUState *cs = env_cpu(env); + CPUState *ccs; + uint32_t nr_threads = cs->nr_threads; + uint32_t core_id = env->spr[SPR_PIR] & ~(nr_threads - 1); + + assert(core_id == env->spr[SPR_PIR] - env->spr[SPR_TIR]); + + if (nr_threads == 1) { + env->spr[sprn] = val; + return; + } + + THREAD_SIBLING_FOREACH(cs, ccs) { + CPUPPCState *cenv = &POWERPC_CPU(ccs)->env; + cenv->spr[sprn] = val; + } +} + void helper_spr_write_CTRL(CPUPPCState *env, uint32_t sprn, target_ulong val) { diff --git a/target/ppc/spr_common.h b/target/ppc/spr_common.h index fbf52123b5..5995070eaf 100644 --- a/target/ppc/spr_common.h +++ b/target/ppc/spr_common.h @@ -82,6 +82,7 @@ void spr_noaccess(DisasContext *ctx, int gprn, int sprn); void spr_read_generic(DisasContext *ctx, int gprn, int sprn); void spr_write_generic(DisasContext *ctx, int sprn, int gprn); void spr_write_generic32(DisasContext *ctx, int sprn, int gprn); +void spr_core_write_generic(DisasContext *ctx, int sprn, int gprn); void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn); void spr_write_MMCR1(DisasContext *ctx, int sprn, int gprn); void spr_write_PMC(DisasContext *ctx, int sprn, int gprn); diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 4556297ab5..e6a0709066 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -438,6 +438,22 @@ void spr_write_generic32(DisasContext *ctx, int sprn, int gprn) #endif } +void spr_core_write_generic(DisasContext *ctx, int sprn, int gprn) +{ + if (!(ctx->flags & POWERPC_FLAG_SMT)) { + spr_write_generic(ctx, sprn, gprn); + return; + } + + if (!gen_serialize(ctx)) { + return; + } + + gen_helper_spr_core_write_generic(cpu_env, tcg_constant_i32(sprn), + cpu_gpr[gprn]); + spr_store_dump_spr(sprn); +} + static void spr_write_CTRL_ST(DisasContext *ctx, int sprn, int gprn) { /* This does not implement >1 thread */ From 934676c7b726fe9cccac02a7a4fa23c1e6a4c91e Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Wed, 5 Jul 2023 22:06:30 +1000 Subject: [PATCH 33/59] ppc/pnv: SMT support for powernv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set the TIR default value with the SMT thread index, and place some standard limits on SMT configurations. Now powernv is able to boot skiboot and Linux with a SMT topology, including booting a KVM guest. There are several SPRs and other features (e.g., broadcast msgsnd) that are not implemented, but not used by OPAL or Linux and can be added incrementally. Reviewed-by: Cédric Le Goater Tested-by: Cédric Le Goater Signed-off-by: Nicholas Piggin Message-ID: <20230705120631.27670-4-npiggin@gmail.com> Signed-off-by: Daniel Henrique Barboza --- docs/system/ppc/powernv.rst | 5 ----- hw/ppc/pnv.c | 12 ++++++++++++ hw/ppc/pnv_core.c | 13 +++++-------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/docs/system/ppc/powernv.rst b/docs/system/ppc/powernv.rst index c8f9762342..09f3965858 100644 --- a/docs/system/ppc/powernv.rst +++ b/docs/system/ppc/powernv.rst @@ -195,11 +195,6 @@ Use a MTD drive to add a PNOR to the machine, and get a NVRAM : -drive file=./witherspoon.pnor,format=raw,if=mtd -CAVEATS -------- - - * No support for multiple HW threads (SMT=1). Same as pseries. - Maintainer contact information ------------------------------ diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 5f25fe985a..23740f9d07 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -887,6 +887,18 @@ static void pnv_init(MachineState *machine) pnv->num_chips = machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads); + + if (machine->smp.threads > 8) { + error_report("Cannot support more than 8 threads/core " + "on a powernv machine"); + exit(1); + } + if (!is_power_of_2(machine->smp.threads)) { + error_report("Cannot support %d threads/core on a powernv" + "machine because it must be a power of 2", + machine->smp.threads); + exit(1); + } /* * TODO: should we decide on how many chips we can create based * on #cores and Venice vs. Murano vs. Naples chip type etc..., diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index b7223bb445..8a72171ce0 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -218,12 +218,13 @@ static const MemoryRegionOps pnv_core_power10_xscom_ops = { .endianness = DEVICE_BIG_ENDIAN, }; -static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp) +static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp, + int thread_index) { CPUPPCState *env = &cpu->env; int core_pir; - int thread_index = 0; /* TODO: TCG supports only one thread */ ppc_spr_t *pir = &env->spr_cb[SPR_PIR]; + ppc_spr_t *tir = &env->spr_cb[SPR_TIR]; Error *local_err = NULL; PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip); @@ -239,11 +240,7 @@ static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp) core_pir = object_property_get_uint(OBJECT(pc), "pir", &error_abort); - /* - * The PIR of a thread is the core PIR + the thread index. We will - * need to find a way to get the thread index when TCG supports - * more than 1. We could use the object name ? - */ + tir->default_value = thread_index; pir->default_value = core_pir + thread_index; /* Set time-base frequency to 512 MHz */ @@ -292,7 +289,7 @@ static void pnv_core_realize(DeviceState *dev, Error **errp) } for (j = 0; j < cc->nr_threads; j++) { - pnv_core_cpu_realize(pc, pc->threads[j], &local_err); + pnv_core_cpu_realize(pc, pc->threads[j], &local_err, j); if (local_err) { goto err; } From 2bef5b9452b2c6239c1e8512461ae900d5e8ebe6 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Wed, 5 Jul 2023 22:06:31 +1000 Subject: [PATCH 34/59] tests/avocado: Add powernv machine test script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This copies ppc_pseries.py to start a set of powernv tests, including a Linux boot test for the newly added SMT mode. Reviewed-by: Cédric Le Goater Signed-off-by: Nicholas Piggin Message-ID: <20230705120631.27670-5-npiggin@gmail.com> Signed-off-by: Daniel Henrique Barboza --- tests/avocado/ppc_powernv.py | 87 ++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 tests/avocado/ppc_powernv.py diff --git a/tests/avocado/ppc_powernv.py b/tests/avocado/ppc_powernv.py new file mode 100644 index 0000000000..d0e5c07bde --- /dev/null +++ b/tests/avocado/ppc_powernv.py @@ -0,0 +1,87 @@ +# Test that Linux kernel boots on ppc powernv machines and check the console +# +# Copyright (c) 2018, 2020 Red Hat, Inc. +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from avocado.utils import archive +from avocado_qemu import QemuSystemTest +from avocado_qemu import wait_for_console_pattern + +class powernvMachine(QemuSystemTest): + + timeout = 90 + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + panic_message = 'Kernel panic - not syncing' + good_message = 'VFS: Cannot open root device' + + def do_test_linux_boot(self): + self.require_accelerator("tcg") + kernel_url = ('https://archives.fedoraproject.org/pub/archive' + '/fedora-secondary/releases/29/Everything/ppc64le/os' + '/ppc/ppc64/vmlinuz') + kernel_hash = '3fe04abfc852b66653b8c3c897a59a689270bc77' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=hvc0' + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.launch() + + def test_linux_boot(self): + """ + :avocado: tags=arch:ppc64 + :avocado: tags=machine:powernv + :avocado: tags=accel:tcg + """ + + self.do_test_linux_boot() + console_pattern = 'VFS: Cannot open root device' + wait_for_console_pattern(self, console_pattern, self.panic_message) + + def test_linux_smp_boot(self): + """ + :avocado: tags=arch:ppc64 + :avocado: tags=machine:powernv + :avocado: tags=accel:tcg + """ + + self.vm.add_args('-smp', '4') + self.do_test_linux_boot() + console_pattern = 'smp: Brought up 1 node, 4 CPUs' + wait_for_console_pattern(self, console_pattern, self.panic_message) + wait_for_console_pattern(self, self.good_message, self.panic_message) + + def test_linux_smt_boot(self): + """ + :avocado: tags=arch:ppc64 + :avocado: tags=machine:powernv + :avocado: tags=accel:tcg + """ + + self.vm.add_args('-smp', '4,threads=4') + self.do_test_linux_boot() + console_pattern = 'CPU maps initialized for 4 threads per core' + wait_for_console_pattern(self, console_pattern, self.panic_message) + console_pattern = 'smp: Brought up 1 node, 4 CPUs' + wait_for_console_pattern(self, console_pattern, self.panic_message) + wait_for_console_pattern(self, self.good_message, self.panic_message) + + def test_linux_big_boot(self): + """ + :avocado: tags=arch:ppc64 + :avocado: tags=machine:powernv + :avocado: tags=accel:tcg + """ + + self.vm.add_args('-smp', '16,threads=4,cores=2,sockets=2') + + # powernv does not support NUMA + self.do_test_linux_boot() + console_pattern = 'CPU maps initialized for 4 threads per core' + wait_for_console_pattern(self, console_pattern, self.panic_message) + console_pattern = 'smp: Brought up 2 nodes, 16 CPUs' + wait_for_console_pattern(self, console_pattern, self.panic_message) + wait_for_console_pattern(self, self.good_message, self.panic_message) From 339d13ce57a33d1536b0bae15ee633af11e6b116 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 5 Jul 2023 22:12:45 +0200 Subject: [PATCH 35/59] ppc440: Change ppc460ex_pcie_init() parameter type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change parameter of ppc460ex_pcie_init() from env to cpu to allow further refactoring. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-ID: <1695d7cc1a9f1070ab498c078916e2389d6e9469.1688586835.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc440.h | 2 +- hw/ppc/ppc440_uc.c | 7 ++++--- hw/ppc/sam460ex.c | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/hw/ppc/ppc440.h b/hw/ppc/ppc440.h index 7c24db8504..ae42bcf0c8 100644 --- a/hw/ppc/ppc440.h +++ b/hw/ppc/ppc440.h @@ -18,6 +18,6 @@ void ppc4xx_cpr_init(CPUPPCState *env); void ppc4xx_sdr_init(CPUPPCState *env); void ppc4xx_ahb_init(CPUPPCState *env); void ppc4xx_dma_init(CPUPPCState *env, int dcr_base); -void ppc460ex_pcie_init(CPUPPCState *env); +void ppc460ex_pcie_init(PowerPCCPU *cpu); #endif /* PPC440_H */ diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c index 651263926e..8eb985d714 100644 --- a/hw/ppc/ppc440_uc.c +++ b/hw/ppc/ppc440_uc.c @@ -17,6 +17,7 @@ #include "hw/qdev-properties.h" #include "hw/pci/pci.h" #include "sysemu/reset.h" +#include "cpu.h" #include "ppc440.h" /*****************************************************************************/ @@ -1108,17 +1109,17 @@ static void ppc460ex_pcie_register_dcrs(PPC460EXPCIEState *s, CPUPPCState *env) &dcr_read_pcie, &dcr_write_pcie); } -void ppc460ex_pcie_init(CPUPPCState *env) +void ppc460ex_pcie_init(PowerPCCPU *cpu) { DeviceState *dev; dev = qdev_new(TYPE_PPC460EX_PCIE_HOST); qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE0_BASE); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), env); + ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), &cpu->env); dev = qdev_new(TYPE_PPC460EX_PCIE_HOST); qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE1_BASE); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), env); + ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), &cpu->env); } diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index cf065aae0e..aaa8d2f4a5 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -422,7 +422,7 @@ static void sam460ex_init(MachineState *machine) usb_create_simple(usb_bus_find(-1), "usb-mouse"); /* PCI bus */ - ppc460ex_pcie_init(env); + ppc460ex_pcie_init(cpu); /* All PCI irqs are connected to the same UIC pin (cf. UBoot source) */ dev = sysbus_create_simple("ppc440-pcix-host", 0xc0ec00000, qdev_get_gpio_in(uic[1], 0)); From 256f06668a7764a3bab581cd3b548964e3861189 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 5 Jul 2023 22:12:46 +0200 Subject: [PATCH 36/59] ppc440: Add cpu link property to PCIe controller model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PCIe controller model uses PPC DCRs but cannot be modeled with TYPE_PPC4xx_DCR_DEVICE as it derives from TYPE_PCIE_HOST_BRIDGE. Add a cpu link property to it similar to other DCR devices to allow registering DCRs from the device model. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-ID: Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc440_uc.c | 130 ++++++++++++++++++++++++--------------------- 1 file changed, 70 insertions(+), 60 deletions(-) diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c index 8eb985d714..b26c0cee1b 100644 --- a/hw/ppc/ppc440_uc.c +++ b/hw/ppc/ppc440_uc.c @@ -779,6 +779,7 @@ struct PPC460EXPCIEState { MemoryRegion iomem; qemu_irq irq[4]; int32_t dcrn_base; + PowerPCCPU *cpu; uint64_t cfg_base; uint32_t cfg_mask; @@ -1001,66 +1002,10 @@ static void ppc460ex_set_irq(void *opaque, int irq_num, int level) qemu_set_irq(s->irq[irq_num], level); } -static void ppc460ex_pcie_realize(DeviceState *dev, Error **errp) +static void ppc460ex_pcie_register_dcrs(PPC460EXPCIEState *s) { - PPC460EXPCIEState *s = PPC460EX_PCIE_HOST(dev); - PCIHostState *pci = PCI_HOST_BRIDGE(dev); - int i, id; - char buf[16]; + CPUPPCState *env = &s->cpu->env; - switch (s->dcrn_base) { - case DCRN_PCIE0_BASE: - id = 0; - break; - case DCRN_PCIE1_BASE: - id = 1; - break; - default: - error_setg(errp, "invalid PCIe DCRN base"); - return; - } - snprintf(buf, sizeof(buf), "pcie%d-io", id); - memory_region_init(&s->iomem, OBJECT(s), buf, UINT64_MAX); - for (i = 0; i < 4; i++) { - sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]); - } - snprintf(buf, sizeof(buf), "pcie.%d", id); - pci->bus = pci_register_root_bus(DEVICE(s), buf, ppc460ex_set_irq, - pci_swizzle_map_irq_fn, s, &s->iomem, - get_system_io(), 0, 4, TYPE_PCIE_BUS); -} - -static Property ppc460ex_pcie_props[] = { - DEFINE_PROP_INT32("dcrn-base", PPC460EXPCIEState, dcrn_base, -1), - DEFINE_PROP_END_OF_LIST(), -}; - -static void ppc460ex_pcie_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - dc->realize = ppc460ex_pcie_realize; - device_class_set_props(dc, ppc460ex_pcie_props); - dc->hotpluggable = false; -} - -static const TypeInfo ppc460ex_pcie_host_info = { - .name = TYPE_PPC460EX_PCIE_HOST, - .parent = TYPE_PCIE_HOST_BRIDGE, - .instance_size = sizeof(PPC460EXPCIEState), - .class_init = ppc460ex_pcie_class_init, -}; - -static void ppc460ex_pcie_register(void) -{ - type_register_static(&ppc460ex_pcie_host_info); -} - -type_init(ppc460ex_pcie_register) - -static void ppc460ex_pcie_register_dcrs(PPC460EXPCIEState *s, CPUPPCState *env) -{ ppc_dcr_register(env, s->dcrn_base + PEGPL_CFGBAH, s, &dcr_read_pcie, &dcr_write_pcie); ppc_dcr_register(env, s->dcrn_base + PEGPL_CFGBAL, s, @@ -1109,17 +1054,82 @@ static void ppc460ex_pcie_register_dcrs(PPC460EXPCIEState *s, CPUPPCState *env) &dcr_read_pcie, &dcr_write_pcie); } +static void ppc460ex_pcie_realize(DeviceState *dev, Error **errp) +{ + PPC460EXPCIEState *s = PPC460EX_PCIE_HOST(dev); + PCIHostState *pci = PCI_HOST_BRIDGE(dev); + int i, id; + char buf[16]; + + if (!s->cpu) { + error_setg(errp, "cpu link property must be set"); + return; + } + switch (s->dcrn_base) { + case DCRN_PCIE0_BASE: + id = 0; + break; + case DCRN_PCIE1_BASE: + id = 1; + break; + default: + error_setg(errp, "invalid PCIe DCRN base"); + return; + } + snprintf(buf, sizeof(buf), "pcie%d-io", id); + memory_region_init(&s->iomem, OBJECT(s), buf, UINT64_MAX); + for (i = 0; i < 4; i++) { + sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]); + } + snprintf(buf, sizeof(buf), "pcie.%d", id); + pci->bus = pci_register_root_bus(DEVICE(s), buf, ppc460ex_set_irq, + pci_swizzle_map_irq_fn, s, &s->iomem, + get_system_io(), 0, 4, TYPE_PCIE_BUS); + ppc460ex_pcie_register_dcrs(s); +} + +static Property ppc460ex_pcie_props[] = { + DEFINE_PROP_INT32("dcrn-base", PPC460EXPCIEState, dcrn_base, -1), + DEFINE_PROP_LINK("cpu", PPC460EXPCIEState, cpu, TYPE_POWERPC_CPU, + PowerPCCPU *), + DEFINE_PROP_END_OF_LIST(), +}; + +static void ppc460ex_pcie_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->realize = ppc460ex_pcie_realize; + device_class_set_props(dc, ppc460ex_pcie_props); + dc->hotpluggable = false; +} + +static const TypeInfo ppc460ex_pcie_host_info = { + .name = TYPE_PPC460EX_PCIE_HOST, + .parent = TYPE_PCIE_HOST_BRIDGE, + .instance_size = sizeof(PPC460EXPCIEState), + .class_init = ppc460ex_pcie_class_init, +}; + +static void ppc460ex_pcie_register(void) +{ + type_register_static(&ppc460ex_pcie_host_info); +} + +type_init(ppc460ex_pcie_register) + void ppc460ex_pcie_init(PowerPCCPU *cpu) { DeviceState *dev; dev = qdev_new(TYPE_PPC460EX_PCIE_HOST); qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE0_BASE); + object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_abort); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), &cpu->env); dev = qdev_new(TYPE_PPC460EX_PCIE_HOST); qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE1_BASE); + object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_abort); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), &cpu->env); } From ca1ae3432f22c33401a0c8cbf4f7cd4cf13e8e6f Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 5 Jul 2023 22:12:47 +0200 Subject: [PATCH 37/59] ppc440: Add a macro to shorten PCIe controller DCR registration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is shorter and more readable to wrap the complex call to ppc_dcr_register() in a macro than to repeat it several times. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-ID: <4dec5ef8115791dc67253afdff9a703eb816a2a8.1688586835.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc440_uc.c | 76 +++++++++++++++++----------------------------- 1 file changed, 28 insertions(+), 48 deletions(-) diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c index b26c0cee1b..b36dc409d7 100644 --- a/hw/ppc/ppc440_uc.c +++ b/hw/ppc/ppc440_uc.c @@ -1002,56 +1002,36 @@ static void ppc460ex_set_irq(void *opaque, int irq_num, int level) qemu_set_irq(s->irq[irq_num], level); } +#define PPC440_PCIE_DCR(s, dcrn) \ + ppc_dcr_register(&(s)->cpu->env, (s)->dcrn_base + (dcrn), (s), \ + &dcr_read_pcie, &dcr_write_pcie) + + static void ppc460ex_pcie_register_dcrs(PPC460EXPCIEState *s) { - CPUPPCState *env = &s->cpu->env; - - ppc_dcr_register(env, s->dcrn_base + PEGPL_CFGBAH, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_CFGBAL, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_CFGMSK, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_MSGBAH, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_MSGBAL, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_MSGMSK, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1BAH, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1BAL, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1MSKH, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1MSKL, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2BAH, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2BAL, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2MSKH, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2MSKL, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3BAH, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3BAL, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3MSKH, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3MSKL, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_REGBAH, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_REGBAL, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_REGMSK, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_SPECIAL, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_CFG, s, - &dcr_read_pcie, &dcr_write_pcie); + PPC440_PCIE_DCR(s, PEGPL_CFGBAH); + PPC440_PCIE_DCR(s, PEGPL_CFGBAL); + PPC440_PCIE_DCR(s, PEGPL_CFGMSK); + PPC440_PCIE_DCR(s, PEGPL_MSGBAH); + PPC440_PCIE_DCR(s, PEGPL_MSGBAL); + PPC440_PCIE_DCR(s, PEGPL_MSGMSK); + PPC440_PCIE_DCR(s, PEGPL_OMR1BAH); + PPC440_PCIE_DCR(s, PEGPL_OMR1BAL); + PPC440_PCIE_DCR(s, PEGPL_OMR1MSKH); + PPC440_PCIE_DCR(s, PEGPL_OMR1MSKL); + PPC440_PCIE_DCR(s, PEGPL_OMR2BAH); + PPC440_PCIE_DCR(s, PEGPL_OMR2BAL); + PPC440_PCIE_DCR(s, PEGPL_OMR2MSKH); + PPC440_PCIE_DCR(s, PEGPL_OMR2MSKL); + PPC440_PCIE_DCR(s, PEGPL_OMR3BAH); + PPC440_PCIE_DCR(s, PEGPL_OMR3BAL); + PPC440_PCIE_DCR(s, PEGPL_OMR3MSKH); + PPC440_PCIE_DCR(s, PEGPL_OMR3MSKL); + PPC440_PCIE_DCR(s, PEGPL_REGBAH); + PPC440_PCIE_DCR(s, PEGPL_REGBAL); + PPC440_PCIE_DCR(s, PEGPL_REGMSK); + PPC440_PCIE_DCR(s, PEGPL_SPECIAL); + PPC440_PCIE_DCR(s, PEGPL_CFG); } static void ppc460ex_pcie_realize(DeviceState *dev, Error **errp) From 48bb07fbb1d9223448a4c11c6b711db0cf1fdc57 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 5 Jul 2023 22:12:48 +0200 Subject: [PATCH 38/59] ppc440: Rename parent field of PPC460EXPCIEState to match code style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QOM prefers to call the parent field parent_obj, change PPC460EXPCIEState ro match that convention. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-ID: <6995f28215d2a489a661b7d91a1783048829d467.1688586835.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc440_uc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c index b36dc409d7..22c74839ae 100644 --- a/hw/ppc/ppc440_uc.c +++ b/hw/ppc/ppc440_uc.c @@ -774,7 +774,7 @@ void ppc4xx_dma_init(CPUPPCState *env, int dcr_base) OBJECT_DECLARE_SIMPLE_TYPE(PPC460EXPCIEState, PPC460EX_PCIE_HOST) struct PPC460EXPCIEState { - PCIExpressHost host; + PCIExpressHost parent_obj; MemoryRegion iomem; qemu_irq irq[4]; From b5d2ad84a14c1305efd9739d98a6adec0bf42e4d Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 5 Jul 2023 22:12:49 +0200 Subject: [PATCH 39/59] ppc440: Rename local variable in dcr_read_pcie() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename local variable storing state struct in dcr_read_pcie() for brevity and consistency with other functions. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-ID: <7b6f0033ada74075fc094b1397deb406e1a05741.1688586835.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc440_uc.c | 50 +++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c index 22c74839ae..5724db2702 100644 --- a/hw/ppc/ppc440_uc.c +++ b/hw/ppc/ppc440_uc.c @@ -828,78 +828,78 @@ enum { static uint32_t dcr_read_pcie(void *opaque, int dcrn) { - PPC460EXPCIEState *state = opaque; + PPC460EXPCIEState *s = opaque; uint32_t ret = 0; - switch (dcrn - state->dcrn_base) { + switch (dcrn - s->dcrn_base) { case PEGPL_CFGBAH: - ret = state->cfg_base >> 32; + ret = s->cfg_base >> 32; break; case PEGPL_CFGBAL: - ret = state->cfg_base; + ret = s->cfg_base; break; case PEGPL_CFGMSK: - ret = state->cfg_mask; + ret = s->cfg_mask; break; case PEGPL_MSGBAH: - ret = state->msg_base >> 32; + ret = s->msg_base >> 32; break; case PEGPL_MSGBAL: - ret = state->msg_base; + ret = s->msg_base; break; case PEGPL_MSGMSK: - ret = state->msg_mask; + ret = s->msg_mask; break; case PEGPL_OMR1BAH: - ret = state->omr1_base >> 32; + ret = s->omr1_base >> 32; break; case PEGPL_OMR1BAL: - ret = state->omr1_base; + ret = s->omr1_base; break; case PEGPL_OMR1MSKH: - ret = state->omr1_mask >> 32; + ret = s->omr1_mask >> 32; break; case PEGPL_OMR1MSKL: - ret = state->omr1_mask; + ret = s->omr1_mask; break; case PEGPL_OMR2BAH: - ret = state->omr2_base >> 32; + ret = s->omr2_base >> 32; break; case PEGPL_OMR2BAL: - ret = state->omr2_base; + ret = s->omr2_base; break; case PEGPL_OMR2MSKH: - ret = state->omr2_mask >> 32; + ret = s->omr2_mask >> 32; break; case PEGPL_OMR2MSKL: - ret = state->omr3_mask; + ret = s->omr3_mask; break; case PEGPL_OMR3BAH: - ret = state->omr3_base >> 32; + ret = s->omr3_base >> 32; break; case PEGPL_OMR3BAL: - ret = state->omr3_base; + ret = s->omr3_base; break; case PEGPL_OMR3MSKH: - ret = state->omr3_mask >> 32; + ret = s->omr3_mask >> 32; break; case PEGPL_OMR3MSKL: - ret = state->omr3_mask; + ret = s->omr3_mask; break; case PEGPL_REGBAH: - ret = state->reg_base >> 32; + ret = s->reg_base >> 32; break; case PEGPL_REGBAL: - ret = state->reg_base; + ret = s->reg_base; break; case PEGPL_REGMSK: - ret = state->reg_mask; + ret = s->reg_mask; break; case PEGPL_SPECIAL: - ret = state->special; + ret = s->special; break; case PEGPL_CFG: - ret = state->cfg; + ret = s->cfg; break; } From 088b61bc49fab767d73d79d49cb828d866346e6d Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 5 Jul 2023 22:12:51 +0200 Subject: [PATCH 40/59] ppc440: Stop using system io region for PCIe buses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add separate memory regions for the mem and io spaces of the PCIe bus to avoid different buses using the same system io region. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-ID: Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc440_uc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c index 5724db2702..663abf3449 100644 --- a/hw/ppc/ppc440_uc.c +++ b/hw/ppc/ppc440_uc.c @@ -776,6 +776,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(PPC460EXPCIEState, PPC460EX_PCIE_HOST) struct PPC460EXPCIEState { PCIExpressHost parent_obj; + MemoryRegion busmem; MemoryRegion iomem; qemu_irq irq[4]; int32_t dcrn_base; @@ -1056,15 +1057,17 @@ static void ppc460ex_pcie_realize(DeviceState *dev, Error **errp) error_setg(errp, "invalid PCIe DCRN base"); return; } + snprintf(buf, sizeof(buf), "pcie%d-mem", id); + memory_region_init(&s->busmem, OBJECT(s), buf, UINT64_MAX); snprintf(buf, sizeof(buf), "pcie%d-io", id); - memory_region_init(&s->iomem, OBJECT(s), buf, UINT64_MAX); + memory_region_init(&s->iomem, OBJECT(s), buf, 64 * KiB); for (i = 0; i < 4; i++) { sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]); } snprintf(buf, sizeof(buf), "pcie.%d", id); pci->bus = pci_register_root_bus(DEVICE(s), buf, ppc460ex_set_irq, - pci_swizzle_map_irq_fn, s, &s->iomem, - get_system_io(), 0, 4, TYPE_PCIE_BUS); + pci_swizzle_map_irq_fn, s, &s->busmem, + &s->iomem, 0, 4, TYPE_PCIE_BUS); ppc460ex_pcie_register_dcrs(s); } From 6ef62c5945316c265189e301b5fadf9285850221 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 5 Jul 2023 22:12:53 +0200 Subject: [PATCH 41/59] ppc440: Add busnum property to PCIe controller model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of guessing controller number from dcrn_base add a property so the device does not need knowledge about where it is used. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-ID: Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc440_uc.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c index 663abf3449..b74b2212fa 100644 --- a/hw/ppc/ppc440_uc.c +++ b/hw/ppc/ppc440_uc.c @@ -779,6 +779,7 @@ struct PPC460EXPCIEState { MemoryRegion busmem; MemoryRegion iomem; qemu_irq irq[4]; + int32_t num; int32_t dcrn_base; PowerPCCPU *cpu; @@ -1039,32 +1040,25 @@ static void ppc460ex_pcie_realize(DeviceState *dev, Error **errp) { PPC460EXPCIEState *s = PPC460EX_PCIE_HOST(dev); PCIHostState *pci = PCI_HOST_BRIDGE(dev); - int i, id; - char buf[16]; + int i; + char buf[20]; if (!s->cpu) { error_setg(errp, "cpu link property must be set"); return; } - switch (s->dcrn_base) { - case DCRN_PCIE0_BASE: - id = 0; - break; - case DCRN_PCIE1_BASE: - id = 1; - break; - default: - error_setg(errp, "invalid PCIe DCRN base"); + if (s->num < 0 || s->dcrn_base < 0) { + error_setg(errp, "busnum and dcrn-base properties must be set"); return; } - snprintf(buf, sizeof(buf), "pcie%d-mem", id); + snprintf(buf, sizeof(buf), "pcie%d-mem", s->num); memory_region_init(&s->busmem, OBJECT(s), buf, UINT64_MAX); - snprintf(buf, sizeof(buf), "pcie%d-io", id); + snprintf(buf, sizeof(buf), "pcie%d-io", s->num); memory_region_init(&s->iomem, OBJECT(s), buf, 64 * KiB); for (i = 0; i < 4; i++) { sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]); } - snprintf(buf, sizeof(buf), "pcie.%d", id); + snprintf(buf, sizeof(buf), "pcie.%d", s->num); pci->bus = pci_register_root_bus(DEVICE(s), buf, ppc460ex_set_irq, pci_swizzle_map_irq_fn, s, &s->busmem, &s->iomem, 0, 4, TYPE_PCIE_BUS); @@ -1072,6 +1066,7 @@ static void ppc460ex_pcie_realize(DeviceState *dev, Error **errp) } static Property ppc460ex_pcie_props[] = { + DEFINE_PROP_INT32("busnum", PPC460EXPCIEState, num, -1), DEFINE_PROP_INT32("dcrn-base", PPC460EXPCIEState, dcrn_base, -1), DEFINE_PROP_LINK("cpu", PPC460EXPCIEState, cpu, TYPE_POWERPC_CPU, PowerPCCPU *), @@ -1107,11 +1102,13 @@ void ppc460ex_pcie_init(PowerPCCPU *cpu) DeviceState *dev; dev = qdev_new(TYPE_PPC460EX_PCIE_HOST); + qdev_prop_set_int32(dev, "busnum", 0); qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE0_BASE); object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_abort); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); dev = qdev_new(TYPE_PPC460EX_PCIE_HOST); + qdev_prop_set_int32(dev, "busnum", 1); qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE1_BASE); object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_abort); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); From 340dc03c798d07fda7fd7f608dc224caa2909849 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 5 Jul 2023 22:12:54 +0200 Subject: [PATCH 42/59] ppc440: Remove ppc460ex_pcie_init legacy init function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After previous changes we can now remove the legacy init function and move the device creation to board code. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-ID: <29aafeea9f1c871c739600a7b093c5456e8a1dc8.1688586835.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc440.h | 1 - hw/ppc/ppc440_uc.c | 21 --------------------- hw/ppc/sam460ex.c | 17 ++++++++++++++++- include/hw/ppc/ppc4xx.h | 1 + 4 files changed, 17 insertions(+), 23 deletions(-) diff --git a/hw/ppc/ppc440.h b/hw/ppc/ppc440.h index ae42bcf0c8..909373fb38 100644 --- a/hw/ppc/ppc440.h +++ b/hw/ppc/ppc440.h @@ -18,6 +18,5 @@ void ppc4xx_cpr_init(CPUPPCState *env); void ppc4xx_sdr_init(CPUPPCState *env); void ppc4xx_ahb_init(CPUPPCState *env); void ppc4xx_dma_init(CPUPPCState *env, int dcr_base); -void ppc460ex_pcie_init(PowerPCCPU *cpu); #endif /* PPC440_H */ diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c index b74b2212fa..4181c843a8 100644 --- a/hw/ppc/ppc440_uc.c +++ b/hw/ppc/ppc440_uc.c @@ -770,7 +770,6 @@ void ppc4xx_dma_init(CPUPPCState *env, int dcr_base) */ #include "hw/pci/pcie_host.h" -#define TYPE_PPC460EX_PCIE_HOST "ppc460ex-pcie-host" OBJECT_DECLARE_SIMPLE_TYPE(PPC460EXPCIEState, PPC460EX_PCIE_HOST) struct PPC460EXPCIEState { @@ -799,9 +798,6 @@ struct PPC460EXPCIEState { uint32_t cfg; }; -#define DCRN_PCIE0_BASE 0x100 -#define DCRN_PCIE1_BASE 0x120 - enum { PEGPL_CFGBAH = 0x0, PEGPL_CFGBAL, @@ -1096,20 +1092,3 @@ static void ppc460ex_pcie_register(void) } type_init(ppc460ex_pcie_register) - -void ppc460ex_pcie_init(PowerPCCPU *cpu) -{ - DeviceState *dev; - - dev = qdev_new(TYPE_PPC460EX_PCIE_HOST); - qdev_prop_set_int32(dev, "busnum", 0); - qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE0_BASE); - object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_abort); - sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - - dev = qdev_new(TYPE_PPC460EX_PCIE_HOST); - qdev_prop_set_int32(dev, "busnum", 1); - qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE1_BASE); - object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_abort); - sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); -} diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index aaa8d2f4a5..1bb23bb18b 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -45,6 +45,9 @@ /* dd bs=1 skip=$(($(stat -c '%s' updater/updater-460) - 0x80000)) \ if=updater/updater-460 of=u-boot-sam460-20100605.bin */ +#define PCIE0_DCRN_BASE 0x100 +#define PCIE1_DCRN_BASE 0x120 + /* from Sam460 U-Boot include/configs/Sam460ex.h */ #define FLASH_BASE 0xfff00000 #define FLASH_BASE_H 0x4 @@ -421,8 +424,20 @@ static void sam460ex_init(MachineState *machine) usb_create_simple(usb_bus_find(-1), "usb-kbd"); usb_create_simple(usb_bus_find(-1), "usb-mouse"); + /* PCIe buses */ + dev = qdev_new(TYPE_PPC460EX_PCIE_HOST); + qdev_prop_set_int32(dev, "busnum", 0); + qdev_prop_set_int32(dev, "dcrn-base", PCIE0_DCRN_BASE); + object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_abort); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + dev = qdev_new(TYPE_PPC460EX_PCIE_HOST); + qdev_prop_set_int32(dev, "busnum", 1); + qdev_prop_set_int32(dev, "dcrn-base", PCIE1_DCRN_BASE); + object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_abort); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + /* PCI bus */ - ppc460ex_pcie_init(cpu); /* All PCI irqs are connected to the same UIC pin (cf. UBoot source) */ dev = sysbus_create_simple("ppc440-pcix-host", 0xc0ec00000, qdev_get_gpio_in(uic[1], 0)); diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h index f8c86e09ec..39ca602442 100644 --- a/include/hw/ppc/ppc4xx.h +++ b/include/hw/ppc/ppc4xx.h @@ -30,6 +30,7 @@ #include "hw/sysbus.h" #define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost" +#define TYPE_PPC460EX_PCIE_HOST "ppc460ex-pcie-host" /* * Generic DCR device From 41cd3e649be9f8f12aa2028623af916dd81d3403 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 5 Jul 2023 22:12:52 +0200 Subject: [PATCH 43/59] ppc/sam460ex: Remove address_space_mem local variable Some places already use get_system_memory() directly so replace the remaining uses and drop the local variable. Signed-off-by: BALATON Zoltan Reviewed-by: Daniel Henrique Barboza Message-ID: Signed-off-by: Daniel Henrique Barboza --- hw/ppc/sam460ex.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index 1bb23bb18b..d446cfc37b 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -269,7 +269,6 @@ static void main_cpu_reset(void *opaque) static void sam460ex_init(MachineState *machine) { - MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *isa = g_new(MemoryRegion, 1); MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1); DeviceState *uic[4]; @@ -409,7 +408,8 @@ static void sam460ex_init(MachineState *machine) /* FIXME: remove this after fixing l2sram mapping in ppc440_uc.c? */ memory_region_init_ram(l2cache_ram, NULL, "ppc440.l2cache_ram", 256 * KiB, &error_abort); - memory_region_add_subregion(address_space_mem, 0x400000000LL, l2cache_ram); + memory_region_add_subregion(get_system_memory(), 0x400000000LL, + l2cache_ram); /* USB */ sysbus_create_simple(TYPE_PPC4xx_EHCI, 0x4bffd0400, @@ -459,13 +459,13 @@ static void sam460ex_init(MachineState *machine) /* SoC has 4 UARTs * but board has only one wired and two are present in fdt */ if (serial_hd(0) != NULL) { - serial_mm_init(address_space_mem, 0x4ef600300, 0, + serial_mm_init(get_system_memory(), 0x4ef600300, 0, qdev_get_gpio_in(uic[1], 1), PPC_SERIAL_MM_BAUDBASE, serial_hd(0), DEVICE_BIG_ENDIAN); } if (serial_hd(1) != NULL) { - serial_mm_init(address_space_mem, 0x4ef600400, 0, + serial_mm_init(get_system_memory(), 0x4ef600400, 0, qdev_get_gpio_in(uic[0], 1), PPC_SERIAL_MM_BAUDBASE, serial_hd(1), DEVICE_BIG_ENDIAN); From 97784278880b58952400cafcfd1c12fc1c0b5124 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 5 Jul 2023 22:12:58 +0200 Subject: [PATCH 44/59] ppc440_pcix: Don't use iomem for regs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The iomem memory region is better used for the PCI IO space but currently used for registers. Stop using it for that to allow this to be cleaned up in the next patch. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-ID: <3def68f200edd4540393d6b3b03baabe15d649f2.1688586835.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc440_pcix.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/ppc/ppc440_pcix.c b/hw/ppc/ppc440_pcix.c index f10f93c533..899558b055 100644 --- a/hw/ppc/ppc440_pcix.c +++ b/hw/ppc/ppc440_pcix.c @@ -64,6 +64,7 @@ struct PPC440PCIXState { MemoryRegion container; MemoryRegion iomem; MemoryRegion busmem; + MemoryRegion regs; }; #define PPC440_REG_BASE 0x80000 @@ -507,11 +508,11 @@ static void ppc440_pcix_realize(DeviceState *dev, Error **errp) h, "pci-conf-idx", 4); memory_region_init_io(&h->data_mem, OBJECT(s), &pci_host_data_le_ops, h, "pci-conf-data", 4); - memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s, - "pci.reg", PPC440_REG_SIZE); + memory_region_init_io(&s->regs, OBJECT(s), &pci_reg_ops, s, "pci-reg", + PPC440_REG_SIZE); memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem); memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem); - memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->iomem); + memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->regs); sysbus_init_mmio(sbd, &s->container); } From dd0f356dfe363d51b0cc0e1925db902b97338e18 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Thu, 6 Jul 2023 13:16:42 +0200 Subject: [PATCH 45/59] ppc440_pcix: Stop using system io region for PCI bus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce the iomem region to 64K and use it for the PCI io space and map it directly from the board without an intermediate alias that is not really needed. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-ID: Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc440_pcix.c | 9 ++++++--- hw/ppc/sam460ex.c | 6 +----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/hw/ppc/ppc440_pcix.c b/hw/ppc/ppc440_pcix.c index 899558b055..54286cfef4 100644 --- a/hw/ppc/ppc440_pcix.c +++ b/hw/ppc/ppc440_pcix.c @@ -23,6 +23,7 @@ #include "qemu/error-report.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qemu/units.h" #include "hw/irq.h" #include "hw/ppc/ppc.h" #include "hw/ppc/ppc4xx.h" @@ -491,10 +492,11 @@ static void ppc440_pcix_realize(DeviceState *dev, Error **errp) s = PPC440_PCIX_HOST_BRIDGE(dev); sysbus_init_irq(sbd, &s->irq); - memory_region_init(&s->busmem, OBJECT(dev), "pci bus memory", UINT64_MAX); + memory_region_init(&s->busmem, OBJECT(dev), "pci-mem", UINT64_MAX); + memory_region_init(&s->iomem, OBJECT(dev), "pci-io", 64 * KiB); h->bus = pci_register_root_bus(dev, NULL, ppc440_pcix_set_irq, - ppc440_pcix_map_irq, &s->irq, &s->busmem, - get_system_io(), PCI_DEVFN(0, 0), 1, TYPE_PCI_BUS); + ppc440_pcix_map_irq, &s->irq, &s->busmem, &s->iomem, + PCI_DEVFN(0, 0), 1, TYPE_PCI_BUS); s->dev = pci_create_simple(h->bus, PCI_DEVFN(0, 0), "ppc4xx-host-bridge"); @@ -514,6 +516,7 @@ static void ppc440_pcix_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem); memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->regs); sysbus_init_mmio(sbd, &s->container); + sysbus_init_mmio(sbd, &s->iomem); } static void ppc440_pcix_class_init(ObjectClass *klass, void *data) diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index d446cfc37b..7da38bd58e 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -269,7 +269,6 @@ static void main_cpu_reset(void *opaque) static void sam460ex_init(MachineState *machine) { - MemoryRegion *isa = g_new(MemoryRegion, 1); MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1); DeviceState *uic[4]; int i; @@ -441,12 +440,9 @@ static void sam460ex_init(MachineState *machine) /* All PCI irqs are connected to the same UIC pin (cf. UBoot source) */ dev = sysbus_create_simple("ppc440-pcix-host", 0xc0ec00000, qdev_get_gpio_in(uic[1], 0)); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, 0xc08000000); pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci.0")); - memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(), - 0, 0x10000); - memory_region_add_subregion(get_system_memory(), 0xc08000000, isa); - /* PCI devices */ pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "sm501"); /* SoC has a single SATA port but we don't emulate that yet From e75a951b89382c77cc2bf63db5996cafa54adc3d Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Thu, 6 Jul 2023 13:16:43 +0200 Subject: [PATCH 46/59] ppc4xx_pci: Rename QOM type name define Rename the TYPE_PPC4xx_PCI_HOST_BRIDGE define and its string value to match each other and other similar types and to avoid confusion with "ppc4xx-host-bridge" type defined in same file. Signed-off-by: BALATON Zoltan Reviewed-by: Daniel Henrique Barboza Message-ID: Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc440_bamboo.c | 3 +-- hw/ppc/ppc4xx_pci.c | 6 +++--- include/hw/ppc/ppc4xx.h | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c index f061b8cf3b..45f409c838 100644 --- a/hw/ppc/ppc440_bamboo.c +++ b/hw/ppc/ppc440_bamboo.c @@ -205,8 +205,7 @@ static void bamboo_init(MachineState *machine) ppc4xx_sdram_ddr_enable(PPC4xx_SDRAM_DDR(dev)); /* PCI */ - dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST_BRIDGE, - PPC440EP_PCI_CONFIG, + dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST, PPC440EP_PCI_CONFIG, qdev_get_gpio_in(uicdev, pci_irq_nrs[0]), qdev_get_gpio_in(uicdev, pci_irq_nrs[1]), qdev_get_gpio_in(uicdev, pci_irq_nrs[2]), diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c index 1d4a50fa7c..fbdf8266d8 100644 --- a/hw/ppc/ppc4xx_pci.c +++ b/hw/ppc/ppc4xx_pci.c @@ -46,7 +46,7 @@ struct PCITargetMap { uint32_t la; }; -OBJECT_DECLARE_SIMPLE_TYPE(PPC4xxPCIState, PPC4xx_PCI_HOST_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(PPC4xxPCIState, PPC4xx_PCI_HOST) #define PPC4xx_PCI_NR_PMMS 3 #define PPC4xx_PCI_NR_PTMS 2 @@ -321,7 +321,7 @@ static void ppc4xx_pcihost_realize(DeviceState *dev, Error **errp) int i; h = PCI_HOST_BRIDGE(dev); - s = PPC4xx_PCI_HOST_BRIDGE(dev); + s = PPC4xx_PCI_HOST(dev); for (i = 0; i < ARRAY_SIZE(s->irq); i++) { sysbus_init_irq(sbd, &s->irq[i]); @@ -386,7 +386,7 @@ static void ppc4xx_pcihost_class_init(ObjectClass *klass, void *data) } static const TypeInfo ppc4xx_pcihost_info = { - .name = TYPE_PPC4xx_PCI_HOST_BRIDGE, + .name = TYPE_PPC4xx_PCI_HOST, .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(PPC4xxPCIState), .class_init = ppc4xx_pcihost_class_init, diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h index 39ca602442..e053b9751b 100644 --- a/include/hw/ppc/ppc4xx.h +++ b/include/hw/ppc/ppc4xx.h @@ -29,7 +29,7 @@ #include "exec/memory.h" #include "hw/sysbus.h" -#define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost" +#define TYPE_PPC4xx_PCI_HOST "ppc4xx-pci-host" #define TYPE_PPC460EX_PCIE_HOST "ppc460ex-pcie-host" /* From 2460bdff8ed704e1e922d327d15b535594893144 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Thu, 6 Jul 2023 13:16:44 +0200 Subject: [PATCH 47/59] ppc4xx_pci: Add define for ppc4xx-host-bridge type name Add a QOM type name define for ppc4xx-host-bridge in the common header and replace direct use of the string name with the constant. Signed-off-by: BALATON Zoltan Reviewed-by: Daniel Henrique Barboza Message-ID: Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc440_pcix.c | 3 ++- hw/ppc/ppc4xx_pci.c | 4 ++-- include/hw/ppc/ppc4xx.h | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/hw/ppc/ppc440_pcix.c b/hw/ppc/ppc440_pcix.c index 54286cfef4..9321ca0abd 100644 --- a/hw/ppc/ppc440_pcix.c +++ b/hw/ppc/ppc440_pcix.c @@ -498,7 +498,8 @@ static void ppc440_pcix_realize(DeviceState *dev, Error **errp) ppc440_pcix_map_irq, &s->irq, &s->busmem, &s->iomem, PCI_DEVFN(0, 0), 1, TYPE_PCI_BUS); - s->dev = pci_create_simple(h->bus, PCI_DEVFN(0, 0), "ppc4xx-host-bridge"); + s->dev = pci_create_simple(h->bus, PCI_DEVFN(0, 0), + TYPE_PPC4xx_HOST_BRIDGE); memory_region_init(&s->bm, OBJECT(s), "bm-ppc440-pcix", UINT64_MAX); memory_region_add_subregion(&s->bm, 0x0, &s->busmem); diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c index fbdf8266d8..6652119008 100644 --- a/hw/ppc/ppc4xx_pci.c +++ b/hw/ppc/ppc4xx_pci.c @@ -333,7 +333,7 @@ static void ppc4xx_pcihost_realize(DeviceState *dev, Error **errp) TYPE_PCI_BUS); h->bus = b; - pci_create_simple(b, 0, "ppc4xx-host-bridge"); + pci_create_simple(b, 0, TYPE_PPC4xx_HOST_BRIDGE); /* XXX split into 2 memory regions, one for config space, one for regs */ memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE); @@ -367,7 +367,7 @@ static void ppc4xx_host_bridge_class_init(ObjectClass *klass, void *data) } static const TypeInfo ppc4xx_host_bridge_info = { - .name = "ppc4xx-host-bridge", + .name = TYPE_PPC4xx_HOST_BRIDGE, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCIDevice), .class_init = ppc4xx_host_bridge_class_init, diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h index e053b9751b..766d575e86 100644 --- a/include/hw/ppc/ppc4xx.h +++ b/include/hw/ppc/ppc4xx.h @@ -29,6 +29,7 @@ #include "exec/memory.h" #include "hw/sysbus.h" +#define TYPE_PPC4xx_HOST_BRIDGE "ppc4xx-host-bridge" #define TYPE_PPC4xx_PCI_HOST "ppc4xx-pci-host" #define TYPE_PPC460EX_PCIE_HOST "ppc460ex-pcie-host" From 5efa7545205e8e9617afd8dc3cf0180943f975b7 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Thu, 6 Jul 2023 13:16:45 +0200 Subject: [PATCH 48/59] ppc440_pcix: Rename QOM type define abd move it to common header Rename TYPE_PPC440_PCIX_HOST_BRIDGE to better match its string value, move it to common header and use it also in sam460ex to replace hard coded type name. Signed-off-by: BALATON Zoltan Reviewed-by: Daniel Henrique Barboza Message-ID: <1a1c3fe4b120f345d1005ad7ceca4500783691f7.1688641673.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc440_pcix.c | 9 ++++----- hw/ppc/sam460ex.c | 2 +- include/hw/ppc/ppc4xx.h | 1 + 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/ppc/ppc440_pcix.c b/hw/ppc/ppc440_pcix.c index 9321ca0abd..672090de94 100644 --- a/hw/ppc/ppc440_pcix.c +++ b/hw/ppc/ppc440_pcix.c @@ -45,8 +45,7 @@ struct PLBInMap { MemoryRegion mr; }; -#define TYPE_PPC440_PCIX_HOST_BRIDGE "ppc440-pcix-host" -OBJECT_DECLARE_SIMPLE_TYPE(PPC440PCIXState, PPC440_PCIX_HOST_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(PPC440PCIXState, PPC440_PCIX_HOST) #define PPC440_PCIX_NR_POMS 3 #define PPC440_PCIX_NR_PIMS 3 @@ -399,7 +398,7 @@ static const MemoryRegionOps pci_reg_ops = { static void ppc440_pcix_reset(DeviceState *dev) { - struct PPC440PCIXState *s = PPC440_PCIX_HOST_BRIDGE(dev); + struct PPC440PCIXState *s = PPC440_PCIX_HOST(dev); int i; for (i = 0; i < PPC440_PCIX_NR_POMS; i++) { @@ -489,7 +488,7 @@ static void ppc440_pcix_realize(DeviceState *dev, Error **errp) PCIHostState *h; h = PCI_HOST_BRIDGE(dev); - s = PPC440_PCIX_HOST_BRIDGE(dev); + s = PPC440_PCIX_HOST(dev); sysbus_init_irq(sbd, &s->irq); memory_region_init(&s->busmem, OBJECT(dev), "pci-mem", UINT64_MAX); @@ -529,7 +528,7 @@ static void ppc440_pcix_class_init(ObjectClass *klass, void *data) } static const TypeInfo ppc440_pcix_info = { - .name = TYPE_PPC440_PCIX_HOST_BRIDGE, + .name = TYPE_PPC440_PCIX_HOST, .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(PPC440PCIXState), .class_init = ppc440_pcix_class_init, diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index 7da38bd58e..1e615b8d35 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -438,7 +438,7 @@ static void sam460ex_init(MachineState *machine) /* PCI bus */ /* All PCI irqs are connected to the same UIC pin (cf. UBoot source) */ - dev = sysbus_create_simple("ppc440-pcix-host", 0xc0ec00000, + dev = sysbus_create_simple(TYPE_PPC440_PCIX_HOST, 0xc0ec00000, qdev_get_gpio_in(uic[1], 0)); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, 0xc08000000); pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci.0")); diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h index 766d575e86..ea7740239b 100644 --- a/include/hw/ppc/ppc4xx.h +++ b/include/hw/ppc/ppc4xx.h @@ -31,6 +31,7 @@ #define TYPE_PPC4xx_HOST_BRIDGE "ppc4xx-host-bridge" #define TYPE_PPC4xx_PCI_HOST "ppc4xx-pci-host" +#define TYPE_PPC440_PCIX_HOST "ppc440-pcix-host" #define TYPE_PPC460EX_PCIE_HOST "ppc460ex-pcie-host" /* From b0afb574bad3c3a27acd2c3e7a17306a3648b0ac Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Thu, 6 Jul 2023 12:15:28 +0930 Subject: [PATCH 49/59] ppc/pnv: Log all unimp warnings with similar message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the function name so there's an indication as to where the message is coming from. Change all prints to use the offset instead of the address. Signed-off-by: Joel Stanley Reviewed-by: Cédric Le Goater Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20230706024528.40065-1-joel@jms.id.au> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/pnv_core.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 8a72171ce0..a59f3f303d 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -85,8 +85,8 @@ static uint64_t pnv_core_power8_xscom_read(void *opaque, hwaddr addr, val = 0x24f000000000000ull; break; default: - qemu_log_mask(LOG_UNIMP, "Warning: reading reg=0x%" HWADDR_PRIx "\n", - addr); + qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, + offset); } return val; @@ -95,8 +95,10 @@ static uint64_t pnv_core_power8_xscom_read(void *opaque, hwaddr addr, static void pnv_core_power8_xscom_write(void *opaque, hwaddr addr, uint64_t val, unsigned int width) { - qemu_log_mask(LOG_UNIMP, "Warning: writing to reg=0x%" HWADDR_PRIx "\n", - addr); + uint32_t offset = addr >> 3; + + qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, + offset); } static const MemoryRegionOps pnv_core_power8_xscom_ops = { @@ -140,8 +142,8 @@ static uint64_t pnv_core_power9_xscom_read(void *opaque, hwaddr addr, val = 0; break; default: - qemu_log_mask(LOG_UNIMP, "Warning: reading reg=0x%" HWADDR_PRIx "\n", - addr); + qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, + offset); } return val; @@ -157,8 +159,8 @@ static void pnv_core_power9_xscom_write(void *opaque, hwaddr addr, uint64_t val, case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR: break; default: - qemu_log_mask(LOG_UNIMP, "Warning: writing to reg=0x%" HWADDR_PRIx "\n", - addr); + qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, + offset); } } @@ -189,8 +191,8 @@ static uint64_t pnv_core_power10_xscom_read(void *opaque, hwaddr addr, val = 0; break; default: - qemu_log_mask(LOG_UNIMP, "Warning: reading reg=0x%" HWADDR_PRIx "\n", - addr); + qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, + offset); } return val; @@ -203,8 +205,8 @@ static void pnv_core_power10_xscom_write(void *opaque, hwaddr addr, switch (offset) { default: - qemu_log_mask(LOG_UNIMP, "Warning: writing to reg=0x%" HWADDR_PRIx "\n", - addr); + qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, + offset); } } @@ -419,7 +421,7 @@ static uint64_t pnv_quad_power9_xscom_read(void *opaque, hwaddr addr, val = 0; break; default: - qemu_log_mask(LOG_UNIMP, "%s: reading @0x%08x\n", __func__, + qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, offset); } @@ -436,7 +438,7 @@ static void pnv_quad_power9_xscom_write(void *opaque, hwaddr addr, uint64_t val, case P9X_EX_NCU_SPEC_BAR + 0x400: /* Second EX */ break; default: - qemu_log_mask(LOG_UNIMP, "%s: writing @0x%08x\n", __func__, + qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, offset); } } @@ -463,7 +465,7 @@ static uint64_t pnv_quad_power10_xscom_read(void *opaque, hwaddr addr, switch (offset) { default: - qemu_log_mask(LOG_UNIMP, "%s: reading @0x%08x\n", __func__, + qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, offset); } @@ -477,7 +479,7 @@ static void pnv_quad_power10_xscom_write(void *opaque, hwaddr addr, switch (offset) { default: - qemu_log_mask(LOG_UNIMP, "%s: writing @0x%08x\n", __func__, + qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, offset); } } From aa2addf96f2629101ef0aa0c9226d38867c72d76 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Thu, 6 Jul 2023 15:39:22 +1000 Subject: [PATCH 50/59] ppc/pnv: Set P10 core xscom region size to match hardware MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The P10 core xscom memory regions overlap because the size is wrong. The P10 core+L2 xscom region size is allocated as 0x1000 (with some unused ranges). "EC" is used as a closer match, as "EX" includes L3 which has a disjoint xscom range that would require a different region if it were implemented. Signed-off-by: Nicholas Piggin Reviewed-by: Cédric Le Goater Tested-by: Cédric Le Goater Message-ID: <20230706053923.115003-2-npiggin@gmail.com> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/pnv_core.c | 6 ++++-- include/hw/ppc/pnv_core.h | 1 + include/hw/ppc/pnv_xscom.h | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index a59f3f303d..9e7cf341dc 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -298,9 +298,8 @@ 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); + pc, name, pcc->xscom_size); qemu_register_reset(pnv_core_reset, pc); return; @@ -352,6 +351,7 @@ static void pnv_core_power8_class_init(ObjectClass *oc, void *data) PnvCoreClass *pcc = PNV_CORE_CLASS(oc); pcc->xscom_ops = &pnv_core_power8_xscom_ops; + pcc->xscom_size = PNV_XSCOM_EX_SIZE; } static void pnv_core_power9_class_init(ObjectClass *oc, void *data) @@ -359,6 +359,7 @@ static void pnv_core_power9_class_init(ObjectClass *oc, void *data) PnvCoreClass *pcc = PNV_CORE_CLASS(oc); pcc->xscom_ops = &pnv_core_power9_xscom_ops; + pcc->xscom_size = PNV_XSCOM_EX_SIZE; } static void pnv_core_power10_class_init(ObjectClass *oc, void *data) @@ -366,6 +367,7 @@ static void pnv_core_power10_class_init(ObjectClass *oc, void *data) PnvCoreClass *pcc = PNV_CORE_CLASS(oc); pcc->xscom_ops = &pnv_core_power10_xscom_ops; + pcc->xscom_size = PNV10_XSCOM_EC_SIZE; } static void pnv_core_class_init(ObjectClass *oc, void *data) diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h index 77ef00f47a..aa5ca281fc 100644 --- a/include/hw/ppc/pnv_core.h +++ b/include/hw/ppc/pnv_core.h @@ -46,6 +46,7 @@ struct PnvCoreClass { DeviceClass parent_class; const MemoryRegionOps *xscom_ops; + uint64_t xscom_size; }; #define PNV_CORE_TYPE_SUFFIX "-" TYPE_PNV_CORE diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h index f7da9a1dc6..a4c9d95dc5 100644 --- a/include/hw/ppc/pnv_xscom.h +++ b/include/hw/ppc/pnv_xscom.h @@ -133,7 +133,7 @@ struct PnvXScomInterfaceClass { #define PNV10_XSCOM_EC_BASE(core) \ ((uint64_t) PNV10_XSCOM_EQ_BASE(core) | PNV10_XSCOM_EC(core & 0x3)) -#define PNV10_XSCOM_EC_SIZE 0x100000 +#define PNV10_XSCOM_EC_SIZE 0x1000 #define PNV10_XSCOM_PSIHB_BASE 0x3011D00 #define PNV10_XSCOM_PSIHB_SIZE 0x100 From e1a821d47167a46e4386e763cd7e7901c856c4b2 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Thu, 6 Jul 2023 15:39:23 +1000 Subject: [PATCH 51/59] tests/qtest: Add xscom tests for powernv10 machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add basic chip and core xscom tests for powernv10 machine, equivalent to tests for powernv8 and 9. Signed-off-by: Nicholas Piggin Reviewed-by: Cédric Le Goater Tested-by: Cédric Le Goater Message-ID: <20230706053923.115003-3-npiggin@gmail.com> Signed-off-by: Daniel Henrique Barboza --- tests/qtest/pnv-xscom-test.c | 47 ++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/tests/qtest/pnv-xscom-test.c b/tests/qtest/pnv-xscom-test.c index 2c46d5cf6d..8a5ac11037 100644 --- a/tests/qtest/pnv-xscom-test.c +++ b/tests/qtest/pnv-xscom-test.c @@ -15,6 +15,7 @@ typedef enum PnvChipType { PNV_CHIP_POWER8, /* AKA Venice */ PNV_CHIP_POWER8NVL, /* AKA Naples */ PNV_CHIP_POWER9, /* AKA Nimbus */ + PNV_CHIP_POWER10, } PnvChipType; typedef struct PnvChip { @@ -46,13 +47,22 @@ static const PnvChip pnv_chips[] = { .cfam_id = 0x220d104900008000ull, .first_core = 0x0, }, + { + .chip_type = PNV_CHIP_POWER10, + .cpu_model = "POWER10", + .xscom_base = 0x000603fc00000000ull, + .cfam_id = 0x120da04900008000ull, + .first_core = 0x0, + }, }; static uint64_t pnv_xscom_addr(const PnvChip *chip, uint32_t pcba) { uint64_t addr = chip->xscom_base; - if (chip->chip_type == PNV_CHIP_POWER9) { + if (chip->chip_type == PNV_CHIP_POWER10) { + addr |= ((uint64_t) pcba << 3); + } else if (chip->chip_type == PNV_CHIP_POWER9) { addr |= ((uint64_t) pcba << 3); } else { addr |= (((uint64_t) pcba << 4) & ~0xffull) | @@ -82,6 +92,8 @@ static void test_cfam_id(const void *data) if (chip->chip_type == PNV_CHIP_POWER9) { machine = "powernv9"; + } else if (chip->chip_type == PNV_CHIP_POWER10) { + machine = "powernv10"; } qts = qtest_initf("-M %s -accel tcg -cpu %s", @@ -96,23 +108,36 @@ static void test_cfam_id(const void *data) (PNV_XSCOM_EX_CORE_BASE | ((uint64_t)(core) << 24)) #define PNV_XSCOM_P9_EC_BASE(core) \ ((uint64_t)(((core) & 0x1F) + 0x20) << 24) +#define PNV_XSCOM_P10_EC_BASE(core) \ + ((uint64_t)((((core) & ~0x3) + 0x20) << 24) + 0x20000 + \ + (0x1000 << (3 - (core & 0x3)))) #define PNV_XSCOM_EX_DTS_RESULT0 0x50000 static void test_xscom_core(QTestState *qts, const PnvChip *chip) { - uint32_t first_core_dts0 = PNV_XSCOM_EX_DTS_RESULT0; - uint64_t dts0; + if (chip->chip_type == PNV_CHIP_POWER10) { + uint32_t first_core_thread_state = + PNV_XSCOM_P10_EC_BASE(chip->first_core) + 0x412; + uint64_t thread_state; - if (chip->chip_type != PNV_CHIP_POWER9) { - first_core_dts0 |= PNV_XSCOM_EX_BASE(chip->first_core); + thread_state = pnv_xscom_read(qts, chip, first_core_thread_state); + + g_assert_cmphex(thread_state, ==, 0); } else { - first_core_dts0 |= PNV_XSCOM_P9_EC_BASE(chip->first_core); + uint32_t first_core_dts0 = PNV_XSCOM_EX_DTS_RESULT0; + uint64_t dts0; + + if (chip->chip_type == PNV_CHIP_POWER9) { + first_core_dts0 |= PNV_XSCOM_P9_EC_BASE(chip->first_core); + } else { /* POWER8 */ + first_core_dts0 |= PNV_XSCOM_EX_BASE(chip->first_core); + } + + dts0 = pnv_xscom_read(qts, chip, first_core_dts0); + + g_assert_cmphex(dts0, ==, 0x26f024f023f0000ull); } - - dts0 = pnv_xscom_read(qts, chip, first_core_dts0); - - g_assert_cmphex(dts0, ==, 0x26f024f023f0000ull); } static void test_core(const void *data) @@ -123,6 +148,8 @@ static void test_core(const void *data) if (chip->chip_type == PNV_CHIP_POWER9) { machine = "powernv9"; + } else if (chip->chip_type == PNV_CHIP_POWER10) { + machine = "powernv10"; } qts = qtest_initf("-M %s -accel tcg -cpu %s", From 55a7fa34f8982f22497b2453787336acc7f79a7c Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Mon, 3 Jul 2023 22:03:01 +1000 Subject: [PATCH 52/59] target/ppc: Machine check on invalid real address access on POWER9/10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ppc currently silently accepts invalid real address access. Catch these and turn them into machine checks on POWER9/10 machines. Signed-off-by: Nicholas Piggin Reviewed-by: Cédric Le Goater Message-ID: <20230703120301.45313-1-npiggin@gmail.com> Signed-off-by: Daniel Henrique Barboza --- target/ppc/cpu_init.c | 1 + target/ppc/excp_helper.c | 49 ++++++++++++++++++++++++++++++++++++++++ target/ppc/internal.h | 5 ++++ 3 files changed, 55 insertions(+) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 720aad9e05..6ac1765a8d 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -7335,6 +7335,7 @@ static const struct TCGCPUOps ppc_tcg_ops = { .cpu_exec_enter = ppc_cpu_exec_enter, .cpu_exec_exit = ppc_cpu_exec_exit, .do_unaligned_access = ppc_cpu_do_unaligned_access, + .do_transaction_failed = ppc_cpu_do_transaction_failed, #endif /* !CONFIG_USER_ONLY */ }; #endif /* CONFIG_TCG */ diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 7683ea0fc9..003805b202 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -1428,7 +1428,9 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) /* machine check exceptions don't have ME set */ new_msr &= ~((target_ulong)1 << MSR_ME); + msr |= env->error_code; break; + case POWERPC_EXCP_DSI: /* Data storage exception */ trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]); break; @@ -3188,5 +3190,52 @@ void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, env->error_code = insn & 0x03FF0000; cpu_loop_exit(cs); } + +void ppc_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, + vaddr vaddr, unsigned size, + MMUAccessType access_type, + int mmu_idx, MemTxAttrs attrs, + MemTxResult response, uintptr_t retaddr) +{ + CPUPPCState *env = cs->env_ptr; + + switch (env->excp_model) { +#if defined(TARGET_PPC64) + case POWERPC_EXCP_POWER9: + case POWERPC_EXCP_POWER10: + /* + * Machine check codes can be found in processor User Manual or + * Linux or skiboot source. + */ + if (access_type == MMU_DATA_LOAD) { + env->spr[SPR_DAR] = vaddr; + env->spr[SPR_DSISR] = PPC_BIT(57); + env->error_code = PPC_BIT(42); + + } else if (access_type == MMU_DATA_STORE) { + /* + * MCE for stores in POWER is asynchronous so hardware does + * not set DAR, but QEMU can do better. + */ + env->spr[SPR_DAR] = vaddr; + env->error_code = PPC_BIT(36) | PPC_BIT(43) | PPC_BIT(45); + env->error_code |= PPC_BIT(42); + + } else { /* Fetch */ + env->error_code = PPC_BIT(36) | PPC_BIT(44) | PPC_BIT(45); + } + break; +#endif + default: + /* + * TODO: Check behaviour for other CPUs, for now do nothing. + * Could add a basic MCE even if real hardware ignores. + */ + return; + } + + cs->exception_index = POWERPC_EXCP_MCHECK; + cpu_loop_exit_restore(cs, retaddr); +} #endif /* CONFIG_TCG */ #endif /* !CONFIG_USER_ONLY */ diff --git a/target/ppc/internal.h b/target/ppc/internal.h index 901bae6d39..57acb3212c 100644 --- a/target/ppc/internal.h +++ b/target/ppc/internal.h @@ -296,6 +296,11 @@ bool ppc_cpu_tlb_fill(CPUState *cs, vaddr address, int size, G_NORETURN void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr addr, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr); +void ppc_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, + vaddr addr, unsigned size, + MMUAccessType access_type, + int mmu_idx, MemTxAttrs attrs, + MemTxResult response, uintptr_t retaddr); #endif FIELD(GER_MSK, XMSK, 0, 4) From 597645ccb570e3288f6937c7710be110b6c8f254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 27 Jun 2023 13:51:19 +0200 Subject: [PATCH 53/59] target/ppc: Have 'kvm_ppc.h' include 'sysemu/kvm.h' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "kvm_ppc.h" declares: int kvm_handle_nmi(PowerPCCPU *cpu, struct kvm_run *run); 'struct kvm_run' is declared in "sysemu/kvm.h", include it. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Greg Kurz Reviewed-by: Cédric Le Goater Message-ID: <20230627115124.19632-2-philmd@linaro.org> Signed-off-by: Daniel Henrique Barboza --- target/ppc/kvm_ppc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h index 611debc3ce..2e395416f0 100644 --- a/target/ppc/kvm_ppc.h +++ b/target/ppc/kvm_ppc.h @@ -9,6 +9,7 @@ #ifndef KVM_PPC_H #define KVM_PPC_H +#include "sysemu/kvm.h" #include "exec/hwaddr.h" #include "cpu.h" From 1b4b1bb5064dc08df6fd4ce9813b5f3370eda085 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 27 Jun 2023 13:51:20 +0200 Subject: [PATCH 54/59] target/ppc: Reorder #ifdef'ry in kvm_ppc.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keep a single if/else/endif block checking CONFIG_KVM. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Cédric Le Goater Message-ID: <20230627115124.19632-3-philmd@linaro.org> Signed-off-by: Daniel Henrique Barboza --- target/ppc/kvm_ppc.h | 62 ++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h index 2e395416f0..49954a300b 100644 --- a/target/ppc/kvm_ppc.h +++ b/target/ppc/kvm_ppc.h @@ -93,7 +93,34 @@ void kvmppc_set_reg_tb_offset(PowerPCCPU *cpu, int64_t tb_offset); int kvm_handle_nmi(PowerPCCPU *cpu, struct kvm_run *run); -#else +#define kvmppc_eieio() \ + do { \ + if (kvm_enabled()) { \ + asm volatile("eieio" : : : "memory"); \ + } \ + } while (0) + +/* Store data cache blocks back to memory */ +static inline void kvmppc_dcbst_range(PowerPCCPU *cpu, uint8_t *addr, int len) +{ + uint8_t *p; + + for (p = addr; p < addr + len; p += cpu->env.dcache_line_size) { + asm volatile("dcbst 0,%0" : : "r"(p) : "memory"); + } +} + +/* Invalidate instruction cache blocks */ +static inline void kvmppc_icbi_range(PowerPCCPU *cpu, uint8_t *addr, int len) +{ + uint8_t *p; + + for (p = addr; p < addr + len; p += cpu->env.icache_line_size) { + asm volatile("icbi 0,%0" : : "r"(p)); + } +} + +#else /* !CONFIG_KVM */ static inline uint32_t kvmppc_get_tbfreq(void) { @@ -440,10 +467,6 @@ static inline bool kvmppc_pvr_workaround_required(PowerPCCPU *cpu) return false; } -#endif - -#ifndef CONFIG_KVM - #define kvmppc_eieio() do { } while (0) static inline void kvmppc_dcbst_range(PowerPCCPU *cpu, uint8_t *addr, int len) @@ -454,35 +477,6 @@ static inline void kvmppc_icbi_range(PowerPCCPU *cpu, uint8_t *addr, int len) { } -#else /* CONFIG_KVM */ - -#define kvmppc_eieio() \ - do { \ - if (kvm_enabled()) { \ - asm volatile("eieio" : : : "memory"); \ - } \ - } while (0) - -/* Store data cache blocks back to memory */ -static inline void kvmppc_dcbst_range(PowerPCCPU *cpu, uint8_t *addr, int len) -{ - uint8_t *p; - - for (p = addr; p < addr + len; p += cpu->env.dcache_line_size) { - asm volatile("dcbst 0,%0" : : "r"(p) : "memory"); - } -} - -/* Invalidate instruction cache blocks */ -static inline void kvmppc_icbi_range(PowerPCCPU *cpu, uint8_t *addr, int len) -{ - uint8_t *p; - - for (p = addr; p < addr + len; p += cpu->env.icache_line_size) { - asm volatile("icbi 0,%0" : : "r"(p)); - } -} - #endif /* CONFIG_KVM */ #endif /* KVM_PPC_H */ From 66453c0f0cbfcc64be3af1f738dd057a2be560da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 27 Jun 2023 13:51:21 +0200 Subject: [PATCH 55/59] target/ppc: Move CPU QOM definitions to cpu-qom.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Cédric Le Goater Message-ID: <20230627115124.19632-4-philmd@linaro.org> [dhb: keep cpu_list define in target/ppc/cpu.h] Signed-off-by: Daniel Henrique Barboza --- target/ppc/cpu-qom.h | 4 ++++ target/ppc/cpu.h | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h index 9666f54f65..c2a66a90f7 100644 --- a/target/ppc/cpu-qom.h +++ b/target/ppc/cpu-qom.h @@ -31,6 +31,10 @@ OBJECT_DECLARE_CPU_TYPE(PowerPCCPU, PowerPCCPUClass, POWERPC_CPU) +#define POWERPC_CPU_TYPE_SUFFIX "-" TYPE_POWERPC_CPU +#define POWERPC_CPU_TYPE_NAME(model) model POWERPC_CPU_TYPE_SUFFIX +#define CPU_RESOLVING_TYPE TYPE_POWERPC_CPU + ObjectClass *ppc_cpu_class_by_name(const char *name); typedef struct CPUArchState CPUPPCState; diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index b269b0d090..25fac9577a 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1471,10 +1471,6 @@ static inline uint64_t ppc_dump_gpr(CPUPPCState *env, int gprn) int ppc_dcr_read(ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp); int ppc_dcr_write(ppc_dcr_t *dcr_env, int dcrn, uint32_t val); -#define POWERPC_CPU_TYPE_SUFFIX "-" TYPE_POWERPC_CPU -#define POWERPC_CPU_TYPE_NAME(model) model POWERPC_CPU_TYPE_SUFFIX -#define CPU_RESOLVING_TYPE TYPE_POWERPC_CPU - #define cpu_list ppc_cpu_list /* MMU modes definitions */ From be67dd4afea13b3a18fab142082a40a59df439ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 27 Jun 2023 13:51:22 +0200 Subject: [PATCH 56/59] target/ppc: Define TYPE_HOST_POWERPC_CPU in cpu-qom.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TYPE_HOST_POWERPC_CPU is used in various places of cpu_init.c, in order to restrict "kvm_ppc.h" to sysemu, move this QOM-related definition to cpu-qom.h. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Cédric Le Goater Reviewed-by: Greg Kurz Message-ID: <20230627115124.19632-5-philmd@linaro.org> Signed-off-by: Daniel Henrique Barboza --- target/ppc/cpu-qom.h | 2 ++ target/ppc/kvm_ppc.h | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h index c2a66a90f7..be33786bd8 100644 --- a/target/ppc/cpu-qom.h +++ b/target/ppc/cpu-qom.h @@ -35,6 +35,8 @@ OBJECT_DECLARE_CPU_TYPE(PowerPCCPU, PowerPCCPUClass, POWERPC_CPU) #define POWERPC_CPU_TYPE_NAME(model) model POWERPC_CPU_TYPE_SUFFIX #define CPU_RESOLVING_TYPE TYPE_POWERPC_CPU +#define TYPE_HOST_POWERPC_CPU POWERPC_CPU_TYPE_NAME("host") + ObjectClass *ppc_cpu_class_by_name(const char *name); typedef struct CPUArchState CPUPPCState; diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h index 49954a300b..901e188c9a 100644 --- a/target/ppc/kvm_ppc.h +++ b/target/ppc/kvm_ppc.h @@ -13,8 +13,6 @@ #include "exec/hwaddr.h" #include "cpu.h" -#define TYPE_HOST_POWERPC_CPU POWERPC_CPU_TYPE_NAME("host") - #ifdef CONFIG_KVM uint32_t kvmppc_get_tbfreq(void); From d0815cb808fe0cebe04aba5339e3f5cfe08cb4d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 27 Jun 2023 13:51:23 +0200 Subject: [PATCH 57/59] target/ppc: Restrict 'kvm_ppc.h' to sysemu in cpu_init.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User emulation shouldn't need any of the KVM prototypes declared in "kvm_ppc.h". Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Cédric Le Goater Reviewed-by: Greg Kurz Message-ID: <20230627115124.19632-6-philmd@linaro.org> Signed-off-by: Daniel Henrique Barboza --- target/ppc/cpu_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 6ac1765a8d..02b7aad9b0 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -21,7 +21,6 @@ #include "qemu/osdep.h" #include "disas/dis-asm.h" #include "gdbstub/helpers.h" -#include "kvm_ppc.h" #include "sysemu/cpus.h" #include "sysemu/hw_accel.h" #include "sysemu/tcg.h" @@ -49,6 +48,7 @@ #ifndef CONFIG_USER_ONLY #include "hw/boards.h" #include "hw/intc/intc.h" +#include "kvm_ppc.h" #endif /* #define PPC_DEBUG_SPR */ From 9c1ce7723bbe18680f57ac318947fe7c7214d474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 27 Jun 2023 13:51:24 +0200 Subject: [PATCH 58/59] target/ppc: Remove pointless checks of CONFIG_USER_ONLY in 'kvm_ppc.h' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Cédric Le Goater Reviewed-by: Greg Kurz Message-ID: <20230627115124.19632-7-philmd@linaro.org> Signed-off-by: Daniel Henrique Barboza --- target/ppc/kvm_ppc.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h index 901e188c9a..6a4dd9c560 100644 --- a/target/ppc/kvm_ppc.h +++ b/target/ppc/kvm_ppc.h @@ -42,7 +42,6 @@ int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu); target_ulong kvmppc_configure_v3_mmu(PowerPCCPU *cpu, bool radix, bool gtse, uint64_t proc_tbl); -#ifndef CONFIG_USER_ONLY bool kvmppc_spapr_use_multitce(void); int kvmppc_spapr_enable_inkernel_multitce(void); void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t page_shift, @@ -52,7 +51,6 @@ int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size); int kvmppc_reset_htab(int shift_hint); uint64_t kvmppc_vrma_limit(unsigned int hash_shift); bool kvmppc_has_cap_spapr_vfio(void); -#endif /* !CONFIG_USER_ONLY */ bool kvmppc_has_cap_epr(void); int kvmppc_define_rtas_kernel_token(uint32_t token, const char *function); int kvmppc_get_htab_fd(bool write, uint64_t index, Error **errp); @@ -262,7 +260,6 @@ static inline void kvmppc_set_reg_tb_offset(PowerPCCPU *cpu, int64_t tb_offset) { } -#ifndef CONFIG_USER_ONLY static inline bool kvmppc_spapr_use_multitce(void) { return false; @@ -322,8 +319,6 @@ static inline void kvmppc_write_hpte(hwaddr ptex, uint64_t pte0, uint64_t pte1) abort(); } -#endif /* !CONFIG_USER_ONLY */ - static inline bool kvmppc_has_cap_epr(void) { return false; From bdb97596f663e9af9741353417c651f0d581de29 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Fri, 7 Jul 2023 16:42:13 +0930 Subject: [PATCH 59/59] ppc/pnv: Add QME region for P10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Quad Management Engine (QME) manages power related settings for its quad. The xscom region is separate from the quad xscoms, therefore a new region is added. The xscoms in a QME select a given core by selecting the forth nibble. Implement dummy reads for the stop state history (SSH) and special wakeup (SPWU) registers. This quietens some sxcom errors when skiboot boots on p10. Power9 does not have a QME. Signed-off-by: Joel Stanley Reviewed-by: Cédric Le Goater Signed-off-by: Joel Stanley Message-ID: <20230707071213.9924-1-joel@jms.id.au> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/pnv.c | 3 ++ hw/ppc/pnv_core.c | 78 +++++++++++++++++++++++++++++++++++++- include/hw/ppc/pnv_core.h | 4 ++ include/hw/ppc/pnv_xscom.h | 11 ++++++ 4 files changed, 94 insertions(+), 2 deletions(-) diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 23740f9d07..eb54f93986 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1685,6 +1685,9 @@ static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp) pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id), &eq->xscom_regs); + + pnv_xscom_add_subregion(chip, PNV10_XSCOM_QME_BASE(eq->quad_id), + &eq->xscom_qme_regs); } } diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 9e7cf341dc..9b39d527de 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -496,7 +496,54 @@ static const MemoryRegionOps pnv_quad_power10_xscom_ops = { .endianness = DEVICE_BIG_ENDIAN, }; -static void pnv_quad_realize(DeviceState *dev, Error **errp) +#define P10_QME_SPWU_HYP 0x83c +#define P10_QME_SSH_HYP 0x82c + +static uint64_t pnv_qme_power10_xscom_read(void *opaque, hwaddr addr, + unsigned int width) +{ + uint32_t offset = addr >> 3; + uint64_t val = -1; + + /* + * Forth nibble selects the core within a quad, mask it to process read + * for any core. + */ + switch (offset & ~0xf000) { + case P10_QME_SPWU_HYP: + case P10_QME_SSH_HYP: + return 0; + default: + qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, + offset); + } + + return val; +} + +static void pnv_qme_power10_xscom_write(void *opaque, hwaddr addr, + uint64_t val, unsigned int width) +{ + uint32_t offset = addr >> 3; + + switch (offset) { + default: + qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, + offset); + } +} + +static const MemoryRegionOps pnv_qme_power10_xscom_ops = { + .read = pnv_qme_power10_xscom_read, + .write = pnv_qme_power10_xscom_write, + .valid.min_access_size = 8, + .valid.max_access_size = 8, + .impl.min_access_size = 8, + .impl.max_access_size = 8, + .endianness = DEVICE_BIG_ENDIAN, +}; + +static void pnv_quad_power9_realize(DeviceState *dev, Error **errp) { PnvQuad *eq = PNV_QUAD(dev); PnvQuadClass *pqc = PNV_QUAD_GET_CLASS(eq); @@ -509,6 +556,25 @@ static void pnv_quad_realize(DeviceState *dev, Error **errp) pqc->xscom_size); } +static void pnv_quad_power10_realize(DeviceState *dev, Error **errp) +{ + PnvQuad *eq = PNV_QUAD(dev); + PnvQuadClass *pqc = PNV_QUAD_GET_CLASS(eq); + char name[32]; + + snprintf(name, sizeof(name), "xscom-quad.%d", eq->quad_id); + pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev), + pqc->xscom_ops, + eq, name, + pqc->xscom_size); + + snprintf(name, sizeof(name), "xscom-qme.%d", eq->quad_id); + pnv_xscom_region_init(&eq->xscom_qme_regs, OBJECT(dev), + pqc->xscom_qme_ops, + eq, name, + pqc->xscom_qme_size); +} + static Property pnv_quad_properties[] = { DEFINE_PROP_UINT32("quad-id", PnvQuad, quad_id, 0), DEFINE_PROP_END_OF_LIST(), @@ -517,6 +583,9 @@ static Property pnv_quad_properties[] = { static void pnv_quad_power9_class_init(ObjectClass *oc, void *data) { PnvQuadClass *pqc = PNV_QUAD_CLASS(oc); + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = pnv_quad_power9_realize; pqc->xscom_ops = &pnv_quad_power9_xscom_ops; pqc->xscom_size = PNV9_XSCOM_EQ_SIZE; @@ -525,16 +594,21 @@ static void pnv_quad_power9_class_init(ObjectClass *oc, void *data) static void pnv_quad_power10_class_init(ObjectClass *oc, void *data) { PnvQuadClass *pqc = PNV_QUAD_CLASS(oc); + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = pnv_quad_power10_realize; pqc->xscom_ops = &pnv_quad_power10_xscom_ops; pqc->xscom_size = PNV10_XSCOM_EQ_SIZE; + + pqc->xscom_qme_ops = &pnv_qme_power10_xscom_ops; + pqc->xscom_qme_size = PNV10_XSCOM_QME_SIZE; } static void pnv_quad_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); - dc->realize = pnv_quad_realize; device_class_set_props(dc, pnv_quad_properties); dc->user_creatable = false; } diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h index aa5ca281fc..4db21229a6 100644 --- a/include/hw/ppc/pnv_core.h +++ b/include/hw/ppc/pnv_core.h @@ -66,6 +66,9 @@ struct PnvQuadClass { const MemoryRegionOps *xscom_ops; uint64_t xscom_size; + + const MemoryRegionOps *xscom_qme_ops; + uint64_t xscom_qme_size; }; #define TYPE_PNV_QUAD "powernv-cpu-quad" @@ -80,5 +83,6 @@ struct PnvQuad { uint32_t quad_id; MemoryRegion xscom_regs; + MemoryRegion xscom_qme_regs; }; #endif /* PPC_PNV_CORE_H */ diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h index a4c9d95dc5..9bc6463547 100644 --- a/include/hw/ppc/pnv_xscom.h +++ b/include/hw/ppc/pnv_xscom.h @@ -127,6 +127,17 @@ struct PnvXScomInterfaceClass { #define PNV10_XSCOM_EC(proc) \ ((0x2 << 16) | ((1 << (3 - (proc))) << 12)) +#define PNV10_XSCOM_QME(chiplet) \ + (PNV10_XSCOM_EQ(chiplet) | (0xE << 16)) + +/* + * Make the region larger by 0x1000 (instead of starting at an offset) so the + * modelled addresses start from 0 + */ +#define PNV10_XSCOM_QME_BASE(core) \ + ((uint64_t) PNV10_XSCOM_QME(PNV10_XSCOM_EQ_CHIPLET(core))) +#define PNV10_XSCOM_QME_SIZE (0x8000 + 0x1000) + #define PNV10_XSCOM_EQ_BASE(core) \ ((uint64_t) PNV10_XSCOM_EQ(PNV10_XSCOM_EQ_CHIPLET(core))) #define PNV10_XSCOM_EQ_SIZE 0x20000