From 613e7a764501a236cdfce39561f9bcf60c78cf49 Mon Sep 17 00:00:00 2001 From: Bharata B Rao Date: Thu, 30 Jul 2015 20:25:15 +0530 Subject: [PATCH 01/36] spapr: Provide an error message when migration fails due to htab_shift mismatch Include an error message when migration fails due to mismatch in htab_shift values at source and target. This should provide a bit more verbose message in addition to the current migration failure message that reads like: qemu-system-ppc64: error while loading state for instance 0x0 of device 'spapr/htab' After this patch, the failure message will look like this: qemu-system-ppc64: htab_shift mismatch: source 29 target 24 qemu-system-ppc64: error while loading state for instance 0x0 of device 'spapr/htab' Signed-off-by: Bharata B Rao Signed-off-by: David Gibson --- hw/ppc/spapr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 05926a3eb2..dd58eb433a 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1329,6 +1329,8 @@ static int htab_load(QEMUFile *f, void *opaque, int version_id) if (section_hdr) { /* First section, just the hash shift */ if (spapr->htab_shift != section_hdr) { + error_report("htab_shift mismatch: source %d target %d", + section_hdr, spapr->htab_shift); return -EINVAL; } return 0; From fb0fc8f62c16b5b0910545f56c64aaafc91533ce Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 12 Aug 2015 13:15:56 +1000 Subject: [PATCH 02/36] spapr: Create pseries-2.5 machine Add pseries-2.5 machine version. Signed-off-by: Bharata B Rao [Altered to merge before memory hotplug -- dwg] [Altered to work with b9f072d01 -- dwg] Signed-off-by: David Gibson --- hw/ppc/spapr.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index dd58eb433a..df76cb7a39 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1976,7 +1976,7 @@ static void spapr_machine_2_4_class_init(ObjectClass *oc, void *data) mc->desc = "pSeries Logical Partition (PAPR compliant) v2.4"; mc->alias = "pseries"; - mc->is_default = 1; + mc->is_default = 0; } static const TypeInfo spapr_machine_2_4_info = { @@ -1985,6 +1985,22 @@ static const TypeInfo spapr_machine_2_4_info = { .class_init = spapr_machine_2_4_class_init, }; +static void spapr_machine_2_5_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->name = "pseries-2.5"; + mc->desc = "pSeries Logical Partition (PAPR compliant) v2.5"; + mc->alias = "pseries"; + mc->is_default = 1; +} + +static const TypeInfo spapr_machine_2_5_info = { + .name = MACHINE_TYPE_NAME("pseries-2.5"), + .parent = TYPE_SPAPR_MACHINE, + .class_init = spapr_machine_2_5_class_init, +}; + static void spapr_machine_register_types(void) { type_register_static(&spapr_machine_info); @@ -1992,6 +2008,7 @@ static void spapr_machine_register_types(void) type_register_static(&spapr_machine_2_2_info); type_register_static(&spapr_machine_2_3_info); type_register_static(&spapr_machine_2_4_info); + type_register_static(&spapr_machine_2_5_info); } type_init(spapr_machine_register_types) From 2c1aaa819a0d68a51086f5d7e8f9a0114ae0305c Mon Sep 17 00:00:00 2001 From: Sam Bobroff Date: Tue, 1 Sep 2015 11:23:19 +1000 Subject: [PATCH 03/36] spapr: Add /ibm,partition-name QEMU has a notion of the guest name, so if it's present we might as well put that into the device tree as /ibm,partition-name. This is specificed by PAPR. Signed-off-by: Sam Bobroff Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index df76cb7a39..09962c4f8e 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -375,6 +375,11 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base, _FDT((fdt_property_string(fdt, "vm,uuid", buf))); g_free(buf); + if (qemu_get_vm_name()) { + _FDT((fdt_property_string(fdt, "ibm,partition-name", + qemu_get_vm_name()))); + } + _FDT((fdt_property_cell(fdt, "#address-cells", 0x2))); _FDT((fdt_property_cell(fdt, "#size-cells", 0x2))); From a95f99224c08efcf91b4259c34754f69d962bf23 Mon Sep 17 00:00:00 2001 From: Sam Bobroff Date: Tue, 1 Sep 2015 11:23:34 +1000 Subject: [PATCH 04/36] spapr: Add /rtas/ibm,change-msix-capable QEMU is MSI-X capable and makes it available via ibm,change-msi, so we should indicate this by adding /rtas/ibm,change-msix-capable to the device tree. This is specificed by PAPR. Signed-off-by: Sam Bobroff Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 09962c4f8e..ed0abd8498 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -432,6 +432,10 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base, _FDT((fdt_property_cell(fdt, "rtas-event-scan-rate", RTAS_EVENT_SCAN_RATE))); + if (msi_supported) { + _FDT((fdt_property(fdt, "ibm,change-msix-capable", NULL, 0))); + } + /* * According to PAPR, rtas ibm,os-term does not guarantee a return * back to the guest cpu. From b359bd6a424b8de7db994d7120e87a7465b69337 Mon Sep 17 00:00:00 2001 From: Sam Bobroff Date: Tue, 1 Sep 2015 11:23:47 +1000 Subject: [PATCH 05/36] spapr: Make ibm, change-msi respect 3 return values Currently, rtas_ibm_change_msi() always returns four values even if less are specified. Correct this by only returning the fourth parameter if it was requested. This is specified by PAPR. Signed-off-by: Sam Bobroff Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr_pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index a2feb4c985..6782fd0b4d 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -375,7 +375,9 @@ out: rtas_st(rets, 0, RTAS_OUT_SUCCESS); rtas_st(rets, 1, req_num); rtas_st(rets, 2, ++seq_num); - rtas_st(rets, 3, ret_intr_type); + if (nret > 3) { + rtas_st(rets, 3, ret_intr_type); + } trace_spapr_pci_rtas_ibm_change_msi(config_addr, func, req_num, irq); } From e39432282e2d2db42645c2ce183dfcaa1488752b Mon Sep 17 00:00:00 2001 From: Sam Bobroff Date: Tue, 1 Sep 2015 11:24:37 +1000 Subject: [PATCH 06/36] spapr: SPLPAR Characteristics Improve the SPLPAR Characteristics information: Add MaxPlatProcs: set to max_cpus, the maximum CPUs that could be addded to the system. Add DesMem: set to the initial memory of the system. Add DesProcs: set to smp_cpus, the inital number of CPUs in the system. These tokens and values are specified by PAPR. Signed-off-by: Sam Bobroff Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr_rtas.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index 9869bc9587..5cbf9a071a 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -34,6 +34,7 @@ #include "hw/ppc/spapr.h" #include "hw/ppc/spapr_vio.h" #include "qapi-event.h" +#include "hw/boards.h" #include #include "hw/ppc/spapr_drc.h" @@ -240,8 +241,14 @@ static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu, switch (parameter) { case RTAS_SYSPARM_SPLPAR_CHARACTERISTICS: { - char *param_val = g_strdup_printf("MaxEntCap=%d,MaxPlatProcs=%d", - max_cpus, smp_cpus); + char *param_val = g_strdup_printf("MaxEntCap=%d," + "DesMem=%llu," + "DesProcs=%d," + "MaxPlatProcs=%d", + max_cpus, + current_machine->ram_size / M_BYTE, + smp_cpus, + max_cpus); rtas_st_buffer(buffer, length, (uint8_t *)param_val, strlen(param_val)); g_free(param_val); break; From ad440b4ae0727dbef5cace419d94d774de96886c Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 1 Sep 2015 11:25:35 +1000 Subject: [PATCH 07/36] spapr: add dumpdtb support dumpdtb (-machine dumpdtb=) allows one to inspect the generated device tree of machine types that generate device trees. This is useful for a) seeing what's there b) debugging/testing device tree generator patches. It can be used as follows $QEMU_CMDLINE -machine dumpdtb=dtb dtc -I dtb -O dts dtb Signed-off-by: Andrew Jones Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index ed0abd8498..a69d7e4754 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -30,6 +30,7 @@ #include "hw/fw-path-provider.h" #include "elf.h" #include "net/net.h" +#include "sysemu/device_tree.h" #include "sysemu/block-backend.h" #include "sysemu/cpus.h" #include "sysemu/kvm.h" @@ -831,6 +832,7 @@ static void spapr_finalize_fdt(sPAPRMachineState *spapr, exit(1); } + qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt)); g_free(bootlist); From 627c2ef7898794a28d706ecdf094491bebbb083a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 3 Sep 2015 10:08:23 +1000 Subject: [PATCH 08/36] spapr_drc: Fix potential undefined behaviour The DRC_INDEX_ID_MASK macro does a left shift on ~0, which is a signed quantity, and therefore undefined behaviour according to the C spec. In particular this causes warnings from the clang sanitizer. This fixes it by calculating the same mask without using ~0 (I think the new method is a more common idiom for generating masks anyway). For good measure I also use 1ULL to force the expression's type to unsigned long long, which should be good for assigning to anything we're going to want to. Reported-by: Peter Maydell Signed-off-by: David Gibson Reviewed-by: Alexey Kardashevskiy --- hw/ppc/spapr_drc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index ee874326ee..8cbcf4d346 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -32,7 +32,7 @@ #define DRC_CONTAINER_PATH "/dr-connector" #define DRC_INDEX_TYPE_SHIFT 28 -#define DRC_INDEX_ID_MASK (~(~0 << DRC_INDEX_TYPE_SHIFT)) +#define DRC_INDEX_ID_MASK ((1ULL << DRC_INDEX_TYPE_SHIFT) - 1) static sPAPRDRConnectorTypeShift get_type_shift(sPAPRDRConnectorType type) { From aaf87c6616370685a7cff6a21616fc5db7495014 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 1 Sep 2015 11:29:02 +1000 Subject: [PATCH 09/36] ppc/spapr: Use qemu_log_mask() for hcall_dprintf() To see the output of the hcall_dprintf statements, you currently have to enable the DEBUG_SPAPR_HCALLS macro in include/hw/ppc/spapr.h. This is ugly because a) not every user who wants to debug guest problems can or wants to recompile QEMU to be able to see such issues, and b) since this macro is disabled by default, the code in the hcall_dprintf() brackets tends to bitrot until somebody temporarily enables that macro again. Since the hcall_dprintf statements except one indicate guest problems, let's always use qemu_log_mask(LOG_GUEST_ERROR, ...) for this macro instead. One spot indicated an unimplemented host feature, so this is changed into qemu_log_mask(LOG_UNIMP, ...) instead. Now it's possible to see all those messages by simply adding the CLI parameter "-d guest_errors,unimp", without the need to re-compile the binary. Signed-off-by: Thomas Huth Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr_hcall.c | 3 ++- include/hw/ppc/spapr.h | 11 +++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 652ddf6e37..71fc9f23a1 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -971,7 +971,8 @@ target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode, } } - hcall_dprintf("Unimplemented hcall 0x" TARGET_FMT_lx "\n", opcode); + qemu_log_mask(LOG_UNIMP, "Unimplemented SPAPR hcall 0x" TARGET_FMT_lx "\n", + opcode); return H_FUNCTION; } diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 91a61abbc4..d2509677fb 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -353,15 +353,10 @@ typedef struct sPAPRDeviceTreeUpdateHeader { uint32_t version_id; } sPAPRDeviceTreeUpdateHeader; -/*#define DEBUG_SPAPR_HCALLS*/ - -#ifdef DEBUG_SPAPR_HCALLS #define hcall_dprintf(fmt, ...) \ - do { fprintf(stderr, "%s: " fmt, __func__, ## __VA_ARGS__); } while (0) -#else -#define hcall_dprintf(fmt, ...) \ - do { } while (0) -#endif + do { \ + qemu_log_mask(LOG_GUEST_ERROR, "%s: " fmt, __func__, ## __VA_ARGS__); \ + } while (0) typedef target_ulong (*spapr_hcall_fn)(PowerPCCPU *cpu, sPAPRMachineState *sm, target_ulong opcode, From e6fc9568c865f2f81499475a4e322cd563fdfd90 Mon Sep 17 00:00:00 2001 From: Bharata B Rao Date: Tue, 1 Sep 2015 09:53:52 +1000 Subject: [PATCH 10/36] spapr_rtas: Prevent QEMU crash during hotplug without a prior device_add If drmgr is used in the guest to hotplug a device before a device_add has been issued via the QEMU monitor, QEMU segfaults in configure_connector call. This occurs due to accessing of NULL FDT which otherwise would have been created and associated with the DRC during device_add command. Check for NULL FDT and return failure from configure_connector call. As per PAPR+, an error value of -9003 seems appropriate for this failure. Signed-off-by: Bharata B Rao Cc: Michael Roth Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr_rtas.c | 6 ++++++ include/hw/ppc/spapr_drc.h | 15 ++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index 5cbf9a071a..2f8e25cfb2 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -522,6 +522,12 @@ static void rtas_ibm_configure_connector(PowerPCCPU *cpu, drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); fdt = drck->get_fdt(drc, NULL); + if (!fdt) { + DPRINTF("rtas_ibm_configure_connector: Missing FDT for DRC index: %xh\n", + drc_index); + rc = SPAPR_DR_CC_RESPONSE_NOT_CONFIGURABLE; + goto out; + } ccs = spapr_ccs_find(spapr, drc_index); if (!ccs) { diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h index 60cda35ed2..28ffeaeb1c 100644 --- a/include/hw/ppc/spapr_drc.h +++ b/include/hw/ppc/spapr_drc.h @@ -119,13 +119,14 @@ typedef enum { } sPAPRDREntitySense; typedef enum { - SPAPR_DR_CC_RESPONSE_NEXT_SIB = 1, /* currently unused */ - SPAPR_DR_CC_RESPONSE_NEXT_CHILD = 2, - SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY = 3, - SPAPR_DR_CC_RESPONSE_PREV_PARENT = 4, - SPAPR_DR_CC_RESPONSE_SUCCESS = 0, - SPAPR_DR_CC_RESPONSE_ERROR = -1, - SPAPR_DR_CC_RESPONSE_CONTINUE = -2, + SPAPR_DR_CC_RESPONSE_NEXT_SIB = 1, /* currently unused */ + SPAPR_DR_CC_RESPONSE_NEXT_CHILD = 2, + SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY = 3, + SPAPR_DR_CC_RESPONSE_PREV_PARENT = 4, + SPAPR_DR_CC_RESPONSE_SUCCESS = 0, + SPAPR_DR_CC_RESPONSE_ERROR = -1, + SPAPR_DR_CC_RESPONSE_CONTINUE = -2, + SPAPR_DR_CC_RESPONSE_NOT_CONFIGURABLE = -9003, } sPAPRDRCCResponse; typedef void (spapr_drc_detach_cb)(DeviceState *d, void *opaque); From a14aa92b20c5482b9b694901304b8100b3c4b5a1 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Tue, 1 Sep 2015 11:05:12 +1000 Subject: [PATCH 11/36] sPAPR: Introduce rtas_ldq() This introduces rtas_ldq() to load 64-bits parameter from continuous two 4-bytes memory chunk of RTAS parameter buffer, to simplify the code. Signed-off-by: Gavin Shan Reviewed-by: Thomas Huth Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr_pci.c | 20 ++++++++++---------- include/hw/ppc/spapr.h | 5 +++++ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 6782fd0b4d..54292c9d81 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -140,7 +140,7 @@ static void rtas_ibm_read_pci_config(PowerPCCPU *cpu, sPAPRMachineState *spapr, return; } - buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); + buid = rtas_ldq(args, 1); size = rtas_ld(args, 3); addr = rtas_ld(args, 0); @@ -206,7 +206,7 @@ static void rtas_ibm_write_pci_config(PowerPCCPU *cpu, sPAPRMachineState *spapr, return; } - buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); + buid = rtas_ldq(args, 1); val = rtas_ld(args, 4); size = rtas_ld(args, 3); addr = rtas_ld(args, 0); @@ -269,7 +269,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr, target_ulong rets) { uint32_t config_addr = rtas_ld(args, 0); - uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); + uint64_t buid = rtas_ldq(args, 1); unsigned int func = rtas_ld(args, 3); unsigned int req_num = rtas_ld(args, 4); /* 0 == remove all */ unsigned int seq_num = rtas_ld(args, 5); @@ -391,7 +391,7 @@ static void rtas_ibm_query_interrupt_source_number(PowerPCCPU *cpu, target_ulong rets) { uint32_t config_addr = rtas_ld(args, 0); - uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); + uint64_t buid = rtas_ldq(args, 1); unsigned int intr_src_num = -1, ioa_intr_num = rtas_ld(args, 3); sPAPRPHBState *phb = NULL; PCIDevice *pdev = NULL; @@ -440,7 +440,7 @@ static void rtas_ibm_set_eeh_option(PowerPCCPU *cpu, goto param_error_exit; } - buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); + buid = rtas_ldq(args, 1); addr = rtas_ld(args, 0); option = rtas_ld(args, 3); @@ -484,7 +484,7 @@ static void rtas_ibm_get_config_addr_info2(PowerPCCPU *cpu, goto param_error_exit; } - buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); + buid = rtas_ldq(args, 1); sphb = spapr_pci_find_phb(spapr, buid); if (!sphb) { goto param_error_exit; @@ -539,7 +539,7 @@ static void rtas_ibm_read_slot_reset_state2(PowerPCCPU *cpu, goto param_error_exit; } - buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); + buid = rtas_ldq(args, 1); sphb = spapr_pci_find_phb(spapr, buid); if (!sphb) { goto param_error_exit; @@ -584,7 +584,7 @@ static void rtas_ibm_set_slot_reset(PowerPCCPU *cpu, goto param_error_exit; } - buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); + buid = rtas_ldq(args, 1); option = rtas_ld(args, 3); sphb = spapr_pci_find_phb(spapr, buid); if (!sphb) { @@ -619,7 +619,7 @@ static void rtas_ibm_configure_pe(PowerPCCPU *cpu, goto param_error_exit; } - buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); + buid = rtas_ldq(args, 1); sphb = spapr_pci_find_phb(spapr, buid); if (!sphb) { goto param_error_exit; @@ -654,7 +654,7 @@ static void rtas_ibm_slot_error_detail(PowerPCCPU *cpu, goto param_error_exit; } - buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); + buid = rtas_ldq(args, 1); sphb = spapr_pci_find_phb(spapr, buid); if (!sphb) { goto param_error_exit; diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index d2509677fb..cbe3463e32 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -489,6 +489,11 @@ static inline uint32_t rtas_ld(target_ulong phys, int n) return ldl_be_phys(&address_space_memory, ppc64_phys_to_real(phys + 4*n)); } +static inline uint64_t rtas_ldq(target_ulong phys, int n) +{ + return (uint64_t)rtas_ld(phys, n) << 32 | rtas_ld(phys, n + 1); +} + static inline void rtas_st(target_ulong phys, int n, uint32_t val) { stl_be_phys(&address_space_memory, ppc64_phys_to_real(phys + 4*n), val); From 785652dc4db2023aeda4e381eb08e0beae67b870 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Thu, 13 Aug 2015 14:53:02 +0200 Subject: [PATCH 12/36] pseries: define coldplugged devices as "configured" When a device is hotplugged, attach() sets "configured" to false, waiting an action from the OS to configure it and then to call ibm,configure-connector. On ibm,configure-connector, the hypervisor sets "configured" to true. In case of coldplugged device, attach() sets "configured" to false, but firmware and OS never call the ibm,configure-connector in this case, so it remains set to false. It could be harmless, but when we unplug a device, hypervisor waits the device becomes configured because for it, a not configured device is a device being configured, so it waits the end of configuration to unplug it... and it never happens, so it is never unplugged. This patch set by default coldplugged device to "configured=true", hotplugged device to "configured=false". Signed-off-by: Laurent Vivier Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr_drc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index 8cbcf4d346..9ce844ab1e 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -310,7 +310,7 @@ static void attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt, drc->dev = d; drc->fdt = fdt; drc->fdt_start_offset = fdt_start_offset; - drc->configured = false; + drc->configured = coldplug; object_property_add_link(OBJECT(drc), "device", object_get_typename(OBJECT(drc->dev)), From 92d7a30cb3656f577f87b19042d9b66ff3b20e3b Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Thu, 13 Aug 2015 19:24:16 +1000 Subject: [PATCH 13/36] pseries: Update SLOF firmware image to qemu-slof-20150813 The changes are: 1. GPT support; 2. Much faster VGA support. The full changelog is: > Add missing half word access case to _FASTRMOVE and _FASTMOVE > Remove unused RMOVE64 stub > fbuffer: Implement RFILL as an accelerated primitive > fbuffer: Implement MRMOVE as an accelerated primitive > fbuffer: Precalculate line length in bytes > terminal: Disable the terminal-write trace by default > boot: remove trailing ":" in the bootpath > ci: implement boot client interface > boot: bootpath should be complete device path > fbuffer: Use a smaller cursor > fbuffer: Improve invert-region helper > usb-hid: Caps is not always shift > cas: Increase FDT buffer size to accomodate larger ibm, cas node properties > README: Update with patch submittion note > disk-label: add support for booting from GPT FAT partition > disk-label: introduce helper to check fat filesystem > introduce 8-byte LE helpers > disk-label: simplify gpt-prep-partition? routine > fbuffer: introduce the invert-region-x helper > fbuffer: introduce the invert-region helper > fbuffer: simplify address computations in fb8-toggle-cursor Signed-off-by: Alexey Kardashevskiy Signed-off-by: David Gibson --- pc-bios/README | 2 +- pc-bios/slof.bin | Bin 912720 -> 915584 bytes roms/SLOF | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pc-bios/README b/pc-bios/README index 05cf0421be..e4154ab9f0 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -17,7 +17,7 @@ - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware implementation for certain IBM POWER hardware. The sources are at https://github.com/aik/SLOF, and the image currently in qemu is - built from git tag qemu-slof-20150429. + built from git tag qemu-slof-20150813. - sgabios (the Serial Graphics Adapter option ROM) provides a means for legacy x86 software to communicate with an attached serial console as diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin index 0398ac67bc8d07410fe2ccc9d62c376ef3cf87c3..701933f7dc7b20f6cfcbb538a95142d0a598ada8 100644 GIT binary patch delta 165318 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 *A>w&_ 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 delta 163955 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 XeDaqAj_$**y?;P!-`)4GKjQxb%CXf` diff --git a/roms/SLOF b/roms/SLOF index 7d766a3ac9..811277ac91 160000 --- a/roms/SLOF +++ b/roms/SLOF @@ -1 +1 @@ -Subproject commit 7d766a3ac9b2474f6c7da0084d43590cbbf047bf +Subproject commit 811277ac91f674a9273e2b529791e9b75350f3e8 From 22419c2a90b859dcab49f9472259ad8a3ce091d6 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 8 Sep 2015 11:21:31 +1000 Subject: [PATCH 14/36] pseries: Fix incorrect calculation of threads per socket for chip-id The device tree presented to pseries machine type guests includes an ibm,chip-id property which gives essentially the socket number of each vcpu core (individual vcpu threads don't get a node in the device tree). To calculate this, it uses a vcpus_per_socket variable computed as (smp_cpus / #sockets). This is correct for the usual case where smp_cpus == smp_threads * smp_cores * #sockets. However, you can start QEMU with the number of cores and threads mismatching the total number of vcpus (whether that _should_ be permitted is a topic for another day). It's a bit hard to say what the "real" number of vcpus per socket here is, but for most purposes (smp_threads * smp_cores) will more meaningfully match how QEMU behaves with respect to socket boundaries. Signed-off-by: David Gibson Reviewed-by: Alexey Kardashevskiy --- hw/ppc/spapr.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index a69d7e4754..ac0d2fe892 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -630,9 +630,7 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000; uint32_t page_sizes_prop[64]; size_t page_sizes_prop_size; - QemuOpts *opts = qemu_opts_find(qemu_find_opts("smp-opts"), NULL); - unsigned sockets = opts ? qemu_opt_get_number(opts, "sockets", 0) : 0; - uint32_t cpus_per_socket = sockets ? (smp_cpus / sockets) : 1; + uint32_t vcpus_per_socket = smp_threads * smp_cores; uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; _FDT((fdt_setprop_cell(fdt, offset, "reg", index))); @@ -701,7 +699,7 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, } _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", - cs->cpu_index / cpus_per_socket))); + cs->cpu_index / vcpus_per_socket))); _FDT((fdt_setprop(fdt, offset, "ibm,pft-size", pft_size_prop, sizeof(pft_size_prop)))); From ef9971dd69bdd84b0987b0e1e4f421223b080afd Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Tue, 8 Sep 2015 11:25:13 +1000 Subject: [PATCH 15/36] spapr: Enable in-kernel H_SET_MODE handling For setting debug watchpoints, sPAPR guests use H_SET_MODE hypercall. The existing QEMU H_SET_MODE handler does not support this but the KVM handler in HV KVM does. However it is not enabled. This enables the in-kernel H_SET_MODE handler which handles: - Completed Instruction Address Breakpoint Register - Watch point 0 registers. The rest is still handled in QEMU. Reported-by: Anton Blanchard Signed-off-by: Alexey Kardashevskiy Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr.c | 1 + target-ppc/kvm.c | 5 +++++ target-ppc/kvm_ppc.h | 5 +++++ 3 files changed, 11 insertions(+) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index ac0d2fe892..d49f322fcc 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1546,6 +1546,7 @@ static void ppc_spapr_init(MachineState *machine) if (kvm_enabled()) { /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */ kvmppc_enable_logical_ci_hcalls(); + kvmppc_enable_set_mode_hcall(); } /* allocate RAM */ diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 110436d088..9cf5308ac3 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -1953,6 +1953,11 @@ void kvmppc_enable_logical_ci_hcalls(void) kvmppc_enable_hcall(kvm_state, H_LOGICAL_CI_STORE); } +void kvmppc_enable_set_mode_hcall(void) +{ + kvmppc_enable_hcall(kvm_state, H_SET_MODE); +} + void kvmppc_set_papr(PowerPCCPU *cpu) { CPUState *cs = CPU(cpu); diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h index 5c1d334ae0..f790d50e51 100644 --- a/target-ppc/kvm_ppc.h +++ b/target-ppc/kvm_ppc.h @@ -23,6 +23,7 @@ int kvmppc_get_hasidle(CPUPPCState *env); int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len); int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level); void kvmppc_enable_logical_ci_hcalls(void); +void kvmppc_enable_set_mode_hcall(void); void kvmppc_set_papr(PowerPCCPU *cpu); int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version); void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy); @@ -110,6 +111,10 @@ static inline void kvmppc_enable_logical_ci_hcalls(void) { } +static inline void kvmppc_enable_set_mode_hcall(void) +{ +} + static inline void kvmppc_set_papr(PowerPCCPU *cpu) { } From a8ad731a001d41582c9cec4015f73ab3bc11a28d Mon Sep 17 00:00:00 2001 From: Michael Roth Date: Tue, 15 Sep 2015 16:34:59 -0500 Subject: [PATCH 16/36] spapr_pci: fix device tree props for MSI/MSI-X PAPR requires ibm,req#msi and ibm,req#msi-x to be present in the device node to define the number of msi/msi-x interrupts the device supports, respectively. Currently we have ibm,req#msi-x hardcoded to a non-sensical constant that happens to be 2, and are missing ibm,req#msi entirely. The result of that is that msi-x capable devices get limited to 2 msi-x interrupts (which can impact performance), and msi-only devices likely wouldn't work at all. Additionally, if devices expect a minimum that exceeds 2, the guest driver may fail to load entirely. SLOF still owns the generation of these properties at boot-time (although other device properties have since been offloaded to QEMU), but for hotplugged devices we rely on the values generated by QEMU and thus hit the limitations above. Fix this by generating these properties in QEMU as expected by guests. In the future it may make sense to modify SLOF to pass through these values directly as we do with other props since we're duplicating SLOF code. Cc: qemu-ppc@nongnu.org Cc: qemu-stable@nongnu.org Cc: David Gibson Cc: Nikunj A Dadhania Signed-off-by: Michael Roth Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr_pci.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 54292c9d81..d2188c854d 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -957,6 +957,7 @@ static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset, int pci_status, err; char *buf = NULL; uint32_t drc_index = spapr_phb_get_pci_drc_index(sphb, dev); + uint32_t max_msi, max_msix; if (pci_default_read_config(dev, PCI_HEADER_TYPE, 1) == PCI_HEADER_TYPE_BRIDGE) { @@ -1037,8 +1038,15 @@ static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset, RESOURCE_CELLS_ADDRESS)); _FDT(fdt_setprop_cell(fdt, offset, "#size-cells", RESOURCE_CELLS_SIZE)); - _FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi-x", - RESOURCE_CELLS_SIZE)); + + max_msi = msi_nr_vectors_allocated(dev); + if (max_msi) { + _FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi", max_msi)); + } + max_msix = dev->msix_entries_nr; + if (max_msix) { + _FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi-x", max_msix)); + } populate_resource_props(dev, &rp); _FDT(fdt_setprop(fdt, offset, "reg", (uint8_t *)rp.reg, rp.reg_len)); From 9d1852ce11c888e3ad5096be505d14045d8b49ae Mon Sep 17 00:00:00 2001 From: Michael Roth Date: Thu, 10 Sep 2015 16:11:03 -0500 Subject: [PATCH 17/36] spapr_drc: don't allow 'empty' DRCs to be unisolated or allocated Logical resources start with allocation-state:UNUSABLE / isolation-state:ISOLATED. During hotplug, guests will transition them to allocation-state:USABLE, and then to isolation-state:UNISOLATED. For cases where we cannot transition to allocation-state:USABLE, in this case due to no device/resource being association with the logical DRC, we should return an error -3. For physical DRCs, we default to allocation-state:USABLE and stay there, so in this case we should report an error -3 when the guest attempts to make the isolation-state:ISOLATED transition for a DRC with no device associated. These are as documented in PAPR 2.7, 13.5.3.4. We also ensure allocation-state:USABLE when the guest attempts transition to isolation-state:UNISOLATED to deal with misbehaving guests attempting to bring online an unallocated logical resource. This is as documented in PAPR 2.7, 13.7. Currently we implement no such error logic. Fix this by handling these error cases as PAPR defines. Cc: Bharata B Rao Signed-off-by: Michael Roth Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr_drc.c | 21 +++++++++++++++++++++ include/hw/ppc/spapr.h | 1 + 2 files changed, 22 insertions(+) diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index 9ce844ab1e..faf8760d2e 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -66,6 +66,16 @@ static int set_isolation_state(sPAPRDRConnector *drc, DPRINTFN("drc: %x, set_isolation_state: %x", get_index(drc), state); + if (state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) { + /* cannot unisolate a non-existant resource, and, or resources + * which are in an 'UNUSABLE' allocation state. (PAPR 2.7, 13.5.3.5) + */ + if (!drc->dev || + drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) { + return RTAS_OUT_NO_SUCH_INDICATOR; + } + } + drc->isolation_state = state; if (drc->isolation_state == SPAPR_DR_ISOLATION_STATE_ISOLATED) { @@ -107,6 +117,17 @@ static int set_allocation_state(sPAPRDRConnector *drc, DPRINTFN("drc: %x, set_allocation_state: %x", get_index(drc), state); + if (state == SPAPR_DR_ALLOCATION_STATE_USABLE) { + /* if there's no resource/device associated with the DRC, there's + * no way for us to put it in an allocation state consistent with + * being 'USABLE'. PAPR 2.7, 13.5.3.4 documents that this should + * result in an RTAS return code of -3 / "no such indicator" + */ + if (!drc->dev) { + return RTAS_OUT_NO_SUCH_INDICATOR; + } + } + if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI) { drc->allocation_state = state; if (drc->awaiting_release && diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index cbe3463e32..8a0a74d5d9 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -409,6 +409,7 @@ int spapr_allocate_irq_block(int num, bool lsi, bool msi); #define RTAS_OUT_BUSY -2 #define RTAS_OUT_PARAM_ERROR -3 #define RTAS_OUT_NOT_SUPPORTED -3 +#define RTAS_OUT_NO_SUCH_INDICATOR -3 #define RTAS_OUT_NOT_AUTHORIZED -9002 /* RTAS tokens */ From 4a1c9cf0073e733b421e7b82ad673e7cf6ed8454 Mon Sep 17 00:00:00 2001 From: Bharata B Rao Date: Mon, 29 Jun 2015 14:14:27 +0530 Subject: [PATCH 18/36] spapr: Initialize hotplug memory address space Initialize a hotplug memory region under which all the hotplugged memory is accommodated. Also enable memory hotplug by setting CONFIG_MEM_HOTPLUG. Modelled on i386 memory hotplug. Signed-off-by: Bharata B Rao Reviewed-by: David Gibson Signed-off-by: David Gibson --- default-configs/ppc64-softmmu.mak | 1 + hw/ppc/spapr.c | 18 ++++++++++++++++++ include/hw/ppc/spapr.h | 12 ++++++++++++ 3 files changed, 31 insertions(+) diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak index ab62cc7ff0..e77cb1ac54 100644 --- a/default-configs/ppc64-softmmu.mak +++ b/default-configs/ppc64-softmmu.mak @@ -52,3 +52,4 @@ CONFIG_XICS_KVM=$(and $(CONFIG_PSERIES),$(CONFIG_KVM)) # For PReP CONFIG_MC146818RTC=y CONFIG_ISA_TESTDEV=y +CONFIG_MEM_HOTPLUG=y diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index d49f322fcc..2fb5e3643c 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1562,6 +1562,24 @@ static void ppc_spapr_init(MachineState *machine) memory_region_add_subregion(sysmem, 0, rma_region); } + /* initialize hotplug memory address space */ + if (machine->ram_size < machine->maxram_size) { + ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size; + + if (machine->ram_slots > SPAPR_MAX_RAM_SLOTS) { + error_report("unsupported amount of memory slots: %"PRIu64, + machine->ram_slots); + exit(EXIT_FAILURE); + } + + spapr->hotplug_memory.base = ROUND_UP(machine->ram_size, + SPAPR_HOTPLUG_MEM_ALIGN); + memory_region_init(&spapr->hotplug_memory.mr, OBJECT(spapr), + "hotplug-memory", hotplug_mem_size); + memory_region_add_subregion(sysmem, spapr->hotplug_memory.base, + &spapr->hotplug_memory.mr); + } + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin"); if (!filename) { error_report("Could not find LPAR rtas '%s'", "spapr-rtas.bin"); diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 8a0a74d5d9..e882770db7 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -5,6 +5,7 @@ #include "hw/boards.h" #include "hw/ppc/xics.h" #include "hw/ppc/spapr_drc.h" +#include "hw/mem/pc-dimm.h" struct VIOsPAPRBus; struct sPAPRPHBState; @@ -76,6 +77,7 @@ struct sPAPRMachineState { /*< public >*/ char *kvm_type; + MemoryHotplugState hotplug_memory; }; #define H_SUCCESS 0 @@ -610,4 +612,14 @@ int spapr_rtc_import_offset(DeviceState *dev, int64_t legacy_offset); #define SPAPR_MEMORY_BLOCK_SIZE (1 << 28) /* 256MB */ +/* + * This defines the maximum number of DIMM slots we can have for sPAPR + * guest. This is not defined by sPAPR but we are defining it to 32 slots + * based on default number of slots provided by PowerPC kernel. + */ +#define SPAPR_MAX_RAM_SLOTS 32 + +/* 1GB alignment for hotplug memory region */ +#define SPAPR_HOTPLUG_MEM_ALIGN (1ULL << 30) + #endif /* !defined (__HW_SPAPR_H__) */ From 0cb688d22b3941af02fee78ba21dc3a39c367e0b Mon Sep 17 00:00:00 2001 From: Michael Roth Date: Thu, 10 Sep 2015 16:11:02 -0500 Subject: [PATCH 19/36] spapr_drc: use RTAS return codes for methods called by RTAS Certain methods in sPAPRDRConnector objects are only ever called by RTAS and in many cases are responsible for the logic that determines the RTAS return codes. Rather than having a level of indirection requiring RTAS code to re-interpret return values from such methods to determine the appropriate return code, just pass them through directly. This requires changing method return types to uint32_t to match the type of values currently passed to RTAS helpers. In the case of read accesses like drc->entity_sense() where we weren't previously reporting any errors, just the read value, we modify the function to return RTAS return code, and pass the read value back via reference. Suggested-by: Bharata B Rao Suggested-by: David Gibson Cc: Bharata B Rao Signed-off-by: Michael Roth Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr_drc.c | 37 ++++++++++++++++++----------------- hw/ppc/spapr_rtas.c | 40 +++++++++++++++++++++----------------- include/hw/ppc/spapr_drc.h | 14 ++++++------- 3 files changed, 48 insertions(+), 43 deletions(-) diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index faf8760d2e..b7b9891714 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -15,6 +15,7 @@ #include "hw/qdev.h" #include "qapi/visitor.h" #include "qemu/error-report.h" +#include "hw/ppc/spapr.h" /* for RTAS return codes */ /* #define DEBUG_SPAPR_DRC */ @@ -59,8 +60,8 @@ static uint32_t get_index(sPAPRDRConnector *drc) (drc->id & DRC_INDEX_ID_MASK); } -static int set_isolation_state(sPAPRDRConnector *drc, - sPAPRDRIsolationState state) +static uint32_t set_isolation_state(sPAPRDRConnector *drc, + sPAPRDRIsolationState state) { sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); @@ -99,19 +100,19 @@ static int set_isolation_state(sPAPRDRConnector *drc, drc->configured = false; } - return 0; + return RTAS_OUT_SUCCESS; } -static int set_indicator_state(sPAPRDRConnector *drc, - sPAPRDRIndicatorState state) +static uint32_t set_indicator_state(sPAPRDRConnector *drc, + sPAPRDRIndicatorState state) { DPRINTFN("drc: %x, set_indicator_state: %x", get_index(drc), state); drc->indicator_state = state; - return 0; + return RTAS_OUT_SUCCESS; } -static int set_allocation_state(sPAPRDRConnector *drc, - sPAPRDRAllocationState state) +static uint32_t set_allocation_state(sPAPRDRConnector *drc, + sPAPRDRAllocationState state) { sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); @@ -137,7 +138,7 @@ static int set_allocation_state(sPAPRDRConnector *drc, drc->detach_cb_opaque, NULL); } } - return 0; + return RTAS_OUT_SUCCESS; } static uint32_t get_type(sPAPRDRConnector *drc) @@ -178,10 +179,8 @@ static void set_configured(sPAPRDRConnector *drc) * based on the current allocation/indicator/power states * for the DR connector. */ -static sPAPRDREntitySense entity_sense(sPAPRDRConnector *drc) +static uint32_t entity_sense(sPAPRDRConnector *drc, sPAPRDREntitySense *state) { - sPAPRDREntitySense state; - if (drc->dev) { if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI && drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) { @@ -190,7 +189,7 @@ static sPAPRDREntitySense entity_sense(sPAPRDRConnector *drc) * Otherwise, report the state as USABLE/PRESENT, * as we would for PCI. */ - state = SPAPR_DR_ENTITY_SENSE_UNUSABLE; + *state = SPAPR_DR_ENTITY_SENSE_UNUSABLE; } else { /* this assumes all PCI devices are assigned to * a 'live insertion' power domain, where QEMU @@ -198,21 +197,21 @@ static sPAPRDREntitySense entity_sense(sPAPRDRConnector *drc) * to the guest. present, non-PCI resources are * unaffected by power state. */ - state = SPAPR_DR_ENTITY_SENSE_PRESENT; + *state = SPAPR_DR_ENTITY_SENSE_PRESENT; } } else { if (drc->type == SPAPR_DR_CONNECTOR_TYPE_PCI) { /* PCI devices, and only PCI devices, use EMPTY * in cases where we'd otherwise use UNUSABLE */ - state = SPAPR_DR_ENTITY_SENSE_EMPTY; + *state = SPAPR_DR_ENTITY_SENSE_EMPTY; } else { - state = SPAPR_DR_ENTITY_SENSE_UNUSABLE; + *state = SPAPR_DR_ENTITY_SENSE_UNUSABLE; } } DPRINTFN("drc: %x, entity_sense: %x", get_index(drc), state); - return state; + return RTAS_OUT_SUCCESS; } static void prop_get_index(Object *obj, Visitor *v, void *opaque, @@ -245,7 +244,9 @@ static void prop_get_entity_sense(Object *obj, Visitor *v, void *opaque, { sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj); sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - uint32_t value = (uint32_t)drck->entity_sense(drc); + uint32_t value; + + drck->entity_sense(drc, &value); visit_type_uint32(v, &value, name, errp); } diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index 2f8e25cfb2..34b12a3b99 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -372,12 +372,13 @@ static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr, uint32_t sensor_type; uint32_t sensor_index; uint32_t sensor_state; + uint32_t ret = RTAS_OUT_SUCCESS; sPAPRDRConnector *drc; sPAPRDRConnectorClass *drck; if (nargs != 3 || nret != 1) { - rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); - return; + ret = RTAS_OUT_PARAM_ERROR; + goto out; } sensor_type = rtas_ld(args, 0); @@ -393,8 +394,8 @@ static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr, if (!drc) { DPRINTF("rtas_set_indicator: invalid sensor/DRC index: %xh\n", sensor_index); - rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); - return; + ret = RTAS_OUT_PARAM_ERROR; + goto out; } drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); @@ -413,19 +414,20 @@ static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr, spapr_ccs_remove(spapr, ccs); } } - drck->set_isolation_state(drc, sensor_state); + ret = drck->set_isolation_state(drc, sensor_state); break; case RTAS_SENSOR_TYPE_DR: - drck->set_indicator_state(drc, sensor_state); + ret = drck->set_indicator_state(drc, sensor_state); break; case RTAS_SENSOR_TYPE_ALLOCATION_STATE: - drck->set_allocation_state(drc, sensor_state); + ret = drck->set_allocation_state(drc, sensor_state); break; default: goto out_unimplemented; } - rtas_st(rets, 0, RTAS_OUT_SUCCESS); +out: + rtas_st(rets, 0, ret); return; out_unimplemented: @@ -442,13 +444,14 @@ static void rtas_get_sensor_state(PowerPCCPU *cpu, sPAPRMachineState *spapr, { uint32_t sensor_type; uint32_t sensor_index; + uint32_t sensor_state = 0; sPAPRDRConnector *drc; sPAPRDRConnectorClass *drck; - uint32_t entity_sense; + uint32_t ret = RTAS_OUT_SUCCESS; if (nargs != 2 || nret != 2) { - rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); - return; + ret = RTAS_OUT_PARAM_ERROR; + goto out; } sensor_type = rtas_ld(args, 0); @@ -458,22 +461,23 @@ static void rtas_get_sensor_state(PowerPCCPU *cpu, sPAPRMachineState *spapr, /* currently only DR-related sensors are implemented */ DPRINTF("rtas_get_sensor_state: sensor/indicator not implemented: %d\n", sensor_type); - rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED); - return; + ret = RTAS_OUT_NOT_SUPPORTED; + goto out; } drc = spapr_dr_connector_by_index(sensor_index); if (!drc) { DPRINTF("rtas_get_sensor_state: invalid sensor/DRC index: %xh\n", sensor_index); - rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); - return; + ret = RTAS_OUT_PARAM_ERROR; + goto out; } drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - entity_sense = drck->entity_sense(drc); + ret = drck->entity_sense(drc, &sensor_state); - rtas_st(rets, 0, RTAS_OUT_SUCCESS); - rtas_st(rets, 1, entity_sense); +out: + rtas_st(rets, 0, ret); + rtas_st(rets, 1, sensor_state); } /* configure-connector work area offsets, int32_t units for field diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h index 28ffeaeb1c..7e5634772c 100644 --- a/include/hw/ppc/spapr_drc.h +++ b/include/hw/ppc/spapr_drc.h @@ -165,17 +165,17 @@ typedef struct sPAPRDRConnectorClass { /*< public >*/ /* accessors for guest-visible (generally via RTAS) DR state */ - int (*set_isolation_state)(sPAPRDRConnector *drc, - sPAPRDRIsolationState state); - int (*set_indicator_state)(sPAPRDRConnector *drc, - sPAPRDRIndicatorState state); - int (*set_allocation_state)(sPAPRDRConnector *drc, - sPAPRDRAllocationState state); + uint32_t (*set_isolation_state)(sPAPRDRConnector *drc, + sPAPRDRIsolationState state); + uint32_t (*set_indicator_state)(sPAPRDRConnector *drc, + sPAPRDRIndicatorState state); + uint32_t (*set_allocation_state)(sPAPRDRConnector *drc, + sPAPRDRAllocationState state); uint32_t (*get_index)(sPAPRDRConnector *drc); uint32_t (*get_type)(sPAPRDRConnector *drc); const char *(*get_name)(sPAPRDRConnector *drc); - sPAPRDREntitySense (*entity_sense)(sPAPRDRConnector *drc); + uint32_t (*entity_sense)(sPAPRDRConnector *drc, sPAPRDREntitySense *state); /* QEMU interfaces for managing FDT/configure-connector */ const void *(*get_fdt)(sPAPRDRConnector *drc, int *fdt_start_offset); From 94649d423e4647fca3bc3e8b2b363d6d2adee9ce Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 16 Sep 2015 16:57:51 +1000 Subject: [PATCH 20/36] spapr: Don't use QOM [*] syntax for DR connectors. The dynamic reconfiguration (hotplug) code for the pseries machine type uses a "DR connector" QOM object for each resource it will be possible to hotplug. Each of these is added to its owner using object_property_add_child(owner, "dr-connector[*], ...); That works ok, mostly, but it means that the property indices are arbitrary, depending on the order in which the connectors are constructed. That might line up to something useful, but it doesn't have to. It will get worse once we add hotplug RAM support. That will add a DR connector object for every 256MB of potential memory. So if maxmem=2T, for example, there are 8192 objects under the same parent. The QOM interfaces aren't really designed for this. In particular object_property_add() with [*] has O(n^2) time complexity (in the number of existing children): first it has a linear search through array indices to find a free slot, each of which is attempted to a recursive call to object_property_add() with a specific [N]. Those calls are O(n) because there's a linear search through all properties to check for duplicates. By using a meaningful index value, which we already know is unique we can avoid the [*] special behaviour. That lets us reduce the total time for creating the DR objects from O(n^3) to O(n^2). O(n^2) is still kind of crappy, but it's enough to reduce the startup time of qemu (with in-progress memory hotplug support) with maxmem=2T from ~20 minutes to ~4 seconds. Signed-off-by: David Gibson Cc: Bharata B Rao Tested-by: Bharata B Rao Reviewed-by: Alexey Kardashevskiy --- hw/ppc/spapr_drc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index b7b9891714..5d6ea7ce41 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -473,14 +473,17 @@ sPAPRDRConnector *spapr_dr_connector_new(Object *owner, { sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(object_new(TYPE_SPAPR_DR_CONNECTOR)); + char *prop_name; g_assert(type); drc->type = type; drc->id = id; drc->owner = owner; - object_property_add_child(owner, "dr-connector[*]", OBJECT(drc), NULL); + prop_name = g_strdup_printf("dr-connector[%"PRIu32"]", get_index(drc)); + object_property_add_child(owner, prop_name, OBJECT(drc), NULL); object_property_set_bool(OBJECT(drc), true, "realized", NULL); + g_free(prop_name); /* human-readable name for a DRC to encode into the DT * description. this is mainly only used within a guest in place From 38b02bd846672f33bc2eabcb9847c4b78069e097 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Thu, 6 Aug 2015 13:37:24 +1000 Subject: [PATCH 21/36] spapr: Use QEMU limit for maximum CPUs number sPAPR uses hard coded limit of maximum 255 supported CPUs which is exactly the same as QEMU-wide limit which is MAX_CPUMASK_BITS and also defined as 255. This makes use of a global CPU number limit for the "pseries" machine. In order to anticipate future increase of the MAX_CPUMASK_BITS (or to help debugging large systems), this also bumps the FDT_MAX_SIZE limit from 256K to 1M assuming that 1 CPU core needs roughly 512 bytes in the device tree so the new limit can cover up to 2048 CPU cores. Signed-off-by: Alexey Kardashevskiy Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 2fb5e3643c..33e22cea65 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -74,7 +74,7 @@ * * We load our kernel at 4M, leaving space for SLOF initial image */ -#define FDT_MAX_SIZE 0x40000 +#define FDT_MAX_SIZE 0x100000 #define RTAS_MAX_SIZE 0x10000 #define RTAS_MAX_ADDR 0x80000000 /* RTAS must stay below that */ #define FW_MAX_SIZE 0x400000 @@ -86,8 +86,6 @@ #define TIMEBASE_FREQ 512000000ULL -#define MAX_CPUS 255 - #define PHANDLE_XICP 0x00001111 #define HTAB_SIZE(spapr) (1ULL << ((spapr)->htab_shift)) @@ -1859,7 +1857,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) mc->init = ppc_spapr_init; mc->reset = ppc_spapr_reset; mc->block_default_type = IF_SCSI; - mc->max_cpus = MAX_CPUS; + mc->max_cpus = MAX_CPUMASK_BITS; mc->no_parallel = 1; mc->default_boot_order = ""; mc->default_ram_size = 512 * M_BYTE; From 224245bf524189789d231f38434c9f8fd57a249c Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 12 Aug 2015 13:16:48 +1000 Subject: [PATCH 22/36] spapr: Add LMB DR connectors Enable memory hotplug for pseries 2.4 and add LMB DR connectors. With memory hotplug, enforce RAM size, NUMA node memory size and maxmem to be a multiple of SPAPR_MEMORY_BLOCK_SIZE (256M) since that's the granularity in which LMBs are represented and hot-added. LMB DR connectors will be used by the memory hotplug code. Signed-off-by: Bharata B Rao Signed-off-by: Michael Roth [spapr_drc_reset implementation] [since this missed the 2.4 cutoff, changing to only enable for 2.5] Signed-off-by: David Gibson --- hw/ppc/spapr.c | 87 ++++++++++++++++++++++++++++++++++++++++++ include/hw/ppc/spapr.h | 1 + 2 files changed, 88 insertions(+) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 33e22cea65..940a82fc71 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -61,6 +61,7 @@ #include "hw/nmi.h" #include "hw/compat.h" +#include "qemu-common.h" #include @@ -1446,10 +1447,84 @@ static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu) qemu_register_reset(spapr_cpu_reset, cpu); } +/* + * Reset routine for LMB DR devices. + * + * Unlike PCI DR devices, LMB DR devices explicitly register this reset + * routine. Reset for PCI DR devices will be handled by PHB reset routine + * when it walks all its children devices. LMB devices reset occurs + * as part of spapr_ppc_reset(). + */ +static void spapr_drc_reset(void *opaque) +{ + sPAPRDRConnector *drc = opaque; + DeviceState *d = DEVICE(drc); + + if (d) { + device_reset(d); + } +} + +static void spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr) +{ + MachineState *machine = MACHINE(spapr); + uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; + uint32_t nr_rma_lmbs = spapr->rma_size/lmb_size; + uint32_t nr_lmbs = machine->maxram_size/lmb_size - nr_rma_lmbs; + uint32_t nr_assigned_lmbs = machine->ram_size/lmb_size - nr_rma_lmbs; + int i; + + for (i = 0; i < nr_lmbs; i++) { + sPAPRDRConnector *drc; + uint64_t addr; + + if (i < nr_assigned_lmbs) { + addr = (i + nr_rma_lmbs) * lmb_size; + } else { + addr = (i - nr_assigned_lmbs) * lmb_size + + spapr->hotplug_memory.base; + } + drc = spapr_dr_connector_new(OBJECT(spapr), SPAPR_DR_CONNECTOR_TYPE_LMB, + addr/lmb_size); + qemu_register_reset(spapr_drc_reset, drc); + } +} + +/* + * If RAM size, maxmem size and individual node mem sizes aren't aligned + * to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest + * since we can't support such unaligned sizes with DRCONF_MEMORY. + */ +static void spapr_validate_node_memory(MachineState *machine) +{ + int i; + + if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE || + machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) { + error_report("Can't support memory configuration where RAM size " + "0x" RAM_ADDR_FMT " or maxmem size " + "0x" RAM_ADDR_FMT " isn't aligned to %llu MB", + machine->ram_size, machine->maxram_size, + SPAPR_MEMORY_BLOCK_SIZE/M_BYTE); + exit(EXIT_FAILURE); + } + + for (i = 0; i < nb_numa_nodes; i++) { + if (numa_info[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) { + error_report("Can't support memory configuration where memory size" + " %" PRIx64 " of node %d isn't aligned to %llu MB", + numa_info[i].node_mem, i, + SPAPR_MEMORY_BLOCK_SIZE/M_BYTE); + exit(EXIT_FAILURE); + } + } +} + /* pSeries LPAR / sPAPR hardware init */ static void ppc_spapr_init(MachineState *machine) { sPAPRMachineState *spapr = SPAPR_MACHINE(machine); + sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *initrd_filename = machine->initrd_filename; @@ -1528,6 +1603,10 @@ static void ppc_spapr_init(MachineState *machine) smp_threads), XICS_IRQS); + if (smc->dr_lmb_enabled) { + spapr_validate_node_memory(machine); + } + /* init CPUs */ if (machine->cpu_model == NULL) { machine->cpu_model = kvm_enabled() ? "host" : "POWER7"; @@ -1578,6 +1657,10 @@ static void ppc_spapr_init(MachineState *machine) &spapr->hotplug_memory.mr); } + if (smc->dr_lmb_enabled) { + spapr_create_lmb_dr_connectors(spapr); + } + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin"); if (!filename) { error_report("Could not find LPAR rtas '%s'", "spapr-rtas.bin"); @@ -1851,6 +1934,7 @@ static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) static void spapr_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); + sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(oc); FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); NMIClass *nc = NMI_CLASS(oc); @@ -1865,6 +1949,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) mc->has_dynamic_sysbus = true; mc->pci_allow_0_address = true; + smc->dr_lmb_enabled = false; fwc->get_dev_path = spapr_get_fw_dev_path; nc->nmi_monitor_handler = spapr_nmi; } @@ -2014,11 +2099,13 @@ static const TypeInfo spapr_machine_2_4_info = { static void spapr_machine_2_5_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); + sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(oc); mc->name = "pseries-2.5"; mc->desc = "pSeries Logical Partition (PAPR compliant) v2.5"; mc->alias = "pseries"; mc->is_default = 1; + smc->dr_lmb_enabled = true; } static const TypeInfo spapr_machine_2_5_info = { diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index e882770db7..5de54d4a93 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -35,6 +35,7 @@ struct sPAPRMachineClass { MachineClass parent_class; /*< public >*/ + bool dr_lmb_enabled; /* enable dynamic-reconfig/hotplug of LMBs */ }; /** From 03d196b7c57f22f796197f221f9d95336debee9e Mon Sep 17 00:00:00 2001 From: Bharata B Rao Date: Mon, 13 Jul 2015 10:34:00 +1000 Subject: [PATCH 23/36] spapr: Support ibm,dynamic-reconfiguration-memory Parse ibm,architecture.vec table obtained from the guest and enable memory node configuration via ibm,dynamic-reconfiguration-memory if guest supports it. This is in preparation to support memory hotplug for sPAPR guests. This changes the way memory node configuration is done. Currently all memory nodes are built upfront. But after this patch, only memory@0 node for RMA is built upfront. Guest kernel boots with just that and rest of the memory nodes (via memory@XXX or ibm,dynamic-reconfiguration-memory) are built when guest does ibm,client-architecture-support call. Note: This patch needs a SLOF enhancement which is already part of SLOF binary in QEMU. Signed-off-by: Bharata B Rao Reviewed-by: David Gibson Signed-off-by: David Gibson --- docs/specs/ppc-spapr-hotplug.txt | 48 +++++++ hw/ppc/spapr.c | 210 ++++++++++++++++++++++++------- hw/ppc/spapr_hcall.c | 51 +++++++- include/hw/ppc/spapr.h | 15 ++- 4 files changed, 274 insertions(+), 50 deletions(-) diff --git a/docs/specs/ppc-spapr-hotplug.txt b/docs/specs/ppc-spapr-hotplug.txt index 46e07196bb..631b0cadae 100644 --- a/docs/specs/ppc-spapr-hotplug.txt +++ b/docs/specs/ppc-spapr-hotplug.txt @@ -302,4 +302,52 @@ consisting of , and . pseries guests use this property to note the maximum allowed CPUs for the guest. +== ibm,dynamic-reconfiguration-memory == + +ibm,dynamic-reconfiguration-memory is a device tree node that represents +dynamically reconfigurable logical memory blocks (LMB). This node +is generated only when the guest advertises the support for it via +ibm,client-architecture-support call. Memory that is not dynamically +reconfigurable is represented by /memory nodes. The properties of this +node that are of interest to the sPAPR memory hotplug implementation +in QEMU are described here. + +ibm,lmb-size + +This 64bit integer defines the size of each dynamically reconfigurable LMB. + +ibm,associativity-lookup-arrays + +This property defines a lookup array in which the NUMA associativity +information for each LMB can be found. It is a property encoded array +that begins with an integer M, the number of associativity lists followed +by an integer N, the number of entries per associativity list and terminated +by M associativity lists each of length N integers. + +This property provides the same information as given by ibm,associativity +property in a /memory node. Each assigned LMB has an index value between +0 and M-1 which is used as an index into this table to select which +associativity list to use for the LMB. This index value for each LMB +is defined in ibm,dynamic-memory property. + +ibm,dynamic-memory + +This property describes the dynamically reconfigurable memory. It is a +property encoded array that has an integer N, the number of LMBs followed +by N LMB list entires. + +Each LMB list entry consists of the following elements: + +- Logical address of the start of the LMB encoded as a 64bit integer. This + corresponds to reg property in /memory node. +- DRC index of the LMB that corresponds to ibm,my-drc-index property + in a /memory node. +- Four bytes reserved for expansion. +- Associativity list index for the LMB that is used as an index into + ibm,associativity-lookup-arrays property described earlier. This + is used to retrieve the right associativity list to be used for this + LMB. +- A 32bit flags word. The bit at bit position 0x00000008 defines whether + the LMB is assigned to the the partition as of boot time. + [1] http://thread.gmane.org/gmane.linux.ports.ppc.embedded/75350/focus=106867 diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 940a82fc71..2f49f97924 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -504,44 +504,7 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base, return fdt; } -int spapr_h_cas_compose_response(sPAPRMachineState *spapr, - target_ulong addr, target_ulong size) -{ - void *fdt, *fdt_skel; - sPAPRDeviceTreeUpdateHeader hdr = { .version_id = 1 }; - - size -= sizeof(hdr); - - /* Create sceleton */ - fdt_skel = g_malloc0(size); - _FDT((fdt_create(fdt_skel, size))); - _FDT((fdt_begin_node(fdt_skel, ""))); - _FDT((fdt_end_node(fdt_skel))); - _FDT((fdt_finish(fdt_skel))); - fdt = g_malloc0(size); - _FDT((fdt_open_into(fdt_skel, fdt, size))); - g_free(fdt_skel); - - /* Fix skeleton up */ - _FDT((spapr_fixup_cpu_dt(fdt, spapr))); - - /* Pack resulting tree */ - _FDT((fdt_pack(fdt))); - - if (fdt_totalsize(fdt) + sizeof(hdr) > size) { - trace_spapr_cas_failed(size); - return -1; - } - - cpu_physical_memory_write(addr, &hdr, sizeof(hdr)); - cpu_physical_memory_write(addr + sizeof(hdr), fdt, fdt_totalsize(fdt)); - trace_spapr_cas_continue(fdt_totalsize(fdt) + sizeof(hdr)); - g_free(fdt); - - return 0; -} - -static void spapr_populate_memory_node(void *fdt, int nodeid, hwaddr start, +static int spapr_populate_memory_node(void *fdt, int nodeid, hwaddr start, hwaddr size) { uint32_t associativity[] = { @@ -564,6 +527,7 @@ static void spapr_populate_memory_node(void *fdt, int nodeid, hwaddr start, sizeof(mem_reg_property)))); _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity, sizeof(associativity)))); + return off; } static int spapr_populate_memory(sPAPRMachineState *spapr, void *fdt) @@ -595,7 +559,6 @@ static int spapr_populate_memory(sPAPRMachineState *spapr, void *fdt) } if (!mem_start) { /* ppc_spapr_init() checks for rma_size <= node0_size already */ - spapr_populate_memory_node(fdt, i, 0, spapr->rma_size); mem_start += spapr->rma_size; node_size -= spapr->rma_size; } @@ -745,6 +708,154 @@ static void spapr_populate_cpus_dt_node(void *fdt, sPAPRMachineState *spapr) } +/* + * Adds ibm,dynamic-reconfiguration-memory node. + * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation + * of this device tree node. + */ +static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) +{ + MachineState *machine = MACHINE(spapr); + int ret, i, offset; + uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; + uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)}; + uint32_t nr_rma_lmbs = spapr->rma_size/lmb_size; + uint32_t nr_lmbs = machine->maxram_size/lmb_size - nr_rma_lmbs; + uint32_t nr_assigned_lmbs = machine->ram_size/lmb_size - nr_rma_lmbs; + uint32_t *int_buf, *cur_index, buf_len; + + /* Allocate enough buffer size to fit in ibm,dynamic-memory */ + buf_len = nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE * sizeof(uint32_t) + + sizeof(uint32_t); + cur_index = int_buf = g_malloc0(buf_len); + + offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory"); + + ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size, + sizeof(prop_lmb_size)); + if (ret < 0) { + goto out; + } + + ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff); + if (ret < 0) { + goto out; + } + + ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0); + if (ret < 0) { + goto out; + } + + /* ibm,dynamic-memory */ + int_buf[0] = cpu_to_be32(nr_lmbs); + cur_index++; + for (i = 0; i < nr_lmbs; i++) { + sPAPRDRConnector *drc; + sPAPRDRConnectorClass *drck; + uint64_t addr; + uint32_t *dynamic_memory = cur_index; + + if (i < nr_assigned_lmbs) { + addr = (i + nr_rma_lmbs) * lmb_size; + } else { + addr = (i - nr_assigned_lmbs) * lmb_size + + spapr->hotplug_memory.base; + } + drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, + addr/lmb_size); + g_assert(drc); + drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + + dynamic_memory[0] = cpu_to_be32(addr >> 32); + dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); + dynamic_memory[2] = cpu_to_be32(drck->get_index(drc)); + dynamic_memory[3] = cpu_to_be32(0); /* reserved */ + dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL)); + if (addr < machine->ram_size || + memory_region_present(get_system_memory(), addr)) { + dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED); + } else { + dynamic_memory[5] = cpu_to_be32(0); + } + + cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE; + } + ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len); + if (ret < 0) { + goto out; + } + + /* ibm,associativity-lookup-arrays */ + cur_index = int_buf; + int_buf[0] = cpu_to_be32(nb_numa_nodes); + int_buf[1] = cpu_to_be32(4); /* Number of entries per associativity list */ + cur_index += 2; + for (i = 0; i < nb_numa_nodes; i++) { + uint32_t associativity[] = { + cpu_to_be32(0x0), + cpu_to_be32(0x0), + cpu_to_be32(0x0), + cpu_to_be32(i) + }; + memcpy(cur_index, associativity, sizeof(associativity)); + cur_index += 4; + } + ret = fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays", int_buf, + (cur_index - int_buf) * sizeof(uint32_t)); +out: + g_free(int_buf); + return ret; +} + +int spapr_h_cas_compose_response(sPAPRMachineState *spapr, + target_ulong addr, target_ulong size, + bool cpu_update, bool memory_update) +{ + void *fdt, *fdt_skel; + sPAPRDeviceTreeUpdateHeader hdr = { .version_id = 1 }; + sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine()); + + size -= sizeof(hdr); + + /* Create sceleton */ + fdt_skel = g_malloc0(size); + _FDT((fdt_create(fdt_skel, size))); + _FDT((fdt_begin_node(fdt_skel, ""))); + _FDT((fdt_end_node(fdt_skel))); + _FDT((fdt_finish(fdt_skel))); + fdt = g_malloc0(size); + _FDT((fdt_open_into(fdt_skel, fdt, size))); + g_free(fdt_skel); + + /* Fixup cpu nodes */ + if (cpu_update) { + _FDT((spapr_fixup_cpu_dt(fdt, spapr))); + } + + /* Generate memory nodes or ibm,dynamic-reconfiguration-memory node */ + if (memory_update && smc->dr_lmb_enabled) { + _FDT((spapr_populate_drconf_memory(spapr, fdt))); + } else { + _FDT((spapr_populate_memory(spapr, fdt))); + } + + /* Pack resulting tree */ + _FDT((fdt_pack(fdt))); + + if (fdt_totalsize(fdt) + sizeof(hdr) > size) { + trace_spapr_cas_failed(size); + return -1; + } + + cpu_physical_memory_write(addr, &hdr, sizeof(hdr)); + cpu_physical_memory_write(addr + sizeof(hdr), fdt, fdt_totalsize(fdt)); + trace_spapr_cas_continue(fdt_totalsize(fdt) + sizeof(hdr)); + g_free(fdt); + + return 0; +} + static void spapr_finalize_fdt(sPAPRMachineState *spapr, hwaddr fdt_addr, hwaddr rtas_addr, @@ -763,10 +874,23 @@ static void spapr_finalize_fdt(sPAPRMachineState *spapr, /* open out the base tree into a temp buffer for the final tweaks */ _FDT((fdt_open_into(spapr->fdt_skel, fdt, FDT_MAX_SIZE))); - ret = spapr_populate_memory(spapr, fdt); - if (ret < 0) { - fprintf(stderr, "couldn't setup memory nodes in fdt\n"); - exit(1); + /* + * Add memory@0 node to represent RMA. Rest of the memory is either + * represented by memory nodes or ibm,dynamic-reconfiguration-memory + * node later during ibm,client-architecture-support call. + * + * If NUMA is configured, ensure that memory@0 ends up in the + * first memory-less node. + */ + if (nb_numa_nodes) { + for (i = 0; i < nb_numa_nodes; ++i) { + if (numa_info[i].node_mem) { + spapr_populate_memory_node(fdt, i, 0, spapr->rma_size); + break; + } + } + } else { + spapr_populate_memory_node(fdt, 0, 0, spapr->rma_size); } ret = spapr_populate_vdevice(spapr->vio_bus, fdt); diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 71fc9f23a1..cebceea69b 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -808,6 +808,32 @@ static target_ulong h_set_mode(PowerPCCPU *cpu, sPAPRMachineState *spapr, return ret; } +/* + * Return the offset to the requested option vector @vector in the + * option vector table @table. + */ +static target_ulong cas_get_option_vector(int vector, target_ulong table) +{ + int i; + char nr_vectors, nr_entries; + + if (!table) { + return 0; + } + + nr_vectors = (ldl_phys(&address_space_memory, table) >> 24) + 1; + if (!vector || vector > nr_vectors) { + return 0; + } + table++; /* skip nr option vectors */ + + for (i = 0; i < vector - 1; i++) { + nr_entries = ldl_phys(&address_space_memory, table) >> 24; + table += nr_entries + 2; + } + return table; +} + typedef struct { PowerPCCPU *cpu; uint32_t cpu_version; @@ -828,19 +854,22 @@ static void do_set_compat(void *arg) ((cpuver) == CPU_POWERPC_LOGICAL_2_06_PLUS) ? 2061 : \ ((cpuver) == CPU_POWERPC_LOGICAL_2_07) ? 2070 : 0) +#define OV5_DRCONF_MEMORY 0x20 + static target_ulong h_client_architecture_support(PowerPCCPU *cpu_, sPAPRMachineState *spapr, target_ulong opcode, target_ulong *args) { - target_ulong list = args[0]; + target_ulong list = args[0], ov_table; PowerPCCPUClass *pcc_ = POWERPC_CPU_GET_CLASS(cpu_); CPUState *cs; - bool cpu_match = false; + bool cpu_match = false, cpu_update = true, memory_update = false; unsigned old_cpu_version = cpu_->cpu_version; unsigned compat_lvl = 0, cpu_version = 0; unsigned max_lvl = get_compat_level(cpu_->max_compat); int counter; + char ov5_byte2; /* Parse PVR list */ for (counter = 0; counter < 512; ++counter) { @@ -890,8 +919,6 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_, } } - /* For the future use: here @list points to the first capability */ - /* Parsing finished */ trace_spapr_cas_pvr(cpu_->cpu_version, cpu_match, cpu_version, pcc_->pcr_mask); @@ -915,14 +942,26 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_, } if (!cpu_version) { - return H_SUCCESS; + cpu_update = false; } + /* For the future use: here @ov_table points to the first option vector */ + ov_table = list; + + list = cas_get_option_vector(5, ov_table); if (!list) { return H_SUCCESS; } - if (spapr_h_cas_compose_response(spapr, args[1], args[2])) { + /* @list now points to OV 5 */ + list += 2; + ov5_byte2 = rtas_ld(list, 0) >> 24; + if (ov5_byte2 & OV5_DRCONF_MEMORY) { + memory_update = true; + } + + if (spapr_h_cas_compose_response(spapr, args[1], args[2], + cpu_update, memory_update)) { qemu_system_reset_request(); } diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 5de54d4a93..7d20798276 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -581,7 +581,8 @@ struct sPAPREventLogEntry { void spapr_events_init(sPAPRMachineState *sm); void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq); int spapr_h_cas_compose_response(sPAPRMachineState *sm, - target_ulong addr, target_ulong size); + target_ulong addr, target_ulong size, + bool cpu_update, bool memory_update); sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn, uint64_t bus_offset, uint32_t page_shift, @@ -623,4 +624,16 @@ int spapr_rtc_import_offset(DeviceState *dev, int64_t legacy_offset); /* 1GB alignment for hotplug memory region */ #define SPAPR_HOTPLUG_MEM_ALIGN (1ULL << 30) +/* + * Number of 32 bit words in each LMB list entry in ibm,dynamic-memory + * property under ibm,dynamic-reconfiguration-memory node. + */ +#define SPAPR_DR_LMB_LIST_ENTRY_SIZE 6 + +/* + * This flag value defines the LMB as assigned in ibm,dynamic-memory + * property under ibm,dynamic-reconfiguration-memory node. + */ +#define SPAPR_LMB_FLAGS_ASSIGNED 0x00000008 + #endif /* !defined (__HW_SPAPR_H__) */ From ce881f774d69d941eb999c25f0cb1f72cd228795 Mon Sep 17 00:00:00 2001 From: Bharata B Rao Date: Mon, 29 Jun 2015 14:14:30 +0530 Subject: [PATCH 24/36] spapr: Make hash table size a factor of maxram_size The hash table size is dependent on ram_size, but since with hotplug the memory can grow till maxram_size. Hence make hash table size dependent on maxram_size. This allows to hotplug huge amounts of memory to the guest. Signed-off-by: Bharata B Rao Reviewed-by: David Gibson Signed-off-by: David Gibson --- 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 2f49f97924..d21e95cf6b 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1715,7 +1715,7 @@ static void ppc_spapr_init(MachineState *machine) * more than needed for the Linux guests we support. */ spapr->htab_shift = 18; /* Minimum architected size */ while (spapr->htab_shift <= 46) { - if ((1ULL << (spapr->htab_shift + 7)) >= machine->ram_size) { + if ((1ULL << (spapr->htab_shift + 7)) >= machine->maxram_size) { break; } spapr->htab_shift++; From c20d332a85c95245e3b720bfea1bd02e3a311463 Mon Sep 17 00:00:00 2001 From: Bharata B Rao Date: Tue, 1 Sep 2015 11:22:35 +1000 Subject: [PATCH 25/36] spapr: Memory hotplug support Make use of pc-dimm infrastructure to support memory hotplug for PowerPC. Signed-off-by: Bharata B Rao Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr.c | 118 ++++++++++++++++++++++++++++++++++++++++++ hw/ppc/spapr_events.c | 8 +-- 2 files changed, 123 insertions(+), 3 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index d21e95cf6b..5b462290a5 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -34,6 +34,7 @@ #include "sysemu/block-backend.h" #include "sysemu/cpus.h" #include "sysemu/kvm.h" +#include "sysemu/device_tree.h" #include "kvm_ppc.h" #include "migration/migration.h" #include "mmu-hash64.h" @@ -862,6 +863,7 @@ static void spapr_finalize_fdt(sPAPRMachineState *spapr, hwaddr rtas_size) { MachineState *machine = MACHINE(qdev_get_machine()); + sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); const char *boot_device = machine->boot_order; int ret, i; size_t cb = 0; @@ -945,6 +947,10 @@ static void spapr_finalize_fdt(sPAPRMachineState *spapr, spapr_populate_chosen_stdout(fdt, spapr->vio_bus); } + if (smc->dr_lmb_enabled) { + _FDT(spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB)); + } + _FDT((fdt_pack(fdt))); if (fdt_totalsize(fdt) > FDT_MAX_SIZE) { @@ -2055,12 +2061,120 @@ static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) } } +static void spapr_add_lmbs(DeviceState *dev, uint64_t addr, uint64_t size, + uint32_t node, Error **errp) +{ + sPAPRDRConnector *drc; + sPAPRDRConnectorClass *drck; + uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; + int i, fdt_offset, fdt_size; + void *fdt; + + /* + * Check for DRC connectors and send hotplug notification to the + * guest only in case of hotplugged memory. This allows cold plugged + * memory to be specified at boot time. + */ + if (!dev->hotplugged) { + return; + } + + for (i = 0; i < nr_lmbs; i++) { + drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, + addr/SPAPR_MEMORY_BLOCK_SIZE); + g_assert(drc); + + fdt = create_device_tree(&fdt_size); + fdt_offset = spapr_populate_memory_node(fdt, node, addr, + SPAPR_MEMORY_BLOCK_SIZE); + + drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp); + spapr_hotplug_req_add_event(drc); + addr += SPAPR_MEMORY_BLOCK_SIZE; + } +} + +static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + uint32_t node, Error **errp) +{ + Error *local_err = NULL; + sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev); + PCDIMMDevice *dimm = PC_DIMM(dev); + PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); + MemoryRegion *mr = ddc->get_memory_region(dimm); + uint64_t align = memory_region_get_alignment(mr); + uint64_t size = memory_region_size(mr); + uint64_t addr; + + if (size % SPAPR_MEMORY_BLOCK_SIZE) { + error_setg(&local_err, "Hotplugged memory size must be a multiple of " + "%lld MB", SPAPR_MEMORY_BLOCK_SIZE/M_BYTE); + goto out; + } + + pc_dimm_memory_plug(dev, &ms->hotplug_memory, mr, align, &local_err); + if (local_err) { + goto out; + } + + addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err); + if (local_err) { + pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr); + goto out; + } + + spapr_add_lmbs(dev, addr, size, node, &error_abort); + +out: + error_propagate(errp, local_err); +} + +static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine()); + + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + uint32_t node; + + if (!smc->dr_lmb_enabled) { + error_setg(errp, "Memory hotplug not supported for this machine"); + return; + } + node = object_property_get_int(OBJECT(dev), PC_DIMM_NODE_PROP, errp); + if (*errp) { + return; + } + + spapr_memory_plug(hotplug_dev, dev, node, errp); + } +} + +static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + error_setg(errp, "Memory hot unplug not supported by sPAPR"); + } +} + +static HotplugHandler *spapr_get_hotpug_handler(MachineState *machine, + DeviceState *dev) +{ + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + return HOTPLUG_HANDLER(machine); + } + return NULL; +} + static void spapr_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(oc); FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); NMIClass *nc = NMI_CLASS(oc); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); mc->init = ppc_spapr_init; mc->reset = ppc_spapr_reset; @@ -2072,6 +2186,9 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) mc->kvm_type = spapr_kvm_type; mc->has_dynamic_sysbus = true; mc->pci_allow_0_address = true; + mc->get_hotplug_handler = spapr_get_hotpug_handler; + hc->plug = spapr_machine_device_plug; + hc->unplug = spapr_machine_device_unplug; smc->dr_lmb_enabled = false; fwc->get_dev_path = spapr_get_fw_dev_path; @@ -2089,6 +2206,7 @@ static const TypeInfo spapr_machine_info = { .interfaces = (InterfaceInfo[]) { { TYPE_FW_PATH_PROVIDER }, { TYPE_NMI }, + { TYPE_HOTPLUG_HANDLER }, { } }, }; diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c index f626eb7b34..98bf7aedfc 100644 --- a/hw/ppc/spapr_events.c +++ b/hw/ppc/spapr_events.c @@ -427,14 +427,16 @@ static void spapr_hotplug_req_event(sPAPRDRConnector *drc, uint8_t hp_action) hp->hdr.section_length = cpu_to_be16(sizeof(*hp)); hp->hdr.section_version = 1; /* includes extended modifier */ hp->hotplug_action = hp_action; - + hp->drc.index = cpu_to_be32(drck->get_index(drc)); + hp->hotplug_identifier = RTAS_LOG_V6_HP_ID_DRC_INDEX; switch (drc_type) { case SPAPR_DR_CONNECTOR_TYPE_PCI: - hp->drc.index = cpu_to_be32(drck->get_index(drc)); - hp->hotplug_identifier = RTAS_LOG_V6_HP_ID_DRC_INDEX; hp->hotplug_type = RTAS_LOG_V6_HP_TYPE_PCI; break; + case SPAPR_DR_CONNECTOR_TYPE_LMB: + hp->hotplug_type = RTAS_LOG_V6_HP_TYPE_MEMORY; + break; default: /* we shouldn't be signaling hotplug events for resources * that don't support them From b556854bd8524c26b8be98ab1bfdf0826831e793 Mon Sep 17 00:00:00 2001 From: Bharata B Rao Date: Mon, 29 Jun 2015 14:14:32 +0530 Subject: [PATCH 26/36] spapr: Don't allow memory hotplug to memory less nodes Currently PowerPC kernel doesn't allow hot-adding memory to memory-less node, but instead will silently add the memory to the first node that has some memory. This causes two unexpected behaviours for the user. - Memory gets hotplugged to a different node than what the user specified. - Since pc-dimm subsystem in QEMU still thinks that memory belongs to memory-less node, a reboot will set things accordingly and the previously hotplugged memory now ends in the right node. This appears as if some memory moved from one node to another. So until kernel starts supporting memory hotplug to memory-less nodes, just prevent such attempts upfront in QEMU. Signed-off-by: Bharata B Rao Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 5b462290a5..1170028578 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2136,7 +2136,7 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine()); if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { - uint32_t node; + int node; if (!smc->dr_lmb_enabled) { error_setg(errp, "Memory hotplug not supported for this machine"); @@ -2147,6 +2147,28 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, return; } + /* + * Currently PowerPC kernel doesn't allow hot-adding memory to + * memory-less node, but instead will silently add the memory + * to the first node that has some memory. This causes two + * unexpected behaviours for the user. + * + * - Memory gets hotplugged to a different node than what the user + * specified. + * - Since pc-dimm subsystem in QEMU still thinks that memory belongs + * to memory-less node, a reboot will set things accordingly + * and the previously hotplugged memory now ends in the right node. + * This appears as if some memory moved from one node to another. + * + * So until kernel starts supporting memory hotplug to memory-less + * nodes, just prevent such attempts upfront in QEMU. + */ + if (nb_numa_nodes && !numa_info[node].node_mem) { + error_setg(errp, "Can't hotplug memory to memory-less node %d", + node); + return; + } + spapr_memory_plug(hotplug_dev, dev, node, errp); } } From 19a35c9e1b964f420ee07141f049e6c96c63b740 Mon Sep 17 00:00:00 2001 From: Bharata B Rao Date: Mon, 3 Aug 2015 11:05:39 +0530 Subject: [PATCH 27/36] spapr: Provide better error message when slots exceed max allowed Currently when user specifies more slots than allowed max of SPAPR_MAX_RAM_SLOTS (32), we error out like this: qemu-system-ppc64: unsupported amount of memory slots: 64 Let the user know about the max allowed slots like this: qemu-system-ppc64: Specified number of memory slots 64 exceeds max supported 32 Signed-off-by: Bharata B Rao Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 1170028578..5c81e19ac7 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1774,8 +1774,8 @@ static void ppc_spapr_init(MachineState *machine) ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size; if (machine->ram_slots > SPAPR_MAX_RAM_SLOTS) { - error_report("unsupported amount of memory slots: %"PRIu64, - machine->ram_slots); + error_report("Specified number of memory slots %"PRIu64" exceeds max supported %d\n", + machine->ram_slots, SPAPR_MAX_RAM_SLOTS); exit(EXIT_FAILURE); } From 6663864e950d40c467ae4ab81c4dac64d7a8d9e6 Mon Sep 17 00:00:00 2001 From: Bharata B Rao Date: Mon, 3 Aug 2015 11:05:40 +0530 Subject: [PATCH 28/36] spapr: Populate ibm,associativity-lookup-arrays correctly for non-NUMA When NUMA isn't configured explicitly, assume node 0 is present for the purpose of creating ibm,associativity-lookup-arrays property under ibm,dynamic-reconfiguration-memory DT node. This ensures that the associativity index property is correctly updated in ibm,dynamic-memory for the LMB that is hotplugged. Signed-off-by: Bharata B Rao Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 5c81e19ac7..64d07cd634 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -724,6 +724,7 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) uint32_t nr_lmbs = machine->maxram_size/lmb_size - nr_rma_lmbs; uint32_t nr_assigned_lmbs = machine->ram_size/lmb_size - nr_rma_lmbs; uint32_t *int_buf, *cur_index, buf_len; + int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1; /* Allocate enough buffer size to fit in ibm,dynamic-memory */ buf_len = nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE * sizeof(uint32_t) + @@ -789,10 +790,10 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) /* ibm,associativity-lookup-arrays */ cur_index = int_buf; - int_buf[0] = cpu_to_be32(nb_numa_nodes); + int_buf[0] = cpu_to_be32(nr_nodes); int_buf[1] = cpu_to_be32(4); /* Number of entries per associativity list */ cur_index += 2; - for (i = 0; i < nb_numa_nodes; i++) { + for (i = 0; i < nr_nodes; i++) { uint32_t associativity[] = { cpu_to_be32(0x0), cpu_to_be32(0x0), From e8f986fc57a664a74b9f685b466506366a15201b Mon Sep 17 00:00:00 2001 From: Bharata B Rao Date: Mon, 3 Aug 2015 11:05:41 +0530 Subject: [PATCH 29/36] spapr: Revert to memory@XXXX representation for non-hotplugged memory Don't represent non-hotluggable memory under drconf node. With this we don't have to create DRC objects for them. The effect of this patch is that we revert back to memory@XXXX representation for all the memory specified with -m option and represent the cold plugged memory and hot-pluggable memory under ibm,dynamic-reconfiguration-memory. Signed-off-by: Bharata B Rao Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr.c | 47 +++++++++-------------------------------------- 1 file changed, 9 insertions(+), 38 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 64d07cd634..402c00d24e 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -560,6 +560,7 @@ static int spapr_populate_memory(sPAPRMachineState *spapr, void *fdt) } if (!mem_start) { /* ppc_spapr_init() checks for rma_size <= node0_size already */ + spapr_populate_memory_node(fdt, i, 0, spapr->rma_size); mem_start += spapr->rma_size; node_size -= spapr->rma_size; } @@ -720,9 +721,7 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) int ret, i, offset; uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)}; - uint32_t nr_rma_lmbs = spapr->rma_size/lmb_size; - uint32_t nr_lmbs = machine->maxram_size/lmb_size - nr_rma_lmbs; - uint32_t nr_assigned_lmbs = machine->ram_size/lmb_size - nr_rma_lmbs; + uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; uint32_t *int_buf, *cur_index, buf_len; int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1; @@ -755,15 +754,9 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) for (i = 0; i < nr_lmbs; i++) { sPAPRDRConnector *drc; sPAPRDRConnectorClass *drck; - uint64_t addr; + uint64_t addr = i * lmb_size + spapr->hotplug_memory.base;; uint32_t *dynamic_memory = cur_index; - if (i < nr_assigned_lmbs) { - addr = (i + nr_rma_lmbs) * lmb_size; - } else { - addr = (i - nr_assigned_lmbs) * lmb_size + - spapr->hotplug_memory.base; - } drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, addr/lmb_size); g_assert(drc); @@ -838,8 +831,6 @@ int spapr_h_cas_compose_response(sPAPRMachineState *spapr, /* Generate memory nodes or ibm,dynamic-reconfiguration-memory node */ if (memory_update && smc->dr_lmb_enabled) { _FDT((spapr_populate_drconf_memory(spapr, fdt))); - } else { - _FDT((spapr_populate_memory(spapr, fdt))); } /* Pack resulting tree */ @@ -877,23 +868,10 @@ static void spapr_finalize_fdt(sPAPRMachineState *spapr, /* open out the base tree into a temp buffer for the final tweaks */ _FDT((fdt_open_into(spapr->fdt_skel, fdt, FDT_MAX_SIZE))); - /* - * Add memory@0 node to represent RMA. Rest of the memory is either - * represented by memory nodes or ibm,dynamic-reconfiguration-memory - * node later during ibm,client-architecture-support call. - * - * If NUMA is configured, ensure that memory@0 ends up in the - * first memory-less node. - */ - if (nb_numa_nodes) { - for (i = 0; i < nb_numa_nodes; ++i) { - if (numa_info[i].node_mem) { - spapr_populate_memory_node(fdt, i, 0, spapr->rma_size); - break; - } - } - } else { - spapr_populate_memory_node(fdt, 0, 0, spapr->rma_size); + ret = spapr_populate_memory(spapr, fdt); + if (ret < 0) { + fprintf(stderr, "couldn't setup memory nodes in fdt\n"); + exit(1); } ret = spapr_populate_vdevice(spapr->vio_bus, fdt); @@ -1600,21 +1578,14 @@ static void spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr) { MachineState *machine = MACHINE(spapr); uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; - uint32_t nr_rma_lmbs = spapr->rma_size/lmb_size; - uint32_t nr_lmbs = machine->maxram_size/lmb_size - nr_rma_lmbs; - uint32_t nr_assigned_lmbs = machine->ram_size/lmb_size - nr_rma_lmbs; + uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; int i; for (i = 0; i < nr_lmbs; i++) { sPAPRDRConnector *drc; uint64_t addr; - if (i < nr_assigned_lmbs) { - addr = (i + nr_rma_lmbs) * lmb_size; - } else { - addr = (i - nr_assigned_lmbs) * lmb_size + - spapr->hotplug_memory.base; - } + addr = i * lmb_size + spapr->hotplug_memory.base; drc = spapr_dr_connector_new(OBJECT(spapr), SPAPR_DR_CONNECTOR_TYPE_LMB, addr/lmb_size); qemu_register_reset(spapr_drc_reset, drc); From 7a36ae7a9f4f136d40fe1da4aab66b364d4aa56d Mon Sep 17 00:00:00 2001 From: Bharata B Rao Date: Mon, 3 Aug 2015 11:05:42 +0530 Subject: [PATCH 30/36] spapr: Support hotplug by specifying DRC count Support hotplug identifier type RTAS_LOG_V6_HP_ID_DRC_COUNT that allows hotplugging of DRCs by specifying the DRC count. While we are here, rename spapr_hotplug_req_add_event() to spapr_hotplug_req_add_by_index() spapr_hotplug_req_remove_event() to spapr_hotplug_req_remove_by_index() so that they match with spapr_hotplug_req_add_by_count(). Signed-off-by: Bharata B Rao Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr.c | 2 +- hw/ppc/spapr_events.c | 47 ++++++++++++++++++++++++++++++++++-------- hw/ppc/spapr_pci.c | 4 ++-- include/hw/ppc/spapr.h | 8 +++++-- 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 402c00d24e..d00513fc34 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2062,7 +2062,7 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr, uint64_t size, drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp); - spapr_hotplug_req_add_event(drc); + spapr_hotplug_req_add_by_index(drc); addr += SPAPR_MEMORY_BLOCK_SIZE; } } diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c index 98bf7aedfc..744ea62ac0 100644 --- a/hw/ppc/spapr_events.c +++ b/hw/ppc/spapr_events.c @@ -386,7 +386,9 @@ static void spapr_powerdown_req(Notifier *n, void *opaque) qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->check_exception_irq)); } -static void spapr_hotplug_req_event(sPAPRDRConnector *drc, uint8_t hp_action) +static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action, + sPAPRDRConnectorType drc_type, + uint32_t drc) { sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); struct hp_log_full *new_hp; @@ -395,8 +397,6 @@ static void spapr_hotplug_req_event(sPAPRDRConnector *drc, uint8_t hp_action) struct rtas_event_log_v6_maina *maina; struct rtas_event_log_v6_mainb *mainb; struct rtas_event_log_v6_hp *hp; - sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - sPAPRDRConnectorType drc_type = drck->get_type(drc); new_hp = g_malloc0(sizeof(struct hp_log_full)); hdr = &new_hp->hdr; @@ -427,8 +427,7 @@ static void spapr_hotplug_req_event(sPAPRDRConnector *drc, uint8_t hp_action) hp->hdr.section_length = cpu_to_be16(sizeof(*hp)); hp->hdr.section_version = 1; /* includes extended modifier */ hp->hotplug_action = hp_action; - hp->drc.index = cpu_to_be32(drck->get_index(drc)); - hp->hotplug_identifier = RTAS_LOG_V6_HP_ID_DRC_INDEX; + hp->hotplug_identifier = hp_id; switch (drc_type) { case SPAPR_DR_CONNECTOR_TYPE_PCI: @@ -445,19 +444,49 @@ static void spapr_hotplug_req_event(sPAPRDRConnector *drc, uint8_t hp_action) return; } + if (hp_id == RTAS_LOG_V6_HP_ID_DRC_COUNT) { + hp->drc.count = cpu_to_be32(drc); + } else if (hp_id == RTAS_LOG_V6_HP_ID_DRC_INDEX) { + hp->drc.index = cpu_to_be32(drc); + } + rtas_event_log_queue(RTAS_LOG_TYPE_HOTPLUG, new_hp, true); qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->check_exception_irq)); } -void spapr_hotplug_req_add_event(sPAPRDRConnector *drc) +void spapr_hotplug_req_add_by_index(sPAPRDRConnector *drc) { - spapr_hotplug_req_event(drc, RTAS_LOG_V6_HP_ACTION_ADD); + sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + sPAPRDRConnectorType drc_type = drck->get_type(drc); + uint32 index = drck->get_index(drc); + + spapr_hotplug_req_event(RTAS_LOG_V6_HP_ID_DRC_INDEX, + RTAS_LOG_V6_HP_ACTION_ADD, drc_type, index); } -void spapr_hotplug_req_remove_event(sPAPRDRConnector *drc) +void spapr_hotplug_req_remove_by_index(sPAPRDRConnector *drc) { - spapr_hotplug_req_event(drc, RTAS_LOG_V6_HP_ACTION_REMOVE); + sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + sPAPRDRConnectorType drc_type = drck->get_type(drc); + uint32 index = drck->get_index(drc); + + spapr_hotplug_req_event(RTAS_LOG_V6_HP_ID_DRC_INDEX, + RTAS_LOG_V6_HP_ACTION_REMOVE, drc_type, index); +} + +void spapr_hotplug_req_add_by_count(sPAPRDRConnectorType drc_type, + uint32_t count) +{ + spapr_hotplug_req_event(RTAS_LOG_V6_HP_ID_DRC_COUNT, + RTAS_LOG_V6_HP_ACTION_ADD, drc_type, count); +} + +void spapr_hotplug_req_remove_by_count(sPAPRDRConnectorType drc_type, + uint32_t count) +{ + spapr_hotplug_req_event(RTAS_LOG_V6_HP_ID_DRC_COUNT, + RTAS_LOG_V6_HP_ACTION_REMOVE, drc_type, count); } static void check_exception(PowerPCCPU *cpu, sPAPRMachineState *spapr, diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index d2188c854d..b088491c9e 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1187,7 +1187,7 @@ static void spapr_phb_hot_plug_child(HotplugHandler *plug_handler, return; } if (plugged_dev->hotplugged) { - spapr_hotplug_req_add_event(drc); + spapr_hotplug_req_add_by_index(drc); } } @@ -1215,7 +1215,7 @@ static void spapr_phb_hot_unplug_child(HotplugHandler *plug_handler, error_propagate(errp, local_err); return; } - spapr_hotplug_req_remove_event(drc); + spapr_hotplug_req_remove_by_index(drc); } } diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 7d20798276..ffb108d64c 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -594,8 +594,12 @@ int spapr_dma_dt(void *fdt, int node_off, const char *propname, int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname, sPAPRTCETable *tcet); void spapr_pci_switch_vga(bool big_endian); -void spapr_hotplug_req_add_event(sPAPRDRConnector *drc); -void spapr_hotplug_req_remove_event(sPAPRDRConnector *drc); +void spapr_hotplug_req_add_by_index(sPAPRDRConnector *drc); +void spapr_hotplug_req_remove_by_index(sPAPRDRConnector *drc); +void spapr_hotplug_req_add_by_count(sPAPRDRConnectorType drc_type, + uint32_t count); +void spapr_hotplug_req_remove_by_count(sPAPRDRConnectorType drc_type, + uint32_t count); /* rtas-configure-connector state */ struct sPAPRConfigureConnectorState { From 0a4178692c2375a4516da7b71629bd08ee8697ee Mon Sep 17 00:00:00 2001 From: Bharata B Rao Date: Mon, 3 Aug 2015 11:05:43 +0530 Subject: [PATCH 31/36] spapr: Move memory hotplug to RTAS_LOG_V6_HP_ID_DRC_COUNT type Till now memory hotplug used RTAS_LOG_V6_HP_ID_DRC_INDEX hotplug type which meant that we generated one hotplug type of EPOW event for every 256MB (SPAPR_MEMORY_BLOCK_SIZE). This quickly overruns the kernel rtas log buffer thus resulting in loss of memory hotplug events. Switch to RTAS_LOG_V6_HP_ID_DRC_COUNT hotplug type for memory so that we generate only one event per hotplug request. Signed-off-by: Bharata B Rao Reviewed-by: Michael Roth Reviewed-by: David Gibson Signed-off-by: David Gibson --- 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 d00513fc34..533c7adae1 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2062,9 +2062,9 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr, uint64_t size, drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp); - spapr_hotplug_req_add_by_index(drc); addr += SPAPR_MEMORY_BLOCK_SIZE; } + spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs); } static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, From 20bb648dca6d7fe8cdd1941194e7851950b25dc5 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 8 Sep 2015 11:21:52 +1000 Subject: [PATCH 32/36] spapr: Fix default NUMA node allocation for threads At present, if guest numa nodes are requested, but the cpus in each node are not specified, spapr just uses the default behaviour or assigning each vcpu round-robin to nodes. If smp_threads != 1, that will assign adjacent threads in a core to different NUMA nodes. As well as being just weird, that's a configuration that can't be represented in the device tree we give to the guest, which means the guest and qemu end up with different ideas of the NUMA topology. This patch implements mc->cpu_index_to_socket_id in the spapr code to make sure vcpus get assigned to nodes only at the socket granularity. Signed-off-by: David Gibson Reviewed-by: Alexey Kardashevskiy --- hw/ppc/spapr.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 533c7adae1..59fc814640 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2162,6 +2162,13 @@ static HotplugHandler *spapr_get_hotpug_handler(MachineState *machine, return NULL; } +static unsigned spapr_cpu_index_to_socket_id(unsigned cpu_index) +{ + /* Allocate to NUMA nodes on a "socket" basis (not that concept of + * socket means much for the paravirtualized PAPR platform) */ + return cpu_index / smp_threads / smp_cores; +} + static void spapr_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -2183,6 +2190,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) mc->get_hotplug_handler = spapr_get_hotpug_handler; hc->plug = spapr_machine_device_plug; hc->unplug = spapr_machine_device_unplug; + mc->cpu_index_to_socket_id = spapr_cpu_index_to_socket_id; smc->dr_lmb_enabled = false; fwc->get_dev_path = spapr_get_fw_dev_path; From ef001f069e0f175a036929782c5c63053df9569a Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 15 Sep 2015 21:34:20 +0200 Subject: [PATCH 33/36] ppc/spapr: Fix buffer overflow in spapr_populate_drconf_memory() The buffer that is allocated in spapr_populate_drconf_memory() is used for setting both, the "ibm,dynamic-memory" and the "ibm,associativity-lookup-arrays" property. However, only the size of the first one is taken into account when allocating the memory. So if the length of the second property is larger than the length of the first one, we run into a buffer overflow here! Fix it by taking the length of the second property into account, too. Fixes: "spapr: Support ibm,dynamic-reconfiguration-memory" patch Signed-off-by: Thomas Huth Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/spapr.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 59fc814640..1333375846 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -725,9 +725,12 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) uint32_t *int_buf, *cur_index, buf_len; int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1; - /* Allocate enough buffer size to fit in ibm,dynamic-memory */ - buf_len = nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE * sizeof(uint32_t) + - sizeof(uint32_t); + /* + * Allocate enough buffer size to fit in ibm,dynamic-memory + * or ibm,associativity-lookup-arrays + */ + buf_len = MAX(nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE + 1, nr_nodes * 4 + 2) + * sizeof(uint32_t); cur_index = int_buf = g_malloc0(buf_len); offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory"); From 4d9392be6c1aada69ce86c0f6584128976985394 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 17 Sep 2015 10:49:41 +0200 Subject: [PATCH 34/36] ppc/spapr: Implement H_RANDOM hypercall in QEMU The PAPR interface defines a hypercall to pass high-quality hardware generated random numbers to guests. Recent kernels can already provide this hypercall to the guest if the right hardware random number generator is available. But in case the user wants to use another source like EGD, or QEMU is running with an older kernel, we should also have this call in QEMU, so that guests that do not support virtio-rng yet can get good random numbers, too. This patch now adds a new pseudo-device to QEMU that either directly provides this hypercall to the guest or is able to enable the in-kernel hypercall if available. The in-kernel hypercall can be enabled with the use-kvm property, e.g.: qemu-system-ppc64 -device spapr-rng,use-kvm=true For handling the hypercall in QEMU instead, a "RngBackend" is required since the hypercall should provide "good" random data instead of pseudo-random (like from a "simple" library function like rand() or g_random_int()). Since there are multiple RngBackends available, the user must select an appropriate back-end via the "rng" property of the device, e.g.: qemu-system-ppc64 -object rng-random,filename=/dev/hwrng,id=gid0 \ -device spapr-rng,rng=gid0 ... See http://wiki.qemu-project.org/Features-Done/VirtIORNG for other example of specifying RngBackends. Signed-off-by: Thomas Huth Signed-off-by: David Gibson --- hw/ppc/Makefile.objs | 2 +- hw/ppc/spapr.c | 8 ++ hw/ppc/spapr_rng.c | 186 +++++++++++++++++++++++++++++++++++++++++ include/hw/ppc/spapr.h | 4 + target-ppc/kvm.c | 9 ++ target-ppc/kvm_ppc.h | 5 ++ 6 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 hw/ppc/spapr_rng.c diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index c8ab06e7f3..c1ffc7771b 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -3,7 +3,7 @@ obj-y += ppc.o ppc_booke.o # IBM pSeries (sPAPR) obj-$(CONFIG_PSERIES) += spapr.o spapr_vio.o spapr_events.o obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o -obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o spapr_drc.o +obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o spapr_drc.o spapr_rng.o ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy) obj-y += spapr_pci_vfio.o endif diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 1333375846..7f4f196e53 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -883,6 +883,14 @@ static void spapr_finalize_fdt(sPAPRMachineState *spapr, exit(1); } + if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)) { + ret = spapr_rng_populate_dt(fdt); + if (ret < 0) { + fprintf(stderr, "could not set up rng device in the fdt\n"); + exit(1); + } + } + QLIST_FOREACH(phb, &spapr->phbs, list) { ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt); } diff --git a/hw/ppc/spapr_rng.c b/hw/ppc/spapr_rng.c new file mode 100644 index 0000000000..ed43d5e042 --- /dev/null +++ b/hw/ppc/spapr_rng.c @@ -0,0 +1,186 @@ +/* + * QEMU sPAPR random number generator "device" for H_RANDOM hypercall + * + * Copyright 2015 Thomas Huth, Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "qemu/error-report.h" +#include "sysemu/sysemu.h" +#include "sysemu/device_tree.h" +#include "sysemu/rng.h" +#include "hw/ppc/spapr.h" +#include "kvm_ppc.h" + +#define SPAPR_RNG(obj) \ + OBJECT_CHECK(sPAPRRngState, (obj), TYPE_SPAPR_RNG) + +struct sPAPRRngState { + /*< private >*/ + DeviceState ds; + RngBackend *backend; + bool use_kvm; +}; +typedef struct sPAPRRngState sPAPRRngState; + +struct HRandomData { + QemuSemaphore sem; + union { + uint64_t v64; + uint8_t v8[8]; + } val; + int received; +}; +typedef struct HRandomData HRandomData; + +/* Callback function for the RngBackend */ +static void random_recv(void *dest, const void *src, size_t size) +{ + HRandomData *hrdp = dest; + + if (src && size > 0) { + assert(size + hrdp->received <= sizeof(hrdp->val.v8)); + memcpy(&hrdp->val.v8[hrdp->received], src, size); + hrdp->received += size; + } + + qemu_sem_post(&hrdp->sem); +} + +/* Handler for the H_RANDOM hypercall */ +static target_ulong h_random(PowerPCCPU *cpu, sPAPRMachineState *spapr, + target_ulong opcode, target_ulong *args) +{ + sPAPRRngState *rngstate; + HRandomData hrdata; + + rngstate = SPAPR_RNG(object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)); + + if (!rngstate || !rngstate->backend) { + return H_HARDWARE; + } + + qemu_sem_init(&hrdata.sem, 0); + hrdata.val.v64 = 0; + hrdata.received = 0; + + qemu_mutex_unlock_iothread(); + while (hrdata.received < 8) { + rng_backend_request_entropy(rngstate->backend, 8 - hrdata.received, + random_recv, &hrdata); + qemu_sem_wait(&hrdata.sem); + } + qemu_mutex_lock_iothread(); + + qemu_sem_destroy(&hrdata.sem); + args[0] = hrdata.val.v64; + + return H_SUCCESS; +} + +static void spapr_rng_instance_init(Object *obj) +{ + sPAPRRngState *rngstate = SPAPR_RNG(obj); + + if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL) != NULL) { + error_report("spapr-rng can not be instantiated twice!"); + return; + } + + object_property_add_link(obj, "rng", TYPE_RNG_BACKEND, + (Object **)&rngstate->backend, + object_property_allow_set_link, + OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL); + object_property_set_description(obj, "rng", + "ID of the random number generator backend", + NULL); +} + +static void spapr_rng_realize(DeviceState *dev, Error **errp) +{ + + sPAPRRngState *rngstate = SPAPR_RNG(dev); + + if (rngstate->use_kvm) { + if (kvmppc_enable_hwrng() == 0) { + return; + } + /* + * If user specified both, use-kvm and a backend, we fall back to + * the backend now. If not, provide an appropriate error message. + */ + if (!rngstate->backend) { + error_setg(errp, "Could not initialize in-kernel H_RANDOM call!"); + return; + } + } + + if (rngstate->backend) { + spapr_register_hypercall(H_RANDOM, h_random); + } else { + error_setg(errp, "spapr-rng needs an RNG backend!"); + } +} + +int spapr_rng_populate_dt(void *fdt) +{ + int node; + int ret; + + node = qemu_fdt_add_subnode(fdt, "/ibm,platform-facilities"); + if (node <= 0) { + return -1; + } + ret = fdt_setprop_string(fdt, node, "device_type", + "ibm,platform-facilities"); + ret |= fdt_setprop_cell(fdt, node, "#address-cells", 0x1); + ret |= fdt_setprop_cell(fdt, node, "#size-cells", 0x0); + + node = fdt_add_subnode(fdt, node, "ibm,random-v1"); + if (node <= 0) { + return -1; + } + ret |= fdt_setprop_string(fdt, node, "compatible", "ibm,random"); + + return ret ? -1 : 0; +} + +static Property spapr_rng_properties[] = { + DEFINE_PROP_BOOL("use-kvm", sPAPRRngState, use_kvm, false), + DEFINE_PROP_END_OF_LIST(), +}; + +static void spapr_rng_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = spapr_rng_realize; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + dc->props = spapr_rng_properties; +} + +static const TypeInfo spapr_rng_info = { + .name = TYPE_SPAPR_RNG, + .parent = TYPE_DEVICE, + .instance_size = sizeof(sPAPRRngState), + .instance_init = spapr_rng_instance_init, + .class_init = spapr_rng_class_init, +}; + +static void spapr_rng_register_type(void) +{ + type_register_static(&spapr_rng_info); +} +type_init(spapr_rng_register_type) diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index ffb108d64c..56c5b0b2b8 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -334,6 +334,7 @@ struct sPAPRMachineState { #define H_SET_MPP 0x2D0 #define H_GET_MPP 0x2D4 #define H_XIRR_X 0x2FC +#define H_RANDOM 0x300 #define H_SET_MODE 0x31C #define MAX_HCALL_OPCODE H_SET_MODE @@ -612,10 +613,13 @@ struct sPAPRConfigureConnectorState { void spapr_ccs_reset_hook(void *opaque); #define TYPE_SPAPR_RTC "spapr-rtc" +#define TYPE_SPAPR_RNG "spapr-rng" void spapr_rtc_read(DeviceState *dev, struct tm *tm, uint32_t *ns); int spapr_rtc_import_offset(DeviceState *dev, int64_t legacy_offset); +int spapr_rng_populate_dt(void *fdt); + #define SPAPR_MEMORY_BLOCK_SIZE (1 << 28) /* 256MB */ /* diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 9cf5308ac3..e641680fb1 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -2489,3 +2489,12 @@ int kvm_arch_msi_data_to_gsi(uint32_t data) { return data & 0xffff; } + +int kvmppc_enable_hwrng(void) +{ + if (!kvm_enabled() || !kvm_check_extension(kvm_state, KVM_CAP_PPC_HWRNG)) { + return -1; + } + + return kvmppc_enable_hcall(kvm_state, H_RANDOM); +} diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h index f790d50e51..470f6d62f7 100644 --- a/target-ppc/kvm_ppc.h +++ b/target-ppc/kvm_ppc.h @@ -54,6 +54,7 @@ void kvmppc_hash64_free_pteg(uint64_t token); void kvmppc_hash64_write_pte(CPUPPCState *env, target_ulong pte_index, target_ulong pte0, target_ulong pte1); bool kvmppc_has_cap_fixup_hcalls(void); +int kvmppc_enable_hwrng(void); #else @@ -251,6 +252,10 @@ static inline bool kvmppc_has_cap_fixup_hcalls(void) abort(); } +static inline int kvmppc_enable_hwrng(void) +{ + return -1; +} #endif #ifndef CONFIG_KVM From 47445c80fb57035331574ac1ac0bcee67fb84aeb Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Fri, 18 Sep 2015 17:30:43 +1000 Subject: [PATCH 35/36] sPAPR: Revert don't enable EEH on emulated PCI devices This reverts commit 7cb18007 ("sPAPR: Don't enable EEH on emulated PCI devices") as rtas_ibm_set_eeh_option() isn't the right place to check if there has the corresponding PCI device for the input address, which can be PE address, not PCI device address. Signed-off-by: Gavin Shan Signed-off-by: David Gibson --- hw/ppc/spapr_pci.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index b088491c9e..617b7f3fdd 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -431,7 +431,6 @@ static void rtas_ibm_set_eeh_option(PowerPCCPU *cpu, { sPAPRPHBState *sphb; sPAPRPHBClass *spc; - PCIDevice *pdev; uint32_t addr, option; uint64_t buid; int ret; @@ -449,12 +448,6 @@ static void rtas_ibm_set_eeh_option(PowerPCCPU *cpu, goto param_error_exit; } - pdev = pci_find_device(PCI_HOST_BRIDGE(sphb)->bus, - (addr >> 16) & 0xFF, (addr >> 8) & 0xFF); - if (!pdev || !object_dynamic_cast(OBJECT(pdev), "vfio-pci")) { - goto param_error_exit; - } - spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb); if (!spc->eeh_set_option) { goto param_error_exit; From d76548a98f4e18d3c65a3d921bbb70caf9be6138 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Fri, 18 Sep 2015 17:30:44 +1000 Subject: [PATCH 36/36] sPAPR: Enable EEH on VFIO PCI device only This checks if the PCI device retrieved from the PCI device address is VFIO PCI device when enabling EEH functionality. If it's not VFIO PCI device, the EEH functonality isn't enabled. Signed-off-by: Gavin Shan Signed-off-by: David Gibson --- hw/ppc/spapr_pci_vfio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c index cca45ed312..a61b418131 100644 --- a/hw/ppc/spapr_pci_vfio.c +++ b/hw/ppc/spapr_pci_vfio.c @@ -117,7 +117,7 @@ static int spapr_phb_vfio_eeh_set_option(sPAPRPHBState *sphb, phb = PCI_HOST_BRIDGE(sphb); pdev = pci_find_device(phb->bus, (addr >> 16) & 0xFF, (addr >> 8) & 0xFF); - if (!pdev) { + if (!pdev || !object_dynamic_cast(OBJECT(pdev), "vfio-pci")) { return RTAS_OUT_PARAM_ERROR; }