[PATCH v2 06/11] ppc/spapr: remove deprecated machine pseries-2.6
Commit 1392617d3576 intended to tag pseries-2.1 - 2.11 machines as deprecated with reasons mentioned in its commit log. Removing pseries-2.6 specific code with this patch for now. Suggested-by: Cédric Le Goater Signed-off-by: Harsh Prateek Bora --- hw/ppc/spapr.c | 18 -- 1 file changed, 18 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index a38d4e098a..d317387b7f 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -5297,24 +5297,6 @@ static void spapr_machine_2_7_class_options(MachineClass *mc) DEFINE_SPAPR_MACHINE(2, 7); -/* - * pseries-2.6 - */ - -static void spapr_machine_2_6_class_options(MachineClass *mc) -{ -static GlobalProperty compat[] = { -{ TYPE_SPAPR_PCI_HOST_BRIDGE, "ddw", "off" }, -}; - -spapr_machine_2_7_class_options(mc); -mc->has_hotpluggable_cpus = false; -compat_props_add(mc->compat_props, hw_compat_2_6, hw_compat_2_6_len); -compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); -} - -DEFINE_SPAPR_MACHINE(2, 6); - static void spapr_machine_register_types(void) { type_register_static(&spapr_machine_info); -- 2.45.2
[PATCH v2 07/11] ppc/spapr: remove deprecated machine pseries-2.7
Commit 1392617d3576 intended to tag pseries-2.1 - 2.11 machines as deprecated with reasons mentioned in its commit log. Removing pseries-2.7 specific code with this patch for now. While at it, also remove pre-2.8-migration hacks introduced for backward migration compatibility. Suggested-by: Cédric Le Goater Signed-off-by: Harsh Prateek Bora --- include/hw/pci-host/spapr.h | 4 -- target/ppc/cpu.h| 5 --- hw/ppc/spapr.c | 75 - hw/ppc/spapr_pci.c | 28 -- target/ppc/cpu_init.c | 1 - target/ppc/machine.c| 52 - 6 files changed, 165 deletions(-) diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h index 3778aac27b..0d40bf48f6 100644 --- a/include/hw/pci-host/spapr.h +++ b/include/hw/pci-host/spapr.h @@ -84,10 +84,6 @@ struct SpaprPhbState { bool pcie_ecs; /* Allow access to PCIe extended config space? */ /* Fields for migration compatibility hacks */ -bool pre_2_8_migration; -uint32_t mig_liobn; -hwaddr mig_mem_win_addr, mig_mem_win_size; -hwaddr mig_io_win_addr, mig_io_win_size; bool pre_5_1_assoc; }; diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 321ed2da75..cab4a46fc1 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1456,11 +1456,6 @@ struct ArchCPU { opc_handler_t *opcodes[PPC_CPU_OPCODES_LEN]; /* Fields related to migration compatibility hacks */ -bool pre_2_8_migration; -target_ulong mig_msr_mask; -uint64_t mig_insns_flags; -uint64_t mig_insns_flags2; -uint32_t mig_nb_BATs; bool pre_2_10_migration; bool pre_3_0_migration; int32_t mig_slb_nr; diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index d317387b7f..4e8f2a5d8e 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -5222,81 +5222,6 @@ static void spapr_machine_2_8_class_options(MachineClass *mc) DEFINE_SPAPR_MACHINE(2, 8); -/* - * pseries-2.7 - */ - -static bool phb_placement_2_7(SpaprMachineState *spapr, uint32_t index, - uint64_t *buid, hwaddr *pio, - hwaddr *mmio32, hwaddr *mmio64, - unsigned n_dma, uint32_t *liobns, Error **errp) -{ -/* Legacy PHB placement for pseries-2.7 and earlier machine types */ -const uint64_t base_buid = 0x8002000ULL; -const hwaddr phb_spacing = 0x10ULL; /* 64 GiB */ -const hwaddr mmio_offset = 0xa000; /* 2 GiB + 512 MiB */ -const hwaddr pio_offset = 0x8000; /* 2 GiB */ -const uint32_t max_index = 255; -const hwaddr phb0_alignment = 0x100ULL; /* 1 TiB */ - -uint64_t ram_top = MACHINE(spapr)->ram_size; -hwaddr phb0_base, phb_base; -int i; - -/* Do we have device memory? */ -if (MACHINE(spapr)->device_memory) { -/* Can't just use maxram_size, because there may be an - * alignment gap between normal and device memory regions - */ -ram_top = MACHINE(spapr)->device_memory->base + -memory_region_size(&MACHINE(spapr)->device_memory->mr); -} - -phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment); - -if (index > max_index) { -error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)", - max_index); -return false; -} - -*buid = base_buid + index; -for (i = 0; i < n_dma; ++i) { -liobns[i] = SPAPR_PCI_LIOBN(index, i); -} - -phb_base = phb0_base + index * phb_spacing; -*pio = phb_base + pio_offset; -*mmio32 = phb_base + mmio_offset; -/* - * We don't set the 64-bit MMIO window, relying on the PHB's - * fallback behaviour of automatically splitting a large "32-bit" - * window into contiguous 32-bit and 64-bit windows - */ - -return true; -} - -static void spapr_machine_2_7_class_options(MachineClass *mc) -{ -SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); -static GlobalProperty compat[] = { -{ TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0xf8000", }, -{ TYPE_SPAPR_PCI_HOST_BRIDGE, "mem64_win_size", "0", }, -{ TYPE_POWERPC_CPU, "pre-2.8-migration", "on", }, -{ TYPE_SPAPR_PCI_HOST_BRIDGE, "pre-2.8-migration", "on", }, -}; - -spapr_machine_2_8_class_options(mc); -mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power7_v2.3"); -mc->default_machine_opts = "modern-hotplug-events=off"; -compat_props_add(mc->compat_props, hw_compat_2_7, hw_compat_2_7_len); -compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); -smc->phb_placement = phb_placement_2_7; -} - -DEFINE_SPAPR_MACHINE(2, 7); - static void spapr_machine_register_types(void) { type_register_static(&spapr_machine_info); diff
[PATCH v2 00/11] ppc/spapr: remove deprecated machines specific code
Commit 1392617d3576 intended to tag pseries-2.1 - 2.11 machines as deprecated with reasons mentioned in its commit log. Removing the arch specific code for the now deprecated machine types. v2: Addressed review comments from Cedric v1: <20240917060300.943496-1-hars...@linux.ibm.com> Harsh Prateek Bora (11): ppc/spapr: remove deprecated machine pseries-2.1 ppc/spapr: remove deprecated machine pseries-2.2 ppc/spapr: remove deprecated machine pseries-2.3 ppc/spapr: remove deprecated machine pseries-2.4 ppc/spapr: remove deprecated machine pseries-2.5 ppc/spapr: remove deprecated machine pseries-2.6 ppc/spapr: remove deprecated machine pseries-2.7 ppc/spapr: remove deprecated machine pseries-2.8 ppc/spapr: remove deprecated machine pseries-2.9 ppc/spapr: remove deprecated machine pseries-2.10 ppc/spapr: remove deprecated machine pseries-2.11 include/hw/pci-host/spapr.h | 4 - target/ppc/cpu.h| 6 - hw/ppc/spapr.c | 235 hw/ppc/spapr_pci.c | 28 - target/ppc/cpu_init.c | 3 - target/ppc/machine.c| 54 + 6 files changed, 1 insertion(+), 329 deletions(-) -- 2.45.2
[PATCH v2 04/11] ppc/spapr: remove deprecated machine pseries-2.4
Commit 1392617d3576 intended to tag pseries-2.1 - 2.11 machines as deprecated with reasons mentioned in its commit log. Removing pseries-2.4 specific code with this patch for now. Suggested-by: Cédric Le Goater Signed-off-by: Harsh Prateek Bora --- hw/ppc/spapr.c | 15 --- 1 file changed, 15 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index f2f20aa5b5..9e78f94ec2 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -5334,21 +5334,6 @@ static void spapr_machine_2_5_class_options(MachineClass *mc) DEFINE_SPAPR_MACHINE(2, 5); -/* - * pseries-2.4 - */ - -static void spapr_machine_2_4_class_options(MachineClass *mc) -{ -SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); - -spapr_machine_2_5_class_options(mc); -smc->dr_lmb_enabled = false; -compat_props_add(mc->compat_props, hw_compat_2_4, hw_compat_2_4_len); -} - -DEFINE_SPAPR_MACHINE(2, 4); - static void spapr_machine_register_types(void) { type_register_static(&spapr_machine_info); -- 2.45.2
[PATCH v2 09/11] ppc/spapr: remove deprecated machine pseries-2.9
Commit 1392617d3576 intended to tag pseries-2.1 - 2.11 machines as deprecated with reasons mentioned in its commit log. Removing pseries-2.9 specific code with this patch for now. Suggested-by: Cédric Le Goater Signed-off-by: Harsh Prateek Bora --- target/ppc/cpu.h | 1 - hw/ppc/spapr.c| 20 target/ppc/cpu_init.c | 2 -- target/ppc/machine.c | 2 +- 4 files changed, 1 insertion(+), 24 deletions(-) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index cab4a46fc1..74a0ab768d 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1456,7 +1456,6 @@ struct ArchCPU { opc_handler_t *opcodes[PPC_CPU_OPCODES_LEN]; /* Fields related to migration compatibility hacks */ -bool pre_2_10_migration; bool pre_3_0_migration; int32_t mig_slb_nr; }; diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 97ab253fcc..84da4ece77 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -5184,26 +5184,6 @@ static void spapr_machine_2_10_class_options(MachineClass *mc) DEFINE_SPAPR_MACHINE(2, 10); -/* - * pseries-2.9 - */ - -static void spapr_machine_2_9_class_options(MachineClass *mc) -{ -SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); -static GlobalProperty compat[] = { -{ TYPE_POWERPC_CPU, "pre-2.10-migration", "on" }, -}; - -spapr_machine_2_10_class_options(mc); -compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len); -compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); -smc->pre_2_10_has_unused_icps = true; -smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED; -} - -DEFINE_SPAPR_MACHINE(2, 9); - static void spapr_machine_register_types(void) { type_register_static(&spapr_machine_info); diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 7768392986..39c19e6674 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -7452,8 +7452,6 @@ static void ppc_disas_set_info(CPUState *cs, disassemble_info *info) } static Property ppc_cpu_properties[] = { -DEFINE_PROP_BOOL("pre-2.10-migration", PowerPCCPU, pre_2_10_migration, - false), DEFINE_PROP_BOOL("pre-3.0-migration", PowerPCCPU, pre_3_0_migration, false), DEFINE_PROP_END_OF_LIST(), diff --git a/target/ppc/machine.c b/target/ppc/machine.c index 21bed7c7c8..47495b68b1 100644 --- a/target/ppc/machine.c +++ b/target/ppc/machine.c @@ -630,7 +630,7 @@ static bool compat_needed(void *opaque) PowerPCCPU *cpu = opaque; assert(!(cpu->compat_pvr && !cpu->vhyp)); -return !cpu->pre_2_10_migration && cpu->compat_pvr != 0; +return cpu->compat_pvr != 0; } static const VMStateDescription vmstate_compat = { -- 2.45.2
[PATCH v2 10/11] ppc/spapr: remove deprecated machine pseries-2.10
Commit 1392617d3576 intended to tag pseries-2.1 - 2.11 machines as deprecated with reasons mentioned in its commit log. Removing pseries-2.10 specific code with this patch for now. Suggested-by: Cédric Le Goater Signed-off-by: Harsh Prateek Bora --- hw/ppc/spapr.c | 12 1 file changed, 12 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 84da4ece77..cb6bf219bf 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -5172,18 +5172,6 @@ static void spapr_machine_2_11_class_options(MachineClass *mc) DEFINE_SPAPR_MACHINE(2, 11); -/* - * pseries-2.10 - */ - -static void spapr_machine_2_10_class_options(MachineClass *mc) -{ -spapr_machine_2_11_class_options(mc); -compat_props_add(mc->compat_props, hw_compat_2_10, hw_compat_2_10_len); -} - -DEFINE_SPAPR_MACHINE(2, 10); - static void spapr_machine_register_types(void) { type_register_static(&spapr_machine_info); -- 2.45.2
[PATCH v2 02/11] ppc/spapr: remove deprecated machine pseries-2.2
Commit 1392617d3576 intended to tag pseries-2.1 - 2.11 machines as deprecated with reasons mentioned in its commit log. Removing pseries-2.2 specific code with this patch for now. Suggested-by: Cédric Le Goater Signed-off-by: Harsh Prateek Bora --- hw/ppc/spapr.c | 17 - 1 file changed, 17 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index ec906e1d77..3c7d251356 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -5364,23 +5364,6 @@ static void spapr_machine_2_3_class_options(MachineClass *mc) } DEFINE_SPAPR_MACHINE(2, 3); -/* - * pseries-2.2 - */ - -static void spapr_machine_2_2_class_options(MachineClass *mc) -{ -static GlobalProperty compat[] = { -{ TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0x2000" }, -}; - -spapr_machine_2_3_class_options(mc); -compat_props_add(mc->compat_props, hw_compat_2_2, hw_compat_2_2_len); -compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); -mc->default_machine_opts = "modern-hotplug-events=off,suppress-vmdesc=on"; -} -DEFINE_SPAPR_MACHINE(2, 2); - static void spapr_machine_register_types(void) { type_register_static(&spapr_machine_info); -- 2.45.2
[PATCH v2 11/11] ppc/spapr: remove deprecated machine pseries-2.11
Commit 1392617d3576 intended to tag pseries-2.1 - 2.11 machines as deprecated with reasons mentioned in its commit log. Removing pseries-2.11 specific code with this patch. Suggested-by: Cédric Le Goater Signed-off-by: Harsh Prateek Bora --- hw/ppc/spapr.c | 15 --- 1 file changed, 15 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index cb6bf219bf..04f06377b4 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -5157,21 +5157,6 @@ static void spapr_machine_2_12_sxxm_class_options(MachineClass *mc) DEFINE_SPAPR_MACHINE_TAGGED(2, 12, sxxm); -/* - * pseries-2.11 - */ - -static void spapr_machine_2_11_class_options(MachineClass *mc) -{ -SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); - -spapr_machine_2_12_class_options(mc); -smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON; -compat_props_add(mc->compat_props, hw_compat_2_11, hw_compat_2_11_len); -} - -DEFINE_SPAPR_MACHINE(2, 11); - static void spapr_machine_register_types(void) { type_register_static(&spapr_machine_info); -- 2.45.2
[PATCH v2 08/11] ppc/spapr: remove deprecated machine pseries-2.8
Commit 1392617d3576 intended to tag pseries-2.1 - 2.11 machines as deprecated with reasons mentioned in its commit log. Removing pseries-2.8 specific code with this patch for now. Suggested-by: Cédric Le Goater Signed-off-by: Harsh Prateek Bora --- hw/ppc/spapr.c | 18 -- 1 file changed, 18 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 4e8f2a5d8e..97ab253fcc 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -5204,24 +5204,6 @@ static void spapr_machine_2_9_class_options(MachineClass *mc) DEFINE_SPAPR_MACHINE(2, 9); -/* - * pseries-2.8 - */ - -static void spapr_machine_2_8_class_options(MachineClass *mc) -{ -static GlobalProperty compat[] = { -{ TYPE_SPAPR_PCI_HOST_BRIDGE, "pcie-extended-configuration-space", "off" }, -}; - -spapr_machine_2_9_class_options(mc); -compat_props_add(mc->compat_props, hw_compat_2_8, hw_compat_2_8_len); -compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); -mc->numa_mem_align_shift = 23; -} - -DEFINE_SPAPR_MACHINE(2, 8); - static void spapr_machine_register_types(void) { type_register_static(&spapr_machine_info); -- 2.45.2
[PATCH v2 01/11] ppc/spapr: remove deprecated machine pseries-2.1
Commit 1392617d3576 intended to tag pseries-2.1 - 2.11 machines as deprecated with reasons mentioned in its commit log. Removing pseries-2.1 specific code with this patch for now. Suggested-by: Cédric Le Goater Signed-off-by: Harsh Prateek Bora --- hw/ppc/spapr.c | 11 --- 1 file changed, 11 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 8aa3ce7449..ec906e1d77 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -5381,17 +5381,6 @@ static void spapr_machine_2_2_class_options(MachineClass *mc) } DEFINE_SPAPR_MACHINE(2, 2); -/* - * pseries-2.1 - */ - -static void spapr_machine_2_1_class_options(MachineClass *mc) -{ -spapr_machine_2_2_class_options(mc); -compat_props_add(mc->compat_props, hw_compat_2_1, hw_compat_2_1_len); -} -DEFINE_SPAPR_MACHINE(2, 1); - static void spapr_machine_register_types(void) { type_register_static(&spapr_machine_info); -- 2.45.2
[PATCH v2 05/11] ppc/spapr: remove deprecated machine pseries-2.5
Commit 1392617d3576 intended to tag pseries-2.1 - 2.11 machines as deprecated with reasons mentioned in its commit log. Removing pseries-2.5 specific code with this patch for now. Suggested-by: Cédric Le Goater Signed-off-by: Harsh Prateek Bora --- hw/ppc/spapr.c | 19 --- 1 file changed, 19 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 9e78f94ec2..a38d4e098a 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -5315,25 +5315,6 @@ static void spapr_machine_2_6_class_options(MachineClass *mc) DEFINE_SPAPR_MACHINE(2, 6); -/* - * pseries-2.5 - */ - -static void spapr_machine_2_5_class_options(MachineClass *mc) -{ -SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); -static GlobalProperty compat[] = { -{ "spapr-vlan", "use-rx-buffer-pools", "off" }, -}; - -spapr_machine_2_6_class_options(mc); -smc->use_ohci_by_default = true; -compat_props_add(mc->compat_props, hw_compat_2_5, hw_compat_2_5_len); -compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); -} - -DEFINE_SPAPR_MACHINE(2, 5); - static void spapr_machine_register_types(void) { type_register_static(&spapr_machine_info); -- 2.45.2
[PATCH v2 03/11] ppc/spapr: remove deprecated machine pseries-2.3
Commit 1392617d3576 intended to tag pseries-2.1 - 2.11 machines as deprecated with reasons mentioned in its commit log. Removing pseries-2.3 specific code with this patch for now. Suggested-by: Cédric Le Goater Signed-off-by: Harsh Prateek Bora --- hw/ppc/spapr.c | 15 --- 1 file changed, 15 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 3c7d251356..f2f20aa5b5 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -5349,21 +5349,6 @@ static void spapr_machine_2_4_class_options(MachineClass *mc) DEFINE_SPAPR_MACHINE(2, 4); -/* - * pseries-2.3 - */ - -static void spapr_machine_2_3_class_options(MachineClass *mc) -{ -static GlobalProperty compat[] = { -{ "spapr-pci-host-bridge", "dynamic-reconfiguration", "off" }, -}; -spapr_machine_2_4_class_options(mc); -compat_props_add(mc->compat_props, hw_compat_2_3, hw_compat_2_3_len); -compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); -} -DEFINE_SPAPR_MACHINE(2, 3); - static void spapr_machine_register_types(void) { type_register_static(&spapr_machine_info); -- 2.45.2
Re: [PATCH v16 02/13] hw/ppc/spapr_pci: Do not create DT for disabled PCI device
On 9/18/24 19:57, Cédric Le Goater wrote: Hello, Adding : Harsh for QEMU/PPC pseries machine, Shivaprasad for KVM/PPC VFIO and IOMMU support. Could you please give us your feedback on these changes ? Thanks, C. On 9/13/24 05:44, Akihiko Odaki wrote: Disabled means it is a disabled SR-IOV VF or it is powered off, and hidden from the guest. Signed-off-by: Akihiko Odaki --- hw/ppc/spapr_pci.c | 4 1 file changed, 4 insertions(+) diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 7cf9904c3546..f63182a03c41 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1296,6 +1296,10 @@ static void spapr_dt_pci_device_cb(PCIBus *bus, PCIDevice *pdev, return; } + if (!pdev->enabled) { + return; + } + While I will let Shivaprasad comment from IO perspective, I would like to suggest merging this condition with the error condition check preceding it. regards, Harsh err = spapr_dt_pci_device(p->sphb, pdev, p->fdt, p->offset); if (err < 0) { p->err = err;
Re: [PATCH] ppc/spapr: remove deprecated machines specific code
Hi Cedric, On 9/17/24 12:31, Cédric Le Goater wrote: Hello Harsh, On 9/17/24 08:03, Harsh Prateek Bora wrote: Commit 1392617d3576 intended to tag pseries-2.1 - 2.11 machines as deprecated with reasons mentioned in its commit log. Removing the arch specific code for the now deprecated machine types. Suggested-by: Cédric Le Goater Signed-off-by: Harsh Prateek Bora There is more to it :/ Some machine versions have their own set of properties, like the "pre-*-migration" ones, and the associated code should be removed also. It impacts more models than just the machine model. I suggest one patch per machine version, or one patch per complex machine version and a combo patch for the simple ones. Sure, I shall post v2 as a patchset addressing your inputs. regards, Harsh Thanks, C. --- hw/ppc/spapr.c | 235 - 1 file changed, 235 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 8aa3ce7449..04f06377b4 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -5157,241 +5157,6 @@ static void spapr_machine_2_12_sxxm_class_options(MachineClass *mc) DEFINE_SPAPR_MACHINE_TAGGED(2, 12, sxxm); -/* - * pseries-2.11 - */ - -static void spapr_machine_2_11_class_options(MachineClass *mc) -{ - SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); - - spapr_machine_2_12_class_options(mc); - smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON; - compat_props_add(mc->compat_props, hw_compat_2_11, hw_compat_2_11_len); -} - -DEFINE_SPAPR_MACHINE(2, 11); - -/* - * pseries-2.10 - */ - -static void spapr_machine_2_10_class_options(MachineClass *mc) -{ - spapr_machine_2_11_class_options(mc); - compat_props_add(mc->compat_props, hw_compat_2_10, hw_compat_2_10_len); -} - -DEFINE_SPAPR_MACHINE(2, 10); - -/* - * pseries-2.9 - */ - -static void spapr_machine_2_9_class_options(MachineClass *mc) -{ - SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); - static GlobalProperty compat[] = { - { TYPE_POWERPC_CPU, "pre-2.10-migration", "on" }, - }; - - spapr_machine_2_10_class_options(mc); - compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len); - compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); - smc->pre_2_10_has_unused_icps = true; - smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED; -} - -DEFINE_SPAPR_MACHINE(2, 9); - -/* - * pseries-2.8 - */ - -static void spapr_machine_2_8_class_options(MachineClass *mc) -{ - static GlobalProperty compat[] = { - { TYPE_SPAPR_PCI_HOST_BRIDGE, "pcie-extended-configuration-space", "off" }, - }; - - spapr_machine_2_9_class_options(mc); - compat_props_add(mc->compat_props, hw_compat_2_8, hw_compat_2_8_len); - compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); - mc->numa_mem_align_shift = 23; -} - -DEFINE_SPAPR_MACHINE(2, 8); - -/* - * pseries-2.7 - */ - -static bool phb_placement_2_7(SpaprMachineState *spapr, uint32_t index, - uint64_t *buid, hwaddr *pio, - hwaddr *mmio32, hwaddr *mmio64, - unsigned n_dma, uint32_t *liobns, Error **errp) -{ - /* Legacy PHB placement for pseries-2.7 and earlier machine types */ - const uint64_t base_buid = 0x8002000ULL; - const hwaddr phb_spacing = 0x10ULL; /* 64 GiB */ - const hwaddr mmio_offset = 0xa000; /* 2 GiB + 512 MiB */ - const hwaddr pio_offset = 0x8000; /* 2 GiB */ - const uint32_t max_index = 255; - const hwaddr phb0_alignment = 0x100ULL; /* 1 TiB */ - - uint64_t ram_top = MACHINE(spapr)->ram_size; - hwaddr phb0_base, phb_base; - int i; - - /* Do we have device memory? */ - if (MACHINE(spapr)->device_memory) { - /* Can't just use maxram_size, because there may be an - * alignment gap between normal and device memory regions - */ - ram_top = MACHINE(spapr)->device_memory->base + - memory_region_size(&MACHINE(spapr)->device_memory->mr); - } - - phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment); - - if (index > max_index) { - error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)", - max_index); - return false; - } - - *buid = base_buid + index; - for (i = 0; i < n_dma; ++i) { - liobns[i] = SPAPR_PCI_LIOBN(index, i); - } - - phb_base = phb0_base + index * phb_spacing; - *pio = phb_base + pio_offset; - *mmio32 = phb_base + mmio_offset; - /* - * We don't set the 64-bit MMIO window, relying on the PHB's - * fallback behaviour of automatically splitting a large "32-bit" - * window into contiguous 32-bit and 64-bit windows - */ - - return true; -} - -static void spapr_machine_2_7_class_options(MachineClass *mc) -{ - Spap
[PATCH] ppc/spapr: remove deprecated machines specific code
Commit 1392617d3576 intended to tag pseries-2.1 - 2.11 machines as deprecated with reasons mentioned in its commit log. Removing the arch specific code for the now deprecated machine types. Suggested-by: Cédric Le Goater Signed-off-by: Harsh Prateek Bora --- hw/ppc/spapr.c | 235 - 1 file changed, 235 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 8aa3ce7449..04f06377b4 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -5157,241 +5157,6 @@ static void spapr_machine_2_12_sxxm_class_options(MachineClass *mc) DEFINE_SPAPR_MACHINE_TAGGED(2, 12, sxxm); -/* - * pseries-2.11 - */ - -static void spapr_machine_2_11_class_options(MachineClass *mc) -{ -SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); - -spapr_machine_2_12_class_options(mc); -smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON; -compat_props_add(mc->compat_props, hw_compat_2_11, hw_compat_2_11_len); -} - -DEFINE_SPAPR_MACHINE(2, 11); - -/* - * pseries-2.10 - */ - -static void spapr_machine_2_10_class_options(MachineClass *mc) -{ -spapr_machine_2_11_class_options(mc); -compat_props_add(mc->compat_props, hw_compat_2_10, hw_compat_2_10_len); -} - -DEFINE_SPAPR_MACHINE(2, 10); - -/* - * pseries-2.9 - */ - -static void spapr_machine_2_9_class_options(MachineClass *mc) -{ -SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); -static GlobalProperty compat[] = { -{ TYPE_POWERPC_CPU, "pre-2.10-migration", "on" }, -}; - -spapr_machine_2_10_class_options(mc); -compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len); -compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); -smc->pre_2_10_has_unused_icps = true; -smc->resize_hpt_default = SPAPR_RESIZE_HPT_DISABLED; -} - -DEFINE_SPAPR_MACHINE(2, 9); - -/* - * pseries-2.8 - */ - -static void spapr_machine_2_8_class_options(MachineClass *mc) -{ -static GlobalProperty compat[] = { -{ TYPE_SPAPR_PCI_HOST_BRIDGE, "pcie-extended-configuration-space", "off" }, -}; - -spapr_machine_2_9_class_options(mc); -compat_props_add(mc->compat_props, hw_compat_2_8, hw_compat_2_8_len); -compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); -mc->numa_mem_align_shift = 23; -} - -DEFINE_SPAPR_MACHINE(2, 8); - -/* - * pseries-2.7 - */ - -static bool phb_placement_2_7(SpaprMachineState *spapr, uint32_t index, - uint64_t *buid, hwaddr *pio, - hwaddr *mmio32, hwaddr *mmio64, - unsigned n_dma, uint32_t *liobns, Error **errp) -{ -/* Legacy PHB placement for pseries-2.7 and earlier machine types */ -const uint64_t base_buid = 0x8002000ULL; -const hwaddr phb_spacing = 0x10ULL; /* 64 GiB */ -const hwaddr mmio_offset = 0xa000; /* 2 GiB + 512 MiB */ -const hwaddr pio_offset = 0x8000; /* 2 GiB */ -const uint32_t max_index = 255; -const hwaddr phb0_alignment = 0x100ULL; /* 1 TiB */ - -uint64_t ram_top = MACHINE(spapr)->ram_size; -hwaddr phb0_base, phb_base; -int i; - -/* Do we have device memory? */ -if (MACHINE(spapr)->device_memory) { -/* Can't just use maxram_size, because there may be an - * alignment gap between normal and device memory regions - */ -ram_top = MACHINE(spapr)->device_memory->base + -memory_region_size(&MACHINE(spapr)->device_memory->mr); -} - -phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment); - -if (index > max_index) { -error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)", - max_index); -return false; -} - -*buid = base_buid + index; -for (i = 0; i < n_dma; ++i) { -liobns[i] = SPAPR_PCI_LIOBN(index, i); -} - -phb_base = phb0_base + index * phb_spacing; -*pio = phb_base + pio_offset; -*mmio32 = phb_base + mmio_offset; -/* - * We don't set the 64-bit MMIO window, relying on the PHB's - * fallback behaviour of automatically splitting a large "32-bit" - * window into contiguous 32-bit and 64-bit windows - */ - -return true; -} - -static void spapr_machine_2_7_class_options(MachineClass *mc) -{ -SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); -static GlobalProperty compat[] = { -{ TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0xf8000", }, -{ TYPE_SPAPR_PCI_HOST_BRIDGE, "mem64_win_size", "0", }, -{ TYPE_POWERPC_CPU, "pre-2.8-migration", "on", }, -{ TYPE_SPAPR_PCI_HOST_BRIDGE, "pre-2.8-migration", "on", }, -}; - -spapr_machine_2_8_class_options(mc); -mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power7_v2.3&qu
Re: [PATCH] target/ppc: Fix inequality check in do_lstxv_X
Hi Fabiano, On 9/13/24 17:02, Fabiano Rosas wrote: Harsh Prateek Bora writes: This fix was earlier introduced for do_lstxv_D form with 2cc0e449d173 however got missed for _X form. This patch fixes the same. Cc: qemu-sta...@nongnu.org Suggested-by: Fabiano Rosas Fixes: 70426b5bb738 ("target/ppc: moved stxvx and lxvx from legacy to decodtree") Signed-off-by: Harsh Prateek Bora --- target/ppc/translate/vsx-impl.c.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/ppc/translate/vsx-impl.c.inc b/target/ppc/translate/vsx-impl.c.inc index 40a87ddc4a..a869f30e86 100644 --- a/target/ppc/translate/vsx-impl.c.inc +++ b/target/ppc/translate/vsx-impl.c.inc @@ -2244,7 +2244,7 @@ static bool do_lstxv_PLS_D(DisasContext *ctx, arg_PLS_D *a, static bool do_lstxv_X(DisasContext *ctx, arg_X *a, bool store, bool paired) { -if (paired || a->rt >= 32) { +if (paired || a->rt < 32) { REQUIRE_VSX(ctx); } else { REQUIRE_VECTOR(ctx); Hi Harsh, Seems I was quicker than you =) https://lore.kernel.org/r/20240911141651.6914-1-faro...@suse.de I'll give my RB and leave up to the maintainers which patch to take: Reviewed-by: Fabiano Rosas Thanks, I missed looking at your patch earlier. I would vote for your patch though. regards, Harsh
Re: [PATCH v3 09/10] target/ppc: simplify var usage in ppc_next_unmasked_interrupt
On 9/13/24 18:20, BALATON Zoltan wrote: On Fri, 13 Sep 2024, Harsh Prateek Bora wrote: As previously done for arch specific handlers, simplify var usage in ppc_next_unmasked_interrupt by caching the env->pending_interrupts and env->spr[SPR_LPCR] in local vars and using it later at multiple places. Signed-off-by: Harsh Prateek Bora --- target/ppc/excp_helper.c | 54 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index d0e0f609a0..4dff5b 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -2022,31 +2022,31 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env, static int ppc_next_unmasked_interrupt(CPUPPCState *env) { + uint32_t pending_interrupts = env->pending_interrupts; + target_ulong lpcr = env->spr[SPR_LPCR]; + bool async_deliver; Maybe easier to review if split into one patch for each variable added so it's easier to see what's replaced and that nothing is missed. Thanks for the reviews. I shall split as suggested in v4. regards, Harsh Regards, BALATON Zoltan + #ifdef TARGET_PPC64 switch (env->excp_model) { case POWERPC_EXCP_POWER7: - return p7_next_unmasked_interrupt(env, env->pending_interrupts, - env->spr[SPR_LPCR]); + return p7_next_unmasked_interrupt(env, pending_interrupts, lpcr); case POWERPC_EXCP_POWER8: - return p8_next_unmasked_interrupt(env, env->pending_interrupts, - env->spr[SPR_LPCR]); + return p8_next_unmasked_interrupt(env, pending_interrupts, lpcr); case POWERPC_EXCP_POWER9: case POWERPC_EXCP_POWER10: case POWERPC_EXCP_POWER11: - return p9_next_unmasked_interrupt(env, env->pending_interrupts, - env->spr[SPR_LPCR]); + return p9_next_unmasked_interrupt(env, pending_interrupts, lpcr); default: break; } #endif - bool async_deliver; /* External reset */ - if (env->pending_interrupts & PPC_INTERRUPT_RESET) { + if (pending_interrupts & PPC_INTERRUPT_RESET) { return PPC_INTERRUPT_RESET; } /* Machine check exception */ - if (env->pending_interrupts & PPC_INTERRUPT_MCK) { + if (pending_interrupts & PPC_INTERRUPT_MCK) { return PPC_INTERRUPT_MCK; } #if 0 /* TODO */ @@ -2065,9 +2065,9 @@ static int ppc_next_unmasked_interrupt(CPUPPCState *env) async_deliver = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset; /* Hypervisor decrementer exception */ - if (env->pending_interrupts & PPC_INTERRUPT_HDECR) { + if (pending_interrupts & PPC_INTERRUPT_HDECR) { /* LPCR will be clear when not supported so this will work */ - bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE); + bool hdice = !!(lpcr & LPCR_HDICE); if ((async_deliver || !FIELD_EX64_HV(env->msr)) && hdice) { /* HDEC clears on delivery */ return PPC_INTERRUPT_HDECR; @@ -2075,18 +2075,18 @@ static int ppc_next_unmasked_interrupt(CPUPPCState *env) } /* Hypervisor virtualization interrupt */ - if (env->pending_interrupts & PPC_INTERRUPT_HVIRT) { + if (pending_interrupts & PPC_INTERRUPT_HVIRT) { /* LPCR will be clear when not supported so this will work */ - bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE); + bool hvice = !!(lpcr & LPCR_HVICE); if ((async_deliver || !FIELD_EX64_HV(env->msr)) && hvice) { return PPC_INTERRUPT_HVIRT; } } /* External interrupt can ignore MSR:EE under some circumstances */ - if (env->pending_interrupts & PPC_INTERRUPT_EXT) { - bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); - bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); + if (pending_interrupts & PPC_INTERRUPT_EXT) { + bool lpes0 = !!(lpcr & LPCR_LPES0); + bool heic = !!(lpcr & LPCR_HEIC); /* HEIC blocks delivery to the hypervisor */ if ((async_deliver && !(heic && FIELD_EX64_HV(env->msr) && !FIELD_EX64(env->msr, MSR, PR))) || @@ -2096,45 +2096,45 @@ static int ppc_next_unmasked_interrupt(CPUPPCState *env) } if (FIELD_EX64(env->msr, MSR, CE)) { /* External critical interrupt */ - if (env->pending_interrupts & PPC_INTERRUPT_CEXT) { + if (pending_interrupts & PPC_INTERRUPT_CEXT) { return PPC_INTERRUPT_CEXT; } } if (async_deliver != 0) { /* Watchdog timer on embedded PowerPC */ - if (env->pending_interrupts & PPC_INTERRUPT_WDT) { + if (pending_interrupts & PPC_INTERRUPT_WDT) { return PPC_INTERRUPT_WDT; } - if (env->pendin
Re: [PULL 20/49] spapr: Tag pseries-2.1 - 2.11 machines as deprecated
Hi Cedric, On 9/16/24 18:44, Cédric Le Goater wrote: Hello Harsh, On 2/19/24 09:29, Nicholas Piggin wrote: From: Cédric Le Goater pseries machines before version 2.11 have undergone many changes to correct issues, mostly regarding migration compatibility. This is obfuscating the code uselessly and makes maintenance more difficult. Remove them and only keep the last version of the 2.x series, 2.12, still in use by old distros. Reviewed-by: Thomas Huth Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater Signed-off-by: Nicholas Piggin --- docs/about/deprecated.rst | 8 hw/ppc/spapr.c | 1 + roms/skiboot | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 5a2305ccd6..36bd3e15ef 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -229,6 +229,14 @@ The Nios II architecture is orphan. The machine is no longer in existence and has been long unmaintained in QEMU. This also holds for the TC51828 16MiB flash that it uses. +``pseries-2.1`` up to ``pseries-2.11`` (since 9.0) +'' + +Older pseries machines before version 2.12 have undergone many changes +to correct issues, mostly regarding migration compatibility. These are +no longer maintained and removing them will make the code easier to +read and maintain. Use versions 2.12 and above as a replacement. + Would you have time, or a KVM PPC team member, to start removing the now deprecated pseries machines in the QEMU 9.2 cycle ? Sure, I can take a look at that. regards, Harsh Thanks, C.
Re: [PATCH] target/ppc: Fix lxv/stxv MSR facility check
Hi Fabiano, On 9/10/24 04:36, Fabiano Rosas wrote: Nicholas Piggin writes: The move to decodetree flipped the inequality test for the VEC / VSX MSR facility check. This caused application crashes under Linux, where these facility unavailable interrupts are used for lazy-switching of VEC/VSX register sets. Getting the incorrect interrupt would result in wrong registers being loaded, potentially overwriting live values and/or exposing stale ones. Cc: qemu-sta...@nongnu.org Reported-by: Joel Stanley Fixes: 70426b5bb738 ("target/ppc: moved stxvx and lxvx from legacy to decodtree") Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1769 Tested-by: Harsh Prateek Bora Signed-off-by: Nicholas Piggin --- target/ppc/translate/vsx-impl.c.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/ppc/translate/vsx-impl.c.inc b/target/ppc/translate/vsx-impl.c.inc index 6db87ab336..0266f09119 100644 --- a/target/ppc/translate/vsx-impl.c.inc +++ b/target/ppc/translate/vsx-impl.c.inc @@ -2268,7 +2268,7 @@ static bool do_lstxv(DisasContext *ctx, int ra, TCGv displ, static bool do_lstxv_D(DisasContext *ctx, arg_D *a, bool store, bool paired) { -if (paired || a->rt >= 32) { +if (paired || a->rt < 32) { REQUIRE_VSX(ctx); } else { REQUIRE_VECTOR(ctx); What about the X-form down below? static bool do_lstxv_X(DisasContext *ctx, arg_X *a, bool store, bool paired) { if (paired || a->rt >= 32) { REQUIRE_VSX(ctx); } else { REQUIRE_VECTOR(ctx); } return do_lstxv(ctx, a->ra, cpu_gpr[a->rb], a->rt, store, paired); } Thanks for catching this. I have posted the fix here: https://lore.kernel.org/qemu-devel/20240913043827.914457-1-hars...@linux.ibm.com/T/#u regards, Harsh
[PATCH] target/ppc: Fix inequality check in do_lstxv_X
This fix was earlier introduced for do_lstxv_D form with 2cc0e449d173 however got missed for _X form. This patch fixes the same. Cc: qemu-sta...@nongnu.org Suggested-by: Fabiano Rosas Fixes: 70426b5bb738 ("target/ppc: moved stxvx and lxvx from legacy to decodtree") Signed-off-by: Harsh Prateek Bora --- target/ppc/translate/vsx-impl.c.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/ppc/translate/vsx-impl.c.inc b/target/ppc/translate/vsx-impl.c.inc index 40a87ddc4a..a869f30e86 100644 --- a/target/ppc/translate/vsx-impl.c.inc +++ b/target/ppc/translate/vsx-impl.c.inc @@ -2244,7 +2244,7 @@ static bool do_lstxv_PLS_D(DisasContext *ctx, arg_PLS_D *a, static bool do_lstxv_X(DisasContext *ctx, arg_X *a, bool store, bool paired) { -if (paired || a->rt >= 32) { +if (paired || a->rt < 32) { REQUIRE_VSX(ctx); } else { REQUIRE_VECTOR(ctx); -- 2.45.2
Re: [PATCH v2 5/7] target/ppc: optimize p9 exception handling routines for lpcr
Hi Nick, On 7/4/24 13:13, Nicholas Piggin wrote: On Thu May 23, 2024 at 3:14 PM AEST, Harsh Prateek Bora wrote: Like pending_interrupts, env->spr[SPR_LPCR] is being used at multiple places across p9 exception handlers. Pass the value during entry and avoid multiple indirect accesses. Ditto for this (does it help code, other CPU functions should be converted similarly). Thanks for your review comments and apologies for a late response. I have posted v3 with suggested updates and some additional patches. Patch 7/7 of this series had been picked by Aditya and updated in his patchset for P11 support so I have excluded that in v3 and just rebased on top of his v6 series. v3: https://lore.kernel.org/qemu-devel/20240913041337.912876-1-hars...@linux.ibm.com/T/#t regards, Harsh Thanks, Nick Signed-off-by: Harsh Prateek Bora --- target/ppc/excp_helper.c | 33 ++--- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 704eddac63..d3db81e6ae 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -1843,13 +1843,14 @@ static int p8_next_unmasked_interrupt(CPUPPCState *env) PPC_INTERRUPT_PIT | PPC_INTERRUPT_THERM) static int p9_interrupt_powersave(CPUPPCState *env, - uint32_t pending_interrupts) + uint32_t pending_interrupts, + target_ulong lpcr) { /* External Exception */ if ((pending_interrupts & PPC_INTERRUPT_EXT) && -(env->spr[SPR_LPCR] & LPCR_EEE)) { -bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); +(lpcr & LPCR_EEE)) { +bool heic = !!(lpcr & LPCR_HEIC); if (!heic || !FIELD_EX64_HV(env->msr) || FIELD_EX64(env->msr, MSR, PR)) { return PPC_INTERRUPT_EXT; @@ -1857,11 +1858,11 @@ static int p9_interrupt_powersave(CPUPPCState *env, } /* Decrementer Exception */ if ((pending_interrupts & PPC_INTERRUPT_DECR) && -(env->spr[SPR_LPCR] & LPCR_DEE)) { +(lpcr & LPCR_DEE)) { return PPC_INTERRUPT_DECR; } /* Machine Check or Hypervisor Maintenance Exception */ -if (env->spr[SPR_LPCR] & LPCR_OEE) { +if (lpcr & LPCR_OEE) { if (pending_interrupts & PPC_INTERRUPT_MCK) { return PPC_INTERRUPT_MCK; } @@ -1871,17 +1872,17 @@ static int p9_interrupt_powersave(CPUPPCState *env, } /* Privileged Doorbell Exception */ if ((pending_interrupts & PPC_INTERRUPT_DOORBELL) && -(env->spr[SPR_LPCR] & LPCR_PDEE)) { +(lpcr & LPCR_PDEE)) { return PPC_INTERRUPT_DOORBELL; } /* Hypervisor Doorbell Exception */ if ((pending_interrupts & PPC_INTERRUPT_HDOORBELL) && -(env->spr[SPR_LPCR] & LPCR_HDEE)) { +(lpcr & LPCR_HDEE)) { return PPC_INTERRUPT_HDOORBELL; } /* Hypervisor virtualization exception */ if ((pending_interrupts & PPC_INTERRUPT_HVIRT) && -(env->spr[SPR_LPCR] & LPCR_HVEE)) { +(lpcr & LPCR_HVEE)) { return PPC_INTERRUPT_HVIRT; } if (pending_interrupts & PPC_INTERRUPT_RESET) { @@ -1891,7 +1892,8 @@ static int p9_interrupt_powersave(CPUPPCState *env, } static int p9_next_unmasked_interrupt(CPUPPCState *env, - uint32_t pending_interrupts) + uint32_t pending_interrupts, + target_ulong lpcr) { CPUState *cs = env_cpu(env); @@ -1906,7 +1908,7 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env, * When PSSCR[EC] is set, LPCR[PECE] controls which interrupts can * wakeup the processor */ -return p9_interrupt_powersave(env, pending_interrupts); +return p9_interrupt_powersave(env, pending_interrupts, lpcr); } else { /* * When it's clear, any system-caused exception exits power-saving @@ -1924,7 +1926,7 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env, /* Hypervisor decrementer exception */ if (pending_interrupts & PPC_INTERRUPT_HDECR) { /* LPCR will be clear when not supported so this will work */ -bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE); +bool hdice = !!(lpcr & LPCR_HDICE); if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) { /* HDEC clears on delivery */ return PPC_INTERRUPT_HDECR; @@ -1934,7 +1936,7 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env, /* Hypervisor virtualization interrupt */ if (pending_interrupts & PPC_INTERRUPT_HVIRT) {
[PATCH v3 09/10] target/ppc: simplify var usage in ppc_next_unmasked_interrupt
As previously done for arch specific handlers, simplify var usage in ppc_next_unmasked_interrupt by caching the env->pending_interrupts and env->spr[SPR_LPCR] in local vars and using it later at multiple places. Signed-off-by: Harsh Prateek Bora --- target/ppc/excp_helper.c | 54 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index d0e0f609a0..4dff5b 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -2022,31 +2022,31 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env, static int ppc_next_unmasked_interrupt(CPUPPCState *env) { +uint32_t pending_interrupts = env->pending_interrupts; +target_ulong lpcr = env->spr[SPR_LPCR]; +bool async_deliver; + #ifdef TARGET_PPC64 switch (env->excp_model) { case POWERPC_EXCP_POWER7: -return p7_next_unmasked_interrupt(env, env->pending_interrupts, - env->spr[SPR_LPCR]); +return p7_next_unmasked_interrupt(env, pending_interrupts, lpcr); case POWERPC_EXCP_POWER8: -return p8_next_unmasked_interrupt(env, env->pending_interrupts, - env->spr[SPR_LPCR]); +return p8_next_unmasked_interrupt(env, pending_interrupts, lpcr); case POWERPC_EXCP_POWER9: case POWERPC_EXCP_POWER10: case POWERPC_EXCP_POWER11: -return p9_next_unmasked_interrupt(env, env->pending_interrupts, - env->spr[SPR_LPCR]); +return p9_next_unmasked_interrupt(env, pending_interrupts, lpcr); default: break; } #endif -bool async_deliver; /* External reset */ -if (env->pending_interrupts & PPC_INTERRUPT_RESET) { +if (pending_interrupts & PPC_INTERRUPT_RESET) { return PPC_INTERRUPT_RESET; } /* Machine check exception */ -if (env->pending_interrupts & PPC_INTERRUPT_MCK) { +if (pending_interrupts & PPC_INTERRUPT_MCK) { return PPC_INTERRUPT_MCK; } #if 0 /* TODO */ @@ -2065,9 +2065,9 @@ static int ppc_next_unmasked_interrupt(CPUPPCState *env) async_deliver = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset; /* Hypervisor decrementer exception */ -if (env->pending_interrupts & PPC_INTERRUPT_HDECR) { +if (pending_interrupts & PPC_INTERRUPT_HDECR) { /* LPCR will be clear when not supported so this will work */ -bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE); +bool hdice = !!(lpcr & LPCR_HDICE); if ((async_deliver || !FIELD_EX64_HV(env->msr)) && hdice) { /* HDEC clears on delivery */ return PPC_INTERRUPT_HDECR; @@ -2075,18 +2075,18 @@ static int ppc_next_unmasked_interrupt(CPUPPCState *env) } /* Hypervisor virtualization interrupt */ -if (env->pending_interrupts & PPC_INTERRUPT_HVIRT) { +if (pending_interrupts & PPC_INTERRUPT_HVIRT) { /* LPCR will be clear when not supported so this will work */ -bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE); +bool hvice = !!(lpcr & LPCR_HVICE); if ((async_deliver || !FIELD_EX64_HV(env->msr)) && hvice) { return PPC_INTERRUPT_HVIRT; } } /* External interrupt can ignore MSR:EE under some circumstances */ -if (env->pending_interrupts & PPC_INTERRUPT_EXT) { -bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); -bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); +if (pending_interrupts & PPC_INTERRUPT_EXT) { +bool lpes0 = !!(lpcr & LPCR_LPES0); +bool heic = !!(lpcr & LPCR_HEIC); /* HEIC blocks delivery to the hypervisor */ if ((async_deliver && !(heic && FIELD_EX64_HV(env->msr) && !FIELD_EX64(env->msr, MSR, PR))) || @@ -2096,45 +2096,45 @@ static int ppc_next_unmasked_interrupt(CPUPPCState *env) } if (FIELD_EX64(env->msr, MSR, CE)) { /* External critical interrupt */ -if (env->pending_interrupts & PPC_INTERRUPT_CEXT) { +if (pending_interrupts & PPC_INTERRUPT_CEXT) { return PPC_INTERRUPT_CEXT; } } if (async_deliver != 0) { /* Watchdog timer on embedded PowerPC */ -if (env->pending_interrupts & PPC_INTERRUPT_WDT) { +if (pending_interrupts & PPC_INTERRUPT_WDT) { return PPC_INTERRUPT_WDT; } -if (env->pending_interrupts & PPC_INTERRUPT_CDOORBELL) { +if (pending_interrupts & PPC_INTERRUPT_CDOORBELL) { return PPC_INTERRUPT_CDOORBELL; } /* Fixed interval timer on embedded PowerPC */ -if (env->pending_interrupts & PPC_INTERRUPT_FIT) { +
[PATCH v3 02/10] target/ppc: optimize hreg_compute_pmu_hflags_value
Cache env->spr[SPR_POWER_MMCR0] in a local variable as used in multiple conditions to avoid multiple indirect accesses. Signed-off-by: Harsh Prateek Bora Reviewed-by: Nicholas Piggin --- target/ppc/helper_regs.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c index fe543ab3b8..7b23e5ef0e 100644 --- a/target/ppc/helper_regs.c +++ b/target/ppc/helper_regs.c @@ -83,15 +83,16 @@ static bool hreg_check_bhrb_enable(CPUPPCState *env) static uint32_t hreg_compute_pmu_hflags_value(CPUPPCState *env) { uint32_t hflags = 0; - #if defined(TARGET_PPC64) -if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCC0) { +target_ulong mmcr0 = env->spr[SPR_POWER_MMCR0]; + +if (mmcr0 & MMCR0_PMCC0) { hflags |= 1 << HFLAGS_PMCC0; } -if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCC1) { +if (mmcr0 & MMCR0_PMCC1) { hflags |= 1 << HFLAGS_PMCC1; } -if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCjCE) { +if (mmcr0 & MMCR0_PMCjCE) { hflags |= 1 << HFLAGS_PMCJCE; } if (hreg_check_bhrb_enable(env)) { -- 2.45.2
[PATCH v3 04/10] target/ppc: optimize p9 exception handling routines
Currently, p9 exception handling has multiple if-condition checks where it does an indirect access to pending_interrupts via env. Pass the value during entry to avoid multiple indirect accesses. Signed-off-by: Harsh Prateek Bora --- target/ppc/excp_helper.c | 47 +--- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 2029144622..31c1653e2b 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -1872,10 +1872,12 @@ static int p8_next_unmasked_interrupt(CPUPPCState *env) PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | PPC_INTERRUPT_FIT | \ PPC_INTERRUPT_PIT | PPC_INTERRUPT_THERM) -static int p9_interrupt_powersave(CPUPPCState *env) +static int p9_interrupt_powersave(CPUPPCState *env, + uint32_t pending_interrupts) { + /* External Exception */ -if ((env->pending_interrupts & PPC_INTERRUPT_EXT) && +if ((pending_interrupts & PPC_INTERRUPT_EXT) && (env->spr[SPR_LPCR] & LPCR_EEE)) { bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); if (!heic || !FIELD_EX64_HV(env->msr) || @@ -1884,48 +1886,49 @@ static int p9_interrupt_powersave(CPUPPCState *env) } } /* Decrementer Exception */ -if ((env->pending_interrupts & PPC_INTERRUPT_DECR) && +if ((pending_interrupts & PPC_INTERRUPT_DECR) && (env->spr[SPR_LPCR] & LPCR_DEE)) { return PPC_INTERRUPT_DECR; } /* Machine Check or Hypervisor Maintenance Exception */ if (env->spr[SPR_LPCR] & LPCR_OEE) { -if (env->pending_interrupts & PPC_INTERRUPT_MCK) { +if (pending_interrupts & PPC_INTERRUPT_MCK) { return PPC_INTERRUPT_MCK; } -if (env->pending_interrupts & PPC_INTERRUPT_HMI) { +if (pending_interrupts & PPC_INTERRUPT_HMI) { return PPC_INTERRUPT_HMI; } } /* Privileged Doorbell Exception */ -if ((env->pending_interrupts & PPC_INTERRUPT_DOORBELL) && +if ((pending_interrupts & PPC_INTERRUPT_DOORBELL) && (env->spr[SPR_LPCR] & LPCR_PDEE)) { return PPC_INTERRUPT_DOORBELL; } /* Hypervisor Doorbell Exception */ -if ((env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) && +if ((pending_interrupts & PPC_INTERRUPT_HDOORBELL) && (env->spr[SPR_LPCR] & LPCR_HDEE)) { return PPC_INTERRUPT_HDOORBELL; } /* Hypervisor virtualization exception */ -if ((env->pending_interrupts & PPC_INTERRUPT_HVIRT) && +if ((pending_interrupts & PPC_INTERRUPT_HVIRT) && (env->spr[SPR_LPCR] & LPCR_HVEE)) { return PPC_INTERRUPT_HVIRT; } -if (env->pending_interrupts & PPC_INTERRUPT_RESET) { +if (pending_interrupts & PPC_INTERRUPT_RESET) { return PPC_INTERRUPT_RESET; } return 0; } -static int p9_next_unmasked_interrupt(CPUPPCState *env) +static int p9_next_unmasked_interrupt(CPUPPCState *env, + uint32_t pending_interrupts) { 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; -assert((env->pending_interrupts & P9_UNUSED_INTERRUPTS) == 0); +assert((pending_interrupts & P9_UNUSED_INTERRUPTS) == 0); if (cs->halted) { if (env->spr[SPR_PSSCR] & PSSCR_EC) { @@ -1933,7 +1936,7 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env) * When PSSCR[EC] is set, LPCR[PECE] controls which interrupts can * wakeup the processor */ -return p9_interrupt_powersave(env); +return p9_interrupt_powersave(env, pending_interrupts); } else { /* * When it's clear, any system-caused exception exits power-saving @@ -1944,12 +1947,12 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env) } /* Machine check exception */ -if (env->pending_interrupts & PPC_INTERRUPT_MCK) { +if (pending_interrupts & PPC_INTERRUPT_MCK) { return PPC_INTERRUPT_MCK; } /* Hypervisor decrementer exception */ -if (env->pending_interrupts & PPC_INTERRUPT_HDECR) { +if (pending_interrupts & PPC_INTERRUPT_HDECR) { /* LPCR will be clear when not supported so this will work */ bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE); if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) { @@ -1959,7 +1962,7 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env) } /* Hypervisor virtualization interrupt */ -if (env->pending_inte
[PATCH v3 10/10] target/ppc: combine multiple ail checks into one
ppc_excp_apply_ail has multiple if-checks for ail which is un-necessary. Combine them as appropriate. Signed-off-by: Harsh Prateek Bora --- target/ppc/excp_helper.c | 10 ++ 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 4dff5b..a8bd537a18 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -324,10 +324,7 @@ static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp, target_ulong msr, } ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT; -if (ail == 0) { -return; -} -if (ail == 1) { +if (ail == 0 || ail == 1) { /* AIL=1 is reserved, treat it like AIL=0 */ return; } @@ -351,10 +348,7 @@ static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp, target_ulong msr, } else { ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT; } -if (ail == 0) { -return; -} -if (ail == 1 || ail == 2) { +if (ail == 0 || ail == 1 || ail == 2) { /* AIL=1 and AIL=2 are reserved, treat them like AIL=0 */ return; } -- 2.45.2
[PATCH v3 05/10] target/ppc: optimize p9 exception handling routines for lpcr
Like pending_interrupts, env->spr[SPR_LPCR] is being used at multiple places across p9 exception handlers. Pass the value during entry and avoid multiple indirect accesses. Signed-off-by: Harsh Prateek Bora --- target/ppc/excp_helper.c | 33 ++--- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 31c1653e2b..c7641898ca 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -1873,13 +1873,14 @@ static int p8_next_unmasked_interrupt(CPUPPCState *env) PPC_INTERRUPT_PIT | PPC_INTERRUPT_THERM) static int p9_interrupt_powersave(CPUPPCState *env, - uint32_t pending_interrupts) + uint32_t pending_interrupts, + target_ulong lpcr) { /* External Exception */ if ((pending_interrupts & PPC_INTERRUPT_EXT) && -(env->spr[SPR_LPCR] & LPCR_EEE)) { -bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); +(lpcr & LPCR_EEE)) { +bool heic = !!(lpcr & LPCR_HEIC); if (!heic || !FIELD_EX64_HV(env->msr) || FIELD_EX64(env->msr, MSR, PR)) { return PPC_INTERRUPT_EXT; @@ -1887,11 +1888,11 @@ static int p9_interrupt_powersave(CPUPPCState *env, } /* Decrementer Exception */ if ((pending_interrupts & PPC_INTERRUPT_DECR) && -(env->spr[SPR_LPCR] & LPCR_DEE)) { +(lpcr & LPCR_DEE)) { return PPC_INTERRUPT_DECR; } /* Machine Check or Hypervisor Maintenance Exception */ -if (env->spr[SPR_LPCR] & LPCR_OEE) { +if (lpcr & LPCR_OEE) { if (pending_interrupts & PPC_INTERRUPT_MCK) { return PPC_INTERRUPT_MCK; } @@ -1901,17 +1902,17 @@ static int p9_interrupt_powersave(CPUPPCState *env, } /* Privileged Doorbell Exception */ if ((pending_interrupts & PPC_INTERRUPT_DOORBELL) && -(env->spr[SPR_LPCR] & LPCR_PDEE)) { +(lpcr & LPCR_PDEE)) { return PPC_INTERRUPT_DOORBELL; } /* Hypervisor Doorbell Exception */ if ((pending_interrupts & PPC_INTERRUPT_HDOORBELL) && -(env->spr[SPR_LPCR] & LPCR_HDEE)) { +(lpcr & LPCR_HDEE)) { return PPC_INTERRUPT_HDOORBELL; } /* Hypervisor virtualization exception */ if ((pending_interrupts & PPC_INTERRUPT_HVIRT) && -(env->spr[SPR_LPCR] & LPCR_HVEE)) { +(lpcr & LPCR_HVEE)) { return PPC_INTERRUPT_HVIRT; } if (pending_interrupts & PPC_INTERRUPT_RESET) { @@ -1921,7 +1922,8 @@ static int p9_interrupt_powersave(CPUPPCState *env, } static int p9_next_unmasked_interrupt(CPUPPCState *env, - uint32_t pending_interrupts) + uint32_t pending_interrupts, + target_ulong lpcr) { CPUState *cs = env_cpu(env); @@ -1936,7 +1938,7 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env, * When PSSCR[EC] is set, LPCR[PECE] controls which interrupts can * wakeup the processor */ -return p9_interrupt_powersave(env, pending_interrupts); +return p9_interrupt_powersave(env, pending_interrupts, lpcr); } else { /* * When it's clear, any system-caused exception exits power-saving @@ -1954,7 +1956,7 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env, /* Hypervisor decrementer exception */ if (pending_interrupts & PPC_INTERRUPT_HDECR) { /* LPCR will be clear when not supported so this will work */ -bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE); +bool hdice = !!(lpcr & LPCR_HDICE); if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) { /* HDEC clears on delivery */ return PPC_INTERRUPT_HDECR; @@ -1964,7 +1966,7 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env, /* Hypervisor virtualization interrupt */ if (pending_interrupts & PPC_INTERRUPT_HVIRT) { /* LPCR will be clear when not supported so this will work */ -bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE); +bool hvice = !!(lpcr & LPCR_HVICE); if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hvice) { return PPC_INTERRUPT_HVIRT; } @@ -1972,8 +1974,8 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env, /* External interrupt can ignore MSR:EE under some circumstances */ if (pending_interrupts & PPC_INTERRUPT_EXT) { -bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); -bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); +bool lpes0 = !!(lpcr & LPCR_LPES0); +
[PATCH v3 01/10] target/ppc: use locally stored msr and avoid indirect access
hreg_compute_hflags_value already stores msr locally to be used in most of the logic in the routine however some instances are still using env->msr which is unnecessary. Use locally stored value as available. Reviewed-by: Nicholas Piggin Signed-off-by: Harsh Prateek Bora --- target/ppc/helper_regs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c index 02076e96fb..fe543ab3b8 100644 --- a/target/ppc/helper_regs.c +++ b/target/ppc/helper_regs.c @@ -143,10 +143,10 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env) if (ppc_flags & POWERPC_FLAG_DE) { target_ulong dbcr0 = env->spr[SPR_BOOKE_DBCR0]; -if ((dbcr0 & DBCR0_ICMP) && FIELD_EX64(env->msr, MSR, DE)) { +if ((dbcr0 & DBCR0_ICMP) && FIELD_EX64(msr, MSR, DE)) { hflags |= 1 << HFLAGS_SE; } -if ((dbcr0 & DBCR0_BRT) && FIELD_EX64(env->msr, MSR, DE)) { +if ((dbcr0 & DBCR0_BRT) && FIELD_EX64(msr, MSR, DE)) { hflags |= 1 << HFLAGS_BE; } } else { -- 2.45.2
[PATCH v3 06/10] target/ppc: reduce duplicate code between init_proc_POWER{9, 10}
Historically, the registration of sprs have been inherited alongwith every new Power arch support being added leading to a lot of code duplication. It's time to do necessary cleanups now to avoid further duplication with newer arch support being added. Signed-off-by: Harsh Prateek Bora --- target/ppc/cpu_init.c | 58 +-- 1 file changed, 12 insertions(+), 46 deletions(-) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 9cb5dd4596..de1dd63bf7 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -6410,7 +6410,7 @@ static struct ppc_radix_page_info POWER9_radix_page_info = { #endif /* CONFIG_USER_ONLY */ #define POWER9_BHRB_ENTRIES_LOG2 5 -static void init_proc_POWER9(CPUPPCState *env) +static void register_power9_common_sprs(CPUPPCState *env) { /* Common Registers */ init_proc_book3s_common(env); @@ -6429,7 +6429,6 @@ static void init_proc_POWER9(CPUPPCState *env) register_power5p_ear_sprs(env); register_power5p_tb_sprs(env); register_power6_common_sprs(env); -register_HEIR32_spr(env); register_power6_dbg_sprs(env); register_power7_common_sprs(env); register_power8_tce_address_control_sprs(env); @@ -6447,16 +6446,21 @@ static void init_proc_POWER9(CPUPPCState *env) register_power8_rpr_sprs(env); register_power9_mmu_sprs(env); -/* POWER9 Specific registers */ -spr_register_kvm(env, SPR_TIDR, "TIDR", NULL, NULL, - spr_read_generic, spr_write_generic, - KVM_REG_PPC_TIDR, 0); - /* FIXME: Filter fields properly based on privilege level */ spr_register_kvm_hv(env, SPR_PSSCR, "PSSCR", NULL, NULL, NULL, NULL, spr_read_generic, spr_write_generic, KVM_REG_PPC_PSSCR, 0); +} + +static void init_proc_POWER9(CPUPPCState *env) +{ +register_power9_common_sprs(env); +register_HEIR32_spr(env); +/* POWER9 Specific registers */ +spr_register_kvm(env, SPR_TIDR, "TIDR", NULL, NULL, + spr_read_generic, spr_write_generic, + KVM_REG_PPC_TIDR, 0); /* env variables */ env->dcache_line_size = 128; env->icache_line_size = 128; @@ -6562,50 +6566,12 @@ static struct ppc_radix_page_info POWER10_radix_page_info = { #define POWER10_BHRB_ENTRIES_LOG2 5 static void init_proc_POWER10(CPUPPCState *env) { -/* Common Registers */ -init_proc_book3s_common(env); -register_book3s_207_dbg_sprs(env); - -/* Common TCG PMU */ -init_tcg_pmu_power8(env); - -/* POWER8 Specific Registers */ -register_book3s_ids_sprs(env); -register_amr_sprs(env); -register_iamr_sprs(env); -register_book3s_purr_sprs(env); -register_power5p_common_sprs(env); -register_power5p_lpar_sprs(env); -register_power5p_ear_sprs(env); -register_power5p_tb_sprs(env); -register_power6_common_sprs(env); +register_power9_common_sprs(env); register_HEIR64_spr(env); -register_power6_dbg_sprs(env); -register_power7_common_sprs(env); -register_power8_tce_address_control_sprs(env); -register_power8_ids_sprs(env); -register_power8_ebb_sprs(env); -register_power8_fscr_sprs(env); -register_power8_pmu_sup_sprs(env); -register_power8_pmu_user_sprs(env); -register_power8_tm_sprs(env); -register_power8_pspb_sprs(env); -register_power8_dpdes_sprs(env); -register_vtb_sprs(env); -register_power8_ic_sprs(env); -register_power9_book4_sprs(env); -register_power8_rpr_sprs(env); -register_power9_mmu_sprs(env); register_power10_hash_sprs(env); register_power10_dexcr_sprs(env); register_power10_pmu_sup_sprs(env); register_power10_pmu_user_sprs(env); - -/* FIXME: Filter fields properly based on privilege level */ -spr_register_kvm_hv(env, SPR_PSSCR, "PSSCR", NULL, NULL, NULL, NULL, -spr_read_generic, spr_write_generic, -KVM_REG_PPC_PSSCR, 0); - /* env variables */ env->dcache_line_size = 128; env->icache_line_size = 128; -- 2.45.2
[PATCH v3 03/10] target/ppc: optimize hreg_compute_pmu_hflags_value
The second if-condition can be true only if the first one above is true. Enclose the latter into the former to avoid un-necessary check if first condition fails. Reviewed-by: BALATON Zoltan Reviewed-by: Nicholas Piggin Signed-off-by: Harsh Prateek Bora --- target/ppc/helper_regs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c index 7b23e5ef0e..42c681ca4a 100644 --- a/target/ppc/helper_regs.c +++ b/target/ppc/helper_regs.c @@ -102,9 +102,9 @@ static uint32_t hreg_compute_pmu_hflags_value(CPUPPCState *env) #ifndef CONFIG_USER_ONLY if (env->pmc_ins_cnt) { hflags |= 1 << HFLAGS_INSN_CNT; -} -if (env->pmc_ins_cnt & 0x1e) { -hflags |= 1 << HFLAGS_PMC_OTHER; +if (env->pmc_ins_cnt & 0x1e) { +hflags |= 1 << HFLAGS_PMC_OTHER; +} } #endif #endif -- 2.45.2
[PATCH v3 07/10] target/ppc: optimize p8 exception handling routines
Most of the p8 exception handling accesses env->pending_interrupts and env->spr[SPR_LPCR] at multiple places. Passing it directly as local variables simplifies the code and avoids multiple indirect accesses. Signed-off-by: Harsh Prateek Bora --- target/ppc/excp_helper.c | 60 +--- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index c7641898ca..c0828aac88 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -1765,39 +1765,42 @@ static int p7_next_unmasked_interrupt(CPUPPCState *env) PPC_INTERRUPT_CEXT | PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | \ PPC_INTERRUPT_FIT | PPC_INTERRUPT_PIT | PPC_INTERRUPT_THERM) -static int p8_interrupt_powersave(CPUPPCState *env) +static int p8_interrupt_powersave(uint32_t pending_interrupts, + target_ulong lpcr) { -if ((env->pending_interrupts & PPC_INTERRUPT_EXT) && -(env->spr[SPR_LPCR] & LPCR_P8_PECE2)) { +if ((pending_interrupts & PPC_INTERRUPT_EXT) && +(lpcr & LPCR_P8_PECE2)) { return PPC_INTERRUPT_EXT; } -if ((env->pending_interrupts & PPC_INTERRUPT_DECR) && -(env->spr[SPR_LPCR] & LPCR_P8_PECE3)) { +if ((pending_interrupts & PPC_INTERRUPT_DECR) && +(lpcr & LPCR_P8_PECE3)) { return PPC_INTERRUPT_DECR; } -if ((env->pending_interrupts & PPC_INTERRUPT_MCK) && -(env->spr[SPR_LPCR] & LPCR_P8_PECE4)) { +if ((pending_interrupts & PPC_INTERRUPT_MCK) && +(lpcr & LPCR_P8_PECE4)) { return PPC_INTERRUPT_MCK; } -if ((env->pending_interrupts & PPC_INTERRUPT_HMI) && -(env->spr[SPR_LPCR] & LPCR_P8_PECE4)) { +if ((pending_interrupts & PPC_INTERRUPT_HMI) && +(lpcr & LPCR_P8_PECE4)) { return PPC_INTERRUPT_HMI; } -if ((env->pending_interrupts & PPC_INTERRUPT_DOORBELL) && -(env->spr[SPR_LPCR] & LPCR_P8_PECE0)) { +if ((pending_interrupts & PPC_INTERRUPT_DOORBELL) && +(lpcr & LPCR_P8_PECE0)) { return PPC_INTERRUPT_DOORBELL; } -if ((env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) && -(env->spr[SPR_LPCR] & LPCR_P8_PECE1)) { +if ((pending_interrupts & PPC_INTERRUPT_HDOORBELL) && +(lpcr & LPCR_P8_PECE1)) { return PPC_INTERRUPT_HDOORBELL; } -if (env->pending_interrupts & PPC_INTERRUPT_RESET) { +if (pending_interrupts & PPC_INTERRUPT_RESET) { return PPC_INTERRUPT_RESET; } return 0; } -static int p8_next_unmasked_interrupt(CPUPPCState *env) +static int p8_next_unmasked_interrupt(CPUPPCState *env, + uint32_t pending_interrupts, + target_ulong lpcr) { CPUState *cs = env_cpu(env); @@ -1808,18 +1811,18 @@ static int p8_next_unmasked_interrupt(CPUPPCState *env) if (cs->halted) { /* LPCR[PECE] controls which interrupts can exit power-saving mode */ -return p8_interrupt_powersave(env); +return p8_interrupt_powersave(pending_interrupts, lpcr); } /* Machine check exception */ -if (env->pending_interrupts & PPC_INTERRUPT_MCK) { +if (pending_interrupts & PPC_INTERRUPT_MCK) { return PPC_INTERRUPT_MCK; } /* Hypervisor decrementer exception */ -if (env->pending_interrupts & PPC_INTERRUPT_HDECR) { +if (pending_interrupts & PPC_INTERRUPT_HDECR) { /* LPCR will be clear when not supported so this will work */ -bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE); +bool hdice = !!(lpcr & LPCR_HDICE); if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) { /* HDEC clears on delivery */ return PPC_INTERRUPT_HDECR; @@ -1827,9 +1830,9 @@ static int p8_next_unmasked_interrupt(CPUPPCState *env) } /* External interrupt can ignore MSR:EE under some circumstances */ -if (env->pending_interrupts & PPC_INTERRUPT_EXT) { -bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); -bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); +if (pending_interrupts & PPC_INTERRUPT_EXT) { +bool lpes0 = !!(lpcr & LPCR_LPES0); +bool heic = !!(lpcr & LPCR_HEIC); /* HEIC blocks delivery to the hypervisor */ if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) && !FIELD_EX64(env->msr, MSR, PR))) || @@ -1839,20 +1842,20 @@ static int p8_next_unmasked_interrupt(CPUPPCState *env) } if (msr_ee != 0) { /* Decrementer exception */ -if (env->pending_
[PATCH v3 00/10] misc ppc improvements/optimizations
This a set of misc ppc arch specific code improvements/optimizations. This version of series extended improvements to p7 and p8 alongwith additional minor improvements. Since patch 7/7 of v2 series have been picked by Aditya in his patchset for P11 support, I have excluded that patch in this series and based on top of his v6 series which contains the required patch as 1/5. Based on: <20240731055022.696051-1-adit...@linux.ibm.com> Changelog: v3: extended improvements to other Power arch p7, p8 (Nick) other minor improvements v2: addressed review comments from BALATON Zoltan v1: Initial patch Harsh Prateek Bora (10): target/ppc: use locally stored msr and avoid indirect access target/ppc: optimize hreg_compute_pmu_hflags_value target/ppc: optimize hreg_compute_pmu_hflags_value target/ppc: optimize p9 exception handling routines target/ppc: optimize p9 exception handling routines for lpcr target/ppc: reduce duplicate code between init_proc_POWER{9, 10} target/ppc: optimize p8 exception handling routines target/ppc: optimize p7 exception handling routines target/ppc: simplify var usage in ppc_next_unmasked_interrupt target/ppc: combine multiple ail checks into one target/ppc/cpu_init.c| 58 ++ target/ppc/excp_helper.c | 230 --- target/ppc/helper_regs.c | 19 ++-- 3 files changed, 141 insertions(+), 166 deletions(-) -- 2.45.2
[PATCH v3 08/10] target/ppc: optimize p7 exception handling routines
Like p8 and p9, simplifying p7 exception handling rotuines to avoid un-necessary multiple indirect accesses to env->pending_interrupts and env->spr[SPR_LPCR]. Signed-off-by: Harsh Prateek Bora --- target/ppc/excp_helper.c | 46 ++-- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index c0828aac88..d0e0f609a0 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -1683,51 +1683,54 @@ void ppc_cpu_do_interrupt(CPUState *cs) PPC_INTERRUPT_PIT | PPC_INTERRUPT_DOORBELL | PPC_INTERRUPT_HDOORBELL | \ PPC_INTERRUPT_THERM | PPC_INTERRUPT_EBB) -static int p7_interrupt_powersave(CPUPPCState *env) +static int p7_interrupt_powersave(uint32_t pending_interrupts, + target_ulong lpcr) { -if ((env->pending_interrupts & PPC_INTERRUPT_EXT) && -(env->spr[SPR_LPCR] & LPCR_P7_PECE0)) { +if ((pending_interrupts & PPC_INTERRUPT_EXT) && +(lpcr & LPCR_P7_PECE0)) { return PPC_INTERRUPT_EXT; } -if ((env->pending_interrupts & PPC_INTERRUPT_DECR) && -(env->spr[SPR_LPCR] & LPCR_P7_PECE1)) { +if ((pending_interrupts & PPC_INTERRUPT_DECR) && +(lpcr & LPCR_P7_PECE1)) { return PPC_INTERRUPT_DECR; } -if ((env->pending_interrupts & PPC_INTERRUPT_MCK) && -(env->spr[SPR_LPCR] & LPCR_P7_PECE2)) { +if ((pending_interrupts & PPC_INTERRUPT_MCK) && +(lpcr & LPCR_P7_PECE2)) { return PPC_INTERRUPT_MCK; } -if ((env->pending_interrupts & PPC_INTERRUPT_HMI) && -(env->spr[SPR_LPCR] & LPCR_P7_PECE2)) { +if ((pending_interrupts & PPC_INTERRUPT_HMI) && +(lpcr & LPCR_P7_PECE2)) { return PPC_INTERRUPT_HMI; } -if (env->pending_interrupts & PPC_INTERRUPT_RESET) { +if (pending_interrupts & PPC_INTERRUPT_RESET) { return PPC_INTERRUPT_RESET; } return 0; } -static int p7_next_unmasked_interrupt(CPUPPCState *env) +static int p7_next_unmasked_interrupt(CPUPPCState *env, + uint32_t pending_interrupts, + target_ulong lpcr) { 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; -assert((env->pending_interrupts & P7_UNUSED_INTERRUPTS) == 0); +assert((pending_interrupts & P7_UNUSED_INTERRUPTS) == 0); if (cs->halted) { /* LPCR[PECE] controls which interrupts can exit power-saving mode */ -return p7_interrupt_powersave(env); +return p7_interrupt_powersave(pending_interrupts, lpcr); } /* Machine check exception */ -if (env->pending_interrupts & PPC_INTERRUPT_MCK) { +if (pending_interrupts & PPC_INTERRUPT_MCK) { return PPC_INTERRUPT_MCK; } /* Hypervisor decrementer exception */ -if (env->pending_interrupts & PPC_INTERRUPT_HDECR) { +if (pending_interrupts & PPC_INTERRUPT_HDECR) { /* LPCR will be clear when not supported so this will work */ bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE); if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) { @@ -1737,9 +1740,9 @@ static int p7_next_unmasked_interrupt(CPUPPCState *env) } /* External interrupt can ignore MSR:EE under some circumstances */ -if (env->pending_interrupts & PPC_INTERRUPT_EXT) { -bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); -bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); +if (pending_interrupts & PPC_INTERRUPT_EXT) { +bool lpes0 = !!(lpcr & LPCR_LPES0); +bool heic = !!(lpcr & LPCR_HEIC); /* HEIC blocks delivery to the hypervisor */ if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) && !FIELD_EX64(env->msr, MSR, PR))) || @@ -1749,10 +1752,10 @@ static int p7_next_unmasked_interrupt(CPUPPCState *env) } if (msr_ee != 0) { /* Decrementer exception */ -if (env->pending_interrupts & PPC_INTERRUPT_DECR) { +if (pending_interrupts & PPC_INTERRUPT_DECR) { return PPC_INTERRUPT_DECR; } -if (env->pending_interrupts & PPC_INTERRUPT_PERFM) { +if (pending_interrupts & PPC_INTERRUPT_PERFM) { return PPC_INTERRUPT_PERFM; } } @@ -2022,7 +2025,8 @@ static int ppc_next_unmasked_interrupt(CPUPPCState *env) #ifdef TARGET_PPC64 switch (env->excp_model) { case POWERPC_EXCP_POWER7: -return p7_next_unmasked_interrupt(env); +return p7_next_unmasked_interrupt(env, env->pending_interrupts, + env->spr[SPR_LPCR]); case POWERPC_EXCP_POWER8: return p8_next_unmasked_interrupt(env, env->pending_interrupts, env->spr[SPR_LPCR]); -- 2.45.2
Re: [PATCH v5 1/5] target/ppc: reduce code duplication across Power9/10 init code
Hi Aditya, On 7/23/24 20:43, Aditya Gupta wrote: Hi Harsh, Is it okay if I do, the changes in your patch ? Sure, feel free to update as suggested and add your sob mentioning the summary of updates. Thanks Harsh Thanks, Aditya Gupta On 23/07/24 10:52, Nicholas Piggin wrote: On Thu Jun 6, 2024 at 10:16 PM AEST, Aditya Gupta wrote: From: Harsh Prateek Bora Power9/10 initialization code consists of a lot of logical OR of various flag bits as supported by respective Power platform during its initialization, most of which is duplicated and only selected bits are added or removed as needed with each new platform support being added. Remove the duplicate code and share using common macros. Signed-off-by: Harsh Prateek Bora --- target/ppc/cpu_init.c | 124 +- target/ppc/cpu_init.h | 78 ++ 2 files changed, 93 insertions(+), 109 deletions(-) create mode 100644 target/ppc/cpu_init.h diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 01e358a4a5ac..3d8a112935ae 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -51,6 +51,7 @@ #include "kvm_ppc.h" #endif +#include "cpu_init.h" /* #define PPC_DEBUG_SPR */ /* #define USE_APPLE_GDB */ @@ -6508,58 +6509,15 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data) dc->fw_name = "PowerPC,POWER9"; dc->desc = "POWER9"; pcc->pvr_match = ppc_pvr_match_power9; - pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06 | PCR_COMPAT_2_07; - pcc->pcr_supported = PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | - PCR_COMPAT_2_05; + pcc->pcr_mask = POWERPC_POWER9_PCC_PCR_MASK; + pcc->pcr_supported = POWERPC_POWER9_PCC_PCR_SUPPORTED; pcc->init_proc = init_proc_POWER9; pcc->check_pow = check_pow_nocheck; pcc->check_attn = check_attn_hid0_power9; - pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB | - PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES | - PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | - PPC_FLOAT_FRSQRTES | - PPC_FLOAT_STFIWX | - PPC_FLOAT_EXT | - PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ | - PPC_MEM_SYNC | PPC_MEM_EIEIO | - PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | - PPC_64B | PPC_64H | PPC_64BX | PPC_ALTIVEC | - PPC_SEGMENT_64B | PPC_SLBI | - PPC_POPCNTB | PPC_POPCNTWD | - PPC_CILDST; - pcc->insns_flags2 = PPC2_VSX | PPC2_VSX207 | PPC2_DFP | PPC2_DBRX | - PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 | - PPC2_ATOMIC_ISA206 | PPC2_FP_CVT_ISA206 | - PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 | - PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 | - PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 | - PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL | PPC2_MEM_LWSYNC | - PPC2_BCDA_ISA206; - pcc->msr_mask = (1ull << MSR_SF) | - (1ull << MSR_HV) | - (1ull << MSR_TM) | - (1ull << MSR_VR) | - (1ull << MSR_VSX) | - (1ull << MSR_EE) | - (1ull << MSR_PR) | - (1ull << MSR_FP) | - (1ull << MSR_ME) | - (1ull << MSR_FE0) | - (1ull << MSR_SE) | - (1ull << MSR_DE) | - (1ull << MSR_FE1) | - (1ull << MSR_IR) | - (1ull << MSR_DR) | - (1ull << MSR_PMM) | - (1ull << MSR_RI) | - (1ull << MSR_LE); - pcc->lpcr_mask = LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD | - (LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL | - LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR | LPCR_LD | - (LPCR_PECE_L_MASK & (LPCR_PDEE | LPCR_HDEE | LPCR_EEE | - LPCR_DEE | LPCR_OEE)) - | LPCR_MER | LPCR_GTSE | LPCR_TC | - LPCR_HEIC | LPCR_LPES0 | LPCR_HVICE | LPCR_HDICE; + pcc->insns_flags = POWERPC_FAMILY_POWER9_INSNS_FLAGS; + pcc->insns_flags2 = POWERPC_FAMILY_POWER9_INSNS_FLAGS2; + pcc->msr_mask = POWERPC_POWER9_PCC_MSR_MASK; + pcc->lpcr_mask = POWERPC_POWER9_PCC_LPCR_MASK; pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE; pcc->mmu_model = POWERPC_MMU_3_00; #if !defined(CONFIG_USER_ONLY) @@ -6572,10 +6530,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data) pcc->excp_mo
Re: [PATCH V13 1/8] accel/kvm: Extract common KVM vCPU {creation,parking} code
+qemu-devel, qemu-ppc Ping! On 6/17/24 15:18, Harsh Prateek Bora wrote: + MST, Igor - to help with early review/merge. TIA. On 6/14/24 16:06, Salil Mehta wrote: Hello From: Harsh Prateek Bora Sent: Friday, June 14, 2024 6:24 AM Hi Paolo, Nick, Can this patch 1/8 be merged earlier provided we have got sufficient R-bys for it and the review of entire series may take a longer time? We have some ppc64 patches based on it, hence the ask. Hi Salil, I am hoping we are not expecting anymore changes to this patch, please confirm. I do not expect any change. I had requested Michael to merge the complete series as it is stranding other users. He then requested Igor to take a final look but he has not reverted yet. I'll remind Michael again. BTW, can you reply to below patch explicitly indicating your interest in the series so that MST knows who else are the stake holders here https://lore.kernel.org/qemu-devel/20240605160327.3c71f...@imammedo.users.ipa.redhat.com/ Hi Paolo, A request, would it be possible to skim through this series from KVM perspective? (although nothing has changed which will affect the KVM and this is architecture agnostic patch-set) Many thanks! Best Salil. regards, Harsh On 6/7/24 17:26, Salil Mehta wrote: > KVM vCPU creation is done once during the vCPU realization when Qemu > vCPU thread is spawned. This is common to all the architectures as of now. > > Hot-unplug of vCPU results in destruction of the vCPU object in QOM > but the corresponding KVM vCPU object in the Host KVM is not destroyed > as KVM doesn't support vCPU removal. Therefore, its representative KVM > vCPU object/context in Qemu is parked. > > Refactor architecture common logic so that some APIs could be reused > by vCPU Hotplug code of some architectures likes ARM, Loongson etc. > Update new/old APIs with trace events. No functional change is intended here. > > Signed-off-by: Salil Mehta > Reviewed-by: Gavin Shan > Tested-by: Vishnu Pajjuri > Reviewed-by: Jonathan Cameron > Tested-by: Xianglai Li > Tested-by: Miguel Luis > Reviewed-by: Shaoqin Huang > Reviewed-by: Vishnu Pajjuri > Reviewed-by: Nicholas Piggin > Tested-by: Zhao Liu > Reviewed-by: Zhao Liu > Reviewed-by: Harsh Prateek Bora > --- > accel/kvm/kvm-all.c | 95 -- > accel/kvm/kvm-cpus.h | 1 - > accel/kvm/trace-events | 5 ++- > include/sysemu/kvm.h | 25 +++ > 4 files changed, 92 insertions(+), 34 deletions(-) > > diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index > c0be9f5eed..8f9128bb92 100644 > --- a/accel/kvm/kvm-all.c > +++ b/accel/kvm/kvm-all.c > @@ -340,14 +340,71 @@ err: > return ret; > } > > +void kvm_park_vcpu(CPUState *cpu) > +{ > + struct KVMParkedVcpu *vcpu; > + > + trace_kvm_park_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu)); > + > + vcpu = g_malloc0(sizeof(*vcpu)); > + vcpu->vcpu_id = kvm_arch_vcpu_id(cpu); > + vcpu->kvm_fd = cpu->kvm_fd; > + QLIST_INSERT_HEAD(&kvm_state->kvm_parked_vcpus, vcpu, node); } > + > +int kvm_unpark_vcpu(KVMState *s, unsigned long vcpu_id) { > + struct KVMParkedVcpu *cpu; > + int kvm_fd = -ENOENT; > + > + QLIST_FOREACH(cpu, &s->kvm_parked_vcpus, node) { > + if (cpu->vcpu_id == vcpu_id) { > + QLIST_REMOVE(cpu, node); > + kvm_fd = cpu->kvm_fd; > + g_free(cpu); > + } > + } > + > + trace_kvm_unpark_vcpu(vcpu_id, kvm_fd > 0 ? "unparked" : "not > + found parked"); > + > + return kvm_fd; > +} > + > +int kvm_create_vcpu(CPUState *cpu) > +{ > + unsigned long vcpu_id = kvm_arch_vcpu_id(cpu); > + KVMState *s = kvm_state; > + int kvm_fd; > + > + /* check if the KVM vCPU already exist but is parked */ > + kvm_fd = kvm_unpark_vcpu(s, vcpu_id); > + if (kvm_fd < 0) { > + /* vCPU not parked: create a new KVM vCPU */ > + kvm_fd = kvm_vm_ioctl(s, KVM_CREATE_VCPU, vcpu_id); > + if (kvm_fd < 0) { > + error_report("KVM_CREATE_VCPU IOCTL failed for vCPU %lu", vcpu_id); > + return kvm_fd; > + } > + } > + > + cpu->kvm_fd = kvm_fd; > + cpu->kvm_state = s; > + cpu->vcpu_dirty = true; > + cpu->dirty_pages = 0; > + cpu->throttle_us_per_full = 0; > + > + trace_kvm_create_vcpu(cpu->cpu_index, vcpu_id, kvm_fd); > + > + return 0; > +} > + > static
Re: [PATCH 2/2] target/ppc/arch_dump: set prstatus pid to cpuid
Hi Omar, On 6/19/24 10:30, Omar Sandoval wrote: Every other architecture does this, and debuggers need it to be able to identify which prstatus note corresponds to which CPU. Signed-off-by: Omar Sandoval --- target/ppc/arch_dump.c | 21 - 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/target/ppc/arch_dump.c b/target/ppc/arch_dump.c index a8315659d9..78b4205319 100644 --- a/target/ppc/arch_dump.c +++ b/target/ppc/arch_dump.c @@ -47,9 +47,11 @@ struct PPCUserRegStruct { } QEMU_PACKED; struct PPCElfPrstatus { -char pad1[112]; +char pad1[32]; +uint32_t pid; +uint8_t pad2[76]; struct PPCUserRegStruct pr_reg; -char pad2[40]; +char pad3[40]; } QEMU_PACKED; Could you please add a comment above the struct providing reference to the spec being referred here for member position across the status bits? With that, Reviewed-by: Harsh Prateek Bora @@ -96,7 +98,7 @@ typedef struct NoteFuncArg { DumpState *state; } NoteFuncArg; -static void ppc_write_elf_prstatus(NoteFuncArg *arg, PowerPCCPU *cpu) +static void ppc_write_elf_prstatus(NoteFuncArg *arg, PowerPCCPU *cpu, int id) { int i; reg_t cr; @@ -109,6 +111,7 @@ static void ppc_write_elf_prstatus(NoteFuncArg *arg, PowerPCCPU *cpu) prstatus = ¬e->contents.prstatus; memset(prstatus, 0, sizeof(*prstatus)); +prstatus->pid = cpu_to_dump32(s, id); reg = &prstatus->pr_reg; for (i = 0; i < 32; i++) { @@ -127,7 +130,7 @@ static void ppc_write_elf_prstatus(NoteFuncArg *arg, PowerPCCPU *cpu) reg->ccr = cpu_to_dump_reg(s, cr); } -static void ppc_write_elf_fpregset(NoteFuncArg *arg, PowerPCCPU *cpu) +static void ppc_write_elf_fpregset(NoteFuncArg *arg, PowerPCCPU *cpu, int id) { int i; struct PPCElfFpregset *fpregset; @@ -146,7 +149,7 @@ static void ppc_write_elf_fpregset(NoteFuncArg *arg, PowerPCCPU *cpu) fpregset->fpscr = cpu_to_dump_reg(s, cpu->env.fpscr); } -static void ppc_write_elf_vmxregset(NoteFuncArg *arg, PowerPCCPU *cpu) +static void ppc_write_elf_vmxregset(NoteFuncArg *arg, PowerPCCPU *cpu, int id) { int i; struct PPCElfVmxregset *vmxregset; @@ -178,7 +181,7 @@ static void ppc_write_elf_vmxregset(NoteFuncArg *arg, PowerPCCPU *cpu) vmxregset->vscr.u32[3] = cpu_to_dump32(s, ppc_get_vscr(&cpu->env)); } -static void ppc_write_elf_vsxregset(NoteFuncArg *arg, PowerPCCPU *cpu) +static void ppc_write_elf_vsxregset(NoteFuncArg *arg, PowerPCCPU *cpu, int id) { int i; struct PPCElfVsxregset *vsxregset; @@ -195,7 +198,7 @@ static void ppc_write_elf_vsxregset(NoteFuncArg *arg, PowerPCCPU *cpu) } } -static void ppc_write_elf_speregset(NoteFuncArg *arg, PowerPCCPU *cpu) +static void ppc_write_elf_speregset(NoteFuncArg *arg, PowerPCCPU *cpu, int id) { struct PPCElfSperegset *speregset; Note *note = &arg->note; @@ -211,7 +214,7 @@ static void ppc_write_elf_speregset(NoteFuncArg *arg, PowerPCCPU *cpu) static const struct NoteFuncDescStruct { int contents_size; -void (*note_contents_func)(NoteFuncArg *arg, PowerPCCPU *cpu); +void (*note_contents_func)(NoteFuncArg *arg, PowerPCCPU *cpu, int id); } note_func[] = { {sizeof_field(Note, contents.prstatus), ppc_write_elf_prstatus}, {sizeof_field(Note, contents.fpregset), ppc_write_elf_fpregset}, @@ -282,7 +285,7 @@ static int ppc_write_all_elf_notes(const char *note_name, arg.note.hdr.n_descsz = cpu_to_dump32(s, nf->contents_size); strncpy(arg.note.name, note_name, sizeof(arg.note.name)); -(*nf->note_contents_func)(&arg, cpu); +(*nf->note_contents_func)(&arg, cpu, id); note_size = sizeof(arg.note) - sizeof(arg.note.contents) + nf->contents_size;
[PATCH v4 0/3] target/ppc: vcpu hotplug failure handling fixes
On ppc64, the PowerVM hypervisor runs with limited memory and a VCPU creation during hotplug may fail during kvm_ioctl for KVM_CREATE_VCPU, leading to termination of guest since errp is set to &error_fatal while calling kvm_init_vcpu. This unexpected behaviour can be avoided by pre-creating and parking vcpu on success or return error otherwise. This enables graceful error delivery for any vcpu hotplug failures while the guest can keep running. This series adds another helper to create and park vcpu, based on [1], exports cpu_get_free_index to be reused later and adds ppc arch specfic handling for vcpu hotplug failure using kvm accel helper cpu_target_realize. [1] <20240607115649.214622-1-salil.me...@huawei.com> Changelog: v4: rebased, comment update in patch 3, added R-bys. v3: Addressed review comments from Nick v2: Addressed review comments from Nick v1: Initial patch Harsh Prateek Bora (3): accel/kvm: Introduce kvm_create_and_park_vcpu() helper cpu-common.c: export cpu_get_free_index to be reused later target/ppc: handle vcpu hotplug failure gracefully include/exec/cpu-common.h | 2 ++ include/sysemu/kvm.h | 8 +++ accel/kvm/kvm-all.c | 12 ++ cpu-common.c | 7 +++--- target/ppc/kvm.c | 46 +++ 5 files changed, 72 insertions(+), 3 deletions(-) -- 2.45.1
[PATCH v4 1/3] accel/kvm: Introduce kvm_create_and_park_vcpu() helper
There are distinct helpers for creating and parking a KVM vCPU. However, there can be cases where a platform needs to create and immediately park the vCPU during early stages of vcpu init which can later be reused when vcpu thread gets initialized. This would help detect failures with kvm_create_vcpu at an early stage. Suggested-by: Nicholas Piggin Reviewed-by: Nicholas Piggin Signed-off-by: Harsh Prateek Bora --- Based on: <20240607115649.214622-1-salil.me...@huawei.com> --- --- include/sysemu/kvm.h | 8 accel/kvm/kvm-all.c | 12 2 files changed, 20 insertions(+) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index c4a914b3d8..9cf14ca3d5 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -338,6 +338,14 @@ void kvm_park_vcpu(CPUState *cpu); */ int kvm_unpark_vcpu(KVMState *s, unsigned long vcpu_id); +/** + * kvm_create_and_park_vcpu - Create and park a KVM vCPU + * @cpu: QOM CPUState object for which KVM vCPU has to be created and parked. + * + * @returns: 0 when success, errno (<0) when failed. + */ +int kvm_create_and_park_vcpu(CPUState *cpu); + /* Arch specific hooks */ extern const KVMCapabilityInfo kvm_arch_required_capabilities[]; diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 4c5f521583..c0cbb6d480 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -398,6 +398,18 @@ int kvm_create_vcpu(CPUState *cpu) return 0; } +int kvm_create_and_park_vcpu(CPUState *cpu) +{ +int ret = 0; + +ret = kvm_create_vcpu(cpu); +if (!ret) { +kvm_park_vcpu(cpu); +} + +return ret; +} + static int do_kvm_destroy_vcpu(CPUState *cpu) { KVMState *s = kvm_state; -- 2.45.1
[PATCH v4 2/3] cpu-common.c: export cpu_get_free_index to be reused later
This helper provides an easy way to identify the next available free cpu index which can be used for vcpu creation. Until now, this is being called at a very later stage and there is a need to be able to call it earlier (for now, with ppc64) hence the need to export. Suggested-by: Nicholas Piggin Reviewed-by: Nicholas Piggin Signed-off-by: Harsh Prateek Bora --- include/exec/cpu-common.h | 2 ++ cpu-common.c | 7 --- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 240ee04369..2e1b499cb7 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -35,6 +35,8 @@ void cpu_list_lock(void); void cpu_list_unlock(void); unsigned int cpu_list_generation_id_get(void); +int cpu_get_free_index(void); + void tcg_iommu_init_notifier_list(CPUState *cpu); void tcg_iommu_free_notifier_list(CPUState *cpu); diff --git a/cpu-common.c b/cpu-common.c index ce78273af5..82bd1b432d 100644 --- a/cpu-common.c +++ b/cpu-common.c @@ -57,14 +57,12 @@ void cpu_list_unlock(void) qemu_mutex_unlock(&qemu_cpu_list_lock); } -static bool cpu_index_auto_assigned; -static int cpu_get_free_index(void) +int cpu_get_free_index(void) { CPUState *some_cpu; int max_cpu_index = 0; -cpu_index_auto_assigned = true; CPU_FOREACH(some_cpu) { if (some_cpu->cpu_index >= max_cpu_index) { max_cpu_index = some_cpu->cpu_index + 1; @@ -83,8 +81,11 @@ unsigned int cpu_list_generation_id_get(void) void cpu_list_add(CPUState *cpu) { +static bool cpu_index_auto_assigned; + QEMU_LOCK_GUARD(&qemu_cpu_list_lock); if (cpu->cpu_index == UNASSIGNED_CPU_INDEX) { +cpu_index_auto_assigned = true; cpu->cpu_index = cpu_get_free_index(); assert(cpu->cpu_index != UNASSIGNED_CPU_INDEX); } else { -- 2.45.1
[PATCH v4 3/3] target/ppc: handle vcpu hotplug failure gracefully
On ppc64, the PowerVM hypervisor runs with limited memory and a VCPU creation during hotplug may fail during kvm_ioctl for KVM_CREATE_VCPU, leading to termination of guest since errp is set to &error_fatal while calling kvm_init_vcpu. This unexpected behaviour can be avoided by pre-creating and parking vcpu on success or return error otherwise. This enables graceful error delivery for any vcpu hotplug failures while the guest can keep running. Also introducing KVM AccelCPUClass to init cpu_target_realize for kvm. Tested OK by repeatedly doing a hotplug/unplug of vcpus as below: #virsh setvcpus hotplug 40 #virsh setvcpus hotplug 70 error: internal error: unable to execute QEMU command 'device_add': kvmppc_cpu_realize: vcpu hotplug failed with -12 Reported-by: Anushree Mathur Suggested-by: Shivaprasad G Bhat Suggested-by: Vaibhav Jain Tested-by: Anushree Mathur Reviewed-by: Nicholas Piggin Signed-off by: Harsh Prateek Bora --- target/ppc/kvm.c | 46 ++ 1 file changed, 46 insertions(+) diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index 005f2239f3..77a3ebae22 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -48,6 +48,8 @@ #include "qemu/mmap-alloc.h" #include "elf.h" #include "sysemu/kvm_int.h" +#include "sysemu/kvm.h" +#include "hw/core/accel-cpu.h" #include CONFIG_DEVICES @@ -2346,6 +2348,30 @@ static void alter_insns(uint64_t *word, uint64_t flags, bool on) } } +static bool kvmppc_cpu_realize(CPUState *cs, Error **errp) +{ +int ret; +const char *vcpu_str = (cs->parent_obj.hotplugged == true) ? + "hotplug" : "create"; +cs->cpu_index = cpu_get_free_index(); + +POWERPC_CPU(cs)->vcpu_id = cs->cpu_index; + +/* create and park to fail gracefully in case vcpu hotplug fails */ +ret = kvm_create_and_park_vcpu(cs); +if (ret) { +/* + * This causes QEMU to terminate if initial CPU creation + * fails, and only CPU hotplug failure if the error happens + * there. + */ +error_setg(errp, "%s: vcpu %s failed with %d", + __func__, vcpu_str, ret); +return false; +} +return true; +} + static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data) { PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); @@ -2966,3 +2992,23 @@ void kvmppc_set_reg_tb_offset(PowerPCCPU *cpu, int64_t tb_offset) void kvm_arch_accel_class_init(ObjectClass *oc) { } + +static void kvm_cpu_accel_class_init(ObjectClass *oc, void *data) +{ +AccelCPUClass *acc = ACCEL_CPU_CLASS(oc); + +acc->cpu_target_realize = kvmppc_cpu_realize; +} + +static const TypeInfo kvm_cpu_accel_type_info = { +.name = ACCEL_CPU_NAME("kvm"), + +.parent = TYPE_ACCEL_CPU, +.class_init = kvm_cpu_accel_class_init, +.abstract = true, +}; +static void kvm_cpu_accel_register_types(void) +{ +type_register_static(&kvm_cpu_accel_type_info); +} +type_init(kvm_cpu_accel_register_types); -- 2.45.1
Re: [PATCH 00/26] hw/ppc: Prefer HumanReadableText over Monitor
On 6/10/24 11:50, Philippe Mathieu-Daudé wrote: Hi, This series remove uses of Monitor in hw/ppc/, replacing by the more generic HumanReadableText. Care is taken to keep the commit bisectables by updating functions one by one, also easing review. For rationale see previous series from Daniel: https://lore.kernel.org/qemu-devel/20211028155457.967291-1-berra...@redhat.com/ Regards, Phil. For the series: Reviewed-by: Harsh Prateek Bora Philippe Mathieu-Daudé (26): hw/ppc: Avoid using Monitor in pnv_phb3_msi_pic_print_info() hw/ppc: Avoid using Monitor in icp_pic_print_info() hw/ppc: Avoid using Monitor in xive_tctx_pic_print_info() hw/ppc: Avoid using Monitor in ics_pic_print_info() hw/ppc: Avoid using Monitor in PnvChipClass::intc_print_info() hw/ppc: Avoid using Monitor in xive_end_queue_pic_print_info() hw/ppc: Avoid using Monitor in spapr_xive_end_pic_print_info() hw/ppc: Avoid using Monitor in spapr_xive_pic_print_info() hw/ppc: Avoid using Monitor in xive_source_pic_print_info() hw/ppc: Avoid using Monitor in pnv_phb4_pic_print_info() hw/ppc: Avoid using Monitor in xive_eas_pic_print_info() hw/ppc: Avoid using Monitor in xive_end_pic_print_info() hw/ppc: Avoid using Monitor in xive_end_eas_pic_print_info() hw/ppc: Avoid using Monitor in xive_nvt_pic_print_info() hw/ppc: Avoid using Monitor in pnv_xive_pic_print_info() hw/ppc: Avoid using Monitor in pnv_psi_pic_print_info() hw/ppc: Avoid using Monitor in xive2_eas_pic_print_info() hw/ppc: Avoid using Monitor in xive2_end_eas_pic_print_info() hw/ppc: Avoid using Monitor in xive2_end_queue_pic_print_info() hw/ppc: Avoid using Monitor in xive2_end_pic_print_info() hw/ppc: Avoid using Monitor in xive2_nvp_pic_print_info() hw/ppc: Avoid using Monitor in pnv_xive2_pic_print_info() hw/ppc: Avoid using Monitor in SpaprInterruptControllerClass::print_info() hw/ppc: Avoid using Monitor in spapr_irq_print_info() hw/ppc: Avoid using Monitor in pnv_chip_power9_pic_print_info_child() hw/ppc: Avoid using Monitor in pic_print_info() include/hw/pci-host/pnv_phb3.h | 2 +- include/hw/pci-host/pnv_phb4.h | 2 +- include/hw/ppc/pnv_chip.h | 4 +- include/hw/ppc/pnv_psi.h | 2 +- include/hw/ppc/pnv_xive.h | 4 +- include/hw/ppc/spapr_irq.h | 4 +- include/hw/ppc/xics.h | 4 +- include/hw/ppc/xive.h | 4 +- include/hw/ppc/xive2_regs.h| 8 +-- include/hw/ppc/xive_regs.h | 8 +-- hw/intc/pnv_xive.c | 38 ++-- hw/intc/pnv_xive2.c| 48 +++ hw/intc/spapr_xive.c | 41 ++--- hw/intc/xics.c | 25 hw/intc/xics_spapr.c | 7 +-- hw/intc/xive.c | 108 - hw/intc/xive2.c| 87 +- hw/pci-host/pnv_phb3_msi.c | 21 +++ hw/pci-host/pnv_phb4.c | 17 +++--- hw/ppc/pnv.c | 52 hw/ppc/pnv_psi.c | 9 ++- hw/ppc/spapr.c | 11 +++- hw/ppc/spapr_irq.c | 4 +- 23 files changed, 256 insertions(+), 254 deletions(-)
Re: [PATCH 08/26] hw/ppc: Avoid using Monitor in spapr_xive_pic_print_info()
On 6/10/24 11:50, Philippe Mathieu-Daudé wrote: @@ -203,10 +201,8 @@ static void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon) spapr_xive_end_pic_print_info(xive, end, buf); } -info = human_readable_text_from_str(buf); -monitor_puts(mon, info->human_readable_text); } -monitor_printf(mon, "\n"); +g_string_append_c(buf, '\n'); Ok, I see caller specific changes are done in separate patches. Ideally one call flow could be squashed into a single patch, which would help avoid addition, followed by removal of common logic like above. However, assuming that would be increasing the patch size, I understand smaller patches are easier to review. Thanks Harsh } }
Re: [PATCH 07/26] hw/ppc: Avoid using Monitor in spapr_xive_end_pic_print_info()
On 6/10/24 11:50, Philippe Mathieu-Daudé wrote: @@ -198,13 +193,18 @@ static void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon) if (!xive_eas_is_masked(eas)) { uint32_t end_idx = xive_get_field64(EAS_END_INDEX, eas->w); XiveEND *end; +g_autoptr(GString) buf = g_string_new(""); +g_autoptr(HumanReadableText) info = NULL; assert(end_idx < xive->nr_ends); end = &xive->endt[end_idx]; if (xive_end_is_valid(end)) { -spapr_xive_end_pic_print_info(xive, end, mon); +spapr_xive_end_pic_print_info(xive, end, buf); } + +info = human_readable_text_from_str(buf); +monitor_puts(mon, info->human_readable_text); } monitor_printf(mon, "\n"); Similarly, this monitor_printf could be g_stringified before doing the human_readable logic ? Thanks Harsh }
Re: [PATCH 06/26] hw/ppc: Avoid using Monitor in xive_end_queue_pic_print_info()
On 6/10/24 11:50, Philippe Mathieu-Daudé wrote: @@ -1389,8 +1392,10 @@ void xive_end_pic_print_info(XiveEND *end, uint32_t end_idx, Monitor *mon) if (qaddr_base) { monitor_printf(mon, " eq:@%08"PRIx64"% 6d/%5d ^%d", qaddr_base, qindex, qentries, qgen); -xive_end_queue_pic_print_info(end, 6, mon); +xive_end_queue_pic_print_info(end, 6, buf); } +info = human_readable_text_from_str(buf); +monitor_puts(mon, info->human_readable_text); monitor_printf(mon, "\n"); This monitor_printf could also be folded in buf before info assignment ? }
Re: [PATCH 01/26] hw/ppc: Avoid using Monitor in pnv_phb3_msi_pic_print_info()
On 6/17/24 15:49, Harsh Prateek Bora wrote: Hi Phillipe, One query below: On 6/17/24 15:41, Harsh Prateek Bora wrote: On 6/10/24 11:50, Philippe Mathieu-Daudé wrote: Replace Monitor API by HumanReadableText one. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Harsh Prateek Bora --- include/hw/pci-host/pnv_phb3.h | 2 +- hw/pci-host/pnv_phb3_msi.c | 21 ++--- hw/ppc/pnv.c | 8 +++- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 6e3a5ccdec..5356a4e295 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -38,6 +38,7 @@ #include "hw/loader.h" #include "hw/nmi.h" #include "qapi/visitor.h" +#include "qapi/type-helpers.h" #include "monitor/monitor.h" #include "hw/intc/intc.h" #include "hw/ipmi/ipmi.h" @@ -774,8 +775,13 @@ static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) for (i = 0; i < chip8->num_phbs; i++) { PnvPHB *phb = chip8->phbs[i]; PnvPHB3 *phb3 = PNV_PHB3(phb->backend); + g_autoptr(GString) buf = g_string_new(""); + g_autoptr(HumanReadableText) info = NULL; + + pnv_phb3_msi_pic_print_info(&phb3->msis, buf); + info = human_readable_text_from_str(buf); + monitor_puts(mon, info->human_readable_text); - pnv_phb3_msi_pic_print_info(&phb3->msis, mon); ics_pic_print_info(&phb3->lsis, mon); How is the memory allocated to info in human_readable_text_from_str being reclaimed here? Isnt it a mem leak ? Ok, I see, g_autoptr takes care of auto cleanup. Please ignore. Thanks Harsh } }
Re: [PATCH 03/26] hw/ppc: Avoid using Monitor in xive_tctx_pic_print_info()
Hi Phillipe, On 6/10/24 11:50, Philippe Mathieu-Daudé wrote: diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index fa23b27a2b..5854358f65 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1223,7 +1223,13 @@ static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, Monitor *mon) { -xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); +g_autoptr(GString) buf = g_string_new(""); +g_autoptr(HumanReadableText) info = NULL; + +xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), buf); + +info = human_readable_text_from_str(buf); +monitor_puts(mon, info->human_readable_text); } static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu, @@ -1267,7 +1273,13 @@ static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, Monitor *mon) { -xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); +g_autoptr(GString) buf = g_string_new(""); +g_autoptr(HumanReadableText) info = NULL; + +xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), buf); + +info = human_readable_text_from_str(buf); +monitor_puts(mon, info->human_readable_text); } We have an existing code duplication in above two routines which is getting worse with these multi-lines getting duplicated. Could _power9_ be changed to inline and called from _power10_ as well? Thanks Harsh
Re: [PATCH 01/26] hw/ppc: Avoid using Monitor in pnv_phb3_msi_pic_print_info()
Hi Phillipe, One query below: On 6/17/24 15:41, Harsh Prateek Bora wrote: On 6/10/24 11:50, Philippe Mathieu-Daudé wrote: Replace Monitor API by HumanReadableText one. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Harsh Prateek Bora --- include/hw/pci-host/pnv_phb3.h | 2 +- hw/pci-host/pnv_phb3_msi.c | 21 ++--- hw/ppc/pnv.c | 8 +++- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 6e3a5ccdec..5356a4e295 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -38,6 +38,7 @@ #include "hw/loader.h" #include "hw/nmi.h" #include "qapi/visitor.h" +#include "qapi/type-helpers.h" #include "monitor/monitor.h" #include "hw/intc/intc.h" #include "hw/ipmi/ipmi.h" @@ -774,8 +775,13 @@ static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) for (i = 0; i < chip8->num_phbs; i++) { PnvPHB *phb = chip8->phbs[i]; PnvPHB3 *phb3 = PNV_PHB3(phb->backend); + g_autoptr(GString) buf = g_string_new(""); + g_autoptr(HumanReadableText) info = NULL; + + pnv_phb3_msi_pic_print_info(&phb3->msis, buf); + info = human_readable_text_from_str(buf); + monitor_puts(mon, info->human_readable_text); - pnv_phb3_msi_pic_print_info(&phb3->msis, mon); ics_pic_print_info(&phb3->lsis, mon); How is the memory allocated to info in human_readable_text_from_str being reclaimed here? Isnt it a mem leak ? Thanks Harsh } }
Re: [PATCH 01/26] hw/ppc: Avoid using Monitor in pnv_phb3_msi_pic_print_info()
On 6/10/24 11:50, Philippe Mathieu-Daudé wrote: Replace Monitor API by HumanReadableText one. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Harsh Prateek Bora --- include/hw/pci-host/pnv_phb3.h | 2 +- hw/pci-host/pnv_phb3_msi.c | 21 ++--- hw/ppc/pnv.c | 8 +++- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/include/hw/pci-host/pnv_phb3.h b/include/hw/pci-host/pnv_phb3.h index d62b3091ac..24ca3dddaa 100644 --- a/include/hw/pci-host/pnv_phb3.h +++ b/include/hw/pci-host/pnv_phb3.h @@ -40,7 +40,7 @@ void pnv_phb3_msi_update_config(Phb3MsiState *msis, uint32_t base, void pnv_phb3_msi_send(Phb3MsiState *msis, uint64_t addr, uint16_t data, int32_t dev_pe); void pnv_phb3_msi_ffi(Phb3MsiState *msis, uint64_t val); -void pnv_phb3_msi_pic_print_info(Phb3MsiState *msis, Monitor *mon); +void pnv_phb3_msi_pic_print_info(Phb3MsiState *msis, GString *buf); /* diff --git a/hw/pci-host/pnv_phb3_msi.c b/hw/pci-host/pnv_phb3_msi.c index a6d827f903..77d673da54 100644 --- a/hw/pci-host/pnv_phb3_msi.c +++ b/hw/pci-host/pnv_phb3_msi.c @@ -13,7 +13,6 @@ #include "hw/pci-host/pnv_phb3.h" #include "hw/ppc/pnv.h" #include "hw/pci/msi.h" -#include "monitor/monitor.h" #include "hw/irq.h" #include "hw/qdev-properties.h" #include "sysemu/reset.h" @@ -316,13 +315,13 @@ static void pnv_phb3_msi_register_types(void) type_init(pnv_phb3_msi_register_types); -void pnv_phb3_msi_pic_print_info(Phb3MsiState *msi, Monitor *mon) +void pnv_phb3_msi_pic_print_info(Phb3MsiState *msi, GString *buf) { ICSState *ics = ICS(msi); int i; -monitor_printf(mon, "ICS %4x..%4x %p\n", - ics->offset, ics->offset + ics->nr_irqs - 1, ics); +g_string_append_printf(buf, "ICS %4x..%4x %p\n", + ics->offset, ics->offset + ics->nr_irqs - 1, ics); for (i = 0; i < ics->nr_irqs; i++) { uint64_t ive; @@ -335,12 +334,12 @@ void pnv_phb3_msi_pic_print_info(Phb3MsiState *msi, Monitor *mon) continue; } -monitor_printf(mon, " %4x %c%c server=%04x prio=%02x gen=%d\n", - ics->offset + i, - GETFIELD(IODA2_IVT_P, ive) ? 'P' : '-', - GETFIELD(IODA2_IVT_Q, ive) ? 'Q' : '-', - (uint32_t) GETFIELD(IODA2_IVT_SERVER, ive) >> 2, - (uint32_t) GETFIELD(IODA2_IVT_PRIORITY, ive), - (uint32_t) GETFIELD(IODA2_IVT_GEN, ive)); +g_string_append_printf(buf, " %4x %c%c server=%04x prio=%02x gen=%d\n", + ics->offset + i, + GETFIELD(IODA2_IVT_P, ive) ? 'P' : '-', + GETFIELD(IODA2_IVT_Q, ive) ? 'Q' : '-', + (uint32_t) GETFIELD(IODA2_IVT_SERVER, ive) >> 2, + (uint32_t) GETFIELD(IODA2_IVT_PRIORITY, ive), + (uint32_t) GETFIELD(IODA2_IVT_GEN, ive)); } } diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 6e3a5ccdec..5356a4e295 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -38,6 +38,7 @@ #include "hw/loader.h" #include "hw/nmi.h" #include "qapi/visitor.h" +#include "qapi/type-helpers.h" #include "monitor/monitor.h" #include "hw/intc/intc.h" #include "hw/ipmi/ipmi.h" @@ -774,8 +775,13 @@ static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) for (i = 0; i < chip8->num_phbs; i++) { PnvPHB *phb = chip8->phbs[i]; PnvPHB3 *phb3 = PNV_PHB3(phb->backend); +g_autoptr(GString) buf = g_string_new(""); +g_autoptr(HumanReadableText) info = NULL; + +pnv_phb3_msi_pic_print_info(&phb3->msis, buf); +info = human_readable_text_from_str(buf); +monitor_puts(mon, info->human_readable_text); -pnv_phb3_msi_pic_print_info(&phb3->msis, mon); ics_pic_print_info(&phb3->lsis, mon); } }
Re: [PATCH v4 01/11] ppc: Add Power11 DD2.0 processor
On 5/30/24 12:18, Aditya Gupta wrote: Hello Harsh, On Thu, May 30, 2024 at 10:57:31AM GMT, Harsh Prateek Bora wrote: Hi Aditya, On 5/28/24 12:35, Aditya Gupta wrote: Add CPU target code to add support for new Power11 Processor. Power11 core is same as Power10, hence reuse functions defined for Power10. Cc: Cédric Le Goater Cc: Daniel Henrique Barboza Cc: Frédéric Barrat Cc: Mahesh J Salgaonkar Cc: Madhavan Srinivasan Cc: Nicholas Piggin Signed-off-by: Aditya Gupta --- target/ppc/compat.c | 7 +++ target/ppc/cpu-models.c | 3 ++ target/ppc/cpu-models.h | 3 ++ target/ppc/cpu_init.c | 102 4 files changed, 115 insertions(+) diff --git a/target/ppc/compat.c b/target/ppc/compat.c index ebef2cccecf3..12dd8ae290ca 100644 --- a/target/ppc/compat.c +++ b/target/ppc/compat.c @@ -100,6 +100,13 @@ static const CompatInfo compat_table[] = { .pcr_level = PCR_COMPAT_3_10, .max_vthreads = 8, }, +{ /* POWER11, ISA3.10 */ +.name = "power11", +.pvr = CPU_POWERPC_LOGICAL_3_10_PLUS, +.pcr = PCR_COMPAT_3_10, +.pcr_level = PCR_COMPAT_3_10, +.max_vthreads = 8, +}, }; static const CompatInfo *compat_by_pvr(uint32_t pvr) diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c index f2301b43f78b..ece348178188 100644 --- a/target/ppc/cpu-models.c +++ b/target/ppc/cpu-models.c @@ -734,6 +734,8 @@ "POWER9 v2.2") POWERPC_DEF("power10_v2.0", CPU_POWERPC_POWER10_DD20, POWER10, "POWER10 v2.0") +POWERPC_DEF("power11_v2.0", CPU_POWERPC_POWER11_DD20, POWER11, +"POWER11_v2.0") #endif /* defined (TARGET_PPC64) */ /***/ @@ -909,6 +911,7 @@ PowerPCCPUAlias ppc_cpu_aliases[] = { { "power8nvl", "power8nvl_v1.0" }, { "power9", "power9_v2.2" }, { "power10", "power10_v2.0" }, +{ "power11", "power11_v2.0" }, #endif /* Generic PowerPCs */ diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h index 0229ef3a9a5c..ef74e387b047 100644 --- a/target/ppc/cpu-models.h +++ b/target/ppc/cpu-models.h @@ -354,6 +354,8 @@ enum { CPU_POWERPC_POWER10_BASE = 0x0080, CPU_POWERPC_POWER10_DD1= 0x00801100, CPU_POWERPC_POWER10_DD20 = 0x00801200, +CPU_POWERPC_POWER11_BASE = 0x0082, +CPU_POWERPC_POWER11_DD20 = 0x00821200, CPU_POWERPC_970_v22= 0x00390202, CPU_POWERPC_970FX_v10 = 0x00391100, CPU_POWERPC_970FX_v20 = 0x003C0200, @@ -391,6 +393,7 @@ enum { CPU_POWERPC_LOGICAL_2_07 = 0x0F04, CPU_POWERPC_LOGICAL_3_00 = 0x0F05, CPU_POWERPC_LOGICAL_3_10 = 0x0F06, +CPU_POWERPC_LOGICAL_3_10_PLUS = 0x0F07, }; /* System version register (used on MPC 8xxx) */ diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 01e358a4a5ac..82d700382cdd 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -6763,6 +6763,108 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data) pcc->l1_icache_size = 0x8000; } +static bool ppc_pvr_match_power11(PowerPCCPUClass *pcc, uint32_t pvr, bool best) +{ +uint32_t base = pvr & CPU_POWERPC_POWER_SERVER_MASK; +uint32_t pcc_base = pcc->pvr & CPU_POWERPC_POWER_SERVER_MASK; + +if (!best && (base == CPU_POWERPC_POWER11_BASE)) { Also, this helper is almost same as that of power10 except for the base check against respective value. This entire logic can be shared by passing respective base value to the another low level routine which takes this base value as arg. Let's try to avoid code duplication by resharing as much as possible. Thanks Harsh +return true; +} + +if (base != pcc_base) { +return false; +} + +if ((pvr & 0x0f00) == (pcc->pvr & 0x0f00)) { +return true; +} + +return false; +} + +POWERPC_FAMILY(POWER11)(ObjectClass *oc, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(oc); +PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); + +dc->fw_name = "PowerPC,POWER11"; +dc->desc = "POWER11"; +pcc->pvr_match = ppc_pvr_match_power11; +pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06 | PCR_COMPAT_2_07 | +PCR_COMPAT_3_00; +pcc->pcr_supported = PCR_COMPAT_3_10 | PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | + PCR_COMPAT_2_06 | PCR_COMPAT_2_05; +pcc->init_proc = init_proc_POWER10; +pcc->check_pow = check_pow_nocheck; +pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MF
Re: [PATCH 1/2] hw/acpi: Remove the deprecated QAPI MEM_UNPLUG_ERROR event
On 5/30/24 12:45, Philippe Mathieu-Daudé wrote: The MEM_UNPLUG_ERROR event is deprecated since commit d43f1670c7 ("qapi/qdev.json: add DEVICE_UNPLUG_GUEST_ERROR QAPI event"), time to remove it. Signed-off-by: Philippe Mathieu-Daudé --- docs/about/deprecated.rst | 5 - docs/about/removed-features.rst | 9 + qapi/machine.json | 28 hw/acpi/memory_hotplug.c| 8 hw/ppc/spapr.c | 11 +-- 5 files changed, 10 insertions(+), 51 deletions(-) For spapr: Reviewed-by: Harsh Prateek Bora diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 40585ca7d5..4a61894db6 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -151,11 +151,6 @@ property types. QEMU Machine Protocol (QMP) events -- -``MEM_UNPLUG_ERROR`` (since 6.2) -'''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -Use the more generic event ``DEVICE_UNPLUG_GUEST_ERROR`` instead. - ``vcpu`` trace events (since 8.1) ''''''''''''''''''''''''''''''''' diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst index fba0cfb0b0..f1e70263e2 100644 --- a/docs/about/removed-features.rst +++ b/docs/about/removed-features.rst @@ -671,6 +671,15 @@ Use ``multifd-channels`` instead. Use ``multifd-compression`` instead. +QEMU Machine Protocol (QMP) events +-- + +``MEM_UNPLUG_ERROR`` (removed in 9.1) +''''''''''''''''''''''''''''''''''''' + +MEM_UNPLUG_ERROR has been replaced by the more generic ``DEVICE_UNPLUG_GUEST_ERROR`` event. + + Human Monitor Protocol (HMP) commands - diff --git a/qapi/machine.json b/qapi/machine.json index bce6e1bbc4..453feb9347 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -1607,34 +1607,6 @@ { 'event': 'MEMORY_DEVICE_SIZE_CHANGE', 'data': { '*id': 'str', 'size': 'size', 'qom-path' : 'str'} } -## -# @MEM_UNPLUG_ERROR: -# -# Emitted when memory hot unplug error occurs. -# -# @device: device name -# -# @msg: Informative message -# -# Features: -# -# @deprecated: This event is deprecated. Use -# @DEVICE_UNPLUG_GUEST_ERROR instead. -# -# Since: 2.4 -# -# Example: -# -# <- { "event": "MEM_UNPLUG_ERROR", -# "data": { "device": "dimm1", -#"msg": "acpi: device unplug for unsupported device" -# }, -# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } -## -{ 'event': 'MEM_UNPLUG_ERROR', - 'data': { 'device': 'str', 'msg': 'str' }, - 'features': ['deprecated'] } - ## # @BootConfiguration: # diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c index de6f974ebb..9b974b7274 100644 --- a/hw/acpi/memory_hotplug.c +++ b/hw/acpi/memory_hotplug.c @@ -178,14 +178,6 @@ static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data, hotplug_handler_unplug(hotplug_ctrl, dev, &local_err); if (local_err) { trace_mhp_acpi_pc_dimm_delete_failed(mem_st->selector); - -/* - * Send both MEM_UNPLUG_ERROR and DEVICE_UNPLUG_GUEST_ERROR - * while the deprecation of MEM_UNPLUG_ERROR is - * pending. - */ -qapi_event_send_mem_unplug_error(dev->id ? : "", - error_get_pretty(local_err)); qapi_event_send_device_unplug_guest_error(dev->id, dev->canonical_path); error_free(local_err); diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 4345764bce..81a187f126 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3786,7 +3786,6 @@ void spapr_memory_unplug_rollback(SpaprMachineState *spapr, DeviceState *dev) SpaprDrc *drc; uint32_t nr_lmbs; uint64_t size, addr_start, addr; -g_autofree char *qapi_error = NULL; int i; if (!dev) { @@ -3823,16 +3822,8 @@ void spapr_memory_unplug_rollback(SpaprMachineState *spapr, DeviceState *dev) /* * Tell QAPI that something happened and the memory - * hotunplug wasn't successful. Keep sending - * MEM_UNPLUG_ERROR even while sending - * DEVICE_UNPLUG_GUEST_ERROR until the deprecation of - * MEM_UNPLUG_ERROR is due. + * hotunplug wasn't successful. */ -qapi_error = g_strdup_printf("Memory hotunplug rejected by the guest " - "for device %s", dev->id); - -qapi_event_send_mem_unplug_error(dev->id ? : "", qapi_error); - qapi_event_send_device_unplug_guest_error(dev->id, dev->canonical_path); }
Re: [PATCH v4 02/11] ppc/pseries: Add Power11 cpu type
On 5/28/24 12:35, Aditya Gupta wrote: Add sPAPR CPU Core definition for Power11 Cc: David Gibson (reviewer:sPAPR (pseries)) Cc: Harsh Prateek Bora (reviewer:sPAPR (pseries)) Cc: Cédric Le Goater Cc: Daniel Henrique Barboza Cc: Frédéric Barrat Cc: Mahesh J Salgaonkar Cc: Madhavan Srinivasan Cc: Nicholas Piggin Signed-off-by: Aditya Gupta --- docs/system/ppc/pseries.rst | 6 +++--- hw/ppc/spapr_cpu_core.c | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/system/ppc/pseries.rst b/docs/system/ppc/pseries.rst index a876d897b6e4..3277564b34c2 100644 --- a/docs/system/ppc/pseries.rst +++ b/docs/system/ppc/pseries.rst @@ -15,9 +15,9 @@ Supported devices = * Multi processor support for many Power processors generations: POWER7, - POWER7+, POWER8, POWER8NVL, POWER9, and Power10. Support for POWER5+ exists, - but its state is unknown. - * Interrupt Controller, XICS (POWER8) and XIVE (POWER9 and Power10) + POWER7+, POWER8, POWER8NVL, POWER9, Power10 and Power11. Support for POWER5+ + exists, but its state is unknown. + * Interrupt Controller, XICS (POWER8) and XIVE (POWER9, Power10, Power11) I think it would look more cleaner to rephrase as below: * Multi processor support for many Power processors generations: - POWER7, POWER7+ - POWER8, POWER8NVL - POWER9 - Power10 - Power11. - Support for POWER5+ exists, but its state is unknown. * Interrupt Controller - XICS (POWER8) - XIVE (Supported by below:) - POWER9 - Power10 - Power11 So, that every next platform just need to add one line for itself. With that, Reviewed-by: Harsh Prateek Bora Thanks Harsh * vPHB PCIe Host bridge. * vscsi and vnet devices, compatible with the same devices available on a PowerVM hypervisor with VIOS managing LPARs. diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index e7c9edd033c8..62416b7e0a7e 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -401,6 +401,7 @@ static const TypeInfo spapr_cpu_core_type_infos[] = { DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.0"), DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.2"), DEFINE_SPAPR_CPU_CORE_TYPE("power10_v2.0"), +DEFINE_SPAPR_CPU_CORE_TYPE("power11_v2.0"), #ifdef CONFIG_KVM DEFINE_SPAPR_CPU_CORE_TYPE("host"), #endif
Re: [PATCH v4 01/11] ppc: Add Power11 DD2.0 processor
Hi Aditya, On 5/28/24 12:35, Aditya Gupta wrote: Add CPU target code to add support for new Power11 Processor. Power11 core is same as Power10, hence reuse functions defined for Power10. Cc: Cédric Le Goater Cc: Daniel Henrique Barboza Cc: Frédéric Barrat Cc: Mahesh J Salgaonkar Cc: Madhavan Srinivasan Cc: Nicholas Piggin Signed-off-by: Aditya Gupta --- target/ppc/compat.c | 7 +++ target/ppc/cpu-models.c | 3 ++ target/ppc/cpu-models.h | 3 ++ target/ppc/cpu_init.c | 102 4 files changed, 115 insertions(+) diff --git a/target/ppc/compat.c b/target/ppc/compat.c index ebef2cccecf3..12dd8ae290ca 100644 --- a/target/ppc/compat.c +++ b/target/ppc/compat.c @@ -100,6 +100,13 @@ static const CompatInfo compat_table[] = { .pcr_level = PCR_COMPAT_3_10, .max_vthreads = 8, }, +{ /* POWER11, ISA3.10 */ +.name = "power11", +.pvr = CPU_POWERPC_LOGICAL_3_10_PLUS, +.pcr = PCR_COMPAT_3_10, +.pcr_level = PCR_COMPAT_3_10, +.max_vthreads = 8, +}, }; static const CompatInfo *compat_by_pvr(uint32_t pvr) diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c index f2301b43f78b..ece348178188 100644 --- a/target/ppc/cpu-models.c +++ b/target/ppc/cpu-models.c @@ -734,6 +734,8 @@ "POWER9 v2.2") POWERPC_DEF("power10_v2.0", CPU_POWERPC_POWER10_DD20, POWER10, "POWER10 v2.0") +POWERPC_DEF("power11_v2.0", CPU_POWERPC_POWER11_DD20, POWER11, +"POWER11_v2.0") #endif /* defined (TARGET_PPC64) */ /***/ @@ -909,6 +911,7 @@ PowerPCCPUAlias ppc_cpu_aliases[] = { { "power8nvl", "power8nvl_v1.0" }, { "power9", "power9_v2.2" }, { "power10", "power10_v2.0" }, +{ "power11", "power11_v2.0" }, #endif /* Generic PowerPCs */ diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h index 0229ef3a9a5c..ef74e387b047 100644 --- a/target/ppc/cpu-models.h +++ b/target/ppc/cpu-models.h @@ -354,6 +354,8 @@ enum { CPU_POWERPC_POWER10_BASE = 0x0080, CPU_POWERPC_POWER10_DD1= 0x00801100, CPU_POWERPC_POWER10_DD20 = 0x00801200, +CPU_POWERPC_POWER11_BASE = 0x0082, +CPU_POWERPC_POWER11_DD20 = 0x00821200, CPU_POWERPC_970_v22= 0x00390202, CPU_POWERPC_970FX_v10 = 0x00391100, CPU_POWERPC_970FX_v20 = 0x003C0200, @@ -391,6 +393,7 @@ enum { CPU_POWERPC_LOGICAL_2_07 = 0x0F04, CPU_POWERPC_LOGICAL_3_00 = 0x0F05, CPU_POWERPC_LOGICAL_3_10 = 0x0F06, +CPU_POWERPC_LOGICAL_3_10_PLUS = 0x0F07, }; /* System version register (used on MPC 8xxx)*/ diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 01e358a4a5ac..82d700382cdd 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -6763,6 +6763,108 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data) pcc->l1_icache_size = 0x8000; } +static bool ppc_pvr_match_power11(PowerPCCPUClass *pcc, uint32_t pvr, bool best) +{ +uint32_t base = pvr & CPU_POWERPC_POWER_SERVER_MASK; +uint32_t pcc_base = pcc->pvr & CPU_POWERPC_POWER_SERVER_MASK; + +if (!best && (base == CPU_POWERPC_POWER11_BASE)) { +return true; +} + +if (base != pcc_base) { +return false; +} + +if ((pvr & 0x0f00) == (pcc->pvr & 0x0f00)) { +return true; +} + +return false; +} + +POWERPC_FAMILY(POWER11)(ObjectClass *oc, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(oc); +PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); + +dc->fw_name = "PowerPC,POWER11"; +dc->desc = "POWER11"; +pcc->pvr_match = ppc_pvr_match_power11; +pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06 | PCR_COMPAT_2_07 | +PCR_COMPAT_3_00; +pcc->pcr_supported = PCR_COMPAT_3_10 | PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | + PCR_COMPAT_2_06 | PCR_COMPAT_2_05; +pcc->init_proc = init_proc_POWER10; +pcc->check_pow = check_pow_nocheck; +pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB | + PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES | + PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | + PPC_FLOAT_FRSQRTES | + PPC_FLOAT_STFIWX | + PPC_FLOAT_EXT | + PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ | + PPC_MEM_SYNC | PPC_MEM_EIEIO | + PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | + PPC_64B | PPC_64H | PPC_64BX | PPC_ALTIVEC | + PPC_SEGMENT_64B | PPC_SLBI | + PPC_POPCNTB | PPC_POPCNTWD | + PPC_CILDST; +pcc->insns_flags2 = PPC2_VSX | PPC2_VSX207 |
Re: [PATCH V12 1/8] accel/kvm: Extract common KVM vCPU {creation,parking} code
On 5/30/24 05:12, Salil Mehta wrote: KVM vCPU creation is done once during the vCPU realization when Qemu vCPU thread is spawned. This is common to all the architectures as of now. Hot-unplug of vCPU results in destruction of the vCPU object in QOM but the corresponding KVM vCPU object in the Host KVM is not destroyed as KVM doesn't support vCPU removal. Therefore, its representative KVM vCPU object/context in Qemu is parked. Refactor architecture common logic so that some APIs could be reused by vCPU Hotplug code of some architectures likes ARM, Loongson etc. Update new/old APIs with trace events. No functional change is intended here. Signed-off-by: Salil Mehta Reviewed-by: Gavin Shan Tested-by: Vishnu Pajjuri Reviewed-by: Jonathan Cameron Tested-by: Xianglai Li Tested-by: Miguel Luis Reviewed-by: Shaoqin Huang Reviewed-by: Vishnu Pajjuri Reviewed-by: Nicholas Piggin Tested-by: Zhao Liu Reviewed-by: Zhao Liu --- accel/kvm/kvm-all.c| 95 -- accel/kvm/kvm-cpus.h | 23 ++ accel/kvm/trace-events | 5 ++- 3 files changed, 90 insertions(+), 33 deletions(-) Since there are no functional changes intended here and we have a different patch series (ppc64 vcpu hotplug failure fixes) depending on this patch as well, it will be nice to see this patch getting merged soon. Reviewed-by: Harsh Prateek Bora diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index c0be9f5eed..8f9128bb92 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -340,14 +340,71 @@ err: return ret; } +void kvm_park_vcpu(CPUState *cpu) +{ +struct KVMParkedVcpu *vcpu; + +trace_kvm_park_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu)); + +vcpu = g_malloc0(sizeof(*vcpu)); +vcpu->vcpu_id = kvm_arch_vcpu_id(cpu); +vcpu->kvm_fd = cpu->kvm_fd; +QLIST_INSERT_HEAD(&kvm_state->kvm_parked_vcpus, vcpu, node); +} + +int kvm_unpark_vcpu(KVMState *s, unsigned long vcpu_id) +{ +struct KVMParkedVcpu *cpu; +int kvm_fd = -ENOENT; + +QLIST_FOREACH(cpu, &s->kvm_parked_vcpus, node) { +if (cpu->vcpu_id == vcpu_id) { +QLIST_REMOVE(cpu, node); +kvm_fd = cpu->kvm_fd; +g_free(cpu); +} +} + +trace_kvm_unpark_vcpu(vcpu_id, kvm_fd > 0 ? "unparked" : "not found parked"); + +return kvm_fd; +} + +int kvm_create_vcpu(CPUState *cpu) +{ +unsigned long vcpu_id = kvm_arch_vcpu_id(cpu); +KVMState *s = kvm_state; +int kvm_fd; + +/* check if the KVM vCPU already exist but is parked */ +kvm_fd = kvm_unpark_vcpu(s, vcpu_id); +if (kvm_fd < 0) { +/* vCPU not parked: create a new KVM vCPU */ +kvm_fd = kvm_vm_ioctl(s, KVM_CREATE_VCPU, vcpu_id); +if (kvm_fd < 0) { +error_report("KVM_CREATE_VCPU IOCTL failed for vCPU %lu", vcpu_id); +return kvm_fd; +} +} + +cpu->kvm_fd = kvm_fd; +cpu->kvm_state = s; +cpu->vcpu_dirty = true; +cpu->dirty_pages = 0; +cpu->throttle_us_per_full = 0; + +trace_kvm_create_vcpu(cpu->cpu_index, vcpu_id, kvm_fd); + +return 0; +} + static int do_kvm_destroy_vcpu(CPUState *cpu) { KVMState *s = kvm_state; long mmap_size; -struct KVMParkedVcpu *vcpu = NULL; int ret = 0; -trace_kvm_destroy_vcpu(); +trace_kvm_destroy_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu)); ret = kvm_arch_destroy_vcpu(cpu); if (ret < 0) { @@ -373,10 +430,7 @@ static int do_kvm_destroy_vcpu(CPUState *cpu) } } -vcpu = g_malloc0(sizeof(*vcpu)); -vcpu->vcpu_id = kvm_arch_vcpu_id(cpu); -vcpu->kvm_fd = cpu->kvm_fd; -QLIST_INSERT_HEAD(&kvm_state->kvm_parked_vcpus, vcpu, node); +kvm_park_vcpu(cpu); err: return ret; } @@ -389,24 +443,6 @@ void kvm_destroy_vcpu(CPUState *cpu) } } -static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id) -{ -struct KVMParkedVcpu *cpu; - -QLIST_FOREACH(cpu, &s->kvm_parked_vcpus, node) { -if (cpu->vcpu_id == vcpu_id) { -int kvm_fd; - -QLIST_REMOVE(cpu, node); -kvm_fd = cpu->kvm_fd; -g_free(cpu); -return kvm_fd; -} -} - -return kvm_vm_ioctl(s, KVM_CREATE_VCPU, (void *)vcpu_id); -} - int kvm_init_vcpu(CPUState *cpu, Error **errp) { KVMState *s = kvm_state; @@ -415,19 +451,14 @@ int kvm_init_vcpu(CPUState *cpu, Error **errp) trace_kvm_init_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu)); -ret = kvm_get_vcpu(s, kvm_arch_vcpu_id(cpu)); +ret = kvm_create_vcpu(cpu); if (ret < 0) { -error_setg_errno(errp, -ret, "kvm_init_vcpu: kvm_get_vcpu failed (%lu)", +error_setg_errno(errp, -ret, + "kvm_init_vcpu: kvm_create_vcpu failed (%lu)",
Re: [RFC PATCH 08/10] ppc/pnv: Invert the design for big-core machine modelling
Hi Nick, On 5/26/24 17:56, Nicholas Piggin wrote: POWER9 and POWER10 machines come in two variants, "big-core" and "small-core". Big core machines are SMT8 from the software point of view, but in the low level platform topology ("xscom registers and pervasive addressing"), these look more like a pair of small cores ganged together. Presently, the way this is modelled is to create an SMT8 PnvCore and add special cases to xscom and pervasive for big-core mode. This is becoming too complicated to manage as more of the machine is modelled. The better approach looks like the inverse, which is creating 2xPnvCore ganging them together to look like an SMT8 core in TCG. The TCG SMT code is quite simple to do that, and then the xscom and pervasive modelling does not need to differentiate big and small core modes for the most part. device-tree building does need a special case to only build one CPU node for each big-core because that's what the firmware expects. And so does a special case workaround in the ChipTOD model. A big-core machine option is added for powernv9 and 10 machines. Signed-off-by: Nicholas Piggin --- include/hw/ppc/pnv.h | 3 + include/hw/ppc/pnv_core.h| 8 ++ target/ppc/cpu.h | 4 +- hw/ppc/pnv.c | 183 --- hw/ppc/pnv_core.c| 20 +++- hw/ppc/spapr_cpu_core.c | 6 +- target/ppc/misc_helper.c | 6 +- target/ppc/timebase_helper.c | 9 ++ 8 files changed, 197 insertions(+), 42 deletions(-) diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index 476b136146..93ecb062b4 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -100,6 +100,9 @@ struct PnvMachineState { PnvPnor *pnor; hwaddr fw_load_addr; + +bool big_core; +bool big_core_tbst_quirk; }; PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id); diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h index 21297262c1..39f8f33e6c 100644 --- a/include/hw/ppc/pnv_core.h +++ b/include/hw/ppc/pnv_core.h @@ -27,6 +27,13 @@ /* ChipTOD and TimeBase State Machine */ struct pnv_tod_tbst { +/* + * POWER10 DD2.0 - big core TFMR drives the state machine on the even + * small core. Skiboot has a workaround that targets the even small core + * for CHIPTOD_TO_TB ops. + */ +bool big_core_quirk; + int tb_ready_for_tod; /* core TB ready to receive TOD from chiptod */ int tod_sent_to_tb; /* chiptod sent TOD to the core TB */ @@ -49,6 +56,7 @@ struct PnvCore { /*< public >*/ PowerPCCPU **threads; +bool big_core; uint32_t pir; uint32_t hwid; uint64_t hrmor; diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 8fd6ade471..de15e38af8 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1248,6 +1248,7 @@ struct CPUArchState { int access_type; /* For SMT processors */ +int has_smt_siblings; bool ? int core_index; #if !defined(CONFIG_USER_ONLY) @@ -1276,7 +1277,6 @@ struct CPUArchState { uint32_t tlb_need_flush; /* Delayed flush needed */ #define TLB_NEED_LOCAL_FLUSH 0x1 #define TLB_NEED_GLOBAL_FLUSH 0x2 - #endif /* Other registers */ @@ -1407,7 +1407,7 @@ struct CPUArchState { }; #define PPC_CPU_HAS_CORE_SIBLINGS(cs) \ -(cs->nr_threads > 1) +(POWERPC_CPU(cs)->env.has_smt_siblings) #define PPC_CPU_HAS_LPAR_SIBLINGS(cs) \ ((POWERPC_CPU(cs)->env.flags & POWERPC_FLAG_SMT_1LPAR) && \ diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 7d062ec16c..5364c55bbb 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -142,7 +142,7 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) CPUPPCState *env = &cpu->env; PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); PnvChipClass *pnv_cc = PNV_CHIP_GET_CLASS(chip); -g_autofree uint32_t *servers_prop = g_new(uint32_t, smt_threads); +uint32_t *servers_prop; int i; uint32_t pir, tir; uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), @@ -157,6 +157,14 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) pnv_cc->processor_id(chip, pc->hwid, 0, &pir, &tir); +/* Only one DT node per (big) core */ +if (tir != 0) { +g_assert(pc->big_core); +g_assert(tir == 1); +g_assert(pc->hwid & 1) > +return -1; +} + nodename = g_strdup_printf("%s@%x", dc->fw_name, pir); offset = fdt_add_subnode(fdt, cpus_offset, nodename); _FDT(offset); @@ -236,12 +244,28 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) } /* Build interrupt servers properties */ -for (i = 0; i < smt_threads; i++) { -pnv_cc->processor_id(chip, pc->hwid, i, &pir, &tir); -servers_prop[i] = cpu_to_be32(pir); +if (pc->big_core) { +servers_prop = g_ne
Re: [RFC PATCH 07/10] target/ppc: Add helpers to check for SMT sibling threads
On 5/26/24 17:56, Nicholas Piggin wrote: Add helpers for TCG code to determine if there are SMT siblings sharing per-core and per-lpar registers. This simplifies the callers and makes SMT register topology simpler to modify with later changes. Signed-off-by: Nicholas Piggin --- target/ppc/cpu.h | 7 +++ target/ppc/cpu_init.c| 2 +- target/ppc/excp_helper.c | 16 +++- target/ppc/misc_helper.c | 27 ++- target/ppc/timebase_helper.c | 20 +++- 5 files changed, 28 insertions(+), 44 deletions(-) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 9a89083932..8fd6ade471 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1406,6 +1406,13 @@ struct CPUArchState { uint64_t pmu_base_time; }; +#define PPC_CPU_HAS_CORE_SIBLINGS(cs) \ +(cs->nr_threads > 1) + +#define PPC_CPU_HAS_LPAR_SIBLINGS(cs) \ +((POWERPC_CPU(cs)->env.flags & POWERPC_FLAG_SMT_1LPAR) && \ + PPC_CPU_HAS_CORE_SIBLINGS(cs)) + #define _CORE_ID(cs)\ (POWERPC_CPU(cs)->env.core_index) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index ae483e20c4..e71ee008ed 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -6975,7 +6975,7 @@ static void ppc_cpu_realize(DeviceState *dev, Error **errp) pcc->parent_realize(dev, errp); -if (env_cpu(env)->nr_threads > 1) { +if (PPC_CPU_HAS_CORE_SIBLINGS(cs)) { env->flags |= POWERPC_FLAG_SMT; } diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 0cd542675f..fd45da0f2b 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -3029,7 +3029,7 @@ void helper_book3s_msgsnd(CPUPPCState *env, target_ulong rb) brdcast = true; } -if (cs->nr_threads == 1 || !brdcast) { +if (!PPC_CPU_HAS_CORE_SIBLINGS(cs) || !brdcast) { Since there are multiple usage of above macro in negation below as well, we may probably want to introduce another macro PPC_CPU_HAS_SINGLE_CORE which checks only for nr_threads == 1. Anyways, Reviewed-by: Harsh Prateek Bora ppc_set_irq(cpu, PPC_INTERRUPT_HDOORBELL, 1); return; } @@ -3067,21 +3067,19 @@ void helper_book3s_msgsndp(CPUPPCState *env, target_ulong rb) CPUState *cs = env_cpu(env); PowerPCCPU *cpu = env_archcpu(env); CPUState *ccs; -uint32_t nr_threads = cs->nr_threads; int ttir = rb & PPC_BITMASK(57, 63); 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) { +if (!dbell_type_server(rb)) { return; } -if (nr_threads == 1) { -ppc_set_irq(cpu, PPC_INTERRUPT_DOORBELL, 1); +/* msgsndp behaves as 1-thread in LPAR-per-thread mode*/ +if (!PPC_CPU_HAS_LPAR_SIBLINGS(cs)) { +if (ttir == 0) { +ppc_set_irq(cpu, PPC_INTERRUPT_DOORBELL, 1); +} return; } diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c index 46ba3a5584..598c956cdd 100644 --- a/target/ppc/misc_helper.c +++ b/target/ppc/misc_helper.c @@ -49,9 +49,8 @@ void helper_spr_core_write_generic(CPUPPCState *env, uint32_t sprn, { CPUState *cs = env_cpu(env); CPUState *ccs; -uint32_t nr_threads = cs->nr_threads; -if (nr_threads == 1) { +if (!PPC_CPU_HAS_CORE_SIBLINGS(cs)) { env->spr[sprn] = val; return; } @@ -196,7 +195,7 @@ void helper_store_ptcr(CPUPPCState *env, target_ulong val) return; } -if (cs->nr_threads == 1 || !(env->flags & POWERPC_FLAG_SMT_1LPAR)) { +if (!PPC_CPU_HAS_LPAR_SIBLINGS(cs)) { env->spr[SPR_PTCR] = val; tlb_flush(cs); } else { @@ -243,16 +242,12 @@ target_ulong helper_load_dpdes(CPUPPCState *env) { CPUState *cs = env_cpu(env); CPUState *ccs; -uint32_t nr_threads = cs->nr_threads; target_ulong dpdes = 0; 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) { +/* DPDES behaves as 1-thread in LPAR-per-thread mode */ +if (!PPC_CPU_HAS_LPAR_SIBLINGS(cs)) { if (env->pending_interrupts & PPC_INTERRUPT_DOORBELL) { dpdes = 1; } @@ -279,21 +274,11 @@ void helper_store_dpdes(CPUPPCState *env, target_ulong val) PowerPCCPU *cpu = env_archcpu(env); CPUState *cs = env_cp
Re: [RFC PATCH 06/10] ppc: Add a core_index to CPUPPCState for SMT vCPUs
corrected typo, it's bitwise. On 5/28/24 14:18, Harsh Prateek Bora wrote: - (POWERPC_CPU(cs)->env.spr_cb[SPR_PIR].default_value & ~(cs->nr_threads - 1)) + (POWERPC_CPU(cs)->env.core_index) Dont we want to keep the bitwise & with ~(cs->nr_threads - 1) ? How's it taken care ?
Re: [RFC PATCH 06/10] ppc: Add a core_index to CPUPPCState for SMT vCPUs
On 5/26/24 17:56, Nicholas Piggin wrote: The way SMT thread siblings are matched is clunky, using hard-coded logic that checks the PIR SPR. Change that to use a new core_index variable in the CPUPPCState, where all siblings have the same core_index. CPU realize routines have flexibility in setting core/sibling topology. Signed-off-by: Nicholas Piggin --- target/ppc/cpu.h| 5 - hw/ppc/pnv_core.c | 2 ++ hw/ppc/spapr_cpu_core.c | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index dac13d4dac..9a89083932 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1247,6 +1247,9 @@ struct CPUArchState { /* when a memory exception occurs, the access type is stored here */ int access_type; +/* For SMT processors */ +int core_index; + #if !defined(CONFIG_USER_ONLY) /* MMU context, only relevant for full system emulation */ #if defined(TARGET_PPC64) @@ -1404,7 +1407,7 @@ struct CPUArchState { }; #define _CORE_ID(cs)\ -(POWERPC_CPU(cs)->env.spr_cb[SPR_PIR].default_value & ~(cs->nr_threads - 1)) +(POWERPC_CPU(cs)->env.core_index) Dont we want to keep the logical & with ~(cs->nr_threads - 1) ? How's it taken care ? #define THREAD_SIBLING_FOREACH(cs, cs_sibling) \ CPU_FOREACH(cs_sibling) \ diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 9b5edd9e48..0f61aabb77 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -252,6 +252,8 @@ static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp, pir_spr->default_value = pir; tir_spr->default_value = tir; +env->core_index = core_hwid; + /* Set time-base frequency to 512 MHz */ cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ); } diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index e7c9edd033..059d372c8a 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -300,16 +300,19 @@ static PowerPCCPU *spapr_create_vcpu(SpaprCpuCore *sc, int i, Error **errp) g_autofree char *id = NULL; CPUState *cs; PowerPCCPU *cpu; +CPUPPCState *env; obj = object_new(scc->cpu_type); cs = CPU(obj); cpu = POWERPC_CPU(obj); +env = &cpu->env; /* * All CPUs start halted. CPU0 is unhalted from the machine level reset code * and the rest are explicitly started up by the guest using an RTAS call. */ qdev_prop_set_bit(DEVICE(obj), "start-powered-off", true); +env->core_index = cc->core_id; We could just do cpu->env.core_index and avoid creating local var env. regards, Harsh cs->cpu_index = cc->core_id + i; if (!spapr_set_vcpu_id(cpu, cs->cpu_index, errp)) { return NULL;
Re: [RFC PATCH 05/10] ppc/pnv: Extend chip_pir class method to TIR as well
On 5/26/24 17:56, Nicholas Piggin wrote: The chip_pir chip class method allows the platform to set the PIR processor identification register. Extend this to a more general ID function which also allows the TIR to be set. This is in preparation for "big core", which is a more complicated topology of cores and threads. Signed-off-by: Nicholas Piggin --- include/hw/ppc/pnv_chip.h | 3 +- hw/ppc/pnv.c | 61 --- hw/ppc/pnv_core.c | 10 --- 3 files changed, 45 insertions(+), 29 deletions(-) diff --git a/include/hw/ppc/pnv_chip.h b/include/hw/ppc/pnv_chip.h index 8589f3291e..679723926a 100644 --- a/include/hw/ppc/pnv_chip.h +++ b/include/hw/ppc/pnv_chip.h @@ -147,7 +147,8 @@ struct PnvChipClass { DeviceRealize parent_realize; -uint32_t (*chip_pir)(PnvChip *chip, uint32_t core_id, uint32_t thread_id); +void (*processor_id)(PnvChip *chip, uint32_t core_id, uint32_t thread_id, + uint32_t *pir, uint32_t *tir); Should it be named get_chip_core_thread_regs() ? void (*intc_create)(PnvChip *chip, PowerPCCPU *cpu, Error **errp); void (*intc_reset)(PnvChip *chip, PowerPCCPU *cpu); void (*intc_destroy)(PnvChip *chip, PowerPCCPU *cpu); diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index a706de2e36..7d062ec16c 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -144,7 +144,7 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) PnvChipClass *pnv_cc = PNV_CHIP_GET_CLASS(chip); g_autofree uint32_t *servers_prop = g_new(uint32_t, smt_threads); int i; -uint32_t pir; +uint32_t pir, tir; uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 0x, 0x}; uint32_t tbfreq = PNV_TIMEBASE_FREQ; @@ -155,7 +155,7 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) char *nodename; int cpus_offset = get_cpus_node(fdt); -pir = pnv_cc->chip_pir(chip, pc->hwid, 0); +pnv_cc->processor_id(chip, pc->hwid, 0, &pir, &tir); As a generic helper API and potentially expandable, it should allow passing NULL for registers whose values are not really sought to avoid having to create un-necessary local variables by the caller. regards, Harsh nodename = g_strdup_printf("%s@%x", dc->fw_name, pir); offset = fdt_add_subnode(fdt, cpus_offset, nodename); @@ -237,7 +237,8 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) /* Build interrupt servers properties */ for (i = 0; i < smt_threads; i++) { -servers_prop[i] = cpu_to_be32(pnv_cc->chip_pir(chip, pc->hwid, i)); +pnv_cc->processor_id(chip, pc->hwid, i, &pir, &tir); +servers_prop[i] = cpu_to_be32(pir); } _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", servers_prop, sizeof(*servers_prop) * smt_threads))); @@ -249,14 +250,17 @@ static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t hwid, uint32_t nr_threads) { PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); -uint32_t pir = pcc->chip_pir(chip, hwid, 0); -uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12); +uint32_t pir, tir; +uint64_t addr; char *name; const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp"; uint32_t irange[2], i, rsize; uint64_t *reg; int offset; +pcc->processor_id(chip, hwid, 0, &pir, &tir); +addr = PNV_ICP_BASE(chip) | (pir << 12); + irange[0] = cpu_to_be32(pir); irange[1] = cpu_to_be32(nr_threads); @@ -1104,10 +1108,12 @@ static void pnv_power10_init(MachineState *machine) * 25:28 Core number * 29:31 Thread ID */ -static uint32_t pnv_chip_pir_p8(PnvChip *chip, uint32_t core_id, -uint32_t thread_id) +static void pnv_processor_id_p8(PnvChip *chip, +uint32_t core_id, uint32_t thread_id, +uint32_t *pir, uint32_t *tir) { -return (chip->chip_id << 7) | (core_id << 3) | thread_id; +*pir = (chip->chip_id << 7) | (core_id << 3) | thread_id; +*tir = thread_id; } static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu, @@ -1159,15 +1165,17 @@ static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, * * We only care about the lower bits. uint32_t is fine for the moment. */ -static uint32_t pnv_chip_pir_p9(PnvChip *chip, uint32_t core_id, -uint32_t thread_id) +static void pnv_processor_id_p9(PnvChip *chip, +uint32_t core_id, uint32_t thread_id, +uint32_t *pir, uint32_t *tir) { if (chip->nr_threads == 8) { -return (chip->chip_id << 8) | ((thread_id & 1) << 2) | (core_id << 3) | +*pir = (chip->chip_id << 8) | ((thread_id & 1) << 2) | (core_id << 3) | (thread_id >> 1);
Re: [RFC PATCH 04/10] ppc/pnv: specialise init for powernv8/9/10 machines
Hi Nick, On 5/26/24 17:56, Nicholas Piggin wrote: This will allow different settings and checks for different machine types with later changes. Signed-off-by: Nicholas Piggin --- hw/ppc/pnv.c | 35 ++- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 6e3a5ccdec..a706de2e36 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -976,11 +976,6 @@ 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", @@ -1076,6 +1071,33 @@ static void pnv_init(MachineState *machine) } } +static void pnv_power8_init(MachineState *machine) +{ +if (machine->smp.threads > 8) { +error_report("Cannot support more than 8 threads/core " + "on a powernv POWER8 machine"); We could use mc->desc for machine name above, so that .. +exit(1); +} with this patch, we can reuse p8 init for both p9 and p10 (and not just reuse p9 for p10 with hard coded string?). With that, Reviewed-by: Harsh Prateek Bora + +pnv_init(machine); +} + +static void pnv_power9_init(MachineState *machine) +{ +if (machine->smp.threads > 8) { +error_report("Cannot support more than 8 threads/core " + "on a powernv9/10 machine"); +exit(1); +} + +pnv_init(machine); +} + +static void pnv_power10_init(MachineState *machine) +{ +pnv_power9_init(machine); +} + /* *0:21 Reserved - Read as zeros * 22:24 Chip ID @@ -2423,6 +2445,7 @@ static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) }; mc->desc = "IBM PowerNV (Non-Virtualized) POWER8"; +mc->init = pnv_power8_init; mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); @@ -2449,6 +2472,7 @@ static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) }; mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; +mc->init = pnv_power9_init; mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.2"); compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); @@ -2473,6 +2497,7 @@ static void pnv_machine_p10_common_class_init(ObjectClass *oc, void *data) { TYPE_PNV_PHB_ROOT_PORT, "version", "5" }, }; +mc->init = pnv_power10_init; mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0"); compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
Re: [RFC PATCH 03/10] target/ppc: Improve SPR indirect registers
Hi Nick, On 5/26/24 17:56, Nicholas Piggin wrote: SPRC/SPRD were recently added to all BookS CPUs supported, but they are only tested on POWER9 and POWER10, so restrict them to those CPUs. Hope you mean to restrict to P9/10 for both spapr and pnv or just pnv ? SPR indirect scratch registers presently replicated per-CPU like SMT SPRs, but the PnvCore is a better place for them since they are restricted to P9/P10. Also add SPR indirect read access to core thread state for POWER9 since skiboot accesses that when booting to check for big-core mode. Signed-off-by: Nicholas Piggin --- include/hw/ppc/pnv_core.h | 1 + target/ppc/cpu.h | 3 -- target/ppc/cpu_init.c | 21 ++-- target/ppc/misc_helper.c | 67 --- 4 files changed, 46 insertions(+), 46 deletions(-) diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h index f434c71547..21297262c1 100644 --- a/include/hw/ppc/pnv_core.h +++ b/include/hw/ppc/pnv_core.h @@ -53,6 +53,7 @@ struct PnvCore { uint32_t hwid; uint64_t hrmor; +target_ulong scratch[8]; /* SCRATCH registers */ struct pnv_tod_tbst pnv_tod_tbst; PnvChip *chip; diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 1e86658da6..dac13d4dac 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1253,9 +1253,6 @@ struct CPUArchState { ppc_slb_t slb[MAX_SLB_ENTRIES]; /* PowerPC 64 SLB area */ struct CPUBreakpoint *ciabr_breakpoint; struct CPUWatchpoint *dawr0_watchpoint; - -/* POWER CPU regs/state */ -target_ulong scratch[8]; /* SCRATCH registers (shared across core) */ #endif target_ulong sr[32]; /* segment registers */ uint32_t nb_BATs; /* number of BATs */ diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 01e358a4a5..ae483e20c4 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -5759,16 +5759,6 @@ static void register_power_common_book4_sprs(CPUPPCState *env) SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_core_write_generic, 0x); -spr_register_hv(env, SPR_POWER_SPRC, "SPRC", - SPR_NOACCESS, SPR_NOACCESS, - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_sprc, - 0x); -spr_register_hv(env, SPR_POWER_SPRD, "SPRD", - SPR_NOACCESS, SPR_NOACCESS, - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_sprd, &spr_write_sprd, - 0x); #endif } @@ -5781,6 +5771,17 @@ static void register_power9_book4_sprs(CPUPPCState *env) SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, KVM_REG_PPC_WORT, 0); +/* SPRC/SPRD exist in earlier CPUs but only tested on POWER9/10 */ +spr_register_hv(env, SPR_POWER_SPRC, "SPRC", + SPR_NOACCESS, SPR_NOACCESS, + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_sprc, + 0x); +spr_register_hv(env, SPR_POWER_SPRD, "SPRD", + SPR_NOACCESS, SPR_NOACCESS, + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_sprd, &spr_write_sprd, + 0x); #endif } diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c index fa47be2298..46ba3a5584 100644 --- a/target/ppc/misc_helper.c +++ b/target/ppc/misc_helper.c @@ -26,6 +26,7 @@ #include "qemu/main-loop.h" #include "mmu-book3s-v3.h" #include "hw/ppc/ppc.h" +#include "hw/ppc/pnv_core.h" #include "helper_regs.h" @@ -321,11 +322,25 @@ void helper_store_sprc(CPUPPCState *env, target_ulong val) target_ulong helper_load_sprd(CPUPPCState *env) { +PowerPCCPU *cpu = env_archcpu(env); +PnvCore *pc = pnv_cpu_state(cpu)->core; We may want to avoid creating local variable cpu here also like previous patches. However, is this helper meant to be accessible for spapr as well ? target_ulong sprc = env->spr[SPR_POWER_SPRC]; -switch (sprc & 0x3c0) { -case 0: /* SCRATCH0-7 */ -return env->scratch[(sprc >> 3) & 0x7]; +switch (sprc & 0x3e0) { +case 0: /* SCRATCH0-3 */ +case 1: /* SCRATCH4-7 */ +return pc->scratch[(sprc >> 3) & 0x7]; If so, will pc be uninitialized in case of spapr ? +case 0x1e0: /* core thread state */ +if (env->excp_model == POWERPC_EXCP_POWER9) { +/* + * Only implement for POWER9 because skiboot uses it to check + * big-core mode. Other bits are unimplemented so we would + * prefer to get unimplemented message on POWER10 if it were + * used. + */ +return 0; +} +/* fallthru */ default: qemu_log_mask(LOG_UNIMP, "mfSPRD: Unimplemented SPRC:0x"
Re: [RFC PATCH 02/10] ppc/pnv: Move timebase state into PnvCore
(PowerPCCPU *cpu) +{ +PnvCore *pc = pnv_cpu_state(cpu)->core; + +return &pc->pnv_tod_tbst; +} + static void tb_state_machine_step(CPUPPCState *env) { +PowerPCCPU *cpu = env_archcpu(env); +struct pnv_tod_tbst *pnv_tod_tbst = cpu_get_tbst(cpu); Since cpu is not used anywhere later, we could just do cpu_get_tbst(env_archcpu(env)) ? uint64_t tfmr = env->spr[SPR_TFMR]; unsigned int tbst = tfmr_get_tb_state(tfmr); @@ -307,15 +317,15 @@ static void tb_state_machine_step(CPUPPCState *env) return; } -if (env->pnv_tod_tbst.tb_sync_pulse_timer) { -env->pnv_tod_tbst.tb_sync_pulse_timer--; +if (pnv_tod_tbst->tb_sync_pulse_timer) { +pnv_tod_tbst->tb_sync_pulse_timer--; } else { tfmr |= TFMR_TB_SYNC_OCCURED; write_tfmr(env, tfmr); } -if (env->pnv_tod_tbst.tb_state_timer) { -env->pnv_tod_tbst.tb_state_timer--; +if (pnv_tod_tbst->tb_state_timer) { +pnv_tod_tbst->tb_state_timer--; return; } @@ -332,20 +342,20 @@ static void tb_state_machine_step(CPUPPCState *env) } else if (tfmr & TFMR_MOVE_CHIP_TOD_TO_TB) { if (tbst == TBST_SYNC_WAIT) { tfmr = tfmr_new_tb_state(tfmr, TBST_GET_TOD); -env->pnv_tod_tbst.tb_state_timer = 3; +pnv_tod_tbst->tb_state_timer = 3; } else if (tbst == TBST_GET_TOD) { -if (env->pnv_tod_tbst.tod_sent_to_tb) { +if (pnv_tod_tbst->tod_sent_to_tb) { tfmr = tfmr_new_tb_state(tfmr, TBST_TB_RUNNING); tfmr &= ~TFMR_MOVE_CHIP_TOD_TO_TB; -env->pnv_tod_tbst.tb_ready_for_tod = 0; -env->pnv_tod_tbst.tod_sent_to_tb = 0; +pnv_tod_tbst->tb_ready_for_tod = 0; +pnv_tod_tbst->tod_sent_to_tb = 0; } } else { qemu_log_mask(LOG_GUEST_ERROR, "TFMR error: MOVE_CHIP_TOD_TO_TB " "state machine in invalid state 0x%x\n", tbst); tfmr = tfmr_new_tb_state(tfmr, TBST_TB_ERROR); tfmr |= TFMR_FIRMWARE_CONTROL_ERROR; -env->pnv_tod_tbst.tb_ready_for_tod = 0; +pnv_tod_tbst->tb_ready_for_tod = 0; } } @@ -361,6 +371,8 @@ target_ulong helper_load_tfmr(CPUPPCState *env) void helper_store_tfmr(CPUPPCState *env, target_ulong val) { +PowerPCCPU *cpu = env_archcpu(env); +struct pnv_tod_tbst *pnv_tod_tbst = cpu_get_tbst(cpu); ... similarly here as well. With suggested minor improvements, Reviewed-by: Harsh Prateek Bora uint64_t tfmr = env->spr[SPR_TFMR]; uint64_t clear_on_write; unsigned int tbst = tfmr_get_tb_state(tfmr); @@ -384,14 +396,7 @@ void helper_store_tfmr(CPUPPCState *env, target_ulong val) * after the second mfspr. */ tfmr &= ~TFMR_TB_SYNC_OCCURED; -env->pnv_tod_tbst.tb_sync_pulse_timer = 1; - -if (ppc_cpu_tir(env_archcpu(env)) != 0 && -(val & (TFMR_LOAD_TOD_MOD | TFMR_MOVE_CHIP_TOD_TO_TB))) { -qemu_log_mask(LOG_UNIMP, "TFMR timebase state machine can only be " - "driven by thread 0\n"); -goto out; -} +pnv_tod_tbst->tb_sync_pulse_timer = 1; if (((tfmr | val) & (TFMR_LOAD_TOD_MOD | TFMR_MOVE_CHIP_TOD_TO_TB)) == (TFMR_LOAD_TOD_MOD | TFMR_MOVE_CHIP_TOD_TO_TB)) { @@ -399,7 +404,7 @@ void helper_store_tfmr(CPUPPCState *env, target_ulong val) "MOVE_CHIP_TOD_TO_TB both set\n"); tfmr = tfmr_new_tb_state(tfmr, TBST_TB_ERROR); tfmr |= TFMR_FIRMWARE_CONTROL_ERROR; -env->pnv_tod_tbst.tb_ready_for_tod = 0; +pnv_tod_tbst->tb_ready_for_tod = 0; goto out; } @@ -413,8 +418,8 @@ void helper_store_tfmr(CPUPPCState *env, target_ulong val) tfmr &= ~TFMR_LOAD_TOD_MOD; tfmr &= ~TFMR_MOVE_CHIP_TOD_TO_TB; tfmr &= ~TFMR_FIRMWARE_CONTROL_ERROR; /* XXX: should this be cleared? */ -env->pnv_tod_tbst.tb_ready_for_tod = 0; -env->pnv_tod_tbst.tod_sent_to_tb = 0; +pnv_tod_tbst->tb_ready_for_tod = 0; +pnv_tod_tbst->tod_sent_to_tb = 0; goto out; } @@ -427,19 +432,19 @@ void helper_store_tfmr(CPUPPCState *env, target_ulong val) if (tfmr & TFMR_LOAD_TOD_MOD) { /* Wait for an arbitrary 3 mfspr until the next state transition. */ -env->pnv_tod_tbst.tb_state_timer = 3; +pnv_tod_tbst->tb_state_timer = 3; } else if (tfmr & TFMR_MOVE_CHIP_TOD_TO_TB) { if (tbst == TBST_NOT_SET) { tfmr = tfmr_new_tb_state(tfmr, TBST_SYNC_WAIT); -env->pnv_tod_tbst.tb_ready_for_tod = 1; -env->p
Re: [RFC PATCH 01/10] ppc/pnv: Add pointer from PnvCPUState to PnvCore
On 5/26/24 17:56, Nicholas Piggin wrote: This helps move core state from CPU to core structures. Signed-off-by: Nicholas Piggin --- include/hw/ppc/pnv_core.h | 1 + hw/ppc/pnv_core.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h index c6d62fd145..30c1e5b1a3 100644 --- a/include/hw/ppc/pnv_core.h +++ b/include/hw/ppc/pnv_core.h @@ -54,6 +54,7 @@ struct PnvCoreClass { #define PNV_CORE_TYPE_NAME(cpu_model) cpu_model PNV_CORE_TYPE_SUFFIX typedef struct PnvCPUState { +PnvCore *core; Naming it *pc might be more intuitive with the most of its usage, although I see few usage as "pnv_core" as well. Reviewed-by: Harsh Prateek Bora Object *intc; } PnvCPUState; diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index f40ab721d6..7b0ea7812b 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -225,6 +225,7 @@ static const MemoryRegionOps pnv_core_power10_xscom_ops = { static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp, int thread_index) { +PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); CPUPPCState *env = &cpu->env; int core_hwid; ppc_spr_t *pir = &env->spr_cb[SPR_PIR]; @@ -232,6 +233,8 @@ static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp, Error *local_err = NULL; PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip); +pnv_cpu->core = pc; + if (!qdev_realize(DEVICE(cpu), NULL, errp)) { return; }
[PATCH v3 2/3] cpu-common.c: export cpu_get_free_index to be reused later
This helper provides an easy way to identify the next available free cpu index which can be used for vcpu creation. Until now, this is being called at a very later stage and there is a need to be able to call it earlier (for now, with ppc64) hence the need to export. Suggested-by: Nicholas Piggin Signed-off-by: Harsh Prateek Bora --- include/exec/cpu-common.h | 2 ++ cpu-common.c | 7 --- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 6d5318895a..0386f1ab29 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -29,6 +29,8 @@ void cpu_list_lock(void); void cpu_list_unlock(void); unsigned int cpu_list_generation_id_get(void); +int cpu_get_free_index(void); + void tcg_iommu_init_notifier_list(CPUState *cpu); void tcg_iommu_free_notifier_list(CPUState *cpu); diff --git a/cpu-common.c b/cpu-common.c index ce78273af5..82bd1b432d 100644 --- a/cpu-common.c +++ b/cpu-common.c @@ -57,14 +57,12 @@ void cpu_list_unlock(void) qemu_mutex_unlock(&qemu_cpu_list_lock); } -static bool cpu_index_auto_assigned; -static int cpu_get_free_index(void) +int cpu_get_free_index(void) { CPUState *some_cpu; int max_cpu_index = 0; -cpu_index_auto_assigned = true; CPU_FOREACH(some_cpu) { if (some_cpu->cpu_index >= max_cpu_index) { max_cpu_index = some_cpu->cpu_index + 1; @@ -83,8 +81,11 @@ unsigned int cpu_list_generation_id_get(void) void cpu_list_add(CPUState *cpu) { +static bool cpu_index_auto_assigned; + QEMU_LOCK_GUARD(&qemu_cpu_list_lock); if (cpu->cpu_index == UNASSIGNED_CPU_INDEX) { +cpu_index_auto_assigned = true; cpu->cpu_index = cpu_get_free_index(); assert(cpu->cpu_index != UNASSIGNED_CPU_INDEX); } else { -- 2.39.3
[PATCH v3 1/3] accel/kvm: Introduce kvm_create_and_park_vcpu() helper
There are distinct helpers for creating and parking a KVM vCPU. However, there can be cases where a platform needs to create and immediately park the vCPU during early stages of vcpu init which can later be reused when vcpu thread gets initialized. This would help detect failures with kvm_create_vcpu at an early stage. Based on api refactoring to create/park vcpus introduced in 1/8 of patch series: https://lore.kernel.org/qemu-devel/2024052221.232114-1-salil.me...@huawei.com/ Suggested-by: Nicholas Piggin Signed-off-by: Harsh Prateek Bora --- accel/kvm/kvm-cpus.h | 8 accel/kvm/kvm-all.c | 12 2 files changed, 20 insertions(+) diff --git a/accel/kvm/kvm-cpus.h b/accel/kvm/kvm-cpus.h index 2e6bb38b5d..00e534b3b9 100644 --- a/accel/kvm/kvm-cpus.h +++ b/accel/kvm/kvm-cpus.h @@ -46,4 +46,12 @@ void kvm_park_vcpu(CPUState *cpu); * @returns: KVM fd */ int kvm_unpark_vcpu(KVMState *s, unsigned long vcpu_id); + +/** + * * kvm_create_and_park_vcpu - Create and park a KVM vCPU + * * @cpu: QOM CPUState object for which KVM vCPU has to be created and parked. + ** + * * @returns: 0 when success, errno (<0) when failed. + * */ +int kvm_create_and_park_vcpu(CPUState *cpu); #endif /* KVM_CPUS_H */ diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index fc30e5d5b8..d70ca62ff5 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -398,6 +398,18 @@ int kvm_create_vcpu(CPUState *cpu) return 0; } +int kvm_create_and_park_vcpu(CPUState *cpu) +{ +int ret = 0; + +ret = kvm_create_vcpu(cpu); +if (!ret) { +kvm_park_vcpu(cpu); +} + +return ret; +} + static int do_kvm_destroy_vcpu(CPUState *cpu) { KVMState *s = kvm_state; -- 2.39.3
[PATCH v3 0/3] target/ppc: vcpu hotplug failure handling fixes
On ppc64, the PowerVM hypervisor runs with limited memory and a VCPU creation during hotplug may fail during kvm_ioctl for KVM_CREATE_VCPU, leading to termination of guest since errp is set to &error_fatal while calling kvm_init_vcpu. This unexpected behaviour can be avoided by pre-creating and parking vcpu on success or return error otherwise. This enables graceful error delivery for any vcpu hotplug failures while the guest can keep running. This series adds another helper to create and park vcpu (based on below patch by Salil), exports cpu_get_free_index to be reused later and adds ppc arch specfic handling for vcpu hotplug failure using kvm accel helper cpu_target_realize. Based on api refactoring to create/park vcpus introduced in 1/8 of patch series: https://lore.kernel.org/qemu-devel/2024052221.232114-1-salil.me...@huawei.com/ Changelog: v3: Addressed review comments from Nick v2: Addressed review comments from Nick v1: Initial patch Harsh Prateek Bora (3): accel/kvm: Introduce kvm_create_and_park_vcpu() helper cpu-common.c: export cpu_get_free_index to be reused later target/ppc: handle vcpu hotplug failure gracefully accel/kvm/kvm-cpus.h | 8 include/exec/cpu-common.h | 2 ++ accel/kvm/kvm-all.c | 12 cpu-common.c | 7 --- target/ppc/kvm.c | 41 +++ 5 files changed, 67 insertions(+), 3 deletions(-) -- 2.39.3
[PATCH v3 3/3] target/ppc: handle vcpu hotplug failure gracefully
On ppc64, the PowerVM hypervisor runs with limited memory and a VCPU creation during hotplug may fail during kvm_ioctl for KVM_CREATE_VCPU, leading to termination of guest since errp is set to &error_fatal while calling kvm_init_vcpu. This unexpected behaviour can be avoided by pre-creating and parking vcpu on success or return error otherwise. This enables graceful error delivery for any vcpu hotplug failures while the guest can keep running. Also introducing KVM AccelCPUClass to init cpu_target_realize for kvm. Tested OK by repeatedly doing a hotplug/unplug of vcpus as below: #virsh setvcpus hotplug 40 #virsh setvcpus hotplug 70 error: internal error: unable to execute QEMU command 'device_add': kvmppc_cpu_realize: vcpu hotplug failed with -12 Reported-by: Anushree Mathur Suggested-by: Shivaprasad G Bhat Suggested-by: Vaibhav Jain Signed-off by: Harsh Prateek Bora Tested-by: Anushree Mathur --- target/ppc/kvm.c | 41 + 1 file changed, 41 insertions(+) diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index 63930d4a77..8e5a7c3d2d 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -48,6 +48,8 @@ #include "qemu/mmap-alloc.h" #include "elf.h" #include "sysemu/kvm_int.h" +#include "accel/kvm/kvm-cpus.h" +#include "hw/core/accel-cpu.h" #define PROC_DEVTREE_CPU "/proc/device-tree/cpus/" @@ -2339,6 +2341,25 @@ static void alter_insns(uint64_t *word, uint64_t flags, bool on) } } +static bool kvmppc_cpu_realize(CPUState *cs, Error **errp) +{ +int ret; +const char *vcpu_str = (cs->parent_obj.hotplugged == true) ? + "hotplug" : "create"; +cs->cpu_index = cpu_get_free_index(); + +POWERPC_CPU(cs)->vcpu_id = cs->cpu_index; + +/* create and park to fail gracefully in case vcpu hotplug fails */ +ret = kvm_create_and_park_vcpu(cs); +if (ret) { +error_setg(errp, "%s: vcpu %s failed with %d", + __func__, vcpu_str, ret); +return false; +} +return true; +} + static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data) { PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); @@ -2959,3 +2980,23 @@ void kvmppc_set_reg_tb_offset(PowerPCCPU *cpu, int64_t tb_offset) void kvm_arch_accel_class_init(ObjectClass *oc) { } + +static void kvm_cpu_accel_class_init(ObjectClass *oc, void *data) +{ +AccelCPUClass *acc = ACCEL_CPU_CLASS(oc); + +acc->cpu_target_realize = kvmppc_cpu_realize; +} + +static const TypeInfo kvm_cpu_accel_type_info = { +.name = ACCEL_CPU_NAME("kvm"), + +.parent = TYPE_ACCEL_CPU, +.class_init = kvm_cpu_accel_class_init, +.abstract = true, +}; +static void kvm_cpu_accel_register_types(void) +{ +type_register_static(&kvm_cpu_accel_type_info); +} +type_init(kvm_cpu_accel_register_types); -- 2.39.3
Re: [PATCH V11 1/8] accel/kvm: Extract common KVM vCPU {creation,parking} code
Hi Salil, On 5/23/24 02:41, Salil Mehta wrote: +void kvm_park_vcpu(CPUState *cpu); + +/** + * kvm_unpark_vcpu - unpark QEMU KVM vCPU context + * @s: KVM State + * @cpu: Architecture vCPU ID of the parked vCPU s/@cpu/@vcpuid ? Thanks Harsh + * + * @returns: KVM fd + */ +int kvm_unpark_vcpu(KVMState *s, unsigned long vcpu_id); #endif /* KVM_CPUS_H */
[PATCH v2 3/7] target/ppc: optimize hreg_compute_pmu_hflags_value
The second if-condition can be true only if the first one above is true. Enclose the latter into the former to avoid un-necessary check if first condition fails. Signed-off-by: Harsh Prateek Bora Reviewed-by: BALATON Zoltan --- target/ppc/helper_regs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c index d09dcacd5e..261a8ba79f 100644 --- a/target/ppc/helper_regs.c +++ b/target/ppc/helper_regs.c @@ -66,9 +66,9 @@ static uint32_t hreg_compute_pmu_hflags_value(CPUPPCState *env) #ifndef CONFIG_USER_ONLY if (env->pmc_ins_cnt) { hflags |= 1 << HFLAGS_INSN_CNT; -} -if (env->pmc_ins_cnt & 0x1e) { -hflags |= 1 << HFLAGS_PMC_OTHER; +if (env->pmc_ins_cnt & 0x1e) { +hflags |= 1 << HFLAGS_PMC_OTHER; +} } #endif #endif -- 2.39.3
Re: [PATCH 6/6] target/ppc: redue code duplication across Power9/10 init code
Hi BALATON, On 5/20/24 17:22, BALATON Zoltan wrote: On Mon, 20 May 2024, Harsh Prateek Bora wrote: Power9/10 initialization code consists of a lot of logical OR of various flag bits as supported by respective Power platform during its initialization, most of which is duplicated and only selected bits are added or removed as needed with each new platform support being added. Remove the duplicate code and share using common macros. Signed-off-by: Harsh Prateek Bora --- target/ppc/cpu_init.h | 79 +++ target/ppc/cpu_init.c | 123 ++ 2 files changed, 94 insertions(+), 108 deletions(-) create mode 100644 target/ppc/cpu_init.h diff --git a/target/ppc/cpu_init.h b/target/ppc/cpu_init.h new file mode 100644 index 00..29358bfdf6 --- /dev/null +++ b/target/ppc/cpu_init.h @@ -0,0 +1,79 @@ +#ifndef TARGET_PPC_CPU_INIT_H +#define TARGET_PPC_CPU_INIT_H + +#define POWERPC_FAMILY_POWER9_INSNS_FLAGS \ + PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB | \ + PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES | \ + PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | PPC_FLOAT_FRSQRTES | \ + PPC_FLOAT_STFIWX | PPC_FLOAT_EXT |PPC_CACHE | PPC_CACHE_ICBI | \ + PPC_CACHE_DCBZ | PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | \ + PPC_MEM_TLBSYNC | PPC_64B | PPC_64H | PPC_64BX | PPC_ALTIVEC | \ + PPC_SEGMENT_64B | PPC_SLBI | PPC_POPCNTB | PPC_POPCNTWD | \ + PPC_CILDST +#define POWERPC_FAMILY_POWER10_INSNS_FLAGS \ + POWERPC_FAMILY_POWER9_INSNS_FLAGS It's a good idea to make the cpu inits more readable but I'm not sure about having two names for the same thing. If these are the same could POWER10 also just use POWERPC_FAMILY_POWER9_INSNS_FLAGS (or if you really want to may call it POWERPC_FAMILY_POWER9_10_INSNS_FLAGS or similar but I think using earlier features where unchanged in newer CPU models would be OK and show these are the same). Thanks for your valuable review comments on this series. I have addressed them and posted in v2. regards, Harsh Regards, BALATON Zoltan + +#define POWERPC_FAMILY_POWER9_INSNS_FLAGS2_COMMON \ + PPC2_VSX | PPC2_VSX207 | PPC2_DFP | PPC2_DBRX | \ + PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 | PPC2_ATOMIC_ISA206 | \ + PPC2_FP_CVT_ISA206 | PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 | \ + PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 | PPC2_ISA205 | \ + PPC2_ISA207S | PPC2_FP_CVT_S64 | PPC2_ISA300 | PPC2_PRCNTL | \ + PPC2_MEM_LWSYNC | PPC2_BCDA_ISA206 + +#define POWERPC_FAMILY_POWER9_INSNS_FLAGS2 \ + POWERPC_FAMILY_POWER9_INSNS_FLAGS2_COMMON | PPC2_TM +#define POWERPC_FAMILY_POWER10_INSNS_FLAGS2 \ + POWERPC_FAMILY_POWER9_INSNS_FLAGS2_COMMON | PPC2_ISA310 + +#define POWERPC_POWER9_COMMON_PCC_MSR_MASK \ + (1ull << MSR_SF) | \ + (1ull << MSR_HV) | \ + (1ull << MSR_VR) | \ + (1ull << MSR_VSX) | \ + (1ull << MSR_EE) | \ + (1ull << MSR_PR) | \ + (1ull << MSR_FP) | \ + (1ull << MSR_ME) | \ + (1ull << MSR_FE0) | \ + (1ull << MSR_SE) | \ + (1ull << MSR_DE) | \ + (1ull << MSR_FE1) | \ + (1ull << MSR_IR) | \ + (1ull << MSR_DR) | \ + (1ull << MSR_PMM) | \ + (1ull << MSR_RI) | \ + (1ull << MSR_LE) + +#define POWERPC_POWER9_PCC_MSR_MASK \ + POWERPC_POWER9_COMMON_PCC_MSR_MASK | (1ull << MSR_TM) +#define POWERPC_POWER10_PCC_MSR_MASK \ + POWERPC_POWER9_COMMON_PCC_MSR_MASK +#define POWERPC_POWER9_PCC_PCR_MASK \ + PCR_COMPAT_2_05 | PCR_COMPAT_2_06 | PCR_COMPAT_2_07 +#define POWERPC_POWER10_PCC_PCR_MASK \ + POWERPC_POWER9_PCC_PCR_MASK | PCR_COMPAT_3_00 +#define POWERPC_POWER9_PCC_PCR_SUPPORTED \ + PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_COMPAT_2_05 +#define POWERPC_POWER10_PCC_PCR_SUPPORTED \ + POWERPC_POWER9_PCC_PCR_SUPPORTED | PCR_COMPAT_3_10 +#define POWERPC_POWER9_PCC_LPCR_MASK \ + LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD | \ + (LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL | \ + LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR | LPCR_LD | \ + (LPCR_PECE_L_MASK & (LPCR_PDEE|LPCR_HDEE|LPCR_EEE|LPCR_DEE|LPCR_OEE)) | \ + LPCR_MER | LPCR_GTSE | LPCR_TC | LPCR_HEIC | LPCR_LPES0 | LPCR_HVICE | \ + LPCR_HDICE +/* DD2 adds an extra HAIL bit */ +#define POWERPC_POWER10_PCC_LPCR_MASK \ + POWERPC_POWE
[PATCH v2 2/7] target/ppc: optimize hreg_compute_pmu_hflags_value
Cache env->spr[SPR_POWER_MMCR0] in a local variable as used in multiple conditions to avoid multiple indirect accesses. Signed-off-by: Harsh Prateek Bora --- target/ppc/helper_regs.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c index 945fa1a596..d09dcacd5e 100644 --- a/target/ppc/helper_regs.c +++ b/target/ppc/helper_regs.c @@ -50,15 +50,16 @@ void hreg_swap_gpr_tgpr(CPUPPCState *env) static uint32_t hreg_compute_pmu_hflags_value(CPUPPCState *env) { uint32_t hflags = 0; - #if defined(TARGET_PPC64) -if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCC0) { +target_ulong mmcr0 = env->spr[SPR_POWER_MMCR0]; + +if (mmcr0 & MMCR0_PMCC0) { hflags |= 1 << HFLAGS_PMCC0; } -if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCC1) { +if (mmcr0 & MMCR0_PMCC1) { hflags |= 1 << HFLAGS_PMCC1; } -if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCjCE) { +if (mmcr0 & MMCR0_PMCjCE) { hflags |= 1 << HFLAGS_PMCJCE; } -- 2.39.3
[PATCH v2 6/7] target/ppc: reduce duplicate code between init_proc_POWER{9, 10}
Historically, the registration of sprs have been inherited alongwith every new Power arch support being added leading to a lot of code duplication. It's time to do necessary cleanups now to avoid further duplication with newer arch support being added. Signed-off-by: Harsh Prateek Bora --- target/ppc/cpu_init.c | 43 +-- 1 file changed, 9 insertions(+), 34 deletions(-) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 6d82f24c87..5fb9a0583e 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -6307,7 +6307,7 @@ static struct ppc_radix_page_info POWER9_radix_page_info = { }; #endif /* CONFIG_USER_ONLY */ -static void init_proc_POWER9(CPUPPCState *env) +static void register_power9_common_sprs(CPUPPCState *env) { /* Common Registers */ init_proc_book3s_common(env); @@ -6326,7 +6326,6 @@ static void init_proc_POWER9(CPUPPCState *env) register_power5p_ear_sprs(env); register_power5p_tb_sprs(env); register_power6_common_sprs(env); -register_HEIR32_spr(env); register_power6_dbg_sprs(env); register_power8_tce_address_control_sprs(env); register_power8_ids_sprs(env); @@ -6342,6 +6341,12 @@ static void init_proc_POWER9(CPUPPCState *env) register_power9_book4_sprs(env); register_power8_rpr_sprs(env); register_power9_mmu_sprs(env); +} + +static void init_proc_POWER9(CPUPPCState *env) +{ +register_power9_common_sprs(env); +register_HEIR32_spr(env); /* POWER9 Specific registers */ spr_register_kvm(env, SPR_TIDR, "TIDR", NULL, NULL, @@ -6499,39 +6504,9 @@ static struct ppc_radix_page_info POWER10_radix_page_info = { static void init_proc_POWER10(CPUPPCState *env) { -/* Common Registers */ -init_proc_book3s_common(env); -register_book3s_207_dbg_sprs(env); - -/* Common TCG PMU */ -init_tcg_pmu_power8(env); - -/* POWER8 Specific Registers */ -register_book3s_ids_sprs(env); -register_amr_sprs(env); -register_iamr_sprs(env); -register_book3s_purr_sprs(env); -register_power5p_common_sprs(env); -register_power5p_lpar_sprs(env); -register_power5p_ear_sprs(env); -register_power5p_tb_sprs(env); -register_power6_common_sprs(env); +register_power9_common_sprs(env); register_HEIR64_spr(env); -register_power6_dbg_sprs(env); -register_power8_tce_address_control_sprs(env); -register_power8_ids_sprs(env); -register_power8_ebb_sprs(env); -register_power8_fscr_sprs(env); -register_power8_pmu_sup_sprs(env); -register_power8_pmu_user_sprs(env); -register_power8_tm_sprs(env); -register_power8_pspb_sprs(env); -register_power8_dpdes_sprs(env); -register_vtb_sprs(env); -register_power8_ic_sprs(env); -register_power9_book4_sprs(env); -register_power8_rpr_sprs(env); -register_power9_mmu_sprs(env); + register_power10_hash_sprs(env); register_power10_dexcr_sprs(env); register_power10_pmu_sup_sprs(env); -- 2.39.3
[PATCH v2 7/7] target/ppc: redue code duplication across Power9/10 init code
Power9/10 initialization code consists of a lot of logical OR of various flag bits as supported by respective Power platform during its initialization, most of which is duplicated and only selected bits are added or removed as needed with each new platform support being added. Remove the duplicate code and share using common macros. Signed-off-by: Harsh Prateek Bora --- target/ppc/cpu_init.h | 77 ++ target/ppc/cpu_init.c | 123 ++ 2 files changed, 92 insertions(+), 108 deletions(-) create mode 100644 target/ppc/cpu_init.h diff --git a/target/ppc/cpu_init.h b/target/ppc/cpu_init.h new file mode 100644 index 00..53909987b0 --- /dev/null +++ b/target/ppc/cpu_init.h @@ -0,0 +1,77 @@ +#ifndef TARGET_PPC_CPU_INIT_H +#define TARGET_PPC_CPU_INIT_H + +#define POWERPC_FAMILY_POWER9_INSNS_FLAGS \ +PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB | \ +PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES | \ +PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | PPC_FLOAT_FRSQRTES | \ +PPC_FLOAT_STFIWX | PPC_FLOAT_EXT |PPC_CACHE | PPC_CACHE_ICBI | \ +PPC_CACHE_DCBZ | PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | \ +PPC_MEM_TLBSYNC | PPC_64B | PPC_64H | PPC_64BX | PPC_ALTIVEC | \ +PPC_SEGMENT_64B | PPC_SLBI | PPC_POPCNTB | PPC_POPCNTWD | \ +PPC_CILDST + +#define POWERPC_FAMILY_POWER9_INSNS_FLAGS2_COMMON \ +PPC2_VSX | PPC2_VSX207 | PPC2_DFP | PPC2_DBRX | \ +PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 | PPC2_ATOMIC_ISA206 | \ +PPC2_FP_CVT_ISA206 | PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 | \ +PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 | PPC2_ISA205 | \ +PPC2_ISA207S | PPC2_FP_CVT_S64 | PPC2_ISA300 | PPC2_PRCNTL |\ +PPC2_MEM_LWSYNC | PPC2_BCDA_ISA206 + +#define POWERPC_FAMILY_POWER9_INSNS_FLAGS2 \ +POWERPC_FAMILY_POWER9_INSNS_FLAGS2_COMMON | PPC2_TM +#define POWERPC_FAMILY_POWER10_INSNS_FLAGS2 \ +POWERPC_FAMILY_POWER9_INSNS_FLAGS2_COMMON | PPC2_ISA310 + +#define POWERPC_POWER9_COMMON_PCC_MSR_MASK \ +(1ull << MSR_SF) | \ +(1ull << MSR_HV) | \ +(1ull << MSR_VR) | \ +(1ull << MSR_VSX) |\ +(1ull << MSR_EE) | \ +(1ull << MSR_PR) | \ +(1ull << MSR_FP) | \ +(1ull << MSR_ME) | \ +(1ull << MSR_FE0) |\ +(1ull << MSR_SE) | \ +(1ull << MSR_DE) | \ +(1ull << MSR_FE1) |\ +(1ull << MSR_IR) | \ +(1ull << MSR_DR) | \ +(1ull << MSR_PMM) |\ +(1ull << MSR_RI) | \ +(1ull << MSR_LE) + +#define POWERPC_POWER9_PCC_MSR_MASK \ +POWERPC_POWER9_COMMON_PCC_MSR_MASK | (1ull << MSR_TM) +#define POWERPC_POWER10_PCC_MSR_MASK \ +POWERPC_POWER9_COMMON_PCC_MSR_MASK +#define POWERPC_POWER9_PCC_PCR_MASK \ +PCR_COMPAT_2_05 | PCR_COMPAT_2_06 | PCR_COMPAT_2_07 +#define POWERPC_POWER10_PCC_PCR_MASK \ +POWERPC_POWER9_PCC_PCR_MASK | PCR_COMPAT_3_00 +#define POWERPC_POWER9_PCC_PCR_SUPPORTED \ +PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_COMPAT_2_05 +#define POWERPC_POWER10_PCC_PCR_SUPPORTED \ +POWERPC_POWER9_PCC_PCR_SUPPORTED | PCR_COMPAT_3_10 +#define POWERPC_POWER9_PCC_LPCR_MASK\ +LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD | \ +(LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL | \ +LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR | LPCR_LD | \ +(LPCR_PECE_L_MASK & (LPCR_PDEE|LPCR_HDEE|LPCR_EEE|LPCR_DEE|LPCR_OEE)) | \ +LPCR_MER | LPCR_GTSE | LPCR_TC | LPCR_HEIC | LPCR_LPES0 | LPCR_HVICE | \ +LPCR_HDICE +/* DD2 adds an extra HAIL bit */ +#define POWERPC_POWER10_PCC_LPCR_MASK \ +POWERPC_POWER9_PCC_LPCR_MASK | LPCR_HAIL +#define POWERPC_POWER9_PCC_FLAGS_COMMON \ +POWERPC_FLAG_VRE | POWERPC_FLAG_SE | POWERPC_FLAG_BE | \ +POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR | \ +POWERPC_FLAG_VSX | POWERPC_FLAG_SCV + +#define POWERPC_POWER9_PCC_FLAGS \ +POWERPC_POWER9_PCC_FLAGS_COMMON | POWERPC_FLAG_TM +#define POWERPC_POWER10_PCC_FLAGS POWERPC_POWER9_PCC_FLAGS_COMMON + +#endif /* TARGET_PPC_CPU_INIT_H */ diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 5fb9a0583e..e4f6ad2399 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -51,6 +51,7 @@ #include "kvm_ppc.h" #endif +#include "cpu_init.h" /* #define PPC_
[PATCH v2 0/7] target/ppc: misc ppc improvements/optimizations
This a set of misc ppc arch specific code improvements/optimizations. Although there exists similar instances for potential improvements in the legacy ppc code, however, that can be taken up later as well. Changelog: v2: addressed review comments from BALATON Zoltan v1: Initial patch Harsh Prateek Bora (7): target/ppc: use locally stored msr and avoid indirect access target/ppc: optimize hreg_compute_pmu_hflags_value target/ppc: optimize hreg_compute_pmu_hflags_value target/ppc: optimize p9 exception handling routines target/ppc: optimize p9 exception handling routines for lpcr target/ppc: reduce duplicate code between init_proc_POWER{9,10} target/ppc: redue code duplication across Power9/10 init code target/ppc/cpu_init.h| 77 ++ target/ppc/cpu_init.c| 166 ++- target/ppc/excp_helper.c | 72 + target/ppc/helper_regs.c | 19 ++--- 4 files changed, 150 insertions(+), 184 deletions(-) create mode 100644 target/ppc/cpu_init.h -- 2.39.3
[PATCH v2 4/7] target/ppc: optimize p9 exception handling routines
Currently, p9 exception handling has multiple if-condition checks where it does an indirect access to pending_interrupts via env. Pass the value during entry to avoid multiple indirect accesses. Signed-off-by: Harsh Prateek Bora --- target/ppc/excp_helper.c | 47 +--- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 0712098cf7..704eddac63 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -1842,10 +1842,12 @@ static int p8_next_unmasked_interrupt(CPUPPCState *env) PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | PPC_INTERRUPT_FIT | \ PPC_INTERRUPT_PIT | PPC_INTERRUPT_THERM) -static int p9_interrupt_powersave(CPUPPCState *env) +static int p9_interrupt_powersave(CPUPPCState *env, + uint32_t pending_interrupts) { + /* External Exception */ -if ((env->pending_interrupts & PPC_INTERRUPT_EXT) && +if ((pending_interrupts & PPC_INTERRUPT_EXT) && (env->spr[SPR_LPCR] & LPCR_EEE)) { bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); if (!heic || !FIELD_EX64_HV(env->msr) || @@ -1854,48 +1856,49 @@ static int p9_interrupt_powersave(CPUPPCState *env) } } /* Decrementer Exception */ -if ((env->pending_interrupts & PPC_INTERRUPT_DECR) && +if ((pending_interrupts & PPC_INTERRUPT_DECR) && (env->spr[SPR_LPCR] & LPCR_DEE)) { return PPC_INTERRUPT_DECR; } /* Machine Check or Hypervisor Maintenance Exception */ if (env->spr[SPR_LPCR] & LPCR_OEE) { -if (env->pending_interrupts & PPC_INTERRUPT_MCK) { +if (pending_interrupts & PPC_INTERRUPT_MCK) { return PPC_INTERRUPT_MCK; } -if (env->pending_interrupts & PPC_INTERRUPT_HMI) { +if (pending_interrupts & PPC_INTERRUPT_HMI) { return PPC_INTERRUPT_HMI; } } /* Privileged Doorbell Exception */ -if ((env->pending_interrupts & PPC_INTERRUPT_DOORBELL) && +if ((pending_interrupts & PPC_INTERRUPT_DOORBELL) && (env->spr[SPR_LPCR] & LPCR_PDEE)) { return PPC_INTERRUPT_DOORBELL; } /* Hypervisor Doorbell Exception */ -if ((env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) && +if ((pending_interrupts & PPC_INTERRUPT_HDOORBELL) && (env->spr[SPR_LPCR] & LPCR_HDEE)) { return PPC_INTERRUPT_HDOORBELL; } /* Hypervisor virtualization exception */ -if ((env->pending_interrupts & PPC_INTERRUPT_HVIRT) && +if ((pending_interrupts & PPC_INTERRUPT_HVIRT) && (env->spr[SPR_LPCR] & LPCR_HVEE)) { return PPC_INTERRUPT_HVIRT; } -if (env->pending_interrupts & PPC_INTERRUPT_RESET) { +if (pending_interrupts & PPC_INTERRUPT_RESET) { return PPC_INTERRUPT_RESET; } return 0; } -static int p9_next_unmasked_interrupt(CPUPPCState *env) +static int p9_next_unmasked_interrupt(CPUPPCState *env, + uint32_t pending_interrupts) { 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; -assert((env->pending_interrupts & P9_UNUSED_INTERRUPTS) == 0); +assert((pending_interrupts & P9_UNUSED_INTERRUPTS) == 0); if (cs->halted) { if (env->spr[SPR_PSSCR] & PSSCR_EC) { @@ -1903,7 +1906,7 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env) * When PSSCR[EC] is set, LPCR[PECE] controls which interrupts can * wakeup the processor */ -return p9_interrupt_powersave(env); +return p9_interrupt_powersave(env, pending_interrupts); } else { /* * When it's clear, any system-caused exception exits power-saving @@ -1914,12 +1917,12 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env) } /* Machine check exception */ -if (env->pending_interrupts & PPC_INTERRUPT_MCK) { +if (pending_interrupts & PPC_INTERRUPT_MCK) { return PPC_INTERRUPT_MCK; } /* Hypervisor decrementer exception */ -if (env->pending_interrupts & PPC_INTERRUPT_HDECR) { +if (pending_interrupts & PPC_INTERRUPT_HDECR) { /* LPCR will be clear when not supported so this will work */ bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE); if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) { @@ -1929,7 +1932,7 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env) } /* Hypervisor virtualization interrupt */ -if (env->pending_inte
[PATCH v2 5/7] target/ppc: optimize p9 exception handling routines for lpcr
Like pending_interrupts, env->spr[SPR_LPCR] is being used at multiple places across p9 exception handlers. Pass the value during entry and avoid multiple indirect accesses. Signed-off-by: Harsh Prateek Bora --- target/ppc/excp_helper.c | 33 ++--- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 704eddac63..d3db81e6ae 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -1843,13 +1843,14 @@ static int p8_next_unmasked_interrupt(CPUPPCState *env) PPC_INTERRUPT_PIT | PPC_INTERRUPT_THERM) static int p9_interrupt_powersave(CPUPPCState *env, - uint32_t pending_interrupts) + uint32_t pending_interrupts, + target_ulong lpcr) { /* External Exception */ if ((pending_interrupts & PPC_INTERRUPT_EXT) && -(env->spr[SPR_LPCR] & LPCR_EEE)) { -bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); +(lpcr & LPCR_EEE)) { +bool heic = !!(lpcr & LPCR_HEIC); if (!heic || !FIELD_EX64_HV(env->msr) || FIELD_EX64(env->msr, MSR, PR)) { return PPC_INTERRUPT_EXT; @@ -1857,11 +1858,11 @@ static int p9_interrupt_powersave(CPUPPCState *env, } /* Decrementer Exception */ if ((pending_interrupts & PPC_INTERRUPT_DECR) && -(env->spr[SPR_LPCR] & LPCR_DEE)) { +(lpcr & LPCR_DEE)) { return PPC_INTERRUPT_DECR; } /* Machine Check or Hypervisor Maintenance Exception */ -if (env->spr[SPR_LPCR] & LPCR_OEE) { +if (lpcr & LPCR_OEE) { if (pending_interrupts & PPC_INTERRUPT_MCK) { return PPC_INTERRUPT_MCK; } @@ -1871,17 +1872,17 @@ static int p9_interrupt_powersave(CPUPPCState *env, } /* Privileged Doorbell Exception */ if ((pending_interrupts & PPC_INTERRUPT_DOORBELL) && -(env->spr[SPR_LPCR] & LPCR_PDEE)) { +(lpcr & LPCR_PDEE)) { return PPC_INTERRUPT_DOORBELL; } /* Hypervisor Doorbell Exception */ if ((pending_interrupts & PPC_INTERRUPT_HDOORBELL) && -(env->spr[SPR_LPCR] & LPCR_HDEE)) { +(lpcr & LPCR_HDEE)) { return PPC_INTERRUPT_HDOORBELL; } /* Hypervisor virtualization exception */ if ((pending_interrupts & PPC_INTERRUPT_HVIRT) && -(env->spr[SPR_LPCR] & LPCR_HVEE)) { +(lpcr & LPCR_HVEE)) { return PPC_INTERRUPT_HVIRT; } if (pending_interrupts & PPC_INTERRUPT_RESET) { @@ -1891,7 +1892,8 @@ static int p9_interrupt_powersave(CPUPPCState *env, } static int p9_next_unmasked_interrupt(CPUPPCState *env, - uint32_t pending_interrupts) + uint32_t pending_interrupts, + target_ulong lpcr) { CPUState *cs = env_cpu(env); @@ -1906,7 +1908,7 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env, * When PSSCR[EC] is set, LPCR[PECE] controls which interrupts can * wakeup the processor */ -return p9_interrupt_powersave(env, pending_interrupts); +return p9_interrupt_powersave(env, pending_interrupts, lpcr); } else { /* * When it's clear, any system-caused exception exits power-saving @@ -1924,7 +1926,7 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env, /* Hypervisor decrementer exception */ if (pending_interrupts & PPC_INTERRUPT_HDECR) { /* LPCR will be clear when not supported so this will work */ -bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE); +bool hdice = !!(lpcr & LPCR_HDICE); if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) { /* HDEC clears on delivery */ return PPC_INTERRUPT_HDECR; @@ -1934,7 +1936,7 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env, /* Hypervisor virtualization interrupt */ if (pending_interrupts & PPC_INTERRUPT_HVIRT) { /* LPCR will be clear when not supported so this will work */ -bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE); +bool hvice = !!(lpcr & LPCR_HVICE); if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hvice) { return PPC_INTERRUPT_HVIRT; } @@ -1942,8 +1944,8 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env, /* External interrupt can ignore MSR:EE under some circumstances */ if (pending_interrupts & PPC_INTERRUPT_EXT) { -bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); -bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); +bool lpes0 = !!(lpcr & LPCR_LPES0); +
[PATCH v2 1/7] target/ppc: use locally stored msr and avoid indirect access
hreg_compute_hflags_value already stores msr locally to be used in most of the logic in the routine however some instances are still using env->msr which is unnecessary. Use locally stored value as available. Signed-off-by: Harsh Prateek Bora --- target/ppc/helper_regs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c index 25258986e3..945fa1a596 100644 --- a/target/ppc/helper_regs.c +++ b/target/ppc/helper_regs.c @@ -106,10 +106,10 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env) if (ppc_flags & POWERPC_FLAG_DE) { target_ulong dbcr0 = env->spr[SPR_BOOKE_DBCR0]; -if ((dbcr0 & DBCR0_ICMP) && FIELD_EX64(env->msr, MSR, DE)) { +if ((dbcr0 & DBCR0_ICMP) && FIELD_EX64(msr, MSR, DE)) { hflags |= 1 << HFLAGS_SE; } -if ((dbcr0 & DBCR0_BRT) && FIELD_EX64(env->msr, MSR, DE)) { +if ((dbcr0 & DBCR0_BRT) && FIELD_EX64(msr, MSR, DE)) { hflags |= 1 << HFLAGS_BE; } } else { -- 2.39.3
[PATCH 6/6] target/ppc: redue code duplication across Power9/10 init code
Power9/10 initialization code consists of a lot of logical OR of various flag bits as supported by respective Power platform during its initialization, most of which is duplicated and only selected bits are added or removed as needed with each new platform support being added. Remove the duplicate code and share using common macros. Signed-off-by: Harsh Prateek Bora --- target/ppc/cpu_init.h | 79 +++ target/ppc/cpu_init.c | 123 ++ 2 files changed, 94 insertions(+), 108 deletions(-) create mode 100644 target/ppc/cpu_init.h diff --git a/target/ppc/cpu_init.h b/target/ppc/cpu_init.h new file mode 100644 index 00..29358bfdf6 --- /dev/null +++ b/target/ppc/cpu_init.h @@ -0,0 +1,79 @@ +#ifndef TARGET_PPC_CPU_INIT_H +#define TARGET_PPC_CPU_INIT_H + +#define POWERPC_FAMILY_POWER9_INSNS_FLAGS \ +PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB | \ +PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES | \ +PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | PPC_FLOAT_FRSQRTES | \ +PPC_FLOAT_STFIWX | PPC_FLOAT_EXT |PPC_CACHE | PPC_CACHE_ICBI | \ +PPC_CACHE_DCBZ | PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | \ +PPC_MEM_TLBSYNC | PPC_64B | PPC_64H | PPC_64BX | PPC_ALTIVEC | \ +PPC_SEGMENT_64B | PPC_SLBI | PPC_POPCNTB | PPC_POPCNTWD | \ +PPC_CILDST +#define POWERPC_FAMILY_POWER10_INSNS_FLAGS \ +POWERPC_FAMILY_POWER9_INSNS_FLAGS + +#define POWERPC_FAMILY_POWER9_INSNS_FLAGS2_COMMON \ +PPC2_VSX | PPC2_VSX207 | PPC2_DFP | PPC2_DBRX | \ +PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 | PPC2_ATOMIC_ISA206 | \ +PPC2_FP_CVT_ISA206 | PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 | \ +PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 | PPC2_ISA205 | \ +PPC2_ISA207S | PPC2_FP_CVT_S64 | PPC2_ISA300 | PPC2_PRCNTL |\ +PPC2_MEM_LWSYNC | PPC2_BCDA_ISA206 + +#define POWERPC_FAMILY_POWER9_INSNS_FLAGS2 \ +POWERPC_FAMILY_POWER9_INSNS_FLAGS2_COMMON | PPC2_TM +#define POWERPC_FAMILY_POWER10_INSNS_FLAGS2 \ +POWERPC_FAMILY_POWER9_INSNS_FLAGS2_COMMON | PPC2_ISA310 + +#define POWERPC_POWER9_COMMON_PCC_MSR_MASK \ +(1ull << MSR_SF) | \ +(1ull << MSR_HV) | \ +(1ull << MSR_VR) | \ +(1ull << MSR_VSX) |\ +(1ull << MSR_EE) | \ +(1ull << MSR_PR) | \ +(1ull << MSR_FP) | \ +(1ull << MSR_ME) | \ +(1ull << MSR_FE0) |\ +(1ull << MSR_SE) | \ +(1ull << MSR_DE) | \ +(1ull << MSR_FE1) |\ +(1ull << MSR_IR) | \ +(1ull << MSR_DR) | \ +(1ull << MSR_PMM) |\ +(1ull << MSR_RI) | \ +(1ull << MSR_LE) + +#define POWERPC_POWER9_PCC_MSR_MASK \ +POWERPC_POWER9_COMMON_PCC_MSR_MASK | (1ull << MSR_TM) +#define POWERPC_POWER10_PCC_MSR_MASK \ +POWERPC_POWER9_COMMON_PCC_MSR_MASK +#define POWERPC_POWER9_PCC_PCR_MASK \ +PCR_COMPAT_2_05 | PCR_COMPAT_2_06 | PCR_COMPAT_2_07 +#define POWERPC_POWER10_PCC_PCR_MASK \ +POWERPC_POWER9_PCC_PCR_MASK | PCR_COMPAT_3_00 +#define POWERPC_POWER9_PCC_PCR_SUPPORTED \ +PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_COMPAT_2_05 +#define POWERPC_POWER10_PCC_PCR_SUPPORTED \ +POWERPC_POWER9_PCC_PCR_SUPPORTED | PCR_COMPAT_3_10 +#define POWERPC_POWER9_PCC_LPCR_MASK\ +LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD | \ +(LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL | \ +LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR | LPCR_LD | \ +(LPCR_PECE_L_MASK & (LPCR_PDEE|LPCR_HDEE|LPCR_EEE|LPCR_DEE|LPCR_OEE)) | \ +LPCR_MER | LPCR_GTSE | LPCR_TC | LPCR_HEIC | LPCR_LPES0 | LPCR_HVICE | \ +LPCR_HDICE +/* DD2 adds an extra HAIL bit */ +#define POWERPC_POWER10_PCC_LPCR_MASK \ +POWERPC_POWER9_PCC_LPCR_MASK | LPCR_HAIL +#define POWERPC_POWER9_PCC_FLAGS_COMMON \ +POWERPC_FLAG_VRE | POWERPC_FLAG_SE | POWERPC_FLAG_BE | \ +POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR | \ +POWERPC_FLAG_VSX | POWERPC_FLAG_SCV + +#define POWERPC_POWER9_PCC_FLAGS \ +POWERPC_POWER9_PCC_FLAGS_COMMON | POWERPC_FLAG_TM +#define POWERPC_POWER10_PCC_FLAGS POWERPC_POWER9_PCC_FLAGS_COMMON + +#endif /* TARGET_PPC_CPU_INIT_H */ diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 636e12ba7a..48773ec831 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -51,6 +5
[PATCH 3/6] target/ppc: optimize hreg_compute_pmu_hflags_value
The second if-condition can be true only if the first one above is true. Enclose the latter into the former to avoid un-necessary check if first condition fails. Signed-off-by: Harsh Prateek Bora --- target/ppc/helper_regs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c index 5de0df5795..89aacdf212 100644 --- a/target/ppc/helper_regs.c +++ b/target/ppc/helper_regs.c @@ -66,9 +66,9 @@ static uint32_t hreg_compute_pmu_hflags_value(CPUPPCState *env) #ifndef CONFIG_USER_ONLY if (env->pmc_ins_cnt) { hflags |= 1 << HFLAGS_INSN_CNT; -} -if (env->pmc_ins_cnt & 0x1e) { -hflags |= 1 << HFLAGS_PMC_OTHER; +if (env->pmc_ins_cnt & 0x1e) { +hflags |= 1 << HFLAGS_PMC_OTHER; +} } #endif #endif -- 2.39.3
[PATCH 4/6] target/ppc: optimize p9 exception handling routines
Currently, p9 exception handling has multiple if-condition checks where it does an indirect access to pending_interrupts via env. Cache the value during entry and reuse later to avoid multiple indirect accesses. Signed-off-by: Harsh Prateek Bora --- target/ppc/excp_helper.c | 39 +-- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 0712098cf7..4f158196bb 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -1844,8 +1844,10 @@ static int p8_next_unmasked_interrupt(CPUPPCState *env) static int p9_interrupt_powersave(CPUPPCState *env) { +uint32_t pending_interrupts = env->pending_interrupts; + /* External Exception */ -if ((env->pending_interrupts & PPC_INTERRUPT_EXT) && +if ((pending_interrupts & PPC_INTERRUPT_EXT) && (env->spr[SPR_LPCR] & LPCR_EEE)) { bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); if (!heic || !FIELD_EX64_HV(env->msr) || @@ -1854,35 +1856,35 @@ static int p9_interrupt_powersave(CPUPPCState *env) } } /* Decrementer Exception */ -if ((env->pending_interrupts & PPC_INTERRUPT_DECR) && +if ((pending_interrupts & PPC_INTERRUPT_DECR) && (env->spr[SPR_LPCR] & LPCR_DEE)) { return PPC_INTERRUPT_DECR; } /* Machine Check or Hypervisor Maintenance Exception */ if (env->spr[SPR_LPCR] & LPCR_OEE) { -if (env->pending_interrupts & PPC_INTERRUPT_MCK) { +if (pending_interrupts & PPC_INTERRUPT_MCK) { return PPC_INTERRUPT_MCK; } -if (env->pending_interrupts & PPC_INTERRUPT_HMI) { +if (pending_interrupts & PPC_INTERRUPT_HMI) { return PPC_INTERRUPT_HMI; } } /* Privileged Doorbell Exception */ -if ((env->pending_interrupts & PPC_INTERRUPT_DOORBELL) && +if ((pending_interrupts & PPC_INTERRUPT_DOORBELL) && (env->spr[SPR_LPCR] & LPCR_PDEE)) { return PPC_INTERRUPT_DOORBELL; } /* Hypervisor Doorbell Exception */ -if ((env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) && +if ((pending_interrupts & PPC_INTERRUPT_HDOORBELL) && (env->spr[SPR_LPCR] & LPCR_HDEE)) { return PPC_INTERRUPT_HDOORBELL; } /* Hypervisor virtualization exception */ -if ((env->pending_interrupts & PPC_INTERRUPT_HVIRT) && +if ((pending_interrupts & PPC_INTERRUPT_HVIRT) && (env->spr[SPR_LPCR] & LPCR_HVEE)) { return PPC_INTERRUPT_HVIRT; } -if (env->pending_interrupts & PPC_INTERRUPT_RESET) { +if (pending_interrupts & PPC_INTERRUPT_RESET) { return PPC_INTERRUPT_RESET; } return 0; @@ -1891,11 +1893,12 @@ static int p9_interrupt_powersave(CPUPPCState *env) static int p9_next_unmasked_interrupt(CPUPPCState *env) { CPUState *cs = env_cpu(env); +uint32_t pending_interrupts = env->pending_interrupts; /* Ignore MSR[EE] when coming out of some power management states */ bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset; -assert((env->pending_interrupts & P9_UNUSED_INTERRUPTS) == 0); +assert((pending_interrupts & P9_UNUSED_INTERRUPTS) == 0); if (cs->halted) { if (env->spr[SPR_PSSCR] & PSSCR_EC) { @@ -1914,12 +1917,12 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env) } /* Machine check exception */ -if (env->pending_interrupts & PPC_INTERRUPT_MCK) { +if (pending_interrupts & PPC_INTERRUPT_MCK) { return PPC_INTERRUPT_MCK; } /* Hypervisor decrementer exception */ -if (env->pending_interrupts & PPC_INTERRUPT_HDECR) { +if (pending_interrupts & PPC_INTERRUPT_HDECR) { /* LPCR will be clear when not supported so this will work */ bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE); if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) { @@ -1929,7 +1932,7 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env) } /* Hypervisor virtualization interrupt */ -if (env->pending_interrupts & PPC_INTERRUPT_HVIRT) { +if (pending_interrupts & PPC_INTERRUPT_HVIRT) { /* LPCR will be clear when not supported so this will work */ bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE); if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hvice) { @@ -1938,7 +1941,7 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env) } /* External interrupt can ignore MSR:EE under some circumstances */ -if (env->pending_interrupts & PPC_INTERRUPT_EXT) { +if (pending_interrupts & PPC_INTERRUPT_EXT) { bool lpes0 =
[PATCH 2/6] target/ppc: optimize hreg_compute_pmu_hflags_value
Cache env->spr[SPR_POWER_MMCR0] in a local variable as used in multiple conditions to avoid multiple indirect accesses. Signed-off-by: Harsh Prateek Bora --- target/ppc/helper_regs.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c index 945fa1a596..5de0df5795 100644 --- a/target/ppc/helper_regs.c +++ b/target/ppc/helper_regs.c @@ -50,15 +50,16 @@ void hreg_swap_gpr_tgpr(CPUPPCState *env) static uint32_t hreg_compute_pmu_hflags_value(CPUPPCState *env) { uint32_t hflags = 0; - #if defined(TARGET_PPC64) -if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCC0) { +target_ulong spr_power_mmcr0 = env->spr[SPR_POWER_MMCR0]; + +if (spr_power_mmcr0 & MMCR0_PMCC0) { hflags |= 1 << HFLAGS_PMCC0; } -if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCC1) { +if (spr_power_mmcr0 & MMCR0_PMCC1) { hflags |= 1 << HFLAGS_PMCC1; } -if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCjCE) { +if (spr_power_mmcr0 & MMCR0_PMCjCE) { hflags |= 1 << HFLAGS_PMCJCE; } -- 2.39.3
[PATCH 1/6] target/ppc: use locally stored msr and avoid indirect access
hreg_compute_hflags_value already stores msr locally to be used in most of the logic in the routine however some instances are still using env->msr which is unnecessary. Use locally stored value as available. Signed-off-by: Harsh Prateek Bora --- target/ppc/helper_regs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c index 25258986e3..945fa1a596 100644 --- a/target/ppc/helper_regs.c +++ b/target/ppc/helper_regs.c @@ -106,10 +106,10 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env) if (ppc_flags & POWERPC_FLAG_DE) { target_ulong dbcr0 = env->spr[SPR_BOOKE_DBCR0]; -if ((dbcr0 & DBCR0_ICMP) && FIELD_EX64(env->msr, MSR, DE)) { +if ((dbcr0 & DBCR0_ICMP) && FIELD_EX64(msr, MSR, DE)) { hflags |= 1 << HFLAGS_SE; } -if ((dbcr0 & DBCR0_BRT) && FIELD_EX64(env->msr, MSR, DE)) { +if ((dbcr0 & DBCR0_BRT) && FIELD_EX64(msr, MSR, DE)) { hflags |= 1 << HFLAGS_BE; } } else { -- 2.39.3
[PATCH 0/6] target/ppc: misc ppc improvements/optimizations
This a set of misc ppc arch specific code improvements/optimizations. Although there exists similar instances for potential improvements in the legacy ppc code, however, that can be taken up later as well. Harsh Prateek Bora (6): target/ppc: use locally stored msr and avoid indirect access target/ppc: optimize hreg_compute_pmu_hflags_value target/ppc: optimize hreg_compute_pmu_hflags_value target/ppc: optimize p9 exception handling routines target/ppc: reduce duplicate code between init_proc_POWER{9,10} target/ppc: redue code duplication across Power9/10 init code target/ppc/cpu_init.h| 79 +++ target/ppc/cpu_init.c| 166 ++- target/ppc/excp_helper.c | 39 - target/ppc/helper_regs.c | 19 ++--- 4 files changed, 134 insertions(+), 169 deletions(-) create mode 100644 target/ppc/cpu_init.h -- 2.39.3
[PATCH 5/6] target/ppc: reduce duplicate code between init_proc_POWER{9, 10}
Historically, the registration of sprs have been inherited alongwith every new Power arch support being added leading to a lot of code duplication. It's time to do necessary cleanups now to avoid further duplication with newer arch support being added. Signed-off-by: Harsh Prateek Bora --- target/ppc/cpu_init.c | 43 +-- 1 file changed, 9 insertions(+), 34 deletions(-) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 6d82f24c87..636e12ba7a 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -6307,7 +6307,7 @@ static struct ppc_radix_page_info POWER9_radix_page_info = { }; #endif /* CONFIG_USER_ONLY */ -static void init_proc_POWER9(CPUPPCState *env) +static inline void register_power9_common_sprs(CPUPPCState *env) { /* Common Registers */ init_proc_book3s_common(env); @@ -6326,7 +6326,6 @@ static void init_proc_POWER9(CPUPPCState *env) register_power5p_ear_sprs(env); register_power5p_tb_sprs(env); register_power6_common_sprs(env); -register_HEIR32_spr(env); register_power6_dbg_sprs(env); register_power8_tce_address_control_sprs(env); register_power8_ids_sprs(env); @@ -6342,6 +6341,12 @@ static void init_proc_POWER9(CPUPPCState *env) register_power9_book4_sprs(env); register_power8_rpr_sprs(env); register_power9_mmu_sprs(env); +} + +static void init_proc_POWER9(CPUPPCState *env) +{ +register_power9_common_sprs(env); +register_HEIR32_spr(env); /* POWER9 Specific registers */ spr_register_kvm(env, SPR_TIDR, "TIDR", NULL, NULL, @@ -6499,39 +6504,9 @@ static struct ppc_radix_page_info POWER10_radix_page_info = { static void init_proc_POWER10(CPUPPCState *env) { -/* Common Registers */ -init_proc_book3s_common(env); -register_book3s_207_dbg_sprs(env); - -/* Common TCG PMU */ -init_tcg_pmu_power8(env); - -/* POWER8 Specific Registers */ -register_book3s_ids_sprs(env); -register_amr_sprs(env); -register_iamr_sprs(env); -register_book3s_purr_sprs(env); -register_power5p_common_sprs(env); -register_power5p_lpar_sprs(env); -register_power5p_ear_sprs(env); -register_power5p_tb_sprs(env); -register_power6_common_sprs(env); +register_power9_common_sprs(env); register_HEIR64_spr(env); -register_power6_dbg_sprs(env); -register_power8_tce_address_control_sprs(env); -register_power8_ids_sprs(env); -register_power8_ebb_sprs(env); -register_power8_fscr_sprs(env); -register_power8_pmu_sup_sprs(env); -register_power8_pmu_user_sprs(env); -register_power8_tm_sprs(env); -register_power8_pspb_sprs(env); -register_power8_dpdes_sprs(env); -register_vtb_sprs(env); -register_power8_ic_sprs(env); -register_power9_book4_sprs(env); -register_power8_rpr_sprs(env); -register_power9_mmu_sprs(env); + register_power10_hash_sprs(env); register_power10_dexcr_sprs(env); register_power10_pmu_sup_sprs(env); -- 2.39.3
Re: [PATCH] target/ppc: handle vcpu hotplug failure gracefully
On 5/17/24 09:30, Nicholas Piggin wrote: On Thu May 16, 2024 at 2:31 PM AEST, Harsh Prateek Bora wrote: Hi Nick, On 5/14/24 08:39, Nicholas Piggin wrote: On Tue Apr 23, 2024 at 4:30 PM AEST, Harsh Prateek Bora wrote: + qemu-devel On 4/23/24 11:40, Harsh Prateek Bora wrote: On ppc64, the PowerVM hypervisor runs with limited memory and a VCPU creation during hotplug may fail during kvm_ioctl for KVM_CREATE_VCPU, leading to termination of guest since errp is set to &error_fatal while calling kvm_init_vcpu. This unexpected behaviour can be avoided by pre-creating vcpu and parking it on success or return error otherwise. This enables graceful error delivery for any vcpu hotplug failures while the guest can keep running. So this puts in on the park list so when kvm_init_vcpu() later runs it will just take it off the park list instead of issuing another KVM_CREATE_VCPU ioctl. And kvm_init_vcpu() runs in the vcpu thread function, which does not have a good way to indicate failure to the caller. I'm don't know a lot about this part of qemu but it seems like a good idea to move fail-able initialisation out of the vcpu thread in that case. So the general idea seems good to me. Yeh .. Based on api refactoring to create/park vcpus introduced in 1/8 of patch series: https://lore.kernel.org/qemu-devel/2024031202.12992-2-salil.me...@huawei.com/ So from this series AFAIKS you're just using kvm_create / kvm_park routines? You could easily pull that patch 1 out ahead of that larger series if progress is slow on it, it's a decent cleanup by itself by the looks. Yeh, patch 1 of that series is only we need but the author mentioned on the list that he is about to post next version soon. Tested OK by repeatedly doing a hotplug/unplug of vcpus as below: #virsh setvcpus hotplug 40 #virsh setvcpus hotplug 70 error: internal error: unable to execute QEMU command 'device_add': kvmppc_cpu_realize: vcpu hotplug failed with -12 Reported-by: Anushree Mathur Suggested-by: Shivaprasad G Bhat Suggested-by: Vaibhav Jain Signed-off by: Harsh Prateek Bora --- --- target/ppc/kvm.c | 42 ++ 1 file changed, 42 insertions(+) diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index 8231feb2d4..c887f6dfa0 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -48,6 +48,8 @@ #include "qemu/mmap-alloc.h" #include "elf.h" #include "sysemu/kvm_int.h" +#include "sysemu/kvm.h" +#include "hw/core/accel-cpu.h" #define PROC_DEVTREE_CPU "/proc/device-tree/cpus/" @@ -2339,6 +2341,43 @@ static void alter_insns(uint64_t *word, uint64_t flags, bool on) } } +static int max_cpu_index = 0; + +static bool kvmppc_cpu_realize(CPUState *cs, Error **errp) +{ +int ret; + +cs->cpu_index = max_cpu_index++; + +POWERPC_CPU(cs)->vcpu_id = cs->cpu_index; So you're overriding the cpu_get_free_index() allocator here. And you need to because vcpu_id needs to be assigned before the KVM create, I guess. Yes .. I guess it works. I would add a comment like s390x has. Not sure which comment you were referring to but with exporting cpu_get_free_index as suggested later, not sure if we still need any comment. Yeah that's true. + +if (cs->parent_obj.hotplugged) { Can _all_ kvm cpu creation go via this path? Why just limit it to hotplugged? For the initial bootup, we actually want to abort if the requested vCPUs cant be allocated so that user can retry until the requested vCPUs are allocated. For hotplug failure, bringing down entire guest isn't fair, hence the fix. But you could make the error handling depend on hotplugged, no? Perhaps put that error handling decision in common code so policy is the same for all targets and back ends. Hmm, I think just setting errp appropriately would suffice for both cases as existing behaviour takes care of the rest of handling. Something like below: +static bool kvmppc_cpu_realize(CPUState *cs, Error **errp) +{ +int ret; +const char *vcpu_str = (cs->parent_obj.hotplugged == true) ? + "hotplug" : "create"; +cs->cpu_index = cpu_get_free_index(); + +POWERPC_CPU(cs)->vcpu_id = cs->cpu_index; + +/* create and park to fail gracefully in case vcpu hotplug fails */ +ret = kvm_create_and_park_vcpu(cs); +if (ret) { +error_setg(errp, "%s: vcpu %s failed with %d", + __func__, vcpu_str, ret); +return false; +} +return true; +} [...] +} + static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data) { PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); @@ -2963,4 +3002,7 @@ bool kvm_arch_cpu_check_are_resettable(void) void kvm_arch_accel_class_init(ObjectClass *oc) { +AccelCla
Re: [PATCH] ppc/spapr: Add ibm,pi-features
On 5/18/24 15:26, Nicholas Piggin wrote: The ibm,pi-features property has a bit to say whether or not msgsndp should be used. Linux checks if it is being run under KVM and avoids msgsndp anyway, but it would be preferable to rely on this bit. Signed-off-by: Nicholas Piggin Reviewed-by: Harsh Prateek Bora --- hw/ppc/spapr.c | 27 +++ 1 file changed, 27 insertions(+) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 611a9e5184..6891d91e6e 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -353,6 +353,31 @@ static void spapr_dt_pa_features(SpaprMachineState *spapr, _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size))); } +static void spapr_dt_pi_features(SpaprMachineState *spapr, + PowerPCCPU *cpu, + void *fdt, int offset) +{ +uint8_t pi_features[] = { 1, 0, +0x00 }; + +if (kvm_enabled() && ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, + 0, cpu->compat_pvr)) { +/* + * POWER9 and later CPUs with KVM run in LPAR-per-thread mode where + * all threads are essentially independent CPUs, and msgsndp does not + * work (because it is physically-addressed) and therefore is + * emulated by KVM, so disable it here to ensure XIVE will be used. + * This is both KVM and CPU implementation-specific behaviour so a KVM + * cap would be cleanest, but for now this works. If KVM ever permits + * native msgsndp execution by guests, a cap could be added at that + * time. + */ +pi_features[2] |= 0x08; /* 4: No msgsndp */ +} + +_FDT((fdt_setprop(fdt, offset, "ibm,pi-features", pi_features, sizeof(pi_features; +} + static hwaddr spapr_node0_size(MachineState *machine) { if (machine->numa_state->num_nodes) { @@ -815,6 +840,8 @@ static void spapr_dt_cpu(CPUState *cs, void *fdt, int offset, spapr_dt_pa_features(spapr, cpu, fdt, offset); +spapr_dt_pi_features(spapr, cpu, fdt, offset); + _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", cs->cpu_index / vcpus_per_socket)));
Re: [PATCH v2 1/4] accel/kvm: Extract common KVM vCPU {creation, parking} code
Hi Salil, On 5/16/24 19:05, Salil Mehta wrote: From: Harsh Prateek Bora Sent: Thursday, May 16, 2024 2:07 PM Hi Salil, On 5/16/24 17:42, Salil Mehta wrote: > Hi Harsh, > >> From: Harsh Prateek Bora >> Sent: Thursday, May 16, 2024 11:15 AM >> >> Hi Salil, >> >> Thanks for your email. >> Your patch 1/8 is included here based on review comments on my previous >> patch from one of the maintainers in the community and therefore I had >> kept you in CC to be aware of the desire of having this independent patch to >> get merged earlier even if your other patches in the series may go through >> further reviews. > > I really don’t know which discussion are you pointing at? Please > understand you are fixing a bug and we are pushing a feature which has got large series. > It will break the patch-set which is about t be merged. > > There will be significant overhead of testing on us for the work we > have been carrying forward for large time. This will be disruptive. Please dont! > I was referring to the review discussion on my prev patch here: https://lore.kernel.org/qemu-devel/d191d2jfar7l.2eh4s445m4...@gmail.com/ Sure, I'm, not sure what this means. No worries. If you had followed the conversation on the review link I shared, I had made it clear that we are expecting a patch update from you and it is included here just to facilitate review of additional patches on the top. Although your patch was included with this series only to facilitate review of the additional patches depending on just one of your patch. Generally you rebase your patch-set over the other and clearly state on the cover letter that this patch-set is dependent upon such and such patch-set. Just imagine if everyone starts to unilaterally pick up patches from each other's patch-set it will create a chaos not only for the feature owners but also for the maintainers. Please go through the review discussion on the link I shared above. It was included on the suggestion of one of the maintainers. However, if you are going to send v9 soon, everyone would be happy to wait. I am not sure what is appearing disruptive here. It is a common practive in the community that maintainer(s) can pick individual patches from the series if it has been vetted by siginificant number of reviewers. Don’t you think this patch-set is asking for acceptance for a patch already part of another patch-set which is about to be accepted and is a bigger feature? Will it cause maintenance overhead at the last moment? Yes, of course! No, I dont think so. However, in this case, since you have mentioned to post next version soon, you need not worry about it as that would be the preferred version for both of the series. Yes, but please understand we are working for the benefit of overall community. Please cooperate here. Hope I cleared your confusion. We are waiting to see your v9 soon. > >> >> I am hoping to see your v9 soon and thereafter maintainer(s) may choose to >> pick the latest independent patch if needs to be merged earlier. > > > I don’t think you are understanding what problem it is causing. For > your small bug fix you are causing significant delays at our end. > I hope I clarfied above that including your patch here doesnt delay anything. Hoping to see your v9 soon! Thanks Harsh > > Thanks > Salil. >> >> Thanks for your work and let's be hopeful it gets merged soon. >> >> regards, >> Harsh >> >> On 5/16/24 14:00, Salil Mehta wrote: >> > Hi Harsh, >> > >> > Thanks for your interest in the patch-set but taking away patches like >> > this from other series without any discussion can disrupt others work >> > and its acceptance on time. This is because we will have to put lot of >> > effort in rebasing bigger series and then testing overhead comes along >> > with it. >> > >> > The patch-set (from where this patch has been taken) is part of even >> > bigger series and there have been many people and companies toiling to >> > fix the bugs collectively in that series and for years. >> > >> > I'm about float the V9 version of the Arch agnostic series which this >> > patch is part of and you can rebase your patch-set from there. I'm >> > hopeful that it will get accepted in this cycle. >> > >> > >> > Many thanks >> > Salil. >> > >> >> From: Harsh Prateek Bora
Re: [PATCH v2 1/4] accel/kvm: Extract common KVM vCPU {creation, parking} code
Hi Salil, On 5/16/24 17:42, Salil Mehta wrote: Hi Harsh, From: Harsh Prateek Bora Sent: Thursday, May 16, 2024 11:15 AM Hi Salil, Thanks for your email. Your patch 1/8 is included here based on review comments on my previous patch from one of the maintainers in the community and therefore I had kept you in CC to be aware of the desire of having this independent patch to get merged earlier even if your other patches in the series may go through further reviews. I really don’t know which discussion are you pointing at? Please understand you are fixing a bug and we are pushing a feature which has got large series. It will break the patch-set which is about t be merged. There will be significant overhead of testing on us for the work we have been carrying forward for large time. This will be disruptive. Please dont! I was referring to the review discussion on my prev patch here: https://lore.kernel.org/qemu-devel/d191d2jfar7l.2eh4s445m4...@gmail.com/ Although your patch was included with this series only to facilitate review of the additional patches depending on just one of your patch. I am not sure what is appearing disruptive here. It is a common practive in the community that maintainer(s) can pick individual patches from the series if it has been vetted by siginificant number of reviewers. However, in this case, since you have mentioned to post next version soon, you need not worry about it as that would be the preferred version for both of the series. I am hoping to see your v9 soon and thereafter maintainer(s) may choose to pick the latest independent patch if needs to be merged earlier. I don’t think you are understanding what problem it is causing. For your small bug fix you are causing significant delays at our end. I hope I clarfied above that including your patch here doesnt delay anything. Hoping to see your v9 soon! Thanks Harsh Thanks Salil. Thanks for your work and let's be hopeful it gets merged soon. regards, Harsh On 5/16/24 14:00, Salil Mehta wrote: > Hi Harsh, > > Thanks for your interest in the patch-set but taking away patches like > this from other series without any discussion can disrupt others work > and its acceptance on time. This is because we will have to put lot of > effort in rebasing bigger series and then testing overhead comes along > with it. > > The patch-set (from where this patch has been taken) is part of even > bigger series and there have been many people and companies toiling to > fix the bugs collectively in that series and for years. > > I'm about float the V9 version of the Arch agnostic series which this > patch is part of and you can rebase your patch-set from there. I'm > hopeful that it will get accepted in this cycle. > > > Many thanks > Salil. > >> From: Harsh Prateek Bora >> Sent: Thursday, May 16, 2024 6:32 AM >> >> From: Salil Mehta >> >> KVM vCPU creation is done once during the vCPU realization when Qemu >> vCPU thread is spawned. This is common to all the architectures as of now. >> >> Hot-unplug of vCPU results in destruction of the vCPU object in QOM but >> the corresponding KVM vCPU object in the Host KVM is not destroyed as >> KVM doesn't support vCPU removal. Therefore, its representative KVM >> vCPU object/context in Qemu is parked. >> >> Refactor architecture common logic so that some APIs could be reused by >> vCPU Hotplug code of some architectures likes ARM, Loongson etc. Update >> new/old APIs with trace events instead of DPRINTF. No functional change is >> intended here. >> >> Signed-off-by: Salil Mehta >> Reviewed-by: Gavin Shan >> Tested-by: Vishnu Pajjuri >> Reviewed-by: Jonathan Cameron >> Tested-by: Xianglai Li >> Tested-by: Miguel Luis >> Reviewed-by: Shaoqin Huang >> [harshpb: fixed rebase failures in include/sysemu/kvm.h] >> Signed-off-by: Harsh Prateek Bora >> --- >>include/sysemu/kvm.h | 15 ++ >>accel/kvm/kvm-all.c| 64 --- - >> -- >>accel/kvm/trace-events | 5 +++- >>3 files changed, 68 insertions(+), 16 deletions(-) >> >> diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index >> eaf801bc93..fa3ec74442 100644 >> --- a/include/sysemu/kvm.h >> +++ b/include/sysemu/kvm.h >> @@ -434,6 +434,21 @@ void kvm_set_sigmask_len(KVMState *s, unsigned >> int sigmask_len); >> >>int kvm_physical_memory_addr_from_host(KVMState *s, void
Re: [PATCH v2 1/4] accel/kvm: Extract common KVM vCPU {creation, parking} code
Hi Salil, Thanks for your email. Your patch 1/8 is included here based on review comments on my previous patch from one of the maintainers in the community and therefore I had kept you in CC to be aware of the desire of having this independent patch to get merged earlier even if your other patches in the series may go through further reviews. I am hoping to see your v9 soon and thereafter maintainer(s) may choose to pick the latest independent patch if needs to be merged earlier. Thanks for your work and let's be hopeful it gets merged soon. regards, Harsh On 5/16/24 14:00, Salil Mehta wrote: Hi Harsh, Thanks for your interest in the patch-set but taking away patches like this from other series without any discussion can disrupt others work and its acceptance on time. This is because we will have to put lot of effort in rebasing bigger series and then testing overhead comes along with it. The patch-set (from where this patch has been taken) is part of even bigger series and there have been many people and companies toiling to fix the bugs collectively in that series and for years. I'm about float the V9 version of the Arch agnostic series which this patch is part of and you can rebase your patch-set from there. I'm hopeful that it will get accepted in this cycle. Many thanks Salil. From: Harsh Prateek Bora Sent: Thursday, May 16, 2024 6:32 AM From: Salil Mehta KVM vCPU creation is done once during the vCPU realization when Qemu vCPU thread is spawned. This is common to all the architectures as of now. Hot-unplug of vCPU results in destruction of the vCPU object in QOM but the corresponding KVM vCPU object in the Host KVM is not destroyed as KVM doesn't support vCPU removal. Therefore, its representative KVM vCPU object/context in Qemu is parked. Refactor architecture common logic so that some APIs could be reused by vCPU Hotplug code of some architectures likes ARM, Loongson etc. Update new/old APIs with trace events instead of DPRINTF. No functional change is intended here. Signed-off-by: Salil Mehta Reviewed-by: Gavin Shan Tested-by: Vishnu Pajjuri Reviewed-by: Jonathan Cameron Tested-by: Xianglai Li Tested-by: Miguel Luis Reviewed-by: Shaoqin Huang [harshpb: fixed rebase failures in include/sysemu/kvm.h] Signed-off-by: Harsh Prateek Bora --- include/sysemu/kvm.h | 15 ++ accel/kvm/kvm-all.c| 64 -- accel/kvm/trace-events | 5 +++- 3 files changed, 68 insertions(+), 16 deletions(-) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index eaf801bc93..fa3ec74442 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -434,6 +434,21 @@ void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len); int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr, hwaddr *phys_addr); +/** + * kvm_create_vcpu - Gets a parked KVM vCPU or creates a KVM vCPU + * @cpu: QOM CPUState object for which KVM vCPU has to be fetched/created. + * + * @returns: 0 when success, errno (<0) when failed. + */ +int kvm_create_vcpu(CPUState *cpu); + +/** + * kvm_park_vcpu - Park QEMU KVM vCPU context + * @cpu: QOM CPUState object for which QEMU KVM vCPU context has to be parked. + * + * @returns: none + */ +void kvm_park_vcpu(CPUState *cpu); #endif /* COMPILING_PER_TARGET */ diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index d7281b93f3..30d42847de 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -128,6 +128,7 @@ static QemuMutex kml_slots_lock; #define kvm_slots_unlock() qemu_mutex_unlock(&kml_slots_lock) static void kvm_slot_init_dirty_bitmap(KVMSlot *mem); +static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id); static inline void kvm_resample_fd_remove(int gsi) { @@ -340,14 +341,53 @@ err: return ret; } +void kvm_park_vcpu(CPUState *cpu) +{ +struct KVMParkedVcpu *vcpu; + +trace_kvm_park_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu)); + +vcpu = g_malloc0(sizeof(*vcpu)); +vcpu->vcpu_id = kvm_arch_vcpu_id(cpu); +vcpu->kvm_fd = cpu->kvm_fd; +QLIST_INSERT_HEAD(&kvm_state->kvm_parked_vcpus, vcpu, node); } + +int kvm_create_vcpu(CPUState *cpu) +{ +unsigned long vcpu_id = kvm_arch_vcpu_id(cpu); +KVMState *s = kvm_state; +int kvm_fd; + +trace_kvm_create_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu)); + +/* check if the KVM vCPU already exist but is parked */ +kvm_fd = kvm_get_vcpu(s, vcpu_id); +if (kvm_fd < 0) { +/* vCPU not parked: create a new KVM vCPU */ +kvm_fd = kvm_vm_ioctl(s, KVM_CREATE_VCPU, vcpu_id); +if (kvm_fd < 0) { +error_report("KVM_CREATE_VCPU IOCTL fa
[PATCH v2 2/4] accel/kvm: Introduce kvm_create_and_park_vcpu() helper
There are distinct helpers for creating and parking a KVM vCPU. However, there can be cases where a platform needs to create and immediately park the vCPU during early stages of vcpu init which can later be reused when vcpu thread gets initialized. This would help detect failures with kvm_create_vcpu at an early stage. Based on api refactoring to create/park vcpus introduced in 1/8 of patch series: https://lore.kernel.org/qemu-devel/2024031202.12992-2-salil.me...@huawei.com/ Suggested-by: Nicholas Piggin Signed-off-by: Harsh Prateek Bora --- include/sysemu/kvm.h | 8 accel/kvm/kvm-all.c | 12 2 files changed, 20 insertions(+) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index fa3ec74442..221e6bd55b 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -450,6 +450,14 @@ int kvm_create_vcpu(CPUState *cpu); */ void kvm_park_vcpu(CPUState *cpu); +/** + * kvm_create_and_park_vcpu - Create and park a KVM vCPU + * @cpu: QOM CPUState object for which KVM vCPU has to be created and parked. + * + * @returns: 0 when success, errno (<0) when failed. + */ +int kvm_create_and_park_vcpu(CPUState *cpu); + #endif /* COMPILING_PER_TARGET */ void kvm_cpu_synchronize_state(CPUState *cpu); diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 30d42847de..3d7e5eaf0b 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -381,6 +381,18 @@ int kvm_create_vcpu(CPUState *cpu) return 0; } +int kvm_create_and_park_vcpu(CPUState *cpu) +{ +int ret = 0; + +ret = kvm_create_vcpu(cpu); +if (!ret) { +kvm_park_vcpu(cpu); +} + +return ret; +} + static int do_kvm_destroy_vcpu(CPUState *cpu) { KVMState *s = kvm_state; -- 2.39.3
[PATCH v2 3/4] cpu-common.c: export cpu_get_free_index to be reused later
This helper provides an easy way to identify the next available free cpu index which can be used for vcpu creation. Until now, this is being called at a very later stage and there is a need to be able to call it earlier (for now, with ppc64) hence the need to export. Suggested-by: Nicholas Piggin Signed-off-by: Harsh Prateek Bora --- include/exec/cpu-common.h | 2 ++ cpu-common.c | 7 --- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 6d5318895a..0386f1ab29 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -29,6 +29,8 @@ void cpu_list_lock(void); void cpu_list_unlock(void); unsigned int cpu_list_generation_id_get(void); +int cpu_get_free_index(void); + void tcg_iommu_init_notifier_list(CPUState *cpu); void tcg_iommu_free_notifier_list(CPUState *cpu); diff --git a/cpu-common.c b/cpu-common.c index ce78273af5..82bd1b432d 100644 --- a/cpu-common.c +++ b/cpu-common.c @@ -57,14 +57,12 @@ void cpu_list_unlock(void) qemu_mutex_unlock(&qemu_cpu_list_lock); } -static bool cpu_index_auto_assigned; -static int cpu_get_free_index(void) +int cpu_get_free_index(void) { CPUState *some_cpu; int max_cpu_index = 0; -cpu_index_auto_assigned = true; CPU_FOREACH(some_cpu) { if (some_cpu->cpu_index >= max_cpu_index) { max_cpu_index = some_cpu->cpu_index + 1; @@ -83,8 +81,11 @@ unsigned int cpu_list_generation_id_get(void) void cpu_list_add(CPUState *cpu) { +static bool cpu_index_auto_assigned; + QEMU_LOCK_GUARD(&qemu_cpu_list_lock); if (cpu->cpu_index == UNASSIGNED_CPU_INDEX) { +cpu_index_auto_assigned = true; cpu->cpu_index = cpu_get_free_index(); assert(cpu->cpu_index != UNASSIGNED_CPU_INDEX); } else { -- 2.39.3
[PATCH v2 1/4] accel/kvm: Extract common KVM vCPU {creation, parking} code
From: Salil Mehta KVM vCPU creation is done once during the vCPU realization when Qemu vCPU thread is spawned. This is common to all the architectures as of now. Hot-unplug of vCPU results in destruction of the vCPU object in QOM but the corresponding KVM vCPU object in the Host KVM is not destroyed as KVM doesn't support vCPU removal. Therefore, its representative KVM vCPU object/context in Qemu is parked. Refactor architecture common logic so that some APIs could be reused by vCPU Hotplug code of some architectures likes ARM, Loongson etc. Update new/old APIs with trace events instead of DPRINTF. No functional change is intended here. Signed-off-by: Salil Mehta Reviewed-by: Gavin Shan Tested-by: Vishnu Pajjuri Reviewed-by: Jonathan Cameron Tested-by: Xianglai Li Tested-by: Miguel Luis Reviewed-by: Shaoqin Huang [harshpb: fixed rebase failures in include/sysemu/kvm.h] Signed-off-by: Harsh Prateek Bora --- include/sysemu/kvm.h | 15 ++ accel/kvm/kvm-all.c| 64 -- accel/kvm/trace-events | 5 +++- 3 files changed, 68 insertions(+), 16 deletions(-) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index eaf801bc93..fa3ec74442 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -434,6 +434,21 @@ void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len); int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr, hwaddr *phys_addr); +/** + * kvm_create_vcpu - Gets a parked KVM vCPU or creates a KVM vCPU + * @cpu: QOM CPUState object for which KVM vCPU has to be fetched/created. + * + * @returns: 0 when success, errno (<0) when failed. + */ +int kvm_create_vcpu(CPUState *cpu); + +/** + * kvm_park_vcpu - Park QEMU KVM vCPU context + * @cpu: QOM CPUState object for which QEMU KVM vCPU context has to be parked. + * + * @returns: none + */ +void kvm_park_vcpu(CPUState *cpu); #endif /* COMPILING_PER_TARGET */ diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index d7281b93f3..30d42847de 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -128,6 +128,7 @@ static QemuMutex kml_slots_lock; #define kvm_slots_unlock() qemu_mutex_unlock(&kml_slots_lock) static void kvm_slot_init_dirty_bitmap(KVMSlot *mem); +static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id); static inline void kvm_resample_fd_remove(int gsi) { @@ -340,14 +341,53 @@ err: return ret; } +void kvm_park_vcpu(CPUState *cpu) +{ +struct KVMParkedVcpu *vcpu; + +trace_kvm_park_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu)); + +vcpu = g_malloc0(sizeof(*vcpu)); +vcpu->vcpu_id = kvm_arch_vcpu_id(cpu); +vcpu->kvm_fd = cpu->kvm_fd; +QLIST_INSERT_HEAD(&kvm_state->kvm_parked_vcpus, vcpu, node); +} + +int kvm_create_vcpu(CPUState *cpu) +{ +unsigned long vcpu_id = kvm_arch_vcpu_id(cpu); +KVMState *s = kvm_state; +int kvm_fd; + +trace_kvm_create_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu)); + +/* check if the KVM vCPU already exist but is parked */ +kvm_fd = kvm_get_vcpu(s, vcpu_id); +if (kvm_fd < 0) { +/* vCPU not parked: create a new KVM vCPU */ +kvm_fd = kvm_vm_ioctl(s, KVM_CREATE_VCPU, vcpu_id); +if (kvm_fd < 0) { +error_report("KVM_CREATE_VCPU IOCTL failed for vCPU %lu", vcpu_id); +return kvm_fd; +} +} + +cpu->kvm_fd = kvm_fd; +cpu->kvm_state = s; +cpu->vcpu_dirty = true; +cpu->dirty_pages = 0; +cpu->throttle_us_per_full = 0; + +return 0; +} + static int do_kvm_destroy_vcpu(CPUState *cpu) { KVMState *s = kvm_state; long mmap_size; -struct KVMParkedVcpu *vcpu = NULL; int ret = 0; -trace_kvm_destroy_vcpu(); +trace_kvm_destroy_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu)); ret = kvm_arch_destroy_vcpu(cpu); if (ret < 0) { @@ -373,10 +413,7 @@ static int do_kvm_destroy_vcpu(CPUState *cpu) } } -vcpu = g_malloc0(sizeof(*vcpu)); -vcpu->vcpu_id = kvm_arch_vcpu_id(cpu); -vcpu->kvm_fd = cpu->kvm_fd; -QLIST_INSERT_HEAD(&kvm_state->kvm_parked_vcpus, vcpu, node); +kvm_park_vcpu(cpu); err: return ret; } @@ -397,6 +434,8 @@ static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id) if (cpu->vcpu_id == vcpu_id) { int kvm_fd; +trace_kvm_get_vcpu(vcpu_id); + QLIST_REMOVE(cpu, node); kvm_fd = cpu->kvm_fd; g_free(cpu); @@ -404,7 +443,7 @@ static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id) } } -return kvm_vm_ioctl(s, KVM_CREATE_VCPU, (void *)vcpu_id); +return -ENOENT; } int kvm_init_vcpu(CPUState *cpu, Error **errp) @@ -415,19 +454,14 @@ int kvm_init_vcpu(CPUState *cpu, Error **errp) trace_kvm_init_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu)); -ret = kvm_get_vcpu(s, kvm_ar
[PATCH v2 4/4] target/ppc: handle vcpu hotplug failure gracefully
On ppc64, the PowerVM hypervisor runs with limited memory and a VCPU creation during hotplug may fail during kvm_ioctl for KVM_CREATE_VCPU, leading to termination of guest since errp is set to &error_fatal while calling kvm_init_vcpu. This unexpected behaviour can be avoided by pre-creating and parking vcpu on success or return error otherwise. This enables graceful error delivery for any vcpu hotplug failures while the guest can keep running. Based on api refactoring to create/park vcpus introduced in 1/8 of patch series: https://lore.kernel.org/qemu-devel/2024031202.12992-2-salil.me...@huawei.com/ Tested OK by repeatedly doing a hotplug/unplug of vcpus as below: #virsh setvcpus hotplug 40 #virsh setvcpus hotplug 70 error: internal error: unable to execute QEMU command 'device_add': kvmppc_cpu_realize: vcpu hotplug failed with -12 Reported-by: Anushree Mathur Suggested-by: Shivaprasad G Bhat Suggested-by: Vaibhav Jain Signed-off by: Harsh Prateek Bora Tested-by: Anushree Mathur --- target/ppc/kvm.c | 24 1 file changed, 24 insertions(+) diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index 63930d4a77..25f0cf0ba8 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -48,6 +48,8 @@ #include "qemu/mmap-alloc.h" #include "elf.h" #include "sysemu/kvm_int.h" +#include "sysemu/kvm.h" +#include "hw/core/accel-cpu.h" #define PROC_DEVTREE_CPU "/proc/device-tree/cpus/" @@ -2339,6 +2341,26 @@ static void alter_insns(uint64_t *word, uint64_t flags, bool on) } } +static bool kvmppc_cpu_realize(CPUState *cs, Error **errp) +{ +int ret; + +cs->cpu_index = cpu_get_free_index(); + +POWERPC_CPU(cs)->vcpu_id = cs->cpu_index; + +if (cs->parent_obj.hotplugged) { +/* create and park to fail gracefully in case vcpu hotplug fails */ +ret = kvm_create_and_park_vcpu(cs); +if (ret) { +error_setg(errp, "%s: vcpu hotplug failed with %d", + __func__, ret); +return false; +} +} +return true; +} + static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data) { PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); @@ -2958,4 +2980,6 @@ void kvmppc_set_reg_tb_offset(PowerPCCPU *cpu, int64_t tb_offset) void kvm_arch_accel_class_init(ObjectClass *oc) { +AccelClass *ac = ACCEL_CLASS(oc); +ac->cpu_common_realize = kvmppc_cpu_realize; } -- 2.39.3
[PATCH v2 0/4] target/ppc: vcpu hotplug failure handling fixes
On ppc64, the PowerVM hypervisor runs with limited memory and a VCPU creation during hotplug may fail during kvm_ioctl for KVM_CREATE_VCPU, leading to termination of guest since errp is set to &error_fatal while calling kvm_init_vcpu. This unexpected behaviour can be avoided by pre-creating and parking vcpu on success or return error otherwise. This enables graceful error delivery for any vcpu hotplug failures while the guest can keep running. This series adds another helper to create and park vcpu (based on below patch by Salil), exports cpu_get_free_index to be reused later and adds ppc arch specfic handling for vcpu hotplug failure. Based on api refactoring to create/park vcpus introduced in 1/8 of patch series: https://lore.kernel.org/qemu-devel/2024031202.12992-2-salil.me...@huawei.com/ PS: I have just included patch 1 of above series after fixing a rebase failure along with this series for better review purpose only. Changelog: v2: Addressed review comments from Nick v1: Initial patch Harsh Prateek Bora (3): accel/kvm: Introduce kvm_create_and_park_vcpu() helper cpu-common.c: export cpu_get_free_index to be reused later target/ppc: handle vcpu hotplug failure gracefully Salil Mehta (1): accel/kvm: Extract common KVM vCPU {creation, parking} code include/exec/cpu-common.h | 2 ++ include/sysemu/kvm.h | 23 accel/kvm/kvm-all.c | 76 +++ cpu-common.c | 7 ++-- target/ppc/kvm.c | 24 + accel/kvm/trace-events| 5 ++- 6 files changed, 118 insertions(+), 19 deletions(-) -- 2.39.3
Re: [PATCH] target/ppc: handle vcpu hotplug failure gracefully
Hi Nick, On 5/14/24 08:39, Nicholas Piggin wrote: On Tue Apr 23, 2024 at 4:30 PM AEST, Harsh Prateek Bora wrote: + qemu-devel On 4/23/24 11:40, Harsh Prateek Bora wrote: On ppc64, the PowerVM hypervisor runs with limited memory and a VCPU creation during hotplug may fail during kvm_ioctl for KVM_CREATE_VCPU, leading to termination of guest since errp is set to &error_fatal while calling kvm_init_vcpu. This unexpected behaviour can be avoided by pre-creating vcpu and parking it on success or return error otherwise. This enables graceful error delivery for any vcpu hotplug failures while the guest can keep running. So this puts in on the park list so when kvm_init_vcpu() later runs it will just take it off the park list instead of issuing another KVM_CREATE_VCPU ioctl. And kvm_init_vcpu() runs in the vcpu thread function, which does not have a good way to indicate failure to the caller. I'm don't know a lot about this part of qemu but it seems like a good idea to move fail-able initialisation out of the vcpu thread in that case. So the general idea seems good to me. Yeh .. Based on api refactoring to create/park vcpus introduced in 1/8 of patch series: https://lore.kernel.org/qemu-devel/2024031202.12992-2-salil.me...@huawei.com/ So from this series AFAIKS you're just using kvm_create / kvm_park routines? You could easily pull that patch 1 out ahead of that larger series if progress is slow on it, it's a decent cleanup by itself by the looks. Yeh, patch 1 of that series is only we need but the author mentioned on the list that he is about to post next version soon. Tested OK by repeatedly doing a hotplug/unplug of vcpus as below: #virsh setvcpus hotplug 40 #virsh setvcpus hotplug 70 error: internal error: unable to execute QEMU command 'device_add': kvmppc_cpu_realize: vcpu hotplug failed with -12 Reported-by: Anushree Mathur Suggested-by: Shivaprasad G Bhat Suggested-by: Vaibhav Jain Signed-off by: Harsh Prateek Bora --- --- target/ppc/kvm.c | 42 ++ 1 file changed, 42 insertions(+) diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index 8231feb2d4..c887f6dfa0 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -48,6 +48,8 @@ #include "qemu/mmap-alloc.h" #include "elf.h" #include "sysemu/kvm_int.h" +#include "sysemu/kvm.h" +#include "hw/core/accel-cpu.h" #define PROC_DEVTREE_CPU "/proc/device-tree/cpus/" @@ -2339,6 +2341,43 @@ static void alter_insns(uint64_t *word, uint64_t flags, bool on) } } +static int max_cpu_index = 0; + +static bool kvmppc_cpu_realize(CPUState *cs, Error **errp) +{ +int ret; + +cs->cpu_index = max_cpu_index++; + +POWERPC_CPU(cs)->vcpu_id = cs->cpu_index; So you're overriding the cpu_get_free_index() allocator here. And you need to because vcpu_id needs to be assigned before the KVM create, I guess. Yes .. I guess it works. I would add a comment like s390x has. Not sure which comment you were referring to but with exporting cpu_get_free_index as suggested later, not sure if we still need any comment. + +if (cs->parent_obj.hotplugged) { Can _all_ kvm cpu creation go via this path? Why just limit it to hotplugged? For the initial bootup, we actually want to abort if the requested vCPUs cant be allocated so that user can retry until the requested vCPUs are allocated. For hotplug failure, bringing down entire guest isn't fair, hence the fix. +/* create and park to fail gracefully in case vcpu hotplug fails */ +ret = kvm_create_vcpu(cs); +if (!ret) { +kvm_park_vcpu(cs); Seems like a small thing, but I would add a new core kvm function that creates and parks the vcpu, so the target code doesn't have to know about the parking internals, just that it needs to be called. Make sense, I will add another kvm helper: kvm_create_and_park_vcpu() Unless I'm missing something, we could get all targets to move their kvm create to here and remove it removed from kvm_init_vcpu(), that would just expect it to be on the parked list. But that could be done incrementally. Hmm .. +} else { +max_cpu_index--; +error_setg(errp, "%s: vcpu hotplug failed with %d", + __func__, ret); +return false; +} +} +return true; +} + +static void kvmppc_cpu_unrealize(CPUState *cpu) +{ +if (POWERPC_CPU(cpu)->vcpu_id == (max_cpu_index - 1)) { +/* only reclaim vcpuid if its the last one assigned + * as reclaiming random vcpuid for parked vcpus may lead + * to unexpected behaviour due to an existing kernel bug + * when drc_index doesnt get reclaimed as expected. + */ +max_cpu_index--; +} This looks like a fairly lossy allocator. Using cpu_get_free_index
Re: [PATCH] spapr: Migrate ail-mode-3 spapr cap
On 5/6/24 17:26, Nicholas Piggin wrote: This cap did not add the migration code when it was introduced. This results in migration failure when changing the default using the command line. Cc: qemu-sta...@nongnu.org Fixes: ccc5a4c5e10 ("spapr: Add SPAPR_CAP_AIL_MODE_3 for AIL mode 3 support for H_SET_MODE hcall") Signed-off-by: Nicholas Piggin Reviewed-by: Harsh Prateek Bora --- include/hw/ppc/spapr.h | 1 + hw/ppc/spapr.c | 1 + hw/ppc/spapr_caps.c| 1 + 3 files changed, 3 insertions(+) diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 4aaf23d28f..f6de3e9972 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -1004,6 +1004,7 @@ extern const VMStateDescription vmstate_spapr_cap_large_decr; extern const VMStateDescription vmstate_spapr_cap_ccf_assist; extern const VMStateDescription vmstate_spapr_cap_fwnmi; extern const VMStateDescription vmstate_spapr_cap_rpt_invalidate; +extern const VMStateDescription vmstate_spapr_cap_ail_mode_3; extern const VMStateDescription vmstate_spapr_wdt; static inline uint8_t spapr_get_cap(SpaprMachineState *spapr, int cap) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index d2d1e310a3..065f58ec93 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2169,6 +2169,7 @@ static const VMStateDescription vmstate_spapr = { &vmstate_spapr_cap_fwnmi, &vmstate_spapr_fwnmi, &vmstate_spapr_cap_rpt_invalidate, +&vmstate_spapr_cap_ail_mode_3, &vmstate_spapr_cap_nested_papr, NULL } diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c index 0a15415a1d..2f74923560 100644 --- a/hw/ppc/spapr_caps.c +++ b/hw/ppc/spapr_caps.c @@ -974,6 +974,7 @@ SPAPR_CAP_MIG_STATE(large_decr, SPAPR_CAP_LARGE_DECREMENTER); SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST); SPAPR_CAP_MIG_STATE(fwnmi, SPAPR_CAP_FWNMI); SPAPR_CAP_MIG_STATE(rpt_invalidate, SPAPR_CAP_RPT_INVALIDATE); +SPAPR_CAP_MIG_STATE(ail_mode_3, SPAPR_CAP_AIL_MODE_3); void spapr_caps_init(SpaprMachineState *spapr) {
Re: [PATCH V8 1/8] accel/kvm: Extract common KVM vCPU {creation, parking} code
+ Nick Hi Salil, I have posted a patch [1] for ppc which based on this refactoring patch. I see there were some comments from Vishnu on this patch. Are we expecting any further updates on this patch before merge? Thanks Harsh [1] https://lore.kernel.org/qemu-devel/a0f9b2fc-4c8a-4c37-bc36-26bbaa627...@linux.ibm.com/T/#u On 3/22/24 13:45, Harsh Prateek Bora wrote: + Vaibhav, Shiva Hi Salil, I came across your patch while trying to solve a related problem on spapr. One query below .. On 3/12/24 07:29, Salil Mehta via wrote: KVM vCPU creation is done once during the vCPU realization when Qemu vCPU thread is spawned. This is common to all the architectures as of now. Hot-unplug of vCPU results in destruction of the vCPU object in QOM but the corresponding KVM vCPU object in the Host KVM is not destroyed as KVM doesn't support vCPU removal. Therefore, its representative KVM vCPU object/context in Qemu is parked. Refactor architecture common logic so that some APIs could be reused by vCPU Hotplug code of some architectures likes ARM, Loongson etc. Update new/old APIs with trace events instead of DPRINTF. No functional change is intended here. Signed-off-by: Salil Mehta Reviewed-by: Gavin Shan Tested-by: Vishnu Pajjuri Reviewed-by: Jonathan Cameron Tested-by: Xianglai Li Tested-by: Miguel Luis Reviewed-by: Shaoqin Huang --- accel/kvm/kvm-all.c | 64 -- accel/kvm/trace-events | 5 +++- include/sysemu/kvm.h | 16 +++ 3 files changed, 69 insertions(+), 16 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index a8cecd040e..3bc3207bda 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -126,6 +126,7 @@ static QemuMutex kml_slots_lock; #define kvm_slots_unlock() qemu_mutex_unlock(&kml_slots_lock) static void kvm_slot_init_dirty_bitmap(KVMSlot *mem); +static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id); static inline void kvm_resample_fd_remove(int gsi) { @@ -314,14 +315,53 @@ err: return ret; } +void kvm_park_vcpu(CPUState *cpu) +{ + struct KVMParkedVcpu *vcpu; + + trace_kvm_park_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu)); + + vcpu = g_malloc0(sizeof(*vcpu)); + vcpu->vcpu_id = kvm_arch_vcpu_id(cpu); + vcpu->kvm_fd = cpu->kvm_fd; + QLIST_INSERT_HEAD(&kvm_state->kvm_parked_vcpus, vcpu, node); +} + +int kvm_create_vcpu(CPUState *cpu) +{ + unsigned long vcpu_id = kvm_arch_vcpu_id(cpu); + KVMState *s = kvm_state; + int kvm_fd; + + trace_kvm_create_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu)); + + /* check if the KVM vCPU already exist but is parked */ + kvm_fd = kvm_get_vcpu(s, vcpu_id); + if (kvm_fd < 0) { + /* vCPU not parked: create a new KVM vCPU */ + kvm_fd = kvm_vm_ioctl(s, KVM_CREATE_VCPU, vcpu_id); + if (kvm_fd < 0) { + error_report("KVM_CREATE_VCPU IOCTL failed for vCPU %lu", vcpu_id); + return kvm_fd; + } + } + + cpu->kvm_fd = kvm_fd; + cpu->kvm_state = s; + cpu->vcpu_dirty = true; + cpu->dirty_pages = 0; + cpu->throttle_us_per_full = 0; + + return 0; +} + static int do_kvm_destroy_vcpu(CPUState *cpu) { KVMState *s = kvm_state; long mmap_size; - struct KVMParkedVcpu *vcpu = NULL; int ret = 0; - trace_kvm_destroy_vcpu(); + trace_kvm_destroy_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu)); ret = kvm_arch_destroy_vcpu(cpu); if (ret < 0) { @@ -347,10 +387,7 @@ static int do_kvm_destroy_vcpu(CPUState *cpu) } } - vcpu = g_malloc0(sizeof(*vcpu)); - vcpu->vcpu_id = kvm_arch_vcpu_id(cpu); - vcpu->kvm_fd = cpu->kvm_fd; - QLIST_INSERT_HEAD(&kvm_state->kvm_parked_vcpus, vcpu, node); + kvm_park_vcpu(cpu); err: return ret; } @@ -371,6 +408,8 @@ static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id) if (cpu->vcpu_id == vcpu_id) { int kvm_fd; + trace_kvm_get_vcpu(vcpu_id); + QLIST_REMOVE(cpu, node); kvm_fd = cpu->kvm_fd; g_free(cpu); @@ -378,7 +417,7 @@ static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id) } } - return kvm_vm_ioctl(s, KVM_CREATE_VCPU, (void *)vcpu_id); + return -ENOENT; } int kvm_init_vcpu(CPUState *cpu, Error **errp) @@ -389,19 +428,14 @@ int kvm_init_vcpu(CPUState *cpu, Error **errp) trace_kvm_init_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu)); - ret = kvm_get_vcpu(s, kvm_arch_vcpu_id(cpu)); + ret = kvm_create_vcpu(cpu); if (ret < 0) { - error_setg_errno(errp, -ret, "kvm_init_vcpu: kvm_get_vcpu failed (%lu)", + error_setg_errno(errp, -ret, + "kvm_init_vcpu: kvm_create_vcpu failed (%lu)", kvm_arch_vcpu_id(cpu)); If a vcpu hotplug fails due to failure with kvm_crea
Re: [PATCH] target/ppc: handle vcpu hotplug failure gracefully
+ qemu-devel On 4/23/24 11:40, Harsh Prateek Bora wrote: On ppc64, the PowerVM hypervisor runs with limited memory and a VCPU creation during hotplug may fail during kvm_ioctl for KVM_CREATE_VCPU, leading to termination of guest since errp is set to &error_fatal while calling kvm_init_vcpu. This unexpected behaviour can be avoided by pre-creating vcpu and parking it on success or return error otherwise. This enables graceful error delivery for any vcpu hotplug failures while the guest can keep running. Based on api refactoring to create/park vcpus introduced in 1/8 of patch series: https://lore.kernel.org/qemu-devel/2024031202.12992-2-salil.me...@huawei.com/ Tested OK by repeatedly doing a hotplug/unplug of vcpus as below: #virsh setvcpus hotplug 40 #virsh setvcpus hotplug 70 error: internal error: unable to execute QEMU command 'device_add': kvmppc_cpu_realize: vcpu hotplug failed with -12 Reported-by: Anushree Mathur Suggested-by: Shivaprasad G Bhat Suggested-by: Vaibhav Jain Signed-off by: Harsh Prateek Bora --- --- target/ppc/kvm.c | 42 ++ 1 file changed, 42 insertions(+) diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index 8231feb2d4..c887f6dfa0 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -48,6 +48,8 @@ #include "qemu/mmap-alloc.h" #include "elf.h" #include "sysemu/kvm_int.h" +#include "sysemu/kvm.h" +#include "hw/core/accel-cpu.h" #define PROC_DEVTREE_CPU "/proc/device-tree/cpus/" @@ -2339,6 +2341,43 @@ static void alter_insns(uint64_t *word, uint64_t flags, bool on) } } +static int max_cpu_index = 0; + +static bool kvmppc_cpu_realize(CPUState *cs, Error **errp) +{ +int ret; + +cs->cpu_index = max_cpu_index++; + +POWERPC_CPU(cs)->vcpu_id = cs->cpu_index; + +if (cs->parent_obj.hotplugged) { +/* create and park to fail gracefully in case vcpu hotplug fails */ +ret = kvm_create_vcpu(cs); +if (!ret) { +kvm_park_vcpu(cs); +} else { +max_cpu_index--; +error_setg(errp, "%s: vcpu hotplug failed with %d", + __func__, ret); +return false; +} +} +return true; +} + +static void kvmppc_cpu_unrealize(CPUState *cpu) +{ +if (POWERPC_CPU(cpu)->vcpu_id == (max_cpu_index - 1)) { +/* only reclaim vcpuid if its the last one assigned + * as reclaiming random vcpuid for parked vcpus may lead + * to unexpected behaviour due to an existing kernel bug + * when drc_index doesnt get reclaimed as expected. + */ +max_cpu_index--; +} +} + static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data) { PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); @@ -2963,4 +3002,7 @@ bool kvm_arch_cpu_check_are_resettable(void) void kvm_arch_accel_class_init(ObjectClass *oc) { +AccelClass *ac = ACCEL_CLASS(oc); +ac->cpu_common_realize = kvmppc_cpu_realize; +ac->cpu_common_unrealize = kvmppc_cpu_unrealize; }
Re: [PATCH 22/24] exec: Remove 'exec/tswap.h' from 'exec/cpu-all.h'
On 4/19/24 00:55, Philippe Mathieu-Daudé wrote: "exec/cpu-all.h" doesn't require "exec/tswap.h". Remove it, including it in the sources when required. Signed-off-by: Philippe Mathieu-Daudé --- hw/xtensa/bootparam.h | 1 + include/exec/cpu-all.h | 1 - accel/tcg/translator.c | 1 + hw/arm/boot.c | 1 + hw/arm/npcm7xx.c| 1 + hw/mips/fuloong2e.c | 1 + hw/mips/malta.c | 1 + hw/ppc/sam460ex.c | 1 + hw/ppc/spapr.c | 1 + For spapr: Reviewed-by: Harsh Prateek Bora hw/ppc/virtex_ml507.c | 1 + hw/sh4/r2d.c| 1 + target/arm/gdbstub.c| 1 + target/xtensa/xtensa-semi.c | 1 + 13 files changed, 12 insertions(+), 1 deletion(-) diff --git a/hw/xtensa/bootparam.h b/hw/xtensa/bootparam.h index f57ff850bc..e1d47b503c 100644 --- a/hw/xtensa/bootparam.h +++ b/hw/xtensa/bootparam.h @@ -1,6 +1,7 @@ #ifndef HW_XTENSA_BOOTPARAM_H #define HW_XTENSA_BOOTPARAM_H +#include "exec/tswap.h" #include "exec/cpu-common.h" #define BP_TAG_COMMAND_LINE 0x1001 /* command line (0-terminated string)*/ diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 554b937ddb..cfbf51822c 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -21,7 +21,6 @@ #include "exec/cpu-common.h" #include "exec/memory.h" -#include "exec/tswap.h" #include "hw/core/cpu.h" /* some important defines: diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index 6832e55135..85950377d9 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -12,6 +12,7 @@ #include "qemu/error-report.h" #include "exec/exec-all.h" #include "exec/translator.h" +#include "exec/tswap.h" #include "exec/cpu_ldst.h" #include "exec/plugin-gen.h" #include "tcg/tcg-op-common.h" diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 84ea6a807a..93945a1a15 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -22,6 +22,7 @@ #include "sysemu/reset.h" #include "hw/loader.h" #include "elf.h" +#include "exec/tswap.h" #include "sysemu/device_tree.h" #include "qemu/config-file.h" #include "qemu/option.h" diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c index cc68b5d8f1..1ef303415b 100644 --- a/hw/arm/npcm7xx.c +++ b/hw/arm/npcm7xx.c @@ -27,6 +27,7 @@ #include "qemu/units.h" #include "sysemu/sysemu.h" #include "target/arm/cpu-qom.h" +#include "exec/tswap.h" /* * This covers the whole MMIO space. We'll use this to catch any MMIO accesses diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index a45aac368c..1d0613a76f 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -40,6 +40,7 @@ #include "sysemu/reset.h" #include "sysemu/sysemu.h" #include "qemu/error-report.h" +#include "exec/tswap.h" #define ENVP_PADDR 0x2000 #define ENVP_VADDR cpu_mips_phys_to_kseg0(NULL, ENVP_PADDR) diff --git a/hw/mips/malta.c b/hw/mips/malta.c index af74008c82..3dca0f100c 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -56,6 +56,7 @@ #include "semihosting/semihost.h" #include "hw/mips/cps.h" #include "hw/qdev-clock.h" +#include "exec/tswap.h" #include "target/mips/internal.h" #include "trace.h" #include "cpu.h" diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index d42b677898..abc02f0817 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -24,6 +24,7 @@ #include "hw/loader.h" #include "elf.h" #include "exec/memory.h" +#include "exec/tswap.h" #include "ppc440.h" #include "hw/pci-host/ppc4xx.h" #include "hw/block/flash.h" diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index e9bc97fee0..b4b1f43983 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -74,6 +74,7 @@ #include "hw/virtio/virtio-scsi.h" #include "hw/virtio/vhost-scsi-common.h" +#include "exec/tswap.h" #include "exec/ram_addr.h" #include "hw/usb.h" #include "qemu/config-file.h" diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c index d02f330650..fd23afebf5 100644 --- a/hw/ppc/virtex_ml507.c +++ b/hw/ppc/virtex_ml507.c @@ -38,6 +38,7 @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/option.h" +#include "exec/tswap.h" #include "hw/intc/ppc-uic.h" #include "hw/ppc/ppc.h" diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c index e5ac6751bd..5f4420f534 100644 --- a/hw/sh4/r2d.c +++ b/hw/sh4/r2d.c @@ -43,6 +43,7 @@ #include "hw/l
Re: [PATCH v2 03/13] hw/ppc/spapr: Replace sprintf() by snprintf()
On 4/11/24 15:45, Philippe Mathieu-Daudé wrote: sprintf() is deprecated on Darwin since macOS 13.0 / XCode 14.1, resulting in painful developper experience. s/developper/developer ? Replace sprintf() by snprintf() in order to avoid: hw/ppc/spapr.c:385:5: warning: 'sprintf' is deprecated: This function is provided for compatibility reasons only. Due to security concerns inherent in the design of sprintf(3), it is highly recommended that you use snprintf(3) instead. [-Wdeprecated-declarations] sprintf(mem_name, "memory@%" HWADDR_PRIx, start); ^ 1 warning generated. Signed-off-by: Philippe Mathieu-Daudé With the typo fixed, Reviewed-by: Harsh Prateek Bora --- hw/ppc/spapr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index e9bc97fee0..9e97992c79 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -382,7 +382,7 @@ static int spapr_dt_memory_node(SpaprMachineState *spapr, void *fdt, int nodeid, mem_reg_property[0] = cpu_to_be64(start); mem_reg_property[1] = cpu_to_be64(size); -sprintf(mem_name, "memory@%" HWADDR_PRIx, start); +snprintf(mem_name, sizeof(mem_name), "memory@%" HWADDR_PRIx, start); off = fdt_add_subnode(fdt, 0, mem_name); _FDT(off); _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
[PATCH] spapr: nested: use bitwise NOT operator for flags check
Check for flag bit in H_GUEST_GETSET_STATE_FLAG_GUEST_WIDE need to use bitwise NOT operator to ensure no other flag bits are set. Reported by Coverity as CID 1540008, 1540009. Reported-by: Peter Maydell Signed-off by: Harsh Prateek Bora --- hw/ppc/spapr_nested.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc/spapr_nested.c b/hw/ppc/spapr_nested.c index 936659b4c0..c02785756c 100644 --- a/hw/ppc/spapr_nested.c +++ b/hw/ppc/spapr_nested.c @@ -1511,7 +1511,7 @@ static target_ulong h_guest_getset_state(PowerPCCPU *cpu, if (flags & H_GUEST_GETSET_STATE_FLAG_GUEST_WIDE) { gsr.flags |= GUEST_STATE_REQUEST_GUEST_WIDE; } -if (flags & !H_GUEST_GETSET_STATE_FLAG_GUEST_WIDE) { +if (flags & ~H_GUEST_GETSET_STATE_FLAG_GUEST_WIDE) { return H_PARAMETER; /* flag not supported yet */ } -- 2.39.3
Re: [PULL 35/38] spapr: nested: Introduce H_GUEST_[GET|SET]_STATE hcalls.
On 3/28/24 20:55, Peter Maydell wrote: On Wed, 27 Mar 2024 at 05:41, Harsh Prateek Bora wrote: On 3/26/24 21:32, Peter Maydell wrote: On Tue, 12 Mar 2024 at 17:11, Nicholas Piggin wrote: From: Harsh Prateek Bora Introduce the nested PAPR hcalls: - H_GUEST_GET_STATE which is used to get state of a nested guest or a guest VCPU. The value field for each element in the request is destination to be updated to reflect current state on success. - H_GUEST_SET_STATE which is used to modify the state of a guest or a guest VCPU. On success, guest (or its VCPU) state shall be updated as per the value field for the requested element(s). Reviewed-by: Nicholas Piggin Signed-off-by: Michael Neuling Signed-off-by: Harsh Prateek Bora Signed-off-by: Nicholas Piggin Hi; Coverity points out a problem with this code (CID 1540008, 1540009): +static target_ulong h_guest_getset_state(PowerPCCPU *cpu, + SpaprMachineState *spapr, + target_ulong *args, + bool set) +{ +target_ulong flags = args[0]; +target_ulong lpid = args[1]; +target_ulong vcpuid = args[2]; +target_ulong buf = args[3]; +target_ulong buflen = args[4]; +struct guest_state_request gsr; +SpaprMachineStateNestedGuest *guest; + +guest = spapr_get_nested_guest(spapr, lpid); +if (!guest) { +return H_P2; +} +gsr.buf = buf; +assert(buflen <= GSB_MAX_BUF_SIZE); +gsr.len = buflen; +gsr.flags = 0; +if (flags & H_GUEST_GETSET_STATE_FLAG_GUEST_WIDE) { flags is a target_ulong, which means it might only be 32 bits. But H_GUEST_GETSET_STATE_FLAG_GUEST_WIDE has a bit set in the upper 32 bits only. So Coverity complains about this condition being always-zero and the body of the if being dead code. What was the intention here? Hi Peter, Ideally this is intended to be running on a ppc64 where target_ulong should be uint64_t. I guess same holds true for existing nested-hv code as well. Sorry, I'm afraid I misread the Coverity report here; sorry for the confusion. The 32-vs-64 bits question is a red herring. What Coverity is actually pointing out is in this next bit: +gsr.flags |= GUEST_STATE_REQUEST_GUEST_WIDE; +} +if (flags & !H_GUEST_GETSET_STATE_FLAG_GUEST_WIDE) { The C operator ! is the logical-NOT operator; since H_GUEST_GETSET_STATE_FLAG_GUEST_WIDE is a non-zero value that means that !H_GUEST_GETSET_STATE_FLAG_GUEST_WIDE is 0; so we're testing (flags & 0), which is always false, and this is the if() body which is dead-code as a result. Should this be the bitwise-NOT ~ (ie "if any flag other than this one is set"), or should this be an else clause to the previous if() (ie "if this flag is not set") ? Oh, this should have been bitwise-NOT, I shall send a follow-up patch for the fix. regards, Harsh +return H_PARAMETER; /* flag not supported yet */ +} + +if (set) { +gsr.flags |= GUEST_STATE_REQUEST_SET; +} +return map_and_getset_state(cpu, guest, vcpuid, &gsr); +} thanks -- PMM