From ec3b4653a47c0c147c1b5f9a8f3cde42ae626c9f Mon Sep 17 00:00:00 2001 From: yezengruan Date: Thu, 11 Aug 2022 19:08:28 +0800 Subject: [PATCH] Qemu update to version 6.2.0-45 numa: Enable numa for SGX EPC sections target/ppc: enhance error handling in kvmppc_read_int* fix pointer double free in func qemu_savevm_state_complete_precopy_non_iterable Signed-off-by: yezengruan (cherry picked from commit bb777b4dcec9cce839f38c256bf8f3856eb859e4) --- ...ouble-free-in-func-qemu_savevm_state.patch | 38 +++ doc-Add-the-SGX-numa-description.patch | 81 +++++ numa-Enable-numa-for-SGX-EPC-sections.patch | 291 ++++++++++++++++++ ...-numa-in-the-monitor-and-Libvirt-int.patch | 213 +++++++++++++ ...-related-comments-and-restore-sectio.patch | 219 +++++++++++++ qemu.spec | 16 +- ...rror-report-when-fopen-fails-in-kvmp.patch | 50 +++ ...ce-error-report-in-kvmppc_read_int_c.patch | 81 +++++ ...1-on-failure-in-kvmppc_get_clockfreq.patch | 51 +++ ...g_autofree-in-kvmppc_read_int_cpu_dt.patch | 43 +++ 10 files changed, 1082 insertions(+), 1 deletion(-) create mode 100644 bugfix-pointer-double-free-in-func-qemu_savevm_state.patch create mode 100644 doc-Add-the-SGX-numa-description.patch create mode 100644 numa-Enable-numa-for-SGX-EPC-sections.patch create mode 100644 numa-Support-SGX-numa-in-the-monitor-and-Libvirt-int.patch create mode 100644 qapi-Cleanup-SGX-related-comments-and-restore-sectio.patch create mode 100644 target-ppc-add-error-report-when-fopen-fails-in-kvmp.patch create mode 100644 target-ppc-enhance-error-report-in-kvmppc_read_int_c.patch create mode 100644 target-ppc-exit-1-on-failure-in-kvmppc_get_clockfreq.patch create mode 100644 target-ppc-use-g_autofree-in-kvmppc_read_int_cpu_dt.patch diff --git a/bugfix-pointer-double-free-in-func-qemu_savevm_state.patch b/bugfix-pointer-double-free-in-func-qemu_savevm_state.patch new file mode 100644 index 0000000..e6e0c2d --- /dev/null +++ b/bugfix-pointer-double-free-in-func-qemu_savevm_state.patch @@ -0,0 +1,38 @@ +From 48ff0d29c594ccfa80a3d58c97bdb7e656c8f541 Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Mon, 20 Jun 2022 17:19:44 +0800 +Subject: [PATCH 9/9] bugfix: pointer double free in func + qemu_savevm_state_complete_precopy_non_iterable + +vmdesc defined in qemu_savevm_state_complete_precopy_non_iterable is a g_autoptr, +it will be auto freed when function return. thus when we call json_writer_free +before function return to free vmdesc, it will be double freed. fix it. + +Signed-off-by: jiangdongxu +--- + migration/savevm.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/migration/savevm.c b/migration/savevm.c +index 803cd9004d..d59e976d50 100644 +--- a/migration/savevm.c ++++ b/migration/savevm.c +@@ -1427,7 +1427,6 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f, + ret = vmstate_save(f, se, vmdesc); + if (ret) { + qemu_file_set_error(f, ret); +- json_writer_free(vmdesc); + return ret; + } + trace_savevm_section_end(se->idstr, se->section_id, 0); +@@ -1444,7 +1443,6 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f, + error_report("%s: bdrv_inactivate_all() failed (%d)", + __func__, ret); + qemu_file_set_error(f, ret); +- json_writer_free(vmdesc); + return ret; + } + } +-- +2.27.0 + diff --git a/doc-Add-the-SGX-numa-description.patch b/doc-Add-the-SGX-numa-description.patch new file mode 100644 index 0000000..9288942 --- /dev/null +++ b/doc-Add-the-SGX-numa-description.patch @@ -0,0 +1,81 @@ +From adba5254ecbd9eace360d8eb3d5c635d3acd8d71 Mon Sep 17 00:00:00 2001 +From: Yang Zhong +Date: Mon, 1 Nov 2021 12:20:08 -0400 +Subject: [PATCH 3/9] doc: Add the SGX numa description + +mainline inclusion +from mainline-v7.0.0-rc0 +commit d1889b36098c79e2e6ac90faf3d0dc5ec0057677 +category: feature +feature: NUMA support for SGX EPC sections +bugzilla: https://gitee.com/openeuler/intel-qemu/issues/I5K27A + +Intel-SIG: commit d1889b36098c ("doc: Add the SGX numa description") + +------------------------------------- + +doc: Add the SGX numa description + +Add the SGX numa reference command and how to check if +SGX numa is support or not with multiple EPC sections. + +Signed-off-by: Yang Zhong +Message-Id: <20211101162009.62161-5-yang.zhong@intel.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Jason Zeng +--- + docs/system/i386/sgx.rst | 31 +++++++++++++++++++++++++++---- + 1 file changed, 27 insertions(+), 4 deletions(-) + +diff --git a/docs/system/i386/sgx.rst b/docs/system/i386/sgx.rst +index f8fade5ac2..0f0a73f758 100644 +--- a/docs/system/i386/sgx.rst ++++ b/docs/system/i386/sgx.rst +@@ -141,8 +141,7 @@ To launch a SGX guest: + |qemu_system_x86| \\ + -cpu host,+sgx-provisionkey \\ + -object memory-backend-epc,id=mem1,size=64M,prealloc=on \\ +- -object memory-backend-epc,id=mem2,size=28M \\ +- -M sgx-epc.0.memdev=mem1,sgx-epc.1.memdev=mem2 ++ -M sgx-epc.0.memdev=mem1,sgx-epc.0.node=0 + + Utilizing SGX in the guest requires a kernel/OS with SGX support. + The support can be determined in guest by:: +@@ -152,8 +151,32 @@ The support can be determined in guest by:: + and SGX epc info by:: + + $ dmesg | grep sgx +- [ 1.242142] sgx: EPC section 0x180000000-0x181bfffff +- [ 1.242319] sgx: EPC section 0x181c00000-0x1837fffff ++ [ 0.182807] sgx: EPC section 0x140000000-0x143ffffff ++ [ 0.183695] sgx: [Firmware Bug]: Unable to map EPC section to online node. Fallback to the NUMA node 0. ++ ++To launch a SGX numa guest: ++ ++.. parsed-literal:: ++ ++ |qemu_system_x86| \\ ++ -cpu host,+sgx-provisionkey \\ ++ -object memory-backend-ram,size=2G,host-nodes=0,policy=bind,id=node0 \\ ++ -object memory-backend-epc,id=mem0,size=64M,prealloc=on,host-nodes=0,policy=bind \\ ++ -numa node,nodeid=0,cpus=0-1,memdev=node0 \\ ++ -object memory-backend-ram,size=2G,host-nodes=1,policy=bind,id=node1 \\ ++ -object memory-backend-epc,id=mem1,size=28M,prealloc=on,host-nodes=1,policy=bind \\ ++ -numa node,nodeid=1,cpus=2-3,memdev=node1 \\ ++ -M sgx-epc.0.memdev=mem0,sgx-epc.0.node=0,sgx-epc.1.memdev=mem1,sgx-epc.1.node=1 ++ ++and SGX epc numa info by:: ++ ++ $ dmesg | grep sgx ++ [ 0.369937] sgx: EPC section 0x180000000-0x183ffffff ++ [ 0.370259] sgx: EPC section 0x184000000-0x185bfffff ++ ++ $ dmesg | grep SRAT ++ [ 0.009981] ACPI: SRAT: Node 0 PXM 0 [mem 0x180000000-0x183ffffff] ++ [ 0.009982] ACPI: SRAT: Node 1 PXM 1 [mem 0x184000000-0x185bfffff] + + References + ---------- +-- +2.27.0 + diff --git a/numa-Enable-numa-for-SGX-EPC-sections.patch b/numa-Enable-numa-for-SGX-EPC-sections.patch new file mode 100644 index 0000000..0eec472 --- /dev/null +++ b/numa-Enable-numa-for-SGX-EPC-sections.patch @@ -0,0 +1,291 @@ +From c9071221ea67c7ee72fab5956e4c2c9da3fd39ef Mon Sep 17 00:00:00 2001 +From: Yang Zhong +Date: Mon, 1 Nov 2021 12:20:05 -0400 +Subject: [PATCH 1/9] numa: Enable numa for SGX EPC sections + +mainline inclusion +from mainline-v7.0.0-rc0 +commit 1105812382e1126d86dddc16b3700f8c79dc93d1 +category: feature +feature: NUMA support for SGX EPC sections +bugzilla: https://gitee.com/openeuler/intel-qemu/issues/I5K27A + +Intel-SIG: commit 1105812382e1 ("numa: Enable numa for SGX EPC sections") + +------------------------------------- + +numa: Enable numa for SGX EPC sections + +The basic SGX did not enable numa for SGX EPC sections, which +result in all EPC sections located in numa node 0. This patch +enable SGX numa function in the guest and the EPC section can +work with RAM as one numa node. + +The Guest kernel related log: +[ 0.009981] ACPI: SRAT: Node 0 PXM 0 [mem 0x180000000-0x183ffffff] +[ 0.009982] ACPI: SRAT: Node 1 PXM 1 [mem 0x184000000-0x185bfffff] +The SRAT table can normally show SGX EPC sections menory info in different +numa nodes. + +The SGX EPC numa related command: + ...... + -m 4G,maxmem=20G \ + -smp sockets=2,cores=2 \ + -cpu host,+sgx-provisionkey \ + -object memory-backend-ram,size=2G,host-nodes=0,policy=bind,id=node0 \ + -object memory-backend-epc,id=mem0,size=64M,prealloc=on,host-nodes=0,policy=bind \ + -numa node,nodeid=0,cpus=0-1,memdev=node0 \ + -object memory-backend-ram,size=2G,host-nodes=1,policy=bind,id=node1 \ + -object memory-backend-epc,id=mem1,size=28M,prealloc=on,host-nodes=1,policy=bind \ + -numa node,nodeid=1,cpus=2-3,memdev=node1 \ + -M sgx-epc.0.memdev=mem0,sgx-epc.0.node=0,sgx-epc.1.memdev=mem1,sgx-epc.1.node=1 \ + ...... + +Signed-off-by: Yang Zhong +Message-Id: <20211101162009.62161-2-yang.zhong@intel.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Jason Zeng +--- + hw/core/numa.c | 5 ++--- + hw/i386/acpi-build.c | 2 ++ + hw/i386/sgx-epc.c | 3 +++ + hw/i386/sgx-stub.c | 4 ++++ + hw/i386/sgx.c | 44 +++++++++++++++++++++++++++++++++++++++ + include/hw/i386/sgx-epc.h | 3 +++ + monitor/hmp-cmds.c | 1 + + qapi/machine.json | 10 ++++++++- + qemu-options.hx | 4 ++-- + 9 files changed, 70 insertions(+), 6 deletions(-) + +diff --git a/hw/core/numa.c b/hw/core/numa.c +index e6050b2273..1aa05dcf42 100644 +--- a/hw/core/numa.c ++++ b/hw/core/numa.c +@@ -784,9 +784,8 @@ static void numa_stat_memory_devices(NumaNodeMem node_mem[]) + break; + case MEMORY_DEVICE_INFO_KIND_SGX_EPC: + se = value->u.sgx_epc.data; +- /* TODO: once we support numa, assign to right node */ +- node_mem[0].node_mem += se->size; +- node_mem[0].node_plugged_mem += se->size; ++ node_mem[se->node].node_mem += se->size; ++ node_mem[se->node].node_plugged_mem = 0; + break; + default: + g_assert_not_reached(); +diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c +index 0ec2932ec2..1e33e1f3d0 100644 +--- a/hw/i386/acpi-build.c ++++ b/hw/i386/acpi-build.c +@@ -2068,6 +2068,8 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) + nvdimm_build_srat(table_data); + } + ++ sgx_epc_build_srat(table_data); ++ + /* + * TODO: this part is not in ACPI spec and current linux kernel boots fine + * without these entries. But I recall there were issues the last time I +diff --git a/hw/i386/sgx-epc.c b/hw/i386/sgx-epc.c +index e508827e78..96b2940d75 100644 +--- a/hw/i386/sgx-epc.c ++++ b/hw/i386/sgx-epc.c +@@ -21,6 +21,7 @@ + + static Property sgx_epc_properties[] = { + DEFINE_PROP_UINT64(SGX_EPC_ADDR_PROP, SGXEPCDevice, addr, 0), ++ DEFINE_PROP_UINT32(SGX_EPC_NUMA_NODE_PROP, SGXEPCDevice, node, 0), + DEFINE_PROP_LINK(SGX_EPC_MEMDEV_PROP, SGXEPCDevice, hostmem, + TYPE_MEMORY_BACKEND_EPC, HostMemoryBackendEpc *), + DEFINE_PROP_END_OF_LIST(), +@@ -139,6 +140,8 @@ static void sgx_epc_md_fill_device_info(const MemoryDeviceState *md, + se->memaddr = epc->addr; + se->size = object_property_get_uint(OBJECT(epc), SGX_EPC_SIZE_PROP, + NULL); ++ se->node = object_property_get_uint(OBJECT(epc), SGX_EPC_NUMA_NODE_PROP, ++ NULL); + se->memdev = object_get_canonical_path(OBJECT(epc->hostmem)); + + info->u.sgx_epc.data = se; +diff --git a/hw/i386/sgx-stub.c b/hw/i386/sgx-stub.c +index c9b379e665..26833eb233 100644 +--- a/hw/i386/sgx-stub.c ++++ b/hw/i386/sgx-stub.c +@@ -6,6 +6,10 @@ + #include "qapi/error.h" + #include "qapi/qapi-commands-misc-target.h" + ++void sgx_epc_build_srat(GArray *table_data) ++{ ++} ++ + SGXInfo *qmp_query_sgx(Error **errp) + { + error_setg(errp, "SGX support is not compiled in"); +diff --git a/hw/i386/sgx.c b/hw/i386/sgx.c +index 8fef3dd8fa..d04299904a 100644 +--- a/hw/i386/sgx.c ++++ b/hw/i386/sgx.c +@@ -23,6 +23,7 @@ + #include "sysemu/hw_accel.h" + #include "sysemu/reset.h" + #include ++#include "hw/acpi/aml-build.h" + + #define SGX_MAX_EPC_SECTIONS 8 + #define SGX_CPUID_EPC_INVALID 0x0 +@@ -36,6 +37,46 @@ + + #define RETRY_NUM 2 + ++static int sgx_epc_device_list(Object *obj, void *opaque) ++{ ++ GSList **list = opaque; ++ ++ if (object_dynamic_cast(obj, TYPE_SGX_EPC)) { ++ *list = g_slist_append(*list, DEVICE(obj)); ++ } ++ ++ object_child_foreach(obj, sgx_epc_device_list, opaque); ++ return 0; ++} ++ ++static GSList *sgx_epc_get_device_list(void) ++{ ++ GSList *list = NULL; ++ ++ object_child_foreach(qdev_get_machine(), sgx_epc_device_list, &list); ++ return list; ++} ++ ++void sgx_epc_build_srat(GArray *table_data) ++{ ++ GSList *device_list = sgx_epc_get_device_list(); ++ ++ for (; device_list; device_list = device_list->next) { ++ DeviceState *dev = device_list->data; ++ Object *obj = OBJECT(dev); ++ uint64_t addr, size; ++ int node; ++ ++ node = object_property_get_uint(obj, SGX_EPC_NUMA_NODE_PROP, ++ &error_abort); ++ addr = object_property_get_uint(obj, SGX_EPC_ADDR_PROP, &error_abort); ++ size = object_property_get_uint(obj, SGX_EPC_SIZE_PROP, &error_abort); ++ ++ build_srat_memory(table_data, addr, size, node, MEM_AFFINITY_ENABLED); ++ } ++ g_slist_free(device_list); ++} ++ + static uint64_t sgx_calc_section_metric(uint64_t low, uint64_t high) + { + return (low & MAKE_64BIT_MASK(12, 20)) + +@@ -226,6 +267,9 @@ void pc_machine_init_sgx_epc(PCMachineState *pcms) + /* set the memdev link with memory backend */ + object_property_parse(obj, SGX_EPC_MEMDEV_PROP, list->value->memdev, + &error_fatal); ++ /* set the numa node property for sgx epc object */ ++ object_property_set_uint(obj, SGX_EPC_NUMA_NODE_PROP, list->value->node, ++ &error_fatal); + object_property_set_bool(obj, "realized", true, &error_fatal); + object_unref(obj); + } +diff --git a/include/hw/i386/sgx-epc.h b/include/hw/i386/sgx-epc.h +index a6a65be854..581fac389a 100644 +--- a/include/hw/i386/sgx-epc.h ++++ b/include/hw/i386/sgx-epc.h +@@ -25,6 +25,7 @@ + #define SGX_EPC_ADDR_PROP "addr" + #define SGX_EPC_SIZE_PROP "size" + #define SGX_EPC_MEMDEV_PROP "memdev" ++#define SGX_EPC_NUMA_NODE_PROP "node" + + /** + * SGXEPCDevice: +@@ -38,6 +39,7 @@ typedef struct SGXEPCDevice { + + /* public */ + uint64_t addr; ++ uint32_t node; + HostMemoryBackendEpc *hostmem; + } SGXEPCDevice; + +@@ -56,6 +58,7 @@ typedef struct SGXEPCState { + } SGXEPCState; + + bool sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size); ++void sgx_epc_build_srat(GArray *table_data); + + static inline uint64_t sgx_epc_above_4g_end(SGXEPCState *sgx_epc) + { +diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c +index 294652034e..9570011232 100644 +--- a/monitor/hmp-cmds.c ++++ b/monitor/hmp-cmds.c +@@ -1823,6 +1823,7 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict) + se->id ? se->id : ""); + monitor_printf(mon, " memaddr: 0x%" PRIx64 "\n", se->memaddr); + monitor_printf(mon, " size: %" PRIu64 "\n", se->size); ++ monitor_printf(mon, " node: %" PRId64 "\n", se->node); + monitor_printf(mon, " memdev: %s\n", se->memdev); + break; + default: +diff --git a/qapi/machine.json b/qapi/machine.json +index 6ed8488255..85c35e7fc5 100644 +--- a/qapi/machine.json ++++ b/qapi/machine.json +@@ -1209,12 +1209,15 @@ + # + # @memdev: memory backend linked with device + # ++# @node: the numa node ++# + # Since: 6.2 + ## + { 'struct': 'SgxEPCDeviceInfo', + 'data': { '*id': 'str', + 'memaddr': 'size', + 'size': 'size', ++ 'node': 'int', + 'memdev': 'str' + } + } +@@ -1287,10 +1290,15 @@ + # + # @memdev: memory backend linked with device + # ++# @node: the numa node ++# + # Since: 6.2 + ## + { 'struct': 'SgxEPC', +- 'data': { 'memdev': 'str' } } ++ 'data': { 'memdev': 'str', ++ 'node': 'int' ++ } ++} + + ## + # @SgxEPCProperties: +diff --git a/qemu-options.hx b/qemu-options.hx +index 74d335e4c3..1aaf38c613 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -127,11 +127,11 @@ SRST + ERST + + DEF("M", HAS_ARG, QEMU_OPTION_M, +- " sgx-epc.0.memdev=memid\n", ++ " sgx-epc.0.memdev=memid,sgx-epc.0.node=numaid\n", + QEMU_ARCH_ALL) + + SRST +-``sgx-epc.0.memdev=@var{memid}`` ++``sgx-epc.0.memdev=@var{memid},sgx-epc.0.node=@var{numaid}`` + Define an SGX EPC section. + ERST + +-- +2.27.0 + diff --git a/numa-Support-SGX-numa-in-the-monitor-and-Libvirt-int.patch b/numa-Support-SGX-numa-in-the-monitor-and-Libvirt-int.patch new file mode 100644 index 0000000..ef45f00 --- /dev/null +++ b/numa-Support-SGX-numa-in-the-monitor-and-Libvirt-int.patch @@ -0,0 +1,213 @@ +From 86648f137c72241005327b55208eeeed8b3cfd5e Mon Sep 17 00:00:00 2001 +From: Yang Zhong +Date: Mon, 1 Nov 2021 12:20:07 -0400 +Subject: [PATCH 2/9] numa: Support SGX numa in the monitor and Libvirt + interfaces + +from mainline-v7.0.0-rc0 +commit 4755927ae12547c2e7cb22c5fa1b39038c6c11b1 +category: feature +feature: NUMA support for SGX EPC sections +bugzilla: https://gitee.com/openeuler/intel-qemu/issues/I5K27A + +Intel-SIG: commit 4755927ae125 ("numa: Support SGX numa in the monitor and +Libvirt interfaces") + ------------------------------------- + +numa: Support SGX numa in the monitor and Libvirt interfaces + +Add the SGXEPCSection list into SGXInfo to show the multiple +SGX EPC sections detailed info, not the total size like before. +This patch can enable numa support for 'info sgx' command and +QMP interfaces. The new interfaces show each EPC section info +in one numa node. Libvirt can use QMP interface to get the +detailed host SGX EPC capabilities to decide how to allocate +host EPC sections to guest. + +(qemu) info sgx + SGX support: enabled + SGX1 support: enabled + SGX2 support: enabled + FLC support: enabled + NUMA node #0: size=67108864 + NUMA node #1: size=29360128 + +The QMP interface show: +(QEMU) query-sgx +{"return": {"sgx": true, "sgx2": true, "sgx1": true, "sections": \ +[{"node": 0, "size": 67108864}, {"node": 1, "size": 29360128}], "flc": true}} + +(QEMU) query-sgx-capabilities +{"return": {"sgx": true, "sgx2": true, "sgx1": true, "sections": \ +[{"node": 0, "size": 17070817280}, {"node": 1, "size": 17079205888}], "flc": true}} + +Signed-off-by: Yang Zhong +Message-Id: <20211101162009.62161-4-yang.zhong@intel.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Jason Zeng +--- + hw/i386/sgx.c | 51 +++++++++++++++++++++++++++++++++++-------- + qapi/misc-target.json | 19 ++++++++++++++-- + 2 files changed, 59 insertions(+), 11 deletions(-) + +diff --git a/hw/i386/sgx.c b/hw/i386/sgx.c +index d04299904a..5de5dd0893 100644 +--- a/hw/i386/sgx.c ++++ b/hw/i386/sgx.c +@@ -83,11 +83,13 @@ static uint64_t sgx_calc_section_metric(uint64_t low, uint64_t high) + ((high & MAKE_64BIT_MASK(0, 20)) << 32); + } + +-static uint64_t sgx_calc_host_epc_section_size(void) ++static SGXEPCSectionList *sgx_calc_host_epc_sections(void) + { ++ SGXEPCSectionList *head = NULL, **tail = &head; ++ SGXEPCSection *section; + uint32_t i, type; + uint32_t eax, ebx, ecx, edx; +- uint64_t size = 0; ++ uint32_t j = 0; + + for (i = 0; i < SGX_MAX_EPC_SECTIONS; i++) { + host_cpuid(0x12, i + 2, &eax, &ebx, &ecx, &edx); +@@ -101,10 +103,13 @@ static uint64_t sgx_calc_host_epc_section_size(void) + break; + } + +- size += sgx_calc_section_metric(ecx, edx); ++ section = g_new0(SGXEPCSection, 1); ++ section->node = j++; ++ section->size = sgx_calc_section_metric(ecx, edx); ++ QAPI_LIST_APPEND(tail, section); + } + +- return size; ++ return head; + } + + static void sgx_epc_reset(void *opaque) +@@ -168,13 +173,35 @@ SGXInfo *qmp_query_sgx_capabilities(Error **errp) + info->sgx1 = eax & (1U << 0) ? true : false; + info->sgx2 = eax & (1U << 1) ? true : false; + +- info->section_size = sgx_calc_host_epc_section_size(); ++ info->sections = sgx_calc_host_epc_sections(); + + close(fd); + + return info; + } + ++static SGXEPCSectionList *sgx_get_epc_sections_list(void) ++{ ++ GSList *device_list = sgx_epc_get_device_list(); ++ SGXEPCSectionList *head = NULL, **tail = &head; ++ SGXEPCSection *section; ++ ++ for (; device_list; device_list = device_list->next) { ++ DeviceState *dev = device_list->data; ++ Object *obj = OBJECT(dev); ++ ++ section = g_new0(SGXEPCSection, 1); ++ section->node = object_property_get_uint(obj, SGX_EPC_NUMA_NODE_PROP, ++ &error_abort); ++ section->size = object_property_get_uint(obj, SGX_EPC_SIZE_PROP, ++ &error_abort); ++ QAPI_LIST_APPEND(tail, section); ++ } ++ g_slist_free(device_list); ++ ++ return head; ++} ++ + SGXInfo *qmp_query_sgx(Error **errp) + { + SGXInfo *info = NULL; +@@ -193,14 +220,13 @@ SGXInfo *qmp_query_sgx(Error **errp) + return NULL; + } + +- SGXEPCState *sgx_epc = &pcms->sgx_epc; + info = g_new0(SGXInfo, 1); + + info->sgx = true; + info->sgx1 = true; + info->sgx2 = true; + info->flc = true; +- info->section_size = sgx_epc->size; ++ info->sections = sgx_get_epc_sections_list(); + + return info; + } +@@ -208,6 +234,7 @@ SGXInfo *qmp_query_sgx(Error **errp) + void hmp_info_sgx(Monitor *mon, const QDict *qdict) + { + Error *err = NULL; ++ SGXEPCSectionList *section_list, *section; + g_autoptr(SGXInfo) info = qmp_query_sgx(&err); + + if (err) { +@@ -222,8 +249,14 @@ void hmp_info_sgx(Monitor *mon, const QDict *qdict) + info->sgx2 ? "enabled" : "disabled"); + monitor_printf(mon, "FLC support: %s\n", + info->flc ? "enabled" : "disabled"); +- monitor_printf(mon, "size: %" PRIu64 "\n", +- info->section_size); ++ ++ section_list = info->sections; ++ for (section = section_list; section; section = section->next) { ++ monitor_printf(mon, "NUMA node #%" PRId64 ": ", ++ section->value->node); ++ monitor_printf(mon, "size=%" PRIu64 "\n", ++ section->value->size); ++ } + } + + bool sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size) +diff --git a/qapi/misc-target.json b/qapi/misc-target.json +index 5aa2b95b7d..1022aa0184 100644 +--- a/qapi/misc-target.json ++++ b/qapi/misc-target.json +@@ -337,6 +337,21 @@ + 'if': 'TARGET_ARM' } + + ++## ++# @SGXEPCSection: ++# ++# Information about intel SGX EPC section info ++# ++# @node: the numa node ++# ++# @size: the size of epc section ++# ++# Since: 6.2 ++## ++{ 'struct': 'SGXEPCSection', ++ 'data': { 'node': 'int', ++ 'size': 'uint64'}} ++ + ## + # @SGXInfo: + # +@@ -350,7 +365,7 @@ + # + # @flc: true if FLC is supported + # +-# @section-size: The EPC section size for guest ++# @sections: The EPC sections info for guest + # + # Since: 6.2 + ## +@@ -359,7 +374,7 @@ + 'sgx1': 'bool', + 'sgx2': 'bool', + 'flc': 'bool', +- 'section-size': 'uint64'}, ++ 'sections': ['SGXEPCSection']}, + 'if': 'TARGET_I386' } + + ## +-- +2.27.0 + diff --git a/qapi-Cleanup-SGX-related-comments-and-restore-sectio.patch b/qapi-Cleanup-SGX-related-comments-and-restore-sectio.patch new file mode 100644 index 0000000..0834e79 --- /dev/null +++ b/qapi-Cleanup-SGX-related-comments-and-restore-sectio.patch @@ -0,0 +1,219 @@ +From 646cfa4209dde2258891668576d32759e1479dfa Mon Sep 17 00:00:00 2001 +From: Yang Zhong +Date: Thu, 20 Jan 2022 17:31:04 -0500 +Subject: [PATCH 4/9] qapi: Cleanup SGX related comments and restore + @section-size +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +mainline inclusion +from mainline-v7.0.0-rc0 +commit a66bd91f030827742778a9e0da19fe55716b4a60 +category: feature +feature: NUMA support for SGX EPC sections +bugzilla: https://gitee.com/openeuler/intel-qemu/issues/I5K27A + +Intel-SIG: commit a66bd91f0308 ("qapi: Cleanup SGX related comments +and restore @section-size") + +------------------------------------- + +qapi: Cleanup SGX related comments and restore @section-size + +The SGX NUMA patches were merged into Qemu 7.0 release, we need +clarify detailed version history information and also change +some related comments, which make SGX related comments clearer. + +The QMP command schema promises backwards compatibility as standard. +We temporarily restore "@section-size", which can avoid incompatible +API breakage. The "@section-size" will be deprecated in 7.2 version. + +Suggested-by: Daniel P. Berrangé +Signed-off-by: Yang Zhong +Reviewed-by: Daniel P. Berrangé +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20220120223104.437161-1-yang.zhong@intel.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Jason Zeng +--- + docs/about/deprecated.rst | 13 +++++++++++++ + hw/i386/sgx.c | 11 +++++++++-- + qapi/machine.json | 4 ++-- + qapi/misc-target.json | 22 +++++++++++++++++----- + 4 files changed, 41 insertions(+), 9 deletions(-) + +diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst +index ff7488cb63..33925edf45 100644 +--- a/docs/about/deprecated.rst ++++ b/docs/about/deprecated.rst +@@ -270,6 +270,19 @@ accepted incorrect commands will return an error. Users should make sure that + all arguments passed to ``device_add`` are consistent with the documented + property types. + ++``query-sgx`` return value member ``section-size`` (since 7.0) ++'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ++ ++Member ``section-size`` in return value elements with meta-type ``uint64`` is ++deprecated. Use ``sections`` instead. ++ ++ ++``query-sgx-capabilities`` return value member ``section-size`` (since 7.0) ++''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ++ ++Member ``section-size`` in return value elements with meta-type ``uint64`` is ++deprecated. Use ``sections`` instead. ++ + System accelerators + ------------------- + +diff --git a/hw/i386/sgx.c b/hw/i386/sgx.c +index 5de5dd0893..a2b318dd93 100644 +--- a/hw/i386/sgx.c ++++ b/hw/i386/sgx.c +@@ -83,7 +83,7 @@ static uint64_t sgx_calc_section_metric(uint64_t low, uint64_t high) + ((high & MAKE_64BIT_MASK(0, 20)) << 32); + } + +-static SGXEPCSectionList *sgx_calc_host_epc_sections(void) ++static SGXEPCSectionList *sgx_calc_host_epc_sections(uint64_t *size) + { + SGXEPCSectionList *head = NULL, **tail = &head; + SGXEPCSection *section; +@@ -106,6 +106,7 @@ static SGXEPCSectionList *sgx_calc_host_epc_sections(void) + section = g_new0(SGXEPCSection, 1); + section->node = j++; + section->size = sgx_calc_section_metric(ecx, edx); ++ *size += section->size; + QAPI_LIST_APPEND(tail, section); + } + +@@ -156,6 +157,7 @@ SGXInfo *qmp_query_sgx_capabilities(Error **errp) + { + SGXInfo *info = NULL; + uint32_t eax, ebx, ecx, edx; ++ uint64_t size = 0; + + int fd = qemu_open_old("/dev/sgx_vepc", O_RDWR); + if (fd < 0) { +@@ -173,7 +175,8 @@ SGXInfo *qmp_query_sgx_capabilities(Error **errp) + info->sgx1 = eax & (1U << 0) ? true : false; + info->sgx2 = eax & (1U << 1) ? true : false; + +- info->sections = sgx_calc_host_epc_sections(); ++ info->sections = sgx_calc_host_epc_sections(&size); ++ info->section_size = size; + + close(fd); + +@@ -220,12 +223,14 @@ SGXInfo *qmp_query_sgx(Error **errp) + return NULL; + } + ++ SGXEPCState *sgx_epc = &pcms->sgx_epc; + info = g_new0(SGXInfo, 1); + + info->sgx = true; + info->sgx1 = true; + info->sgx2 = true; + info->flc = true; ++ info->section_size = sgx_epc->size; + info->sections = sgx_get_epc_sections_list(); + + return info; +@@ -249,6 +254,8 @@ void hmp_info_sgx(Monitor *mon, const QDict *qdict) + info->sgx2 ? "enabled" : "disabled"); + monitor_printf(mon, "FLC support: %s\n", + info->flc ? "enabled" : "disabled"); ++ monitor_printf(mon, "size: %" PRIu64 "\n", ++ info->section_size); + + section_list = info->sections; + for (section = section_list; section; section = section->next) { +diff --git a/qapi/machine.json b/qapi/machine.json +index 85c35e7fc5..03cfb268a4 100644 +--- a/qapi/machine.json ++++ b/qapi/machine.json +@@ -1209,7 +1209,7 @@ + # + # @memdev: memory backend linked with device + # +-# @node: the numa node ++# @node: the numa node (Since: 7.0) + # + # Since: 6.2 + ## +@@ -1290,7 +1290,7 @@ + # + # @memdev: memory backend linked with device + # +-# @node: the numa node ++# @node: the numa node (Since: 7.0) + # + # Since: 6.2 + ## +diff --git a/qapi/misc-target.json b/qapi/misc-target.json +index 1022aa0184..4bc45d2474 100644 +--- a/qapi/misc-target.json ++++ b/qapi/misc-target.json +@@ -344,9 +344,9 @@ + # + # @node: the numa node + # +-# @size: the size of epc section ++# @size: the size of EPC section + # +-# Since: 6.2 ++# Since: 7.0 + ## + { 'struct': 'SGXEPCSection', + 'data': { 'node': 'int', +@@ -365,7 +365,13 @@ + # + # @flc: true if FLC is supported + # +-# @sections: The EPC sections info for guest ++# @section-size: The EPC section size for guest ++# Redundant with @sections. Just for backward compatibility. ++# ++# @sections: The EPC sections info for guest (Since: 7.0) ++# ++# Features: ++# @deprecated: Member @section-size is deprecated. Use @sections instead. + # + # Since: 6.2 + ## +@@ -374,6 +380,8 @@ + 'sgx1': 'bool', + 'sgx2': 'bool', + 'flc': 'bool', ++ 'section-size': { 'type': 'uint64', ++ 'features': [ 'deprecated' ] }, + 'sections': ['SGXEPCSection']}, + 'if': 'TARGET_I386' } + +@@ -390,7 +398,9 @@ + # + # -> { "execute": "query-sgx" } + # <- { "return": { "sgx": true, "sgx1" : true, "sgx2" : true, +-# "flc": true, "section-size" : 0 } } ++# "flc": true, "section-size" : 96468992, ++# "sections": [{"node": 0, "size": 67108864}, ++# {"node": 1, "size": 29360128}]} } + # + ## + { 'command': 'query-sgx', 'returns': 'SGXInfo', 'if': 'TARGET_I386' } +@@ -408,7 +418,9 @@ + # + # -> { "execute": "query-sgx-capabilities" } + # <- { "return": { "sgx": true, "sgx1" : true, "sgx2" : true, +-# "flc": true, "section-size" : 0 } } ++# "flc": true, "section-size" : 96468992, ++# "section" : [{"node": 0, "size": 67108864}, ++# {"node": 1, "size": 29360128}]} } + # + ## + { 'command': 'query-sgx-capabilities', 'returns': 'SGXInfo', 'if': 'TARGET_I386' } +-- +2.27.0 + diff --git a/qemu.spec b/qemu.spec index 8f7892f..ebe08ff 100644 --- a/qemu.spec +++ b/qemu.spec @@ -1,6 +1,6 @@ Name: qemu Version: 6.2.0 -Release: 44 +Release: 45 Epoch: 2 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -283,6 +283,15 @@ Patch0269: hw-nvme-fix-CVE-2021-3929.patch Patch0270: acpi-validate-hotplug-selector-on-access.patch Patch0271: virtiofsd-Drop-membership-of-all-supplementary-group.patch Patch0272: softmmu-Always-initialize-xlat-in-address_space_tran.patch +Patch0273: numa-Enable-numa-for-SGX-EPC-sections.patch +Patch0274: numa-Support-SGX-numa-in-the-monitor-and-Libvirt-int.patch +Patch0275: doc-Add-the-SGX-numa-description.patch +Patch0276: qapi-Cleanup-SGX-related-comments-and-restore-sectio.patch +Patch0277: target-ppc-add-error-report-when-fopen-fails-in-kvmp.patch +Patch0278: target-ppc-enhance-error-report-in-kvmppc_read_int_c.patch +Patch0279: target-ppc-use-g_autofree-in-kvmppc_read_int_cpu_dt.patch +Patch0280: target-ppc-exit-1-on-failure-in-kvmppc_get_clockfreq.patch +Patch0281: bugfix-pointer-double-free-in-func-qemu_savevm_state.patch BuildRequires: flex BuildRequires: gcc @@ -786,6 +795,11 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Thu Aug 11 2022 yezengruan - 2:6.2.0-45 +- numa: Enable numa for SGX EPC sections +- target/ppc: enhance error handling in kvmppc_read_int* +- fix pointer double free in func qemu_savevm_state_complete_precopy_non_iterable + * Mon Jul 25 2022 yezengruan - 2:6.2.0-44 - add Requires libgcc diff --git a/target-ppc-add-error-report-when-fopen-fails-in-kvmp.patch b/target-ppc-add-error-report-when-fopen-fails-in-kvmp.patch new file mode 100644 index 0000000..6c0c8a1 --- /dev/null +++ b/target-ppc-add-error-report-when-fopen-fails-in-kvmp.patch @@ -0,0 +1,50 @@ +From 67a8e57c784ccbce4989c39dd44c70ae7f5aeda4 Mon Sep 17 00:00:00 2001 +From: jianchunfu +Date: Thu, 4 Aug 2022 15:37:47 +0800 +Subject: [PATCH 5/9] target/ppc: add error report when fopen fails in + kvmppc_read_int_dt() + +Use an Error pointer to report the error back to the caller. +While we're at it, return '0' instead of '-1' on error since the +function is supposed to return an uint64_t. + +Signed-off-by: jianchunfu +--- + target/ppc/kvm.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c +index dc93b99189..63382256c3 100644 +--- a/target/ppc/kvm.c ++++ b/target/ppc/kvm.c +@@ -1895,7 +1895,7 @@ static int kvmppc_find_cpu_dt(char *buf, int buf_len) + return 0; + } + +-static uint64_t kvmppc_read_int_dt(const char *filename) ++static uint64_t kvmppc_read_int_dt(const char *filename, Error **errp) + { + union { + uint32_t v32; +@@ -1906,7 +1906,8 @@ static uint64_t kvmppc_read_int_dt(const char *filename) + + f = fopen(filename, "rb"); + if (!f) { +- return -1; ++ error_setg_errno(errp, errno, "error opening %s", filename); ++ return 0; + } + + len = fread(&u, 1, sizeof(u), f); +@@ -1937,7 +1938,7 @@ static uint64_t kvmppc_read_int_cpu_dt(const char *propname) + } + + tmp = g_strdup_printf("%s/%s", buf, propname); +- val = kvmppc_read_int_dt(tmp); ++ val = kvmppc_read_int_dt(tmp, NULL); + g_free(tmp); + + return val; +-- +2.27.0 + diff --git a/target-ppc-enhance-error-report-in-kvmppc_read_int_c.patch b/target-ppc-enhance-error-report-in-kvmppc_read_int_c.patch new file mode 100644 index 0000000..c05844a --- /dev/null +++ b/target-ppc-enhance-error-report-in-kvmppc_read_int_c.patch @@ -0,0 +1,81 @@ +From b167d664414e7d4a5a7a7058bc4c7699f6e66d48 Mon Sep 17 00:00:00 2001 +From: jianchunfu +Date: Thu, 4 Aug 2022 15:57:46 +0800 +Subject: [PATCH 6/9] target/ppc: enhance error report in + kvmppc_read_int_cpu_dt() + +First and foremost, the function can't return '-1' when an error occurs +because the return type is set to uint64_t. Let's fix that. +After that, the function can't simply return 0 whether an error happened +and call it a day. We must provide a way of letting callers know if the +zero return is legitimate or due to an error. +Add an Error pointer to kvmppc_read_int_cpu_dt() that will be filled +with an appropriate error, if one occurs. Callers are then free to pass +an Error pointer and handle it. + +Signed-off-by: jianchunfu +--- + target/ppc/kvm.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c +index 63382256c3..d64d7c5b4a 100644 +--- a/target/ppc/kvm.c ++++ b/target/ppc/kvm.c +@@ -1925,20 +1925,22 @@ static uint64_t kvmppc_read_int_dt(const char *filename, Error **errp) + + /* + * Read a CPU node property from the host device tree that's a single +- * integer (32-bit or 64-bit). Returns 0 if anything goes wrong +- * (can't find or open the property, or doesn't understand the format) ++ * integer (32-bit or 64-bit). Returns 0 and set errp if anything goes ++ * wrong (can't find or open the property, or doesn't understand the ++ * format) + */ +-static uint64_t kvmppc_read_int_cpu_dt(const char *propname) ++static uint64_t kvmppc_read_int_cpu_dt(const char *propname, Error **errp) + { + char buf[PATH_MAX], *tmp; + uint64_t val; + + if (kvmppc_find_cpu_dt(buf, sizeof(buf))) { +- return -1; ++ error_setg(errp, "Failed to read CPU property %s", propname); ++ return 0; + } + + tmp = g_strdup_printf("%s/%s", buf, propname); +- val = kvmppc_read_int_dt(tmp, NULL); ++ val = kvmppc_read_int_dt(tmp, errp); + g_free(tmp); + + return val; +@@ -1946,12 +1948,12 @@ static uint64_t kvmppc_read_int_cpu_dt(const char *propname) + + uint64_t kvmppc_get_clockfreq(void) + { +- return kvmppc_read_int_cpu_dt("clock-frequency"); ++ return kvmppc_read_int_cpu_dt("clock-frequency", NULL); + } + + static int kvmppc_get_dec_bits(void) + { +- int nr_bits = kvmppc_read_int_cpu_dt("ibm,dec-bits"); ++ int nr_bits = kvmppc_read_int_cpu_dt("ibm,dec-bits", NULL); + + if (nr_bits > 0) { + return nr_bits; +@@ -2336,8 +2338,8 @@ static void alter_insns(uint64_t *word, uint64_t flags, bool on) + static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data) + { + PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); +- uint32_t dcache_size = kvmppc_read_int_cpu_dt("d-cache-size"); +- uint32_t icache_size = kvmppc_read_int_cpu_dt("i-cache-size"); ++ uint32_t dcache_size = kvmppc_read_int_cpu_dt("d-cache-size", NULL); ++ uint32_t icache_size = kvmppc_read_int_cpu_dt("i-cache-size", NULL); + + /* Now fix up the class with information we can query from the host */ + pcc->pvr = mfpvr(); +-- +2.27.0 + diff --git a/target-ppc-exit-1-on-failure-in-kvmppc_get_clockfreq.patch b/target-ppc-exit-1-on-failure-in-kvmppc_get_clockfreq.patch new file mode 100644 index 0000000..140f2fd --- /dev/null +++ b/target-ppc-exit-1-on-failure-in-kvmppc_get_clockfreq.patch @@ -0,0 +1,51 @@ +From 584a648e0de0b0bda49e87349f2db3b2f0f87c33 Mon Sep 17 00:00:00 2001 +From: jianchunfu +Date: Thu, 4 Aug 2022 16:47:26 +0800 +Subject: [PATCH 8/9] target/ppc: exit(1) on failure in kvmppc_get_clockfreq() + +When running under KVM accel it is expected to have 'clock-frequency' in +the DT. Not having this attribute is too risky for both the machine +emulation and userspace. +We have a way of telling whether this error scenario might happen or not +via kvmppc_read_int_cpu_dt() now being able to report errors. From now +on, when running KVM, we will assume that 'clock-frequency' will always +be present in the DT. + +Signed-off-by: jianchunfu +--- + target/ppc/kvm.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c +index 1a6c6b6fa0..d73563045b 100644 +--- a/target/ppc/kvm.c ++++ b/target/ppc/kvm.c +@@ -1944,9 +1944,24 @@ static uint64_t kvmppc_read_int_cpu_dt(const char *propname, Error **errp) + return kvmppc_read_int_dt(tmp, errp); + } + ++/* ++ * Read the clock-frequency from the DT. On error (e.g. ++ * 'clock-frequency' is not present in the DT) will ++ * report an error and exit(1). ++ */ + uint64_t kvmppc_get_clockfreq(void) + { +- return kvmppc_read_int_cpu_dt("clock-frequency", NULL); ++ Error *local_err = NULL; ++ int ret; ++ ++ ret = kvmppc_read_int_cpu_dt("clock-frequency", &local_err); ++ ++ if (local_err) { ++ error_report_err(local_err); ++ exit(1); ++ } ++ ++ return ret; + } + + static int kvmppc_get_dec_bits(void) +-- +2.27.0 + diff --git a/target-ppc-use-g_autofree-in-kvmppc_read_int_cpu_dt.patch b/target-ppc-use-g_autofree-in-kvmppc_read_int_cpu_dt.patch new file mode 100644 index 0000000..7ffb973 --- /dev/null +++ b/target-ppc-use-g_autofree-in-kvmppc_read_int_cpu_dt.patch @@ -0,0 +1,43 @@ +From 02a15861235d29dcf89b61bf88fed2ec4ccee9dc Mon Sep 17 00:00:00 2001 +From: jianchunfu +Date: Thu, 4 Aug 2022 16:41:35 +0800 +Subject: [PATCH 7/9] target/ppc: use g_autofree in kvmppc_read_int_cpu_dt() + +This spares us a g_free() call. Let's also not use 'val' and return the +value of kvmppc_read_int_dt() directly. + +Signed-off-by: jianchunfu +--- + target/ppc/kvm.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c +index d64d7c5b4a..1a6c6b6fa0 100644 +--- a/target/ppc/kvm.c ++++ b/target/ppc/kvm.c +@@ -1931,8 +1931,8 @@ static uint64_t kvmppc_read_int_dt(const char *filename, Error **errp) + */ + static uint64_t kvmppc_read_int_cpu_dt(const char *propname, Error **errp) + { +- char buf[PATH_MAX], *tmp; +- uint64_t val; ++ g_autofree char *tmp = NULL; ++ char buf[PATH_MAX]; + + if (kvmppc_find_cpu_dt(buf, sizeof(buf))) { + error_setg(errp, "Failed to read CPU property %s", propname); +@@ -1940,10 +1940,8 @@ static uint64_t kvmppc_read_int_cpu_dt(const char *propname, Error **errp) + } + + tmp = g_strdup_printf("%s/%s", buf, propname); +- val = kvmppc_read_int_dt(tmp, errp); +- g_free(tmp); + +- return val; ++ return kvmppc_read_int_dt(tmp, errp); + } + + uint64_t kvmppc_get_clockfreq(void) +-- +2.27.0 + -- Gitee