Update patch with openeuler !232

Signed-off-by: imxcc <xingchaochao@huawei.com>
This commit is contained in:
imxcc 2022-02-17 22:34:34 +08:00 committed by yezengruan
parent 65b515392c
commit 8a7a7c9d07
26 changed files with 3168 additions and 1 deletions

Binary file not shown.

View File

@ -0,0 +1,616 @@
From e7e28e79988eb671051d0d2af0eb010314c83d41 Mon Sep 17 00:00:00 2001
From: Ying Fang <fangying1@huawei.com>
Date: Tue, 8 Feb 2022 21:01:09 +0800
Subject: [PATCH 24/24] arm64: Add the cpufreq device to show cpufreq info to
guest
On ARM64 platform, cpu frequency is retrieved via ACPI CPPC.
A virtual cpufreq device based on ACPI CPPC is created to
present cpu frequency info to the guest.
The default frequency is set to host cpu nominal frequency,
which is obtained from the host CPPC sysfs. Other performance
data are set to the same value, since we don't support guest
performance scaling here.
Performance counters are also not emulated and they simply
return 1 if read, and guest should fallback to use desired
performance value as the current performance.
Guest kernel version above 4.18 is required to make it work.
This series is backported from:
https://patchwork.kernel.org/cover/11379943/
Signed-off-by: Ying Fang <fangying1@huawei.com>
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
---
configs/devices/aarch64-softmmu/default.mak | 1 +
hw/acpi/aml-build.c | 22 ++
hw/acpi/cpufreq.c | 283 ++++++++++++++++++++
hw/acpi/meson.build | 1 +
hw/arm/virt-acpi-build.c | 77 +++++-
hw/arm/virt.c | 13 +
hw/char/Kconfig | 4 +
include/hw/acpi/acpi-defs.h | 38 +++
include/hw/acpi/aml-build.h | 3 +
include/hw/arm/virt.h | 1 +
tests/data/acpi/virt/DSDT | Bin 5196 -> 5669 bytes
tests/data/acpi/virt/DSDT.memhp | Bin 6557 -> 7030 bytes
tests/data/acpi/virt/DSDT.numamem | Bin 5196 -> 5669 bytes
tests/data/acpi/virt/DSDT.pxb | Bin 7679 -> 8152 bytes
14 files changed, 441 insertions(+), 2 deletions(-)
create mode 100644 hw/acpi/cpufreq.c
diff --git a/configs/devices/aarch64-softmmu/default.mak b/configs/devices/aarch64-softmmu/default.mak
index cf43ac8da1..c7a710a0f1 100644
--- a/configs/devices/aarch64-softmmu/default.mak
+++ b/configs/devices/aarch64-softmmu/default.mak
@@ -6,3 +6,4 @@ include ../arm-softmmu/default.mak
CONFIG_XLNX_ZYNQMP_ARM=y
CONFIG_XLNX_VERSAL=y
CONFIG_SBSA_REF=y
+CONFIG_CPUFREQ=y
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index bebf49622b..c4edaafa4a 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1554,6 +1554,28 @@ Aml *aml_sleep(uint64_t msec)
return var;
}
+/* ACPI 5.0b: 6.4.3.7 Generic Register Descriptor */
+Aml *aml_generic_register(AmlRegionSpace rs, uint8_t reg_width,
+ uint8_t reg_offset, AmlAccessType type, uint64_t addr)
+{
+ int i;
+ Aml *var = aml_alloc();
+ build_append_byte(var->buf, 0x82); /* Generic Register Descriptor */
+ build_append_byte(var->buf, 0x0C); /* Length, bits[7:0] value = 0x0C */
+ build_append_byte(var->buf, 0); /* Length, bits[15:8] value = 0 */
+ build_append_byte(var->buf, rs); /* Address Space ID */
+ build_append_byte(var->buf, reg_width); /* Register Bit Width */
+ build_append_byte(var->buf, reg_offset); /* Register Bit Offset */
+ build_append_byte(var->buf, type); /* Access Size */
+
+ /* Register address */
+ for (i = 0; i < 8; i++) {
+ build_append_byte(var->buf, extract64(addr, i * 8, 8));
+ }
+
+ return var;
+}
+
static uint8_t Hex2Byte(const char *src)
{
int hi, lo;
diff --git a/hw/acpi/cpufreq.c b/hw/acpi/cpufreq.c
new file mode 100644
index 0000000000..a84db490b3
--- /dev/null
+++ b/hw/acpi/cpufreq.c
@@ -0,0 +1,283 @@
+/*
+ * ACPI CPPC register device
+ *
+ * Support for showing CPU frequency in guest OS.
+ *
+ * Copyright (c) 2019 HUAWEI TECHNOLOGIES CO.,LTD.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "chardev/char.h"
+#include "qemu/log.h"
+#include "trace.h"
+#include "qemu/option.h"
+#include "sysemu/sysemu.h"
+#include "hw/acpi/acpi-defs.h"
+#include "qemu/cutils.h"
+#include "qemu/error-report.h"
+#include "hw/boards.h"
+
+#define TYPE_CPUFREQ "cpufreq"
+#define CPUFREQ(obj) OBJECT_CHECK(CpuhzState, (obj), TYPE_CPUFREQ)
+#define NOMINAL_FREQ_FILE "/sys/devices/system/cpu/cpu0/acpi_cppc/nominal_freq"
+#define CPU_MAX_FREQ_FILE "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq"
+#define HZ_MAX_LENGTH 1024
+#define MAX_SUPPORT_SPACE 0x10000
+
+/*
+ * Since Hi1616 will not support CPPC, we simply use its nominal frequency as
+ * the default.
+ */
+#define DEFAULT_HZ 2400
+
+int cppc_regs_offset[CPPC_REG_COUNT] = {
+ [HIGHEST_PERF] = 0,
+ [NOMINAL_PERF] = 4,
+ [LOW_NON_LINEAR_PERF] = 8,
+ [LOWEST_PERF] = 12,
+ [GUARANTEED_PERF] = 16,
+ [DESIRED_PERF] = 20,
+ [MIN_PERF] = -1,
+ [MAX_PERF] = -1,
+ [PERF_REDUC_TOLERANCE] = -1,
+ [TIME_WINDOW] = -1,
+ [CTR_WRAP_TIME] = -1,
+ [REFERENCE_CTR] = 24,
+ [DELIVERED_CTR] = 32,
+ [PERF_LIMITED] = 40,
+ [ENABLE] = -1,
+ [AUTO_SEL_ENABLE] = -1,
+ [AUTO_ACT_WINDOW] = -1,
+ [ENERGY_PERF] = -1,
+ [REFERENCE_PERF] = -1,
+ [LOWEST_FREQ] = 44,
+ [NOMINAL_FREQ] = 48,
+};
+
+typedef struct CpuhzState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ uint32_t HighestPerformance;
+ uint32_t NominalPerformance;
+ uint32_t LowestNonlinearPerformance;
+ uint32_t LowestPerformance;
+ uint32_t GuaranteedPerformance;
+ uint32_t DesiredPerformance;
+ uint64_t ReferencePerformanceCounter;
+ uint64_t DeliveredPerformanceCounter;
+ uint32_t PerformanceLimited;
+ uint32_t LowestFreq;
+ uint32_t NominalFreq;
+ uint32_t reg_size;
+} CpuhzState;
+
+
+static uint64_t cpufreq_read(void *opaque, hwaddr offset, unsigned size)
+{
+ CpuhzState *s = (CpuhzState *)opaque;
+ uint64_t r;
+ uint64_t n;
+
+ MachineState *ms = MACHINE(qdev_get_machine());
+ unsigned int smp_cpus = ms->smp.cpus;
+
+ if (offset >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) {
+ warn_report("cpufreq_read: offset 0x%lx out of range", offset);
+ return 0;
+ }
+
+ n = offset % CPPC_REG_PER_CPU_STRIDE;
+ switch (n) {
+ case 0:
+ r = s->HighestPerformance;
+ break;
+ case 4:
+ r = s->NominalPerformance;
+ break;
+ case 8:
+ r = s->LowestNonlinearPerformance;
+ break;
+ case 12:
+ r = s->LowestPerformance;
+ break;
+ case 16:
+ r = s->GuaranteedPerformance;
+ break;
+ case 20:
+ r = s->DesiredPerformance;
+ break;
+ /*
+ * We don't have real counters and it is hard to emulate, so always set the
+ * counter value to 1 to rely on Linux to use the DesiredPerformance value
+ * directly.
+ */
+ case 24:
+ r = s->ReferencePerformanceCounter;
+ break;
+ /*
+ * Guest may still access the register by 32bit; add the process to
+ * eliminate unnecessary warnings.
+ */
+ case 28:
+ r = s->ReferencePerformanceCounter >> 32;
+ break;
+ case 32:
+ r = s->DeliveredPerformanceCounter;
+ break;
+ case 36:
+ r = s->DeliveredPerformanceCounter >> 32;
+ break;
+
+ case 40:
+ r = s->PerformanceLimited;
+ break;
+ case 44:
+ r = s->LowestFreq;
+ break;
+ case 48:
+ r = s->NominalFreq;
+ break;
+ default:
+ error_printf("cpufreq_read: Bad offset 0x%lx\n", offset);
+ r = 0;
+ break;
+ }
+ return r;
+}
+
+static void cpufreq_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+ uint64_t n;
+ MachineState *ms = MACHINE(qdev_get_machine());
+ unsigned int smp_cpus = ms->smp.cpus;
+
+ if (offset >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) {
+ error_printf("cpufreq_write: offset 0x%lx out of range", offset);
+ return;
+ }
+
+ n = offset % CPPC_REG_PER_CPU_STRIDE;
+
+ switch (n) {
+ case 20:
+ break;
+ default:
+ error_printf("cpufreq_write: Bad offset 0x%lx\n", offset);
+ }
+}
+
+static uint32_t CPPC_Read(const char *hostpath)
+{
+ int fd;
+ char buffer[HZ_MAX_LENGTH] = { 0 };
+ uint64_t hz;
+ int len;
+ const char *endptr = NULL;
+ int ret;
+
+ fd = qemu_open_old(hostpath, O_RDONLY);
+ if (fd < 0) {
+ return 0;
+ }
+
+ len = read(fd, buffer, HZ_MAX_LENGTH);
+ qemu_close(fd);
+ if (len <= 0) {
+ return 0;
+ }
+ ret = qemu_strtoul(buffer, &endptr, 0, &hz);
+ if (ret < 0) {
+ return 0;
+ }
+ return (uint32_t)hz;
+}
+
+static const MemoryRegionOps cpufreq_ops = {
+ .read = cpufreq_read,
+ .write = cpufreq_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void hz_init(CpuhzState *s)
+{
+ uint32_t hz;
+
+ hz = CPPC_Read(NOMINAL_FREQ_FILE);
+ if (hz == 0) {
+ hz = CPPC_Read(CPU_MAX_FREQ_FILE);
+ if (hz == 0) {
+ hz = DEFAULT_HZ;
+ } else {
+ /* Value in CpuMaxFrequency is in KHz unit; convert to MHz */
+ hz = hz / 1000;
+ }
+ }
+
+ s->HighestPerformance = hz;
+ s->NominalPerformance = hz;
+ s->LowestNonlinearPerformance = hz;
+ s->LowestPerformance = hz;
+ s->GuaranteedPerformance = hz;
+ s->DesiredPerformance = hz;
+ s->ReferencePerformanceCounter = 1;
+ s->DeliveredPerformanceCounter = 1;
+ s->PerformanceLimited = 0;
+ s->LowestFreq = hz;
+ s->NominalFreq = hz;
+}
+
+static void cpufreq_init(Object *obj)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ CpuhzState *s = CPUFREQ(obj);
+
+ MachineState *ms = MACHINE(qdev_get_machine());
+ unsigned int smp_cpus = ms->smp.cpus;
+
+ s->reg_size = smp_cpus * CPPC_REG_PER_CPU_STRIDE;
+ if (s->reg_size > MAX_SUPPORT_SPACE) {
+ error_report("Required space 0x%x excesses the max support 0x%x",
+ s->reg_size, MAX_SUPPORT_SPACE);
+ goto err_end;
+ }
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &cpufreq_ops, s, "cpufreq",
+ s->reg_size);
+ sysbus_init_mmio(sbd, &s->iomem);
+ hz_init(s);
+ return;
+
+err_end:
+ /* Set desired perf register offset to -1 to indicate no support for CPPC */
+ cppc_regs_offset[DESIRED_PERF] = -1;
+}
+
+static const TypeInfo cpufreq_arm_info = {
+ .name = TYPE_CPUFREQ,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(CpuhzState),
+ .instance_init = cpufreq_init,
+};
+
+static void cpufreq_register_types(void)
+{
+ type_register_static(&cpufreq_arm_info);
+}
+
+type_init(cpufreq_register_types)
diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build
index adf6347bc4..448ea6afb4 100644
--- a/hw/acpi/meson.build
+++ b/hw/acpi/meson.build
@@ -25,6 +25,7 @@ acpi_ss.add(when: 'CONFIG_ACPI_X86_ICH', if_true: files('ich9.c', 'tco.c'))
acpi_ss.add(when: 'CONFIG_IPMI', if_true: files('ipmi.c'), if_false: files('ipmi-stub.c'))
acpi_ss.add(when: 'CONFIG_PC', if_false: files('acpi-x86-stub.c'))
acpi_ss.add(when: 'CONFIG_TPM', if_true: files('tpm.c'))
+acpi_ss.add(when: 'CONFIG_CPUFREQ', if_true: files('cpufreq.c'))
softmmu_ss.add(when: 'CONFIG_ACPI', if_false: files('acpi-stub.c', 'aml-build-stub.c', 'ghes-stub.c'))
softmmu_ss.add_all(when: 'CONFIG_ACPI', if_true: acpi_ss)
softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('acpi-stub.c', 'aml-build-stub.c',
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 674f902652..1ca705654b 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -60,7 +60,68 @@
#define ACPI_BUILD_TABLE_SIZE 0x20000
-static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms)
+static void acpi_dsdt_add_psd(Aml *dev, int cpus)
+{
+ Aml *pkg;
+ Aml *sub;
+
+ sub = aml_package(5);
+ aml_append(sub, aml_int(5));
+ aml_append(sub, aml_int(0));
+ /* Assume all vCPUs belong to the same domain */
+ aml_append(sub, aml_int(0));
+ /* SW_ANY: OSPM coordinate, initiate on any processor */
+ aml_append(sub, aml_int(0xFD));
+ aml_append(sub, aml_int(cpus));
+
+ pkg = aml_package(1);
+ aml_append(pkg, sub);
+
+ aml_append(dev, aml_name_decl("_PSD", pkg));
+}
+
+static void acpi_dsdt_add_cppc(Aml *dev, uint64_t cpu_base, int *regs_offset)
+{
+ Aml *cpc;
+ int i;
+
+ /* Use version 3 of CPPC table from ACPI 6.3 */
+ cpc = aml_package(23);
+ aml_append(cpc, aml_int(23));
+ aml_append(cpc, aml_int(3));
+
+ for (i = 0; i < CPPC_REG_COUNT; i++) {
+ Aml *res;
+ uint8_t reg_width;
+ uint8_t acc_type;
+ uint64_t addr;
+
+ if (regs_offset[i] == -1) {
+ reg_width = 0;
+ acc_type = AML_ANY_ACC;
+ addr = 0;
+ } else {
+ addr = cpu_base + regs_offset[i];
+ if (i == REFERENCE_CTR || i == DELIVERED_CTR) {
+ reg_width = 64;
+ acc_type = AML_QWORD_ACC;
+ } else {
+ reg_width = 32;
+ acc_type = AML_DWORD_ACC;
+ }
+ }
+
+ res = aml_resource_template();
+ aml_append(res, aml_generic_register(AML_SYSTEM_MEMORY, reg_width, 0,
+ acc_type, addr));
+ aml_append(cpc, res);
+ }
+
+ aml_append(dev, aml_name_decl("_CPC", cpc));
+}
+
+static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms,
+ const MemMapEntry *cppc_memmap)
{
MachineState *ms = MACHINE(vms);
uint16_t i;
@@ -69,6 +130,18 @@ static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms)
Aml *dev = aml_device("C%.03X", i);
aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007")));
aml_append(dev, aml_name_decl("_UID", aml_int(i)));
+
+ /*
+ * Append _CPC and _PSD to support CPU frequence show
+ * Check CPPC available by DESIRED_PERF register
+ */
+ if (cppc_regs_offset[DESIRED_PERF] != -1) {
+ acpi_dsdt_add_cppc(dev,
+ cppc_memmap->base + i * CPPC_REG_PER_CPU_STRIDE,
+ cppc_regs_offset);
+ acpi_dsdt_add_psd(dev, ms->smp.cpus);
+ }
+
aml_append(scope, dev);
}
}
@@ -858,7 +931,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
* the RTC ACPI device at all when using UEFI.
*/
scope = aml_scope("\\_SB");
- acpi_dsdt_add_cpus(scope, vms);
+ acpi_dsdt_add_cpus(scope, vms, &memmap[VIRT_CPUFREQ]);
acpi_dsdt_add_uart(scope, &memmap[VIRT_UART],
(irqmap[VIRT_UART] + ARM_SPI_BASE));
if (vmc->acpi_expose_flash) {
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 529c0d38b6..0538d258fa 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -154,6 +154,7 @@ static const MemMapEntry base_memmap[] = {
[VIRT_PVTIME] = { 0x090a0000, 0x00010000 },
[VIRT_SECURE_GPIO] = { 0x090b0000, 0x00001000 },
[VIRT_MMIO] = { 0x0a000000, 0x00000200 },
+ [VIRT_CPUFREQ] = { 0x0b000000, 0x00010000 },
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
[VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 },
[VIRT_SECURE_MEM] = { 0x0e000000, 0x01000000 },
@@ -931,6 +932,16 @@ static void create_uart(const VirtMachineState *vms, int uart,
g_free(nodename);
}
+static void create_cpufreq(const VirtMachineState *vms, MemoryRegion *mem)
+{
+ hwaddr base = vms->memmap[VIRT_CPUFREQ].base;
+ DeviceState *dev = qdev_new("cpufreq");
+ SysBusDevice *s = SYS_BUS_DEVICE(dev);
+
+ sysbus_realize_and_unref(s, &error_fatal);
+ memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0));
+}
+
static void create_rtc(const VirtMachineState *vms)
{
char *nodename;
@@ -2190,6 +2201,8 @@ static void machvirt_init(MachineState *machine)
create_uart(vms, VIRT_UART, sysmem, serial_hd(0));
+ create_cpufreq(vms, sysmem);
+
if (vms->secure) {
create_secure_ram(vms, secure_sysmem, secure_tag_sysmem);
create_uart(vms, VIRT_SECURE_UART, secure_sysmem, serial_hd(1));
diff --git a/hw/char/Kconfig b/hw/char/Kconfig
index 6b6cf2fc1d..335a60c2c1 100644
--- a/hw/char/Kconfig
+++ b/hw/char/Kconfig
@@ -71,3 +71,7 @@ config GOLDFISH_TTY
config SHAKTI_UART
bool
+
+config CPUFREQ
+ bool
+ default y
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index c97e8633ad..ab86583228 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -92,4 +92,42 @@ typedef struct AcpiFadtData {
#define ACPI_FADT_ARM_PSCI_COMPLIANT (1 << 0)
#define ACPI_FADT_ARM_PSCI_USE_HVC (1 << 1)
+/*
+ * CPPC register definition from kernel header
+ * include/acpi/cppc_acpi.h
+ * The last element is newly added for easy use
+ */
+enum cppc_regs {
+ HIGHEST_PERF,
+ NOMINAL_PERF,
+ LOW_NON_LINEAR_PERF,
+ LOWEST_PERF,
+ GUARANTEED_PERF,
+ DESIRED_PERF,
+ MIN_PERF,
+ MAX_PERF,
+ PERF_REDUC_TOLERANCE,
+ TIME_WINDOW,
+ CTR_WRAP_TIME,
+ REFERENCE_CTR,
+ DELIVERED_CTR,
+ PERF_LIMITED,
+ ENABLE,
+ AUTO_SEL_ENABLE,
+ AUTO_ACT_WINDOW,
+ ENERGY_PERF,
+ REFERENCE_PERF,
+ LOWEST_FREQ,
+ NOMINAL_FREQ,
+ CPPC_REG_COUNT,
+};
+
+#define CPPC_REG_PER_CPU_STRIDE 0x40
+
+/*
+ * Offset for each CPPC register; -1 for unavailable
+ * The whole register space is unavailable if desired perf offset is -1.
+ */
+extern int cppc_regs_offset[CPPC_REG_COUNT];
+
#endif
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 8e8ad8029e..2e00d2e208 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -429,6 +429,9 @@ Aml *aml_dma(AmlDmaType typ, AmlDmaBusMaster bm, AmlTransferSize sz,
uint8_t channel);
Aml *aml_sleep(uint64_t msec);
Aml *aml_i2c_serial_bus_device(uint16_t address, const char *resource_source);
+Aml *aml_generic_register(AmlRegionSpace rs, uint8_t reg_width,
+ uint8_t reg_offset, AmlAccessType type,
+ uint64_t addr);
/* Block AML object primitives */
Aml *aml_scope(const char *name_format, ...) GCC_FMT_ATTR(1, 2);
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index dc6b66ffc8..a4356cf736 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -70,6 +70,7 @@ enum {
VIRT_GIC_REDIST,
VIRT_SMMU,
VIRT_UART,
+ VIRT_CPUFREQ,
VIRT_MMIO,
VIRT_RTC,
VIRT_FW_CFG,
--
2.27.0

View File

@ -0,0 +1,113 @@
From 66c935b435d90ef9c1ae4446c5edc07cbd8ba0ed Mon Sep 17 00:00:00 2001
From: Yanan Wang <wangyanan55@huawei.com>
Date: Fri, 7 Jan 2022 16:32:29 +0800
Subject: [PATCH 17/24] hw/acpi/aml-build: Improve scalability of PPTT
generation
Use g_queue APIs to reduce the nested loops and code indentation
with the processor hierarchy levels increasing. Consenquently,
it's more scalable to add new topology level to build_pptt.
No functional change intended.
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Message-id: 20220107083232.16256-4-wangyanan55@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
hw/acpi/aml-build.c | 50 +++++++++++++++++++++++++++++----------------
1 file changed, 32 insertions(+), 18 deletions(-)
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index b3b3310df3..6aaedca2e5 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -2001,7 +2001,10 @@ static void build_processor_hierarchy_node(GArray *tbl, uint32_t flags,
void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
const char *oem_id, const char *oem_table_id)
{
- int pptt_start = table_data->len;
+ GQueue *list = g_queue_new();
+ guint pptt_start = table_data->len;
+ guint parent_offset;
+ guint length, i;
int uid = 0;
int socket;
AcpiTable table = { .sig = "PPTT", .rev = 2,
@@ -2010,9 +2013,8 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
acpi_table_begin(&table, table_data);
for (socket = 0; socket < ms->smp.sockets; socket++) {
- uint32_t socket_offset = table_data->len - pptt_start;
- int core;
-
+ g_queue_push_tail(list,
+ GUINT_TO_POINTER(table_data->len - pptt_start));
build_processor_hierarchy_node(
table_data,
/*
@@ -2021,35 +2023,47 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
*/
(1 << 0),
0, socket, NULL, 0);
+ }
- for (core = 0; core < ms->smp.cores; core++) {
- uint32_t core_offset = table_data->len - pptt_start;
- int thread;
+ length = g_queue_get_length(list);
+ for (i = 0; i < length; i++) {
+ int core;
+ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
+ for (core = 0; core < ms->smp.cores; core++) {
if (ms->smp.threads > 1) {
+ g_queue_push_tail(list,
+ GUINT_TO_POINTER(table_data->len - pptt_start));
build_processor_hierarchy_node(
table_data,
(0 << 0), /* not a physical package */
- socket_offset, core, NULL, 0);
-
- for (thread = 0; thread < ms->smp.threads; thread++) {
- build_processor_hierarchy_node(
- table_data,
- (1 << 1) | /* ACPI Processor ID valid */
- (1 << 2) | /* Processor is a Thread */
- (1 << 3), /* Node is a Leaf */
- core_offset, uid++, NULL, 0);
- }
+ parent_offset, core, NULL, 0);
} else {
build_processor_hierarchy_node(
table_data,
(1 << 1) | /* ACPI Processor ID valid */
(1 << 3), /* Node is a Leaf */
- socket_offset, uid++, NULL, 0);
+ parent_offset, uid++, NULL, 0);
}
}
}
+ length = g_queue_get_length(list);
+ for (i = 0; i < length; i++) {
+ int thread;
+
+ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
+ for (thread = 0; thread < ms->smp.threads; thread++) {
+ build_processor_hierarchy_node(
+ table_data,
+ (1 << 1) | /* ACPI Processor ID valid */
+ (1 << 2) | /* Processor is a Thread */
+ (1 << 3), /* Node is a Leaf */
+ parent_offset, uid++, NULL, 0);
+ }
+ }
+
+ g_queue_free(list);
acpi_table_end(linker, &table);
}
--
2.27.0

View File

@ -0,0 +1,56 @@
From 9c16924ba0a77c34246b69e8b1faee219f266445 Mon Sep 17 00:00:00 2001
From: Yanan Wang <wangyanan55@huawei.com>
Date: Fri, 7 Jan 2022 16:32:31 +0800
Subject: [PATCH 19/24] hw/acpi/aml-build: Support cluster level in PPTT
generation
Support CPU cluster topology level in generation of ACPI
Processor Properties Topology Table (PPTT).
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Message-id: 20220107083232.16256-6-wangyanan55@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
hw/acpi/aml-build.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 6aaedca2e5..bb2cad63b5 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -2001,6 +2001,7 @@ static void build_processor_hierarchy_node(GArray *tbl, uint32_t flags,
void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
const char *oem_id, const char *oem_table_id)
{
+ MachineClass *mc = MACHINE_GET_CLASS(ms);
GQueue *list = g_queue_new();
guint pptt_start = table_data->len;
guint parent_offset;
@@ -2025,6 +2026,23 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
0, socket, NULL, 0);
}
+ if (mc->smp_props.clusters_supported) {
+ length = g_queue_get_length(list);
+ for (i = 0; i < length; i++) {
+ int cluster;
+
+ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
+ for (cluster = 0; cluster < ms->smp.clusters; cluster++) {
+ g_queue_push_tail(list,
+ GUINT_TO_POINTER(table_data->len - pptt_start));
+ build_processor_hierarchy_node(
+ table_data,
+ (0 << 0), /* not a physical package */
+ parent_offset, cluster, NULL, 0);
+ }
+ }
+ }
+
length = g_queue_get_length(list);
for (i = 0; i < length; i++) {
int core;
--
2.27.0

View File

@ -0,0 +1,69 @@
From 1fab7ee365c8daccedd19d3a1be56babe36afcc6 Mon Sep 17 00:00:00 2001
From: Yanan Wang <wangyanan55@huawei.com>
Date: Fri, 7 Jan 2022 16:32:27 +0800
Subject: [PATCH 15/24] hw/arm/virt: Support CPU cluster on ARM virt machine
ARM64 machines like Kunpeng Family Server Chips have a level
of hardware topology in which a group of CPU cores share L3
cache tag or L2 cache. For example, Kunpeng 920 typically
has 6 or 8 clusters in each NUMA node (also represent range
of CPU die), and each cluster has 4 CPU cores. All clusters
share L3 cache data, but CPU cores in each cluster share a
local L3 tag.
Running a guest kernel with Cluster-Aware Scheduling on the
Hosts which have physical clusters, if we can design a vCPU
topology with cluster level for guest kernel and then have
a dedicated vCPU pinning, the guest will gain scheduling
performance improvement from cache affinity of CPU cluster.
So let's enable the support for this new parameter on ARM
virt machines. After this patch, we can define a 4-level
CPU hierarchy like: cpus=*,maxcpus=*,sockets=*,clusters=*,
cores=*,threads=*.
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Message-id: 20220107083232.16256-2-wangyanan55@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
hw/arm/virt.c | 1 +
qemu-options.hx | 10 ++++++++++
2 files changed, 11 insertions(+)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 3c972fdab0..6ca9cbe2cf 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2704,6 +2704,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
hc->unplug_request = virt_machine_device_unplug_request_cb;
hc->unplug = virt_machine_device_unplug_cb;
mc->nvdimm_supported = true;
+ mc->smp_props.clusters_supported = true;
mc->auto_enable_numa_with_memhp = true;
mc->auto_enable_numa_with_memdev = true;
mc->default_ram_id = "mach-virt.ram";
diff --git a/qemu-options.hx b/qemu-options.hx
index 0f26f7dad7..74d335e4c3 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -277,6 +277,16 @@ SRST
-smp 16,sockets=2,dies=2,cores=2,threads=2,maxcpus=16
+ The following sub-option defines a CPU topology hierarchy (2 sockets
+ totally on the machine, 2 clusters per socket, 2 cores per cluster,
+ 2 threads per core) for ARM virt machines which support sockets/clusters
+ /cores/threads. Some members of the option can be omitted but their values
+ will be automatically computed:
+
+ ::
+
+ -smp 16,sockets=2,clusters=2,cores=2,threads=2,maxcpus=16
+
Historically preference was given to the coarsest topology parameters
when computing missing values (ie sockets preferred over cores, which
were preferred over threads), however, this behaviour is considered
--
2.27.0

View File

@ -0,0 +1,57 @@
From 38d9ae59b9344f13198e6b4de03b04787bd6b89d Mon Sep 17 00:00:00 2001
From: Yanan Wang <wangyanan55@huawei.com>
Date: Fri, 7 Jan 2022 16:32:28 +0800
Subject: [PATCH 16/24] hw/arm/virt: Support cluster level in DT cpu-map
Support one cluster level between core and physical package in the
cpu-map of Arm/virt devicetree. This is also consistent with Linux
Doc "Documentation/devicetree/bindings/cpu/cpu-topology.txt".
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Message-id: 20220107083232.16256-3-wangyanan55@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
hw/arm/virt.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 6ca9cbe2cf..ddcb73f714 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -434,9 +434,8 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
* can contain several layers of clustering within a single physical
* package and cluster nodes can be contained in parent cluster nodes.
*
- * Given that cluster is not yet supported in the vCPU topology,
- * we currently generate one cluster node within each socket node
- * by default.
+ * Note: currently we only support one layer of clustering within
+ * each physical package.
*/
qemu_fdt_add_subnode(ms->fdt, "/cpus/cpu-map");
@@ -446,14 +445,16 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
if (ms->smp.threads > 1) {
map_path = g_strdup_printf(
- "/cpus/cpu-map/socket%d/cluster0/core%d/thread%d",
- cpu / (ms->smp.cores * ms->smp.threads),
+ "/cpus/cpu-map/socket%d/cluster%d/core%d/thread%d",
+ cpu / (ms->smp.clusters * ms->smp.cores * ms->smp.threads),
+ (cpu / (ms->smp.cores * ms->smp.threads)) % ms->smp.clusters,
(cpu / ms->smp.threads) % ms->smp.cores,
cpu % ms->smp.threads);
} else {
map_path = g_strdup_printf(
- "/cpus/cpu-map/socket%d/cluster0/core%d",
- cpu / ms->smp.cores,
+ "/cpus/cpu-map/socket%d/cluster%d/core%d",
+ cpu / (ms->smp.clusters * ms->smp.cores),
+ (cpu / ms->smp.cores) % ms->smp.clusters,
cpu % ms->smp.cores);
}
qemu_fdt_add_path(ms->fdt, map_path);
--
2.27.0

View File

@ -0,0 +1,353 @@
From c5cd762bb7513b6df07e26f4eb619dccbd1918b7 Mon Sep 17 00:00:00 2001
From: Ying Fang <fangying1@huawei.com>
Date: Tue, 8 Feb 2022 11:31:15 +0800
Subject: [PATCH 23/24] hw/arm64: add vcpu cache info support
Support VCPU Cache info by dtb and PPTT table, including L1, L2 and L3 Cache.
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Honghao <honghao5@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
---
hw/acpi/aml-build.c | 158 ++++++++++++++++++++++++++++++++++++
hw/arm/virt.c | 72 ++++++++++++++++
include/hw/acpi/aml-build.h | 47 +++++++++++
tests/data/acpi/virt/PPTT | Bin 96 -> 208 bytes
4 files changed, 277 insertions(+)
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index bb2cad63b5..bebf49622b 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1994,6 +1994,163 @@ static void build_processor_hierarchy_node(GArray *tbl, uint32_t flags,
}
}
+#ifdef __aarch64__
+/*
+ * ACPI spec, Revision 6.3
+ * 5.2.29.2 Cache Type Structure (Type 1)
+ */
+static void build_cache_hierarchy_node(GArray *tbl, uint32_t next_level,
+ uint32_t cache_type)
+{
+ build_append_byte(tbl, 1);
+ build_append_byte(tbl, 24);
+ build_append_int_noprefix(tbl, 0, 2);
+ build_append_int_noprefix(tbl, 127, 4);
+ build_append_int_noprefix(tbl, next_level, 4);
+
+ switch (cache_type) {
+ case ARM_L1D_CACHE: /* L1 dcache info */
+ build_append_int_noprefix(tbl, ARM_L1DCACHE_SIZE, 4);
+ build_append_int_noprefix(tbl, ARM_L1DCACHE_SETS, 4);
+ build_append_byte(tbl, ARM_L1DCACHE_ASSOCIATIVITY);
+ build_append_byte(tbl, ARM_L1DCACHE_ATTRIBUTES);
+ build_append_int_noprefix(tbl, ARM_L1DCACHE_LINE_SIZE, 2);
+ break;
+ case ARM_L1I_CACHE: /* L1 icache info */
+ build_append_int_noprefix(tbl, ARM_L1ICACHE_SIZE, 4);
+ build_append_int_noprefix(tbl, ARM_L1ICACHE_SETS, 4);
+ build_append_byte(tbl, ARM_L1ICACHE_ASSOCIATIVITY);
+ build_append_byte(tbl, ARM_L1ICACHE_ATTRIBUTES);
+ build_append_int_noprefix(tbl, ARM_L1ICACHE_LINE_SIZE, 2);
+ break;
+ case ARM_L2_CACHE: /* L2 cache info */
+ build_append_int_noprefix(tbl, ARM_L2CACHE_SIZE, 4);
+ build_append_int_noprefix(tbl, ARM_L2CACHE_SETS, 4);
+ build_append_byte(tbl, ARM_L2CACHE_ASSOCIATIVITY);
+ build_append_byte(tbl, ARM_L2CACHE_ATTRIBUTES);
+ build_append_int_noprefix(tbl, ARM_L2CACHE_LINE_SIZE, 2);
+ break;
+ case ARM_L3_CACHE: /* L3 cache info */
+ build_append_int_noprefix(tbl, ARM_L3CACHE_SIZE, 4);
+ build_append_int_noprefix(tbl, ARM_L3CACHE_SETS, 4);
+ build_append_byte(tbl, ARM_L3CACHE_ASSOCIATIVITY);
+ build_append_byte(tbl, ARM_L3CACHE_ATTRIBUTES);
+ build_append_int_noprefix(tbl, ARM_L3CACHE_LINE_SIZE, 2);
+ break;
+ default:
+ build_append_int_noprefix(tbl, 0, 4);
+ build_append_int_noprefix(tbl, 0, 4);
+ build_append_byte(tbl, 0);
+ build_append_byte(tbl, 0);
+ build_append_int_noprefix(tbl, 0, 2);
+ }
+}
+
+/*
+ * ACPI spec, Revision 6.3
+ * 5.2.29 Processor Properties Topology Table (PPTT)
+ */
+void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
+ const char *oem_id, const char *oem_table_id)
+{
+ MachineClass *mc = MACHINE_GET_CLASS(ms);
+ GQueue *list = g_queue_new();
+ guint pptt_start = table_data->len;
+ guint parent_offset;
+ guint length, i;
+ int uid = 0;
+ int socket;
+ AcpiTable table = { .sig = "PPTT", .rev = 2,
+ .oem_id = oem_id, .oem_table_id = oem_table_id };
+
+ acpi_table_begin(&table, table_data);
+
+ for (socket = 0; socket < ms->smp.sockets; socket++) {
+ uint32_t l3_cache_offset = table_data->len - pptt_start;
+ build_cache_hierarchy_node(table_data, 0, ARM_L3_CACHE);
+
+ g_queue_push_tail(list,
+ GUINT_TO_POINTER(table_data->len - pptt_start));
+ build_processor_hierarchy_node(
+ table_data,
+ /*
+ * Physical package - represents the boundary
+ * of a physical package
+ */
+ (1 << 0),
+ 0, socket, &l3_cache_offset, 1);
+ }
+
+ if (mc->smp_props.clusters_supported) {
+ length = g_queue_get_length(list);
+ for (i = 0; i < length; i++) {
+ int cluster;
+
+ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
+ for (cluster = 0; cluster < ms->smp.clusters; cluster++) {
+ g_queue_push_tail(list,
+ GUINT_TO_POINTER(table_data->len - pptt_start));
+ build_processor_hierarchy_node(
+ table_data,
+ (0 << 0), /* not a physical package */
+ parent_offset, cluster, NULL, 0);
+ }
+ }
+ }
+
+ length = g_queue_get_length(list);
+ for (i = 0; i < length; i++) {
+ int core;
+
+ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
+ for (core = 0; core < ms->smp.cores; core++) {
+ uint32_t priv_rsrc[3] = {};
+ priv_rsrc[0] = table_data->len - pptt_start; /* L2 cache offset */
+ build_cache_hierarchy_node(table_data, 0, ARM_L2_CACHE);
+
+ priv_rsrc[1] = table_data->len - pptt_start; /* L1 dcache offset */
+ build_cache_hierarchy_node(table_data, priv_rsrc[0], ARM_L1D_CACHE);
+
+ priv_rsrc[2] = table_data->len - pptt_start; /* L1 icache offset */
+ build_cache_hierarchy_node(table_data, priv_rsrc[0], ARM_L1I_CACHE);
+
+ if (ms->smp.threads > 1) {
+ g_queue_push_tail(list,
+ GUINT_TO_POINTER(table_data->len - pptt_start));
+ build_processor_hierarchy_node(
+ table_data,
+ (0 << 0), /* not a physical package */
+ parent_offset, core, priv_rsrc, 3);
+ } else {
+ build_processor_hierarchy_node(
+ table_data,
+ (1 << 1) | /* ACPI Processor ID valid */
+ (1 << 3), /* Node is a Leaf */
+ parent_offset, uid++, priv_rsrc, 3);
+ }
+ }
+ }
+
+ length = g_queue_get_length(list);
+ for (i = 0; i < length; i++) {
+ int thread;
+
+ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
+ for (thread = 0; thread < ms->smp.threads; thread++) {
+ build_processor_hierarchy_node(
+ table_data,
+ (1 << 1) | /* ACPI Processor ID valid */
+ (1 << 2) | /* Processor is a Thread */
+ (1 << 3), /* Node is a Leaf */
+ parent_offset, uid++, NULL, 0);
+ }
+ }
+
+ g_queue_free(list);
+ acpi_table_end(linker, &table);
+}
+
+#else
/*
* ACPI spec, Revision 6.3
* 5.2.29 Processor Properties Topology Table (PPTT)
@@ -2084,6 +2241,7 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
g_queue_free(list);
acpi_table_end(linker, &table);
}
+#endif
/* build rev1/rev3/rev5.1 FADT */
void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index ddcb73f714..529c0d38b6 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -350,6 +350,72 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL2_IRQ, irqflags);
}
+static void fdt_add_l3cache_nodes(const VirtMachineState *vms)
+{
+ int i;
+ const MachineState *ms = MACHINE(vms);
+ int cpus_per_socket = ms->smp.clusters * ms->smp.cores * ms->smp.threads;
+ int sockets = (ms->smp.cpus + cpus_per_socket - 1) / cpus_per_socket;
+
+ for (i = 0; i < sockets; i++) {
+ char *nodename = g_strdup_printf("/cpus/l3-cache%d", i);
+
+ qemu_fdt_add_subnode(ms->fdt, nodename);
+ qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cache");
+ qemu_fdt_setprop_string(ms->fdt, nodename, "cache-unified", "true");
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-level", 3);
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-size", 0x2000000);
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-line-size", 128);
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-sets", 2048);
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle",
+ qemu_fdt_alloc_phandle(ms->fdt));
+ g_free(nodename);
+ }
+}
+
+static void fdt_add_l2cache_nodes(const VirtMachineState *vms)
+{
+ const MachineState *ms = MACHINE(vms);
+ int cpus_per_socket = ms->smp.clusters * ms->smp.cores * ms->smp.threads;
+ int cpu;
+
+ for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
+ char *next_path = g_strdup_printf("/cpus/l3-cache%d",
+ cpu / cpus_per_socket);
+ char *nodename = g_strdup_printf("/cpus/l2-cache%d", cpu);
+
+ qemu_fdt_add_subnode(ms->fdt, nodename);
+ qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cache");
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-size", 0x80000);
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-line-size", 64);
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-sets", 1024);
+ qemu_fdt_setprop_phandle(ms->fdt, nodename, "next-level-cache",
+ next_path);
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle",
+ qemu_fdt_alloc_phandle(ms->fdt));
+
+ g_free(next_path);
+ g_free(nodename);
+ }
+}
+
+static void fdt_add_l1cache_prop(const VirtMachineState *vms,
+ char *nodename, int cpu)
+{
+ const MachineState *ms = MACHINE(vms);
+ char *cachename = g_strdup_printf("/cpus/l2-cache%d", cpu);
+
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-size", 0x10000);
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-line-size", 64);
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-sets", 256);
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-size", 0x10000);
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-line-size", 64);
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-sets", 256);
+ qemu_fdt_setprop_phandle(ms->fdt, nodename, "next-level-cache",
+ cachename);
+ g_free(cachename);
+}
+
static void fdt_add_cpu_nodes(const VirtMachineState *vms)
{
int cpu;
@@ -384,6 +450,11 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#address-cells", addr_cells);
qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#size-cells", 0x0);
+ if (!vmc->no_cpu_topology) {
+ fdt_add_l3cache_nodes(vms);
+ fdt_add_l2cache_nodes(vms);
+ }
+
for (cpu = smp_cpus - 1; cpu >= 0; cpu--) {
char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
@@ -413,6 +484,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
}
if (!vmc->no_cpu_topology) {
+ fdt_add_l1cache_prop(vms, nodename, cpu);
qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle",
qemu_fdt_alloc_phandle(ms->fdt));
}
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 8346003a22..8e8ad8029e 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -221,6 +221,53 @@ struct AcpiBuildTables {
BIOSLinker *linker;
} AcpiBuildTables;
+#ifdef __aarch64__
+/* Definitions of the hardcoded cache info*/
+
+typedef enum {
+ ARM_L1D_CACHE,
+ ARM_L1I_CACHE,
+ ARM_L2_CACHE,
+ ARM_L3_CACHE
+} ArmCacheType;
+
+/* L1 data cache: */
+#define ARM_L1DCACHE_SIZE 65536
+#define ARM_L1DCACHE_SETS 256
+#define ARM_L1DCACHE_ASSOCIATIVITY 4
+#define ARM_L1DCACHE_ATTRIBUTES 2
+#define ARM_L1DCACHE_LINE_SIZE 64
+
+/* L1 instruction cache: */
+#define ARM_L1ICACHE_SIZE 65536
+#define ARM_L1ICACHE_SETS 256
+#define ARM_L1ICACHE_ASSOCIATIVITY 4
+#define ARM_L1ICACHE_ATTRIBUTES 4
+#define ARM_L1ICACHE_LINE_SIZE 64
+
+/* Level 2 unified cache: */
+#define ARM_L2CACHE_SIZE 524288
+#define ARM_L2CACHE_SETS 1024
+#define ARM_L2CACHE_ASSOCIATIVITY 8
+#define ARM_L2CACHE_ATTRIBUTES 10
+#define ARM_L2CACHE_LINE_SIZE 64
+
+/* Level 3 unified cache: */
+#define ARM_L3CACHE_SIZE 33554432
+#define ARM_L3CACHE_SETS 2048
+#define ARM_L3CACHE_ASSOCIATIVITY 15
+#define ARM_L3CACHE_ATTRIBUTES 10
+#define ARM_L3CACHE_LINE_SIZE 128
+
+struct offset_status {
+ uint32_t parent;
+ uint32_t l2_offset;
+ uint32_t l1d_offset;
+ uint32_t l1i_offset;
+};
+
+#endif
+
typedef
struct CrsRangeEntry {
uint64_t base;
--
2.27.0

View File

@ -0,0 +1,114 @@
From 2ce1daae407033e689a559b7346523b18651ee0a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <philmd@redhat.com>
Date: Thu, 11 Nov 2021 10:21:23 +0100
Subject: [PATCH 09/24] hw/core: Rename smp_parse() ->
machine_parse_smp_config()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
All methods related to MachineState are prefixed with "machine_".
smp_parse() does not need to be an exception. Rename it and
const'ify the SMPConfiguration argument, since it doesn't need
to be modified.
Reviewed-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Yanan Wang <wangyanan55@huawei.com>
Tested-by: Yanan Wang <wangyanan55@huawei.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20211216132015.815493-9-philmd@redhat.com>
---
hw/core/machine-smp.c | 6 ++++--
hw/core/machine.c | 2 +-
include/hw/boards.h | 3 ++-
tests/unit/test-smp-parse.c | 8 ++++----
4 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/hw/core/machine-smp.c b/hw/core/machine-smp.c
index 116a0cbbfa..2cbfd57429 100644
--- a/hw/core/machine-smp.c
+++ b/hw/core/machine-smp.c
@@ -44,7 +44,8 @@ static char *cpu_hierarchy_to_string(MachineState *ms)
}
/*
- * smp_parse - Generic function used to parse the given SMP configuration
+ * machine_parse_smp_config: Generic function used to parse the given
+ * SMP configuration
*
* Any missing parameter in "cpus/maxcpus/sockets/cores/threads" will be
* automatically computed based on the provided ones.
@@ -63,7 +64,8 @@ static char *cpu_hierarchy_to_string(MachineState *ms)
* introduced topology members which are likely to be target specific should
* be directly set as 1 if they are omitted (e.g. dies for PC since 4.1).
*/
-void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
+void machine_parse_smp_config(MachineState *ms,
+ const SMPConfiguration *config, Error **errp)
{
MachineClass *mc = MACHINE_GET_CLASS(ms);
unsigned cpus = config->has_cpus ? config->cpus : 0;
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 53a99abc56..3993c534b9 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -761,7 +761,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
return;
}
- smp_parse(ms, config, errp);
+ machine_parse_smp_config(ms, config, errp);
}
static void machine_class_init(ObjectClass *oc, void *data)
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 9c1c190104..7597cec440 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -34,7 +34,8 @@ HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine);
void machine_set_cpu_numa_node(MachineState *machine,
const CpuInstanceProperties *props,
Error **errp);
-void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp);
+void machine_parse_smp_config(MachineState *ms,
+ const SMPConfiguration *config, Error **errp);
/**
* machine_class_allow_dynamic_sysbus_dev: Add type to list of valid devices
diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c
index 0f98c9509e..b6df8137fc 100644
--- a/tests/unit/test-smp-parse.c
+++ b/tests/unit/test-smp-parse.c
@@ -337,7 +337,7 @@ static const struct SMPTestData data_with_dies_invalid[] = {
},
};
-static char *smp_config_to_string(SMPConfiguration *config)
+static char *smp_config_to_string(const SMPConfiguration *config)
{
return g_strdup_printf(
"(SMPConfiguration) {\n"
@@ -371,7 +371,7 @@ static char *cpu_topology_to_string(const CpuTopology *topo)
topo->cores, topo->threads, topo->max_cpus);
}
-static void check_parse(MachineState *ms, SMPConfiguration *config,
+static void check_parse(MachineState *ms, const SMPConfiguration *config,
const CpuTopology *expect_topo, const char *expect_err,
bool is_valid)
{
@@ -380,8 +380,8 @@ static void check_parse(MachineState *ms, SMPConfiguration *config,
g_autofree char *output_topo_str = NULL;
Error *err = NULL;
- /* call the generic parser smp_parse() */
- smp_parse(ms, config, &err);
+ /* call the generic parser */
+ machine_parse_smp_config(ms, config, &err);
output_topo_str = cpu_topology_to_string(&ms->smp);
--
2.27.0

View File

@ -0,0 +1,283 @@
From bf4a20a82bd4804842dd2960db30e0be7ecb2d32 Mon Sep 17 00:00:00 2001
From: Yanan Wang <wangyanan55@huawei.com>
Date: Tue, 28 Dec 2021 17:22:09 +0800
Subject: [PATCH 11/24] hw/core/machine: Introduce CPU cluster topology support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The new Cluster-Aware Scheduling support has landed in Linux 5.16,
which has been proved to benefit the scheduling performance (e.g.
load balance and wake_affine strategy) on both x86_64 and AArch64.
So now in Linux 5.16 we have four-level arch-neutral CPU topology
definition like below and a new scheduler level for clusters.
struct cpu_topology {
int thread_id;
int core_id;
int cluster_id;
int package_id;
int llc_id;
cpumask_t thread_sibling;
cpumask_t core_sibling;
cpumask_t cluster_sibling;
cpumask_t llc_sibling;
}
A cluster generally means a group of CPU cores which share L2 cache
or other mid-level resources, and it is the shared resources that
is used to improve scheduler's behavior. From the point of view of
the size range, it's between CPU die and CPU core. For example, on
some ARM64 Kunpeng servers, we have 6 clusters in each NUMA node,
and 4 CPU cores in each cluster. The 4 CPU cores share a separate
L2 cache and a L3 cache tag, which brings cache affinity advantage.
In virtualization, on the Hosts which have pClusters (physical
clusters), if we can design a vCPU topology with cluster level for
guest kernel and have a dedicated vCPU pinning. A Cluster-Aware
Guest kernel can also make use of the cache affinity of CPU clusters
to gain similar scheduling performance.
This patch adds infrastructure for CPU cluster level topology
configuration and parsing, so that the user can specify cluster
parameter if their machines support it.
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Message-Id: <20211228092221.21068-3-wangyanan55@huawei.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
[PMD: Added '(since 7.0)' to @clusters in qapi/machine.json]
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
hw/core/machine-smp.c | 26 +++++++++++++++++++-------
hw/core/machine.c | 3 +++
include/hw/boards.h | 6 +++++-
qapi/machine.json | 5 ++++-
qemu-options.hx | 7 ++++---
softmmu/vl.c | 3 +++
6 files changed, 38 insertions(+), 12 deletions(-)
diff --git a/hw/core/machine-smp.c b/hw/core/machine-smp.c
index 2cbfd57429..b39ed21e65 100644
--- a/hw/core/machine-smp.c
+++ b/hw/core/machine-smp.c
@@ -37,6 +37,10 @@ static char *cpu_hierarchy_to_string(MachineState *ms)
g_string_append_printf(s, " * dies (%u)", ms->smp.dies);
}
+ if (mc->smp_props.clusters_supported) {
+ g_string_append_printf(s, " * clusters (%u)", ms->smp.clusters);
+ }
+
g_string_append_printf(s, " * cores (%u)", ms->smp.cores);
g_string_append_printf(s, " * threads (%u)", ms->smp.threads);
@@ -71,6 +75,7 @@ void machine_parse_smp_config(MachineState *ms,
unsigned cpus = config->has_cpus ? config->cpus : 0;
unsigned sockets = config->has_sockets ? config->sockets : 0;
unsigned dies = config->has_dies ? config->dies : 0;
+ unsigned clusters = config->has_clusters ? config->clusters : 0;
unsigned cores = config->has_cores ? config->cores : 0;
unsigned threads = config->has_threads ? config->threads : 0;
unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0;
@@ -82,6 +87,7 @@ void machine_parse_smp_config(MachineState *ms,
if ((config->has_cpus && config->cpus == 0) ||
(config->has_sockets && config->sockets == 0) ||
(config->has_dies && config->dies == 0) ||
+ (config->has_clusters && config->clusters == 0) ||
(config->has_cores && config->cores == 0) ||
(config->has_threads && config->threads == 0) ||
(config->has_maxcpus && config->maxcpus == 0)) {
@@ -97,8 +103,13 @@ void machine_parse_smp_config(MachineState *ms,
error_setg(errp, "dies not supported by this machine's CPU topology");
return;
}
+ if (!mc->smp_props.clusters_supported && clusters > 1) {
+ error_setg(errp, "clusters not supported by this machine's CPU topology");
+ return;
+ }
dies = dies > 0 ? dies : 1;
+ clusters = clusters > 0 ? clusters : 1;
/* compute missing values based on the provided ones */
if (cpus == 0 && maxcpus == 0) {
@@ -113,41 +124,42 @@ void machine_parse_smp_config(MachineState *ms,
if (sockets == 0) {
cores = cores > 0 ? cores : 1;
threads = threads > 0 ? threads : 1;
- sockets = maxcpus / (dies * cores * threads);
+ sockets = maxcpus / (dies * clusters * cores * threads);
} else if (cores == 0) {
threads = threads > 0 ? threads : 1;
- cores = maxcpus / (sockets * dies * threads);
+ cores = maxcpus / (sockets * dies * clusters * threads);
}
} else {
/* prefer cores over sockets since 6.2 */
if (cores == 0) {
sockets = sockets > 0 ? sockets : 1;
threads = threads > 0 ? threads : 1;
- cores = maxcpus / (sockets * dies * threads);
+ cores = maxcpus / (sockets * dies * clusters * threads);
} else if (sockets == 0) {
threads = threads > 0 ? threads : 1;
- sockets = maxcpus / (dies * cores * threads);
+ sockets = maxcpus / (dies * clusters * cores * threads);
}
}
/* try to calculate omitted threads at last */
if (threads == 0) {
- threads = maxcpus / (sockets * dies * cores);
+ threads = maxcpus / (sockets * dies * clusters * cores);
}
}
- maxcpus = maxcpus > 0 ? maxcpus : sockets * dies * cores * threads;
+ maxcpus = maxcpus > 0 ? maxcpus : sockets * dies * clusters * cores * threads;
cpus = cpus > 0 ? cpus : maxcpus;
ms->smp.cpus = cpus;
ms->smp.sockets = sockets;
ms->smp.dies = dies;
+ ms->smp.clusters = clusters;
ms->smp.cores = cores;
ms->smp.threads = threads;
ms->smp.max_cpus = maxcpus;
/* sanity-check of the computed topology */
- if (sockets * dies * cores * threads != maxcpus) {
+ if (sockets * dies * clusters * cores * threads != maxcpus) {
g_autofree char *topo_msg = cpu_hierarchy_to_string(ms);
error_setg(errp, "Invalid CPU topology: "
"product of the hierarchy must match maxcpus: "
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 3993c534b9..a4a2df405f 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -742,10 +742,12 @@ static void machine_get_smp(Object *obj, Visitor *v, const char *name,
.has_cpus = true, .cpus = ms->smp.cpus,
.has_sockets = true, .sockets = ms->smp.sockets,
.has_dies = true, .dies = ms->smp.dies,
+ .has_clusters = true, .clusters = ms->smp.clusters,
.has_cores = true, .cores = ms->smp.cores,
.has_threads = true, .threads = ms->smp.threads,
.has_maxcpus = true, .maxcpus = ms->smp.max_cpus,
};
+
if (!visit_type_SMPConfiguration(v, name, &config, &error_abort)) {
return;
}
@@ -932,6 +934,7 @@ static void machine_initfn(Object *obj)
ms->smp.max_cpus = mc->default_cpus;
ms->smp.sockets = 1;
ms->smp.dies = 1;
+ ms->smp.clusters = 1;
ms->smp.cores = 1;
ms->smp.threads = 1;
}
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 7597cec440..f49a2578ea 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -129,10 +129,12 @@ typedef struct {
* SMPCompatProps:
* @prefer_sockets - whether sockets are preferred over cores in smp parsing
* @dies_supported - whether dies are supported by the machine
+ * @clusters_supported - whether clusters are supported by the machine
*/
typedef struct {
bool prefer_sockets;
bool dies_supported;
+ bool clusters_supported;
} SMPCompatProps;
/**
@@ -299,7 +301,8 @@ typedef struct DeviceMemoryState {
* @cpus: the number of present logical processors on the machine
* @sockets: the number of sockets on the machine
* @dies: the number of dies in one socket
- * @cores: the number of cores in one die
+ * @clusters: the number of clusters in one die
+ * @cores: the number of cores in one cluster
* @threads: the number of threads in one core
* @max_cpus: the maximum number of logical processors on the machine
*/
@@ -307,6 +310,7 @@ typedef struct CpuTopology {
unsigned int cpus;
unsigned int sockets;
unsigned int dies;
+ unsigned int clusters;
unsigned int cores;
unsigned int threads;
unsigned int max_cpus;
diff --git a/qapi/machine.json b/qapi/machine.json
index f1839acf20..8faa51074e 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -1396,7 +1396,9 @@
#
# @dies: number of dies per socket in the CPU topology
#
-# @cores: number of cores per die in the CPU topology
+# @clusters: number of clusters per die in the CPU topology (since 7.0)
+#
+# @cores: number of cores per cluster in the CPU topology
#
# @threads: number of threads per core in the CPU topology
#
@@ -1408,6 +1410,7 @@
'*cpus': 'int',
'*sockets': 'int',
'*dies': 'int',
+ '*clusters': 'int',
'*cores': 'int',
'*threads': 'int',
'*maxcpus': 'int' } }
diff --git a/qemu-options.hx b/qemu-options.hx
index 7a59db7764..0f26f7dad7 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -206,13 +206,14 @@ SRST
ERST
DEF("smp", HAS_ARG, QEMU_OPTION_smp,
- "-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,cores=cores][,threads=threads]\n"
+ "-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,clusters=clusters][,cores=cores][,threads=threads]\n"
" set the number of initial CPUs to 'n' [default=1]\n"
" maxcpus= maximum number of total CPUs, including\n"
" offline CPUs for hotplug, etc\n"
" sockets= number of sockets on the machine board\n"
" dies= number of dies in one socket\n"
- " cores= number of cores in one die\n"
+ " clusters= number of clusters in one die\n"
+ " cores= number of cores in one cluster\n"
" threads= number of threads in one core\n"
"Note: Different machines may have different subsets of the CPU topology\n"
" parameters supported, so the actual meaning of the supported parameters\n"
@@ -228,7 +229,7 @@ DEF("smp", HAS_ARG, QEMU_OPTION_smp,
" must be set as 1 in the purpose of correct parsing.\n",
QEMU_ARCH_ALL)
SRST
-``-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,cores=cores][,threads=threads]``
+``-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,clusters=clusters][,cores=cores][,threads=threads]``
Simulate a SMP system with '\ ``n``\ ' CPUs initially present on
the machine type board. On boards supporting CPU hotplug, the optional
'\ ``maxcpus``\ ' parameter can be set to enable further CPUs to be
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 620a1f1367..d9e4c619d3 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -726,6 +726,9 @@ static QemuOptsList qemu_smp_opts = {
}, {
.name = "dies",
.type = QEMU_OPT_NUMBER,
+ }, {
+ .name = "clusters",
+ .type = QEMU_OPT_NUMBER,
}, {
.name = "cores",
.type = QEMU_OPT_NUMBER,
--
2.27.0

View File

@ -0,0 +1,35 @@
From b04e92ed13e49f666f62c8f3daa5746109caf17b Mon Sep 17 00:00:00 2001
From: Yanan Wang <wangyanan55@huawei.com>
Date: Mon, 22 Nov 2021 11:26:51 +0800
Subject: [PATCH 01/24] qapi/machine.json: Fix incorrect description for die-id
In terms of scope, die-id should mean "the die number within
socket the CPU belongs to" instead of "the die number within
node/board the CPU belongs to". Fix it to avoid confusing
the Doc reader.
Fixes: 176d2cda0d ("i386/cpu: Consolidate die-id validity in smp context")
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20211122032651.16064-1-wangyanan55@huawei.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
qapi/machine.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/qapi/machine.json b/qapi/machine.json
index 067e3f5378..f1839acf20 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -867,7 +867,7 @@
#
# @node-id: NUMA node ID the CPU belongs to
# @socket-id: socket number within node/board the CPU belongs to
-# @die-id: die number within node/board the CPU belongs to (Since 4.1)
+# @die-id: die number within socket the CPU belongs to (since 4.1)
# @core-id: core number within die the CPU belongs to
# @thread-id: thread number within core the CPU belongs to
#
--
2.27.0

View File

@ -0,0 +1,146 @@
From 07991b049fc9ebdb62c311eda1535ad4831625e5 Mon Sep 17 00:00:00 2001
From: Yanan Wang <wangyanan55@huawei.com>
Date: Tue, 28 Dec 2021 17:22:08 +0800
Subject: [PATCH 10/24] qemu-options: Improve readability of SMP related Docs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
We have a description in qemu-options.hx for each CPU topology
parameter to explain what it exactly means, and also an extra
declaration for the target-specific one, e.g. "for PC only"
when describing "dies", and "for PC, it's on one die" when
describing "cores".
Now we are going to introduce one more non-generic parameter
"clusters", it will make the Doc less readable and if we still
continue to use the legacy way to describe it.
So let's at first make two tweaks of the Docs to improve the
readability and also scalability:
1) In the -help text: Delete the extra specific declaration and
describe each topology parameter level by level. Then add a
note to declare that different machines may support different
subsets and the actual meaning of the supported parameters
will vary accordingly.
2) In the rST text: List all the sub-hierarchies currently
supported in QEMU, and correspondingly give an example of
-smp configuration for each of them.
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20211228092221.21068-2-wangyanan55@huawei.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
qemu-options.hx | 76 ++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 59 insertions(+), 17 deletions(-)
diff --git a/qemu-options.hx b/qemu-options.hx
index ae2c6dbbfc..7a59db7764 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -207,14 +207,26 @@ ERST
DEF("smp", HAS_ARG, QEMU_OPTION_smp,
"-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,cores=cores][,threads=threads]\n"
- " set the number of CPUs to 'n' [default=1]\n"
+ " set the number of initial CPUs to 'n' [default=1]\n"
" maxcpus= maximum number of total CPUs, including\n"
" offline CPUs for hotplug, etc\n"
- " sockets= number of discrete sockets in the system\n"
- " dies= number of CPU dies on one socket (for PC only)\n"
- " cores= number of CPU cores on one socket (for PC, it's on one die)\n"
- " threads= number of threads on one CPU core\n",
- QEMU_ARCH_ALL)
+ " sockets= number of sockets on the machine board\n"
+ " dies= number of dies in one socket\n"
+ " cores= number of cores in one die\n"
+ " threads= number of threads in one core\n"
+ "Note: Different machines may have different subsets of the CPU topology\n"
+ " parameters supported, so the actual meaning of the supported parameters\n"
+ " will vary accordingly. For example, for a machine type that supports a\n"
+ " three-level CPU hierarchy of sockets/cores/threads, the parameters will\n"
+ " sequentially mean as below:\n"
+ " sockets means the number of sockets on the machine board\n"
+ " cores means the number of cores in one socket\n"
+ " threads means the number of threads in one core\n"
+ " For a particular machine type board, an expected CPU topology hierarchy\n"
+ " can be defined through the supported sub-option. Unsupported parameters\n"
+ " can also be provided in addition to the sub-option, but their values\n"
+ " must be set as 1 in the purpose of correct parsing.\n",
+ QEMU_ARCH_ALL)
SRST
``-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,cores=cores][,threads=threads]``
Simulate a SMP system with '\ ``n``\ ' CPUs initially present on
@@ -225,27 +237,57 @@ SRST
initial CPU count will match the maximum number. When only one of them
is given then the omitted one will be set to its counterpart's value.
Both parameters may be specified, but the maximum number of CPUs must
- be equal to or greater than the initial CPU count. Both parameters are
- subject to an upper limit that is determined by the specific machine
- type chosen.
-
- To control reporting of CPU topology information, the number of sockets,
- dies per socket, cores per die, and threads per core can be specified.
- The sum `` sockets * cores * dies * threads `` must be equal to the
- maximum CPU count. CPU targets may only support a subset of the topology
- parameters. Where a CPU target does not support use of a particular
- topology parameter, its value should be assumed to be 1 for the purpose
- of computing the CPU maximum count.
+ be equal to or greater than the initial CPU count. Product of the
+ CPU topology hierarchy must be equal to the maximum number of CPUs.
+ Both parameters are subject to an upper limit that is determined by
+ the specific machine type chosen.
+
+ To control reporting of CPU topology information, values of the topology
+ parameters can be specified. Machines may only support a subset of the
+ parameters and different machines may have different subsets supported
+ which vary depending on capacity of the corresponding CPU targets. So
+ for a particular machine type board, an expected topology hierarchy can
+ be defined through the supported sub-option. Unsupported parameters can
+ also be provided in addition to the sub-option, but their values must be
+ set as 1 in the purpose of correct parsing.
Either the initial CPU count, or at least one of the topology parameters
must be specified. The specified parameters must be greater than zero,
explicit configuration like "cpus=0" is not allowed. Values for any
omitted parameters will be computed from those which are given.
+
+ For example, the following sub-option defines a CPU topology hierarchy
+ (2 sockets totally on the machine, 2 cores per socket, 2 threads per
+ core) for a machine that only supports sockets/cores/threads.
+ Some members of the option can be omitted but their values will be
+ automatically computed:
+
+ ::
+
+ -smp 8,sockets=2,cores=2,threads=2,maxcpus=8
+
+ The following sub-option defines a CPU topology hierarchy (2 sockets
+ totally on the machine, 2 dies per socket, 2 cores per die, 2 threads
+ per core) for PC machines which support sockets/dies/cores/threads.
+ Some members of the option can be omitted but their values will be
+ automatically computed:
+
+ ::
+
+ -smp 16,sockets=2,dies=2,cores=2,threads=2,maxcpus=16
+
Historically preference was given to the coarsest topology parameters
when computing missing values (ie sockets preferred over cores, which
were preferred over threads), however, this behaviour is considered
liable to change. Prior to 6.2 the preference was sockets over cores
over threads. Since 6.2 the preference is cores over sockets over threads.
+
+ For example, the following option defines a machine board with 2 sockets
+ of 1 core before 6.2 and 1 socket of 2 cores after 6.2:
+
+ ::
+
+ -smp 2
ERST
DEF("numa", HAS_ARG, QEMU_OPTION_numa,
--
2.27.0

View File

@ -1,6 +1,6 @@
Name: qemu
Version: 6.2.0
Release: 18
Release: 19
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
@ -173,6 +173,30 @@ Patch0159: seabios-add-check-to-avoid-dereference-NULL-pointer.patch
Patch0160: qemu-img-add-qemu-img-direct-create.patch
Patch0161: log-Delete-redudant-qemu_log.patch
Patch0162: bios-tables-test-Update-expected-q35-SSDT.dimmpxm-fi.patch
Patch0163: qapi-machine.json-Fix-incorrect-description-for-die-.patch
Patch0164: tests-unit-test-smp-parse-Pass-machine-type-as-argum.patch
Patch0165: tests-unit-test-smp-parse-Split-the-generic-test-in-.patch
Patch0166: tests-unit-test-smp-parse-Add-smp-with-dies-machine-.patch
Patch0167: tests-unit-test-smp-parse-Add-smp-generic-invalid-ma.patch
Patch0168: tests-unit-test-smp-parse-Add-smp-generic-valid-mach.patch
Patch0169: tests-unit-test-smp-parse-Simplify-pointer-to-compou.patch
Patch0170: tests-unit-test-smp-parse-Constify-some-pointer-stru.patch
Patch0171: hw-core-Rename-smp_parse-machine_parse_smp_config.patch
Patch0172: qemu-options-Improve-readability-of-SMP-related-Docs.patch
Patch0173: hw-core-machine-Introduce-CPU-cluster-topology-suppo.patch
Patch0174: tests-unit-test-smp-parse-Add-testcases-for-CPU-clus.patch
Patch0175: tests-unit-test-smp-parse-No-need-to-explicitly-zero.patch
Patch0176: tests-unit-test-smp-parse-Keep-default-MIN-MAX-CPUs-.patch
Patch0177: hw-arm-virt-Support-CPU-cluster-on-ARM-virt-machine.patch
Patch0178: hw-arm-virt-Support-cluster-level-in-DT-cpu-map.patch
Patch0179: hw-acpi-aml-build-Improve-scalability-of-PPTT-genera.patch
Patch0180: tests-acpi-bios-tables-test-Allow-changes-to-virt-PP.patch
Patch0181: hw-acpi-aml-build-Support-cluster-level-in-PPTT-gene.patch
Patch0182: tests-acpi-bios-table-test-Update-expected-virt-PPTT.patch
Patch0183: softmmu-device_tree-Silence-compiler-warning-with-en.patch
Patch0184: softmmu-device_tree-Remove-redundant-pointer-assignm.patch
Patch0185: hw-arm64-add-vcpu-cache-info-support.patch
Patch0186: arm64-Add-the-cpufreq-device-to-show-cpufreq-info-to.patch
BuildRequires: flex
BuildRequires: gcc
@ -620,6 +644,35 @@ getent passwd qemu >/dev/null || \
%endif
%changelog
* Thu Feb 17 2022 imxcc <xingchaochao@huawei.com>
- qapi/machine.json: Fix incorrect description for die-id
- tests/unit/test-smp-parse: Pass machine type as
- tests/unit/test-smp-parse: Split the 'generic' test in
- tests/unit/test-smp-parse: Add 'smp-with-dies' machine
- tests/unit/test-smp-parse: Add 'smp-generic-invalid'
- tests/unit/test-smp-parse: Add 'smp-generic-valid'
- tests/unit/test-smp-parse: Simplify pointer to compound
- tests/unit/test-smp-parse: Constify some pointer/struct
- hw/core: Rename smp_parse() ->
- qemu-options: Improve readability of SMP related Docs
- hw/core/machine: Introduce CPU cluster topology support
- tests/unit/test-smp-parse: Add testcases for CPU
- tests/unit/test-smp-parse: No need to explicitly zero
- tests/unit/test-smp-parse: Keep default MIN/MAX CPUs in
- hw/arm/virt: Support CPU cluster on ARM virt machine
- hw/arm/virt: Support cluster level in DT cpu-map
- hw/acpi/aml-build: Improve scalability of PPTT
- tests/acpi/bios-tables-test: Allow changes to virt/PPTT
- hw/acpi/aml-build: Support cluster level in PPTT
- tests/acpi/bios-table-test: Update expected virt/PPTT
- update BinDir
- softmmu/device_tree: Silence compiler warning with
- softmmu/device_tree: Remove redundant pointer
- hw/arm64: add vcpu cache info support
- update BinDir
- arm64: Add the cpufreq device to show cpufreq info to
- update BinDir
* Thu Feb 17 2022 imxcc <xingchaochao@huawei.com>
- bios-tables-test: Update expected q35/SSDT.dimmpxm file
- spec: add BinDir

View File

@ -0,0 +1,58 @@
From ebf1ac6c0ead3d6fbc32466028c286588333c1ea Mon Sep 17 00:00:00 2001
From: Yanan Wang <wangyanan55@huawei.com>
Date: Tue, 11 Jan 2022 11:27:58 +0800
Subject: [PATCH 22/24] softmmu/device_tree: Remove redundant pointer
assignment
The pointer assignment "const char *p = path;" in function
qemu_fdt_add_path is unnecessary. Let's remove it and just
use the "path" passed in. No functional change.
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-id: 20220111032758.27804-1-wangyanan55@huawei.com
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
softmmu/device_tree.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/softmmu/device_tree.c b/softmmu/device_tree.c
index 9e96f5ecd5..8897c79ea4 100644
--- a/softmmu/device_tree.c
+++ b/softmmu/device_tree.c
@@ -556,7 +556,6 @@ int qemu_fdt_add_subnode(void *fdt, const char *name)
int qemu_fdt_add_path(void *fdt, const char *path)
{
const char *name;
- const char *p = path;
int namelen, retval;
int parent = 0;
@@ -565,9 +564,9 @@ int qemu_fdt_add_path(void *fdt, const char *path)
}
do {
- name = p + 1;
- p = strchr(name, '/');
- namelen = p != NULL ? p - name : strlen(name);
+ name = path + 1;
+ path = strchr(name, '/');
+ namelen = path != NULL ? path - name : strlen(name);
retval = fdt_subnode_offset_namelen(fdt, parent, name, namelen);
if (retval < 0 && retval != -FDT_ERR_NOTFOUND) {
@@ -584,7 +583,7 @@ int qemu_fdt_add_path(void *fdt, const char *path)
}
parent = retval;
- } while (p);
+ } while (path);
return retval;
}
--
2.27.0

View File

@ -0,0 +1,60 @@
From ecc0eb93e8856321ad940a85970f0db14ab9f146 Mon Sep 17 00:00:00 2001
From: Thomas Huth <thuth@redhat.com>
Date: Fri, 7 Jan 2022 14:38:44 +0100
Subject: [PATCH 21/24] softmmu/device_tree: Silence compiler warning with
--enable-sanitizers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
If I configure my build with --enable-sanitizers, my GCC (v8.5.0)
complains:
.../softmmu/device_tree.c: In function qemu_fdt_add_path:
.../softmmu/device_tree.c:560:18: error: retval may be used uninitialized
in this function [-Werror=maybe-uninitialized]
int namelen, retval;
^~~~~~
It's a false warning since the while loop is always executed at least
once (p has to be non-NULL, otherwise the derefence in the if-statement
earlier will crash). Thus let's switch to a do-while loop here instead
to make the compiler happy in all cases.
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Yanan Wang <wangyanan55@huawei.com>
Message-id: 20220107133844.145039-1-thuth@redhat.com
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
softmmu/device_tree.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/softmmu/device_tree.c b/softmmu/device_tree.c
index 3965c834ca..9e96f5ecd5 100644
--- a/softmmu/device_tree.c
+++ b/softmmu/device_tree.c
@@ -564,7 +564,7 @@ int qemu_fdt_add_path(void *fdt, const char *path)
return -1;
}
- while (p) {
+ do {
name = p + 1;
p = strchr(name, '/');
namelen = p != NULL ? p - name : strlen(name);
@@ -584,7 +584,7 @@ int qemu_fdt_add_path(void *fdt, const char *path)
}
parent = retval;
- }
+ } while (p);
return retval;
}
--
2.27.0

View File

@ -0,0 +1,110 @@
From 6f89f06e686a61acf681038ac06732facc6e7b93 Mon Sep 17 00:00:00 2001
From: Yanan Wang <wangyanan55@huawei.com>
Date: Fri, 7 Jan 2022 16:32:32 +0800
Subject: [PATCH 20/24] tests/acpi/bios-table-test: Update expected virt/PPTT
file
Run ./tests/data/acpi/rebuild-expected-aml.sh from build directory
to update PPTT binary. Also empty bios-tables-test-allowed-diff.h.
The disassembled differences between actual and expected PPTT:
/*
* Intel ACPI Component Architecture
* AML/ASL+ Disassembler version 20200528 (64-bit version)
* Copyright (c) 2000 - 2020 Intel Corporation
*
- * Disassembly of tests/data/acpi/virt/PPTT, Tue Jan 4 12:51:11 2022
+ * Disassembly of /tmp/aml-2ZGOF1, Tue Jan 4 12:51:11 2022
*
* ACPI Data Table [PPTT]
*
* Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue
*/
[000h 0000 4] Signature : "PPTT" [Processor Properties Topology Table]
-[004h 0004 4] Table Length : 0000004C
+[004h 0004 4] Table Length : 00000060
[008h 0008 1] Revision : 02
-[009h 0009 1] Checksum : A8
+[009h 0009 1] Checksum : 48
[00Ah 0010 6] Oem ID : "BOCHS "
[010h 0016 8] Oem Table ID : "BXPC "
[018h 0024 4] Oem Revision : 00000001
[01Ch 0028 4] Asl Compiler ID : "BXPC"
[020h 0032 4] Asl Compiler Revision : 00000001
[024h 0036 1] Subtable Type : 00 [Processor Hierarchy Node]
[025h 0037 1] Length : 14
[026h 0038 2] Reserved : 0000
[028h 0040 4] Flags (decoded below) : 00000001
Physical package : 1
ACPI Processor ID valid : 0
Processor is a thread : 0
Node is a leaf : 0
Identical Implementation : 0
[02Ch 0044 4] Parent : 00000000
[030h 0048 4] ACPI Processor ID : 00000000
[034h 0052 4] Private Resource Number : 00000000
[038h 0056 1] Subtable Type : 00 [Processor Hierarchy Node]
[039h 0057 1] Length : 14
[03Ah 0058 2] Reserved : 0000
-[03Ch 0060 4] Flags (decoded below) : 0000000A
+[03Ch 0060 4] Flags (decoded below) : 00000000
Physical package : 0
- ACPI Processor ID valid : 1
+ ACPI Processor ID valid : 0
Processor is a thread : 0
- Node is a leaf : 1
+ Node is a leaf : 0
Identical Implementation : 0
[040h 0064 4] Parent : 00000024
[044h 0068 4] ACPI Processor ID : 00000000
[048h 0072 4] Private Resource Number : 00000000
-Raw Table Data: Length 76 (0x4C)
+[04Ch 0076 1] Subtable Type : 00 [Processor Hierarchy Node]
+[04Dh 0077 1] Length : 14
+[04Eh 0078 2] Reserved : 0000
+[050h 0080 4] Flags (decoded below) : 0000000A
+ Physical package : 0
+ ACPI Processor ID valid : 1
+ Processor is a thread : 0
+ Node is a leaf : 1
+ Identical Implementation : 0
+[054h 0084 4] Parent : 00000038
+[058h 0088 4] ACPI Processor ID : 00000000
+[05Ch 0092 4] Private Resource Number : 00000000
+
+Raw Table Data: Length 96 (0x60)
- 0000: 50 50 54 54 4C 00 00 00 02 A8 42 4F 43 48 53 20 // PPTTL.....BOCHS
+ 0000: 50 50 54 54 60 00 00 00 02 48 42 4F 43 48 53 20 // PPTT`....HBOCHS
0010: 42 58 50 43 20 20 20 20 01 00 00 00 42 58 50 43 // BXPC ....BXPC
0020: 01 00 00 00 00 14 00 00 01 00 00 00 00 00 00 00 // ................
- 0030: 00 00 00 00 00 00 00 00 00 14 00 00 0A 00 00 00 // ................
- 0040: 24 00 00 00 00 00 00 00 00 00 00 00 // $...........
+ 0030: 00 00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 // ................
+ 0040: 24 00 00 00 00 00 00 00 00 00 00 00 00 14 00 00 // $...............
+ 0050: 0A 00 00 00 38 00 00 00 00 00 00 00 00 00 00 00 // ....8...........
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Ani Sinha <ani@anisinha.ca>
Message-id: 20220107083232.16256-7-wangyanan55@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
tests/data/acpi/virt/PPTT | Bin 76 -> 96 bytes
tests/qtest/bios-tables-test-allowed-diff.h | 1 -
2 files changed, 1 deletion(-)
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
index cb143a55a6..dfb8523c8b 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1,2 +1 @@
/* List of comma-separated changed AML files to ignore */
-"tests/data/acpi/virt/PPTT",
--
2.27.0

View File

@ -0,0 +1,27 @@
From 225034a72c803b8e3819cec22bc6fb8bfc9e7366 Mon Sep 17 00:00:00 2001
From: Yanan Wang <wangyanan55@huawei.com>
Date: Fri, 7 Jan 2022 16:32:30 +0800
Subject: [PATCH 18/24] tests/acpi/bios-tables-test: Allow changes to virt/PPTT
file
List test/data/acpi/virt/PPTT as the expected files allowed to
be changed in tests/qtest/bios-tables-test-allowed-diff.h
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Acked-by: Ani Sinha <ani@anisinha.ca>
Message-id: 20220107083232.16256-5-wangyanan55@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
tests/qtest/bios-tables-test-allowed-diff.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..cb143a55a6 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,2 @@
/* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/virt/PPTT",
--
2.27.0

View File

@ -0,0 +1,87 @@
From 9a98659dcb37c81e69f54d8f6cbe5116ceba5a36 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <philmd@redhat.com>
Date: Mon, 15 Nov 2021 15:44:07 +0100
Subject: [PATCH 05/24] tests/unit/test-smp-parse: Add 'smp-generic-invalid'
machine type
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Avoid modifying the MachineClass internals by adding the
'smp-generic-invalid' machine, which inherits from TYPE_MACHINE.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Yanan Wang <wangyanan55@huawei.com>
Message-Id: <20211216132015.815493-5-philmd@redhat.com>
---
tests/unit/test-smp-parse.c | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c
index f66cf7bb59..47e11089e2 100644
--- a/tests/unit/test-smp-parse.c
+++ b/tests/unit/test-smp-parse.c
@@ -487,6 +487,17 @@ static void machine_base_class_init(ObjectClass *oc, void *data)
mc->name = g_strdup(SMP_MACHINE_NAME);
}
+static void machine_generic_invalid_class_init(ObjectClass *oc, void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+
+ /* Force invalid min CPUs and max CPUs */
+ mc->min_cpus = 2;
+ mc->max_cpus = 511;
+
+ mc->smp_props.dies_supported = false;
+}
+
static void machine_with_dies_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
@@ -530,10 +541,6 @@ static void test_generic_invalid(const void *opaque)
SMPTestData *data = &(SMPTestData){};
int i;
- /* Force invalid min CPUs and max CPUs */
- mc->min_cpus = 2;
- mc->max_cpus = 511;
-
for (i = 0; i < ARRAY_SIZE(data_generic_invalid); i++) {
*data = data_generic_invalid[i];
unsupported_params_init(mc, data);
@@ -541,10 +548,6 @@ static void test_generic_invalid(const void *opaque)
smp_parse_test(ms, data, false);
}
- /* Reset the supported min CPUs and max CPUs */
- mc->min_cpus = MIN_CPUS;
- mc->max_cpus = MAX_CPUS;
-
object_unref(obj);
}
@@ -606,6 +609,10 @@ static const TypeInfo smp_machine_types[] = {
.class_init = machine_base_class_init,
.class_size = sizeof(MachineClass),
.instance_size = sizeof(MachineState),
+ }, {
+ .name = MACHINE_TYPE_NAME("smp-generic-invalid"),
+ .parent = TYPE_MACHINE,
+ .class_init = machine_generic_invalid_class_init,
}, {
.name = MACHINE_TYPE_NAME("smp-with-dies"),
.parent = TYPE_MACHINE,
@@ -625,7 +632,7 @@ int main(int argc, char *argv[])
TYPE_MACHINE,
test_generic_valid);
g_test_add_data_func("/test-smp-parse/generic/invalid",
- TYPE_MACHINE,
+ MACHINE_TYPE_NAME("smp-generic-invalid"),
test_generic_invalid);
g_test_add_data_func("/test-smp-parse/with_dies",
MACHINE_TYPE_NAME("smp-with-dies"),
--
2.27.0

View File

@ -0,0 +1,75 @@
From c33c7dd51eebf5ae7b7ece1e829b0a5ffdcebfe1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <philmd@redhat.com>
Date: Mon, 15 Nov 2021 15:49:59 +0100
Subject: [PATCH 06/24] tests/unit/test-smp-parse: Add 'smp-generic-valid'
machine type
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Keep the common TYPE_MACHINE class initialization in
machine_base_class_init(), make it abstract, and move
the non-common code to a new class: "smp-generic-valid".
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Yanan Wang <wangyanan55@huawei.com>
Message-Id: <20211216132015.815493-6-philmd@redhat.com>
---
tests/unit/test-smp-parse.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c
index 47e11089e2..b20bf2c235 100644
--- a/tests/unit/test-smp-parse.c
+++ b/tests/unit/test-smp-parse.c
@@ -478,13 +478,19 @@ static void machine_base_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
+ mc->smp_props.prefer_sockets = true;
+
+ mc->name = g_strdup(SMP_MACHINE_NAME);
+}
+
+static void machine_generic_valid_class_init(ObjectClass *oc, void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+
mc->min_cpus = MIN_CPUS;
mc->max_cpus = MAX_CPUS;
- mc->smp_props.prefer_sockets = true;
mc->smp_props.dies_supported = false;
-
- mc->name = g_strdup(SMP_MACHINE_NAME);
}
static void machine_generic_invalid_class_init(ObjectClass *oc, void *data)
@@ -606,9 +612,14 @@ static const TypeInfo smp_machine_types[] = {
{
.name = TYPE_MACHINE,
.parent = TYPE_OBJECT,
+ .abstract = true,
.class_init = machine_base_class_init,
.class_size = sizeof(MachineClass),
.instance_size = sizeof(MachineState),
+ }, {
+ .name = MACHINE_TYPE_NAME("smp-generic-valid"),
+ .parent = TYPE_MACHINE,
+ .class_init = machine_generic_valid_class_init,
}, {
.name = MACHINE_TYPE_NAME("smp-generic-invalid"),
.parent = TYPE_MACHINE,
@@ -629,7 +640,7 @@ int main(int argc, char *argv[])
g_test_init(&argc, &argv, NULL);
g_test_add_data_func("/test-smp-parse/generic/valid",
- TYPE_MACHINE,
+ MACHINE_TYPE_NAME("smp-generic-valid"),
test_generic_valid);
g_test_add_data_func("/test-smp-parse/generic/invalid",
MACHINE_TYPE_NAME("smp-generic-invalid"),
--
2.27.0

View File

@ -0,0 +1,85 @@
From 4981e75623db6ca681d13719ffcf61b0cfac3edc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <philmd@redhat.com>
Date: Mon, 15 Nov 2021 12:39:12 +0100
Subject: [PATCH 04/24] tests/unit/test-smp-parse: Add 'smp-with-dies' machine
type
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Avoid modifying the MachineClass internals by adding the
'smp-with-dies' machine, which inherits from TYPE_MACHINE.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Yanan Wang <wangyanan55@huawei.com>
Tested-by: Yanan Wang <wangyanan55@huawei.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20211216132015.815493-4-philmd@redhat.com>
---
tests/unit/test-smp-parse.c | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c
index 425ed6b6b9..f66cf7bb59 100644
--- a/tests/unit/test-smp-parse.c
+++ b/tests/unit/test-smp-parse.c
@@ -487,6 +487,16 @@ static void machine_base_class_init(ObjectClass *oc, void *data)
mc->name = g_strdup(SMP_MACHINE_NAME);
}
+static void machine_with_dies_class_init(ObjectClass *oc, void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+
+ mc->min_cpus = MIN_CPUS;
+ mc->max_cpus = MAX_CPUS;
+
+ mc->smp_props.dies_supported = true;
+}
+
static void test_generic_valid(const void *opaque)
{
const char *machine_type = opaque;
@@ -548,9 +558,6 @@ static void test_with_dies(const void *opaque)
unsigned int num_dies = 2;
int i;
- /* Force the SMP compat properties */
- mc->smp_props.dies_supported = true;
-
for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
*data = data_generic_valid[i];
unsupported_params_init(mc, data);
@@ -588,9 +595,6 @@ static void test_with_dies(const void *opaque)
smp_parse_test(ms, data, false);
}
- /* Restore the SMP compat properties */
- mc->smp_props.dies_supported = false;
-
object_unref(obj);
}
@@ -602,6 +606,10 @@ static const TypeInfo smp_machine_types[] = {
.class_init = machine_base_class_init,
.class_size = sizeof(MachineClass),
.instance_size = sizeof(MachineState),
+ }, {
+ .name = MACHINE_TYPE_NAME("smp-with-dies"),
+ .parent = TYPE_MACHINE,
+ .class_init = machine_with_dies_class_init,
}
};
@@ -620,7 +628,7 @@ int main(int argc, char *argv[])
TYPE_MACHINE,
test_generic_invalid);
g_test_add_data_func("/test-smp-parse/with_dies",
- TYPE_MACHINE,
+ MACHINE_TYPE_NAME("smp-with-dies"),
test_with_dies);
g_test_run();
--
2.27.0

View File

@ -0,0 +1,254 @@
From 5e8a39a560ea58308f66d47639c0d5d2e704997f Mon Sep 17 00:00:00 2001
From: Yanan Wang <wangyanan55@huawei.com>
Date: Tue, 28 Dec 2021 17:22:11 +0800
Subject: [PATCH 12/24] tests/unit/test-smp-parse: Add testcases for CPU
clusters
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add testcases for parsing of the four-level CPU topology hierarchy,
ie sockets/clusters/cores/threads, which will be supported on ARM
virt machines.
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20211228092221.21068-5-wangyanan55@huawei.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
tests/unit/test-smp-parse.c | 130 ++++++++++++++++++++++++++++++++++--
1 file changed, 123 insertions(+), 7 deletions(-)
diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c
index b6df8137fc..331719bbc4 100644
--- a/tests/unit/test-smp-parse.c
+++ b/tests/unit/test-smp-parse.c
@@ -61,6 +61,20 @@
.has_maxcpus = hf, .maxcpus = f, \
}
+/*
+ * Currently a 4-level topology hierarchy is supported on ARM virt machines
+ * -sockets/clusters/cores/threads
+ */
+#define SMP_CONFIG_WITH_CLUSTERS(ha, a, hb, b, hc, c, hd, d, he, e, hf, f) \
+ { \
+ .has_cpus = ha, .cpus = a, \
+ .has_sockets = hb, .sockets = b, \
+ .has_clusters = hc, .clusters = c, \
+ .has_cores = hd, .cores = d, \
+ .has_threads = he, .threads = e, \
+ .has_maxcpus = hf, .maxcpus = f, \
+ }
+
/**
* @config - the given SMP configuration
* @expect_prefer_sockets - the expected parsing result for the
@@ -290,6 +304,10 @@ static const struct SMPTestData data_generic_invalid[] = {
/* config: -smp 2,dies=2 */
.config = SMP_CONFIG_WITH_DIES(T, 2, F, 0, T, 2, F, 0, F, 0, F, 0),
.expect_error = "dies not supported by this machine's CPU topology",
+ }, {
+ /* config: -smp 2,clusters=2 */
+ .config = SMP_CONFIG_WITH_CLUSTERS(T, 2, F, 0, T, 2, F, 0, F, 0, F, 0),
+ .expect_error = "clusters not supported by this machine's CPU topology",
}, {
/* config: -smp 8,sockets=2,cores=4,threads=2,maxcpus=8 */
.config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, T, 2, T, 8),
@@ -337,20 +355,40 @@ static const struct SMPTestData data_with_dies_invalid[] = {
},
};
+static const struct SMPTestData data_with_clusters_invalid[] = {
+ {
+ /* config: -smp 16,sockets=2,clusters=2,cores=4,threads=2,maxcpus=16 */
+ .config = SMP_CONFIG_WITH_CLUSTERS(T, 16, T, 2, T, 2, T, 4, T, 2, T, 16),
+ .expect_error = "Invalid CPU topology: "
+ "product of the hierarchy must match maxcpus: "
+ "sockets (2) * clusters (2) * cores (4) * threads (2) "
+ "!= maxcpus (16)",
+ }, {
+ /* config: -smp 34,sockets=2,clusters=2,cores=4,threads=2,maxcpus=32 */
+ .config = SMP_CONFIG_WITH_CLUSTERS(T, 34, T, 2, T, 2, T, 4, T, 2, T, 32),
+ .expect_error = "Invalid CPU topology: "
+ "maxcpus must be equal to or greater than smp: "
+ "sockets (2) * clusters (2) * cores (4) * threads (2) "
+ "== maxcpus (32) < smp_cpus (34)",
+ },
+};
+
static char *smp_config_to_string(const SMPConfiguration *config)
{
return g_strdup_printf(
"(SMPConfiguration) {\n"
- " .has_cpus = %5s, cpus = %" PRId64 ",\n"
- " .has_sockets = %5s, sockets = %" PRId64 ",\n"
- " .has_dies = %5s, dies = %" PRId64 ",\n"
- " .has_cores = %5s, cores = %" PRId64 ",\n"
- " .has_threads = %5s, threads = %" PRId64 ",\n"
- " .has_maxcpus = %5s, maxcpus = %" PRId64 ",\n"
+ " .has_cpus = %5s, cpus = %" PRId64 ",\n"
+ " .has_sockets = %5s, sockets = %" PRId64 ",\n"
+ " .has_dies = %5s, dies = %" PRId64 ",\n"
+ " .has_clusters = %5s, clusters = %" PRId64 ",\n"
+ " .has_cores = %5s, cores = %" PRId64 ",\n"
+ " .has_threads = %5s, threads = %" PRId64 ",\n"
+ " .has_maxcpus = %5s, maxcpus = %" PRId64 ",\n"
"}",
config->has_cpus ? "true" : "false", config->cpus,
config->has_sockets ? "true" : "false", config->sockets,
config->has_dies ? "true" : "false", config->dies,
+ config->has_clusters ? "true" : "false", config->clusters,
config->has_cores ? "true" : "false", config->cores,
config->has_threads ? "true" : "false", config->threads,
config->has_maxcpus ? "true" : "false", config->maxcpus);
@@ -363,11 +401,12 @@ static char *cpu_topology_to_string(const CpuTopology *topo)
" .cpus = %u,\n"
" .sockets = %u,\n"
" .dies = %u,\n"
+ " .clusters = %u,\n"
" .cores = %u,\n"
" .threads = %u,\n"
" .max_cpus = %u,\n"
"}",
- topo->cpus, topo->sockets, topo->dies,
+ topo->cpus, topo->sockets, topo->dies, topo->clusters,
topo->cores, topo->threads, topo->max_cpus);
}
@@ -391,6 +430,7 @@ static void check_parse(MachineState *ms, const SMPConfiguration *config,
(ms->smp.cpus == expect_topo->cpus) &&
(ms->smp.sockets == expect_topo->sockets) &&
(ms->smp.dies == expect_topo->dies) &&
+ (ms->smp.clusters == expect_topo->clusters) &&
(ms->smp.cores == expect_topo->cores) &&
(ms->smp.threads == expect_topo->threads) &&
(ms->smp.max_cpus == expect_topo->max_cpus)) {
@@ -472,6 +512,11 @@ static void unsupported_params_init(const MachineClass *mc, SMPTestData *data)
data->expect_prefer_sockets.dies = 1;
data->expect_prefer_cores.dies = 1;
}
+
+ if (!mc->smp_props.clusters_supported) {
+ data->expect_prefer_sockets.clusters = 1;
+ data->expect_prefer_cores.clusters = 1;
+ }
}
static void machine_base_class_init(ObjectClass *oc, void *data)
@@ -491,6 +536,7 @@ static void machine_generic_valid_class_init(ObjectClass *oc, void *data)
mc->max_cpus = MAX_CPUS;
mc->smp_props.dies_supported = false;
+ mc->smp_props.clusters_supported = false;
}
static void machine_generic_invalid_class_init(ObjectClass *oc, void *data)
@@ -502,6 +548,7 @@ static void machine_generic_invalid_class_init(ObjectClass *oc, void *data)
mc->max_cpus = 511;
mc->smp_props.dies_supported = false;
+ mc->smp_props.clusters_supported = false;
}
static void machine_with_dies_class_init(ObjectClass *oc, void *data)
@@ -512,6 +559,18 @@ static void machine_with_dies_class_init(ObjectClass *oc, void *data)
mc->max_cpus = MAX_CPUS;
mc->smp_props.dies_supported = true;
+ mc->smp_props.clusters_supported = false;
+}
+
+static void machine_with_clusters_class_init(ObjectClass *oc, void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+
+ mc->min_cpus = MIN_CPUS;
+ mc->max_cpus = MAX_CPUS;
+
+ mc->smp_props.clusters_supported = true;
+ mc->smp_props.dies_supported = false;
}
static void test_generic_valid(const void *opaque)
@@ -607,6 +666,56 @@ static void test_with_dies(const void *opaque)
object_unref(obj);
}
+static void test_with_clusters(const void *opaque)
+{
+ const char *machine_type = opaque;
+ Object *obj = object_new(machine_type);
+ MachineState *ms = MACHINE(obj);
+ MachineClass *mc = MACHINE_GET_CLASS(obj);
+ SMPTestData data = {};
+ unsigned int num_clusters = 2;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
+ data = data_generic_valid[i];
+ unsupported_params_init(mc, &data);
+
+ /* when clusters parameter is omitted, it will be set as 1 */
+ data.expect_prefer_sockets.clusters = 1;
+ data.expect_prefer_cores.clusters = 1;
+
+ smp_parse_test(ms, &data, true);
+
+ /* when clusters parameter is specified */
+ data.config.has_clusters = true;
+ data.config.clusters = num_clusters;
+ if (data.config.has_cpus) {
+ data.config.cpus *= num_clusters;
+ }
+ if (data.config.has_maxcpus) {
+ data.config.maxcpus *= num_clusters;
+ }
+
+ data.expect_prefer_sockets.clusters = num_clusters;
+ data.expect_prefer_sockets.cpus *= num_clusters;
+ data.expect_prefer_sockets.max_cpus *= num_clusters;
+ data.expect_prefer_cores.clusters = num_clusters;
+ data.expect_prefer_cores.cpus *= num_clusters;
+ data.expect_prefer_cores.max_cpus *= num_clusters;
+
+ smp_parse_test(ms, &data, true);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(data_with_clusters_invalid); i++) {
+ data = data_with_clusters_invalid[i];
+ unsupported_params_init(mc, &data);
+
+ smp_parse_test(ms, &data, false);
+ }
+
+ object_unref(obj);
+}
+
/* Type info of the tested machine */
static const TypeInfo smp_machine_types[] = {
{
@@ -628,6 +737,10 @@ static const TypeInfo smp_machine_types[] = {
.name = MACHINE_TYPE_NAME("smp-with-dies"),
.parent = TYPE_MACHINE,
.class_init = machine_with_dies_class_init,
+ }, {
+ .name = MACHINE_TYPE_NAME("smp-with-clusters"),
+ .parent = TYPE_MACHINE,
+ .class_init = machine_with_clusters_class_init,
}
};
@@ -648,6 +761,9 @@ int main(int argc, char *argv[])
g_test_add_data_func("/test-smp-parse/with_dies",
MACHINE_TYPE_NAME("smp-with-dies"),
test_with_dies);
+ g_test_add_data_func("/test-smp-parse/with_clusters",
+ MACHINE_TYPE_NAME("smp-with-clusters"),
+ test_with_clusters);
g_test_run();
--
2.27.0

View File

@ -0,0 +1,82 @@
From bcf4b802bd8971c0c5a255e606b15900cd47c6b6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <philmd@redhat.com>
Date: Thu, 11 Nov 2021 10:23:06 +0100
Subject: [PATCH 08/24] tests/unit/test-smp-parse: Constify some pointer/struct
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Declare structures const when we don't need to modify
them at runtime.
Reviewed-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Yanan Wang <wangyanan55@huawei.com>
Tested-by: Yanan Wang <wangyanan55@huawei.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20211216132015.815493-8-philmd@redhat.com>
---
tests/unit/test-smp-parse.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c
index 395929b66c..0f98c9509e 100644
--- a/tests/unit/test-smp-parse.c
+++ b/tests/unit/test-smp-parse.c
@@ -83,7 +83,7 @@ typedef struct SMPTestData {
* then test the automatic calculation algorithm of the missing
* values in the parser.
*/
-static struct SMPTestData data_generic_valid[] = {
+static const struct SMPTestData data_generic_valid[] = {
{
/* config: no configuration provided
* expect: cpus=1,sockets=1,cores=1,threads=1,maxcpus=1 */
@@ -285,7 +285,7 @@ static struct SMPTestData data_generic_valid[] = {
},
};
-static struct SMPTestData data_generic_invalid[] = {
+static const struct SMPTestData data_generic_invalid[] = {
{
/* config: -smp 2,dies=2 */
.config = SMP_CONFIG_WITH_DIES(T, 2, F, 0, T, 2, F, 0, F, 0, F, 0),
@@ -319,7 +319,7 @@ static struct SMPTestData data_generic_invalid[] = {
},
};
-static struct SMPTestData data_with_dies_invalid[] = {
+static const struct SMPTestData data_with_dies_invalid[] = {
{
/* config: -smp 16,sockets=2,dies=2,cores=4,threads=2,maxcpus=16 */
.config = SMP_CONFIG_WITH_DIES(T, 16, T, 2, T, 2, T, 4, T, 2, T, 16),
@@ -356,7 +356,7 @@ static char *smp_config_to_string(SMPConfiguration *config)
config->has_maxcpus ? "true" : "false", config->maxcpus);
}
-static char *cpu_topology_to_string(CpuTopology *topo)
+static char *cpu_topology_to_string(const CpuTopology *topo)
{
return g_strdup_printf(
"(CpuTopology) {\n"
@@ -372,7 +372,7 @@ static char *cpu_topology_to_string(CpuTopology *topo)
}
static void check_parse(MachineState *ms, SMPConfiguration *config,
- CpuTopology *expect_topo, const char *expect_err,
+ const CpuTopology *expect_topo, const char *expect_err,
bool is_valid)
{
g_autofree char *config_str = smp_config_to_string(config);
@@ -466,7 +466,7 @@ static void smp_parse_test(MachineState *ms, SMPTestData *data, bool is_valid)
}
/* The parsed results of the unsupported parameters should be 1 */
-static void unsupported_params_init(MachineClass *mc, SMPTestData *data)
+static void unsupported_params_init(const MachineClass *mc, SMPTestData *data)
{
if (!mc->smp_props.dies_supported) {
data->expect_prefer_sockets.dies = 1;
--
2.27.0

View File

@ -0,0 +1,76 @@
From 214511b1799b94cfd514a222d087bb888ed808ba Mon Sep 17 00:00:00 2001
From: Yanan Wang <wangyanan55@huawei.com>
Date: Tue, 28 Dec 2021 17:22:13 +0800
Subject: [PATCH 14/24] tests/unit/test-smp-parse: Keep default MIN/MAX CPUs in
machine_base_class_init
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Most machine types in test-smp-parse will be OK to have the default
MIN/MAX CPUs except "smp-generic-invalid", let's keep the default
values in machine_base_class_init which will be inherited. And if
we hope a different value for a specific machine, modify it in its
own initialization function.
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20211228092221.21068-7-wangyanan55@huawei.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
tests/unit/test-smp-parse.c | 16 ++--------------
1 file changed, 2 insertions(+), 14 deletions(-)
diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c
index 72d83d1bbc..fdc39a846c 100644
--- a/tests/unit/test-smp-parse.c
+++ b/tests/unit/test-smp-parse.c
@@ -523,15 +523,10 @@ static void machine_base_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
- mc->name = g_strdup(SMP_MACHINE_NAME);
-}
-
-static void machine_generic_valid_class_init(ObjectClass *oc, void *data)
-{
- MachineClass *mc = MACHINE_CLASS(oc);
-
mc->min_cpus = MIN_CPUS;
mc->max_cpus = MAX_CPUS;
+
+ mc->name = g_strdup(SMP_MACHINE_NAME);
}
static void machine_generic_invalid_class_init(ObjectClass *oc, void *data)
@@ -547,9 +542,6 @@ static void machine_with_dies_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
- mc->min_cpus = MIN_CPUS;
- mc->max_cpus = MAX_CPUS;
-
mc->smp_props.dies_supported = true;
}
@@ -557,9 +549,6 @@ static void machine_with_clusters_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
- mc->min_cpus = MIN_CPUS;
- mc->max_cpus = MAX_CPUS;
-
mc->smp_props.clusters_supported = true;
}
@@ -718,7 +707,6 @@ static const TypeInfo smp_machine_types[] = {
}, {
.name = MACHINE_TYPE_NAME("smp-generic-valid"),
.parent = TYPE_MACHINE,
- .class_init = machine_generic_valid_class_init,
}, {
.name = MACHINE_TYPE_NAME("smp-generic-invalid"),
.parent = TYPE_MACHINE,
--
2.27.0

View File

@ -0,0 +1,75 @@
From 77bca7d51e99f8ba4d11635ff9f51615739f4d55 Mon Sep 17 00:00:00 2001
From: Yanan Wang <wangyanan55@huawei.com>
Date: Tue, 28 Dec 2021 17:22:12 +0800
Subject: [PATCH 13/24] tests/unit/test-smp-parse: No need to explicitly zero
MachineClass members
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The default value of the MachineClass members is 0, which
means we don't have to explicitly zero them. Also the value
of "mc->smp_props.prefer_sockets" will be taken care of by
smp_parse_test(), we don't necessarily need the statement
in machine_base_class_init() either.
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20211228092221.21068-6-wangyanan55@huawei.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
tests/unit/test-smp-parse.c | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c
index 331719bbc4..72d83d1bbc 100644
--- a/tests/unit/test-smp-parse.c
+++ b/tests/unit/test-smp-parse.c
@@ -523,8 +523,6 @@ static void machine_base_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
- mc->smp_props.prefer_sockets = true;
-
mc->name = g_strdup(SMP_MACHINE_NAME);
}
@@ -534,9 +532,6 @@ static void machine_generic_valid_class_init(ObjectClass *oc, void *data)
mc->min_cpus = MIN_CPUS;
mc->max_cpus = MAX_CPUS;
-
- mc->smp_props.dies_supported = false;
- mc->smp_props.clusters_supported = false;
}
static void machine_generic_invalid_class_init(ObjectClass *oc, void *data)
@@ -546,9 +541,6 @@ static void machine_generic_invalid_class_init(ObjectClass *oc, void *data)
/* Force invalid min CPUs and max CPUs */
mc->min_cpus = 2;
mc->max_cpus = 511;
-
- mc->smp_props.dies_supported = false;
- mc->smp_props.clusters_supported = false;
}
static void machine_with_dies_class_init(ObjectClass *oc, void *data)
@@ -559,7 +551,6 @@ static void machine_with_dies_class_init(ObjectClass *oc, void *data)
mc->max_cpus = MAX_CPUS;
mc->smp_props.dies_supported = true;
- mc->smp_props.clusters_supported = false;
}
static void machine_with_clusters_class_init(ObjectClass *oc, void *data)
@@ -570,7 +561,6 @@ static void machine_with_clusters_class_init(ObjectClass *oc, void *data)
mc->max_cpus = MAX_CPUS;
mc->smp_props.clusters_supported = true;
- mc->smp_props.dies_supported = false;
}
static void test_generic_valid(const void *opaque)
--
2.27.0

View File

@ -0,0 +1,69 @@
From d8b2aee4fd6ccd8eb621522b647c392c1dd7955c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <philmd@redhat.com>
Date: Mon, 15 Nov 2021 12:32:09 +0100
Subject: [PATCH 02/24] tests/unit/test-smp-parse: Pass machine type as
argument to tests
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Use g_test_add_data_func() instead of g_test_add_func() so we can
pass the machine type to the tests (we will soon have different
machine types).
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Yanan Wang <wangyanan55@huawei.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20211216132015.815493-2-philmd@redhat.com>
---
tests/unit/test-smp-parse.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c
index b02450e25a..37c6b4981d 100644
--- a/tests/unit/test-smp-parse.c
+++ b/tests/unit/test-smp-parse.c
@@ -487,9 +487,10 @@ static void machine_base_class_init(ObjectClass *oc, void *data)
mc->name = g_strdup(SMP_MACHINE_NAME);
}
-static void test_generic(void)
+static void test_generic(const void *opaque)
{
- Object *obj = object_new(TYPE_MACHINE);
+ const char *machine_type = opaque;
+ Object *obj = object_new(machine_type);
MachineState *ms = MACHINE(obj);
MachineClass *mc = MACHINE_GET_CLASS(obj);
SMPTestData *data = &(SMPTestData){{ }};
@@ -525,9 +526,10 @@ static void test_generic(void)
object_unref(obj);
}
-static void test_with_dies(void)
+static void test_with_dies(const void *opaque)
{
- Object *obj = object_new(TYPE_MACHINE);
+ const char *machine_type = opaque;
+ Object *obj = object_new(machine_type);
MachineState *ms = MACHINE(obj);
MachineClass *mc = MACHINE_GET_CLASS(obj);
SMPTestData *data = &(SMPTestData){{ }};
@@ -599,8 +601,12 @@ int main(int argc, char *argv[])
g_test_init(&argc, &argv, NULL);
- g_test_add_func("/test-smp-parse/generic", test_generic);
- g_test_add_func("/test-smp-parse/with_dies", test_with_dies);
+ g_test_add_data_func("/test-smp-parse/generic",
+ TYPE_MACHINE,
+ test_generic);
+ g_test_add_data_func("/test-smp-parse/with_dies",
+ TYPE_MACHINE,
+ test_with_dies);
g_test_run();
--
2.27.0

View File

@ -0,0 +1,143 @@
From 964965721bbed1941bf77e5a748efc1274b7c289 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <philmd@redhat.com>
Date: Thu, 11 Nov 2021 08:58:40 +0100
Subject: [PATCH 07/24] tests/unit/test-smp-parse: Simplify pointer to compound
literal use
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
We can simply use a local variable (and pass its pointer) instead
of a pointer to a compound literal.
Reviewed-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Yanan Wang <wangyanan55@huawei.com>
Tested-by: Yanan Wang <wangyanan55@huawei.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20211216132015.815493-7-philmd@redhat.com>
---
tests/unit/test-smp-parse.c | 66 ++++++++++++++++++-------------------
1 file changed, 33 insertions(+), 33 deletions(-)
diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c
index b20bf2c235..395929b66c 100644
--- a/tests/unit/test-smp-parse.c
+++ b/tests/unit/test-smp-parse.c
@@ -520,19 +520,19 @@ static void test_generic_valid(const void *opaque)
Object *obj = object_new(machine_type);
MachineState *ms = MACHINE(obj);
MachineClass *mc = MACHINE_GET_CLASS(obj);
- SMPTestData *data = &(SMPTestData){{ }};
+ SMPTestData data = {};
int i;
for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
- *data = data_generic_valid[i];
- unsupported_params_init(mc, data);
+ data = data_generic_valid[i];
+ unsupported_params_init(mc, &data);
- smp_parse_test(ms, data, true);
+ smp_parse_test(ms, &data, true);
/* Unsupported parameters can be provided with their values as 1 */
- data->config.has_dies = true;
- data->config.dies = 1;
- smp_parse_test(ms, data, true);
+ data.config.has_dies = true;
+ data.config.dies = 1;
+ smp_parse_test(ms, &data, true);
}
object_unref(obj);
@@ -544,14 +544,14 @@ static void test_generic_invalid(const void *opaque)
Object *obj = object_new(machine_type);
MachineState *ms = MACHINE(obj);
MachineClass *mc = MACHINE_GET_CLASS(obj);
- SMPTestData *data = &(SMPTestData){};
+ SMPTestData data = {};
int i;
for (i = 0; i < ARRAY_SIZE(data_generic_invalid); i++) {
- *data = data_generic_invalid[i];
- unsupported_params_init(mc, data);
+ data = data_generic_invalid[i];
+ unsupported_params_init(mc, &data);
- smp_parse_test(ms, data, false);
+ smp_parse_test(ms, &data, false);
}
object_unref(obj);
@@ -563,45 +563,45 @@ static void test_with_dies(const void *opaque)
Object *obj = object_new(machine_type);
MachineState *ms = MACHINE(obj);
MachineClass *mc = MACHINE_GET_CLASS(obj);
- SMPTestData *data = &(SMPTestData){{ }};
+ SMPTestData data = {};
unsigned int num_dies = 2;
int i;
for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
- *data = data_generic_valid[i];
- unsupported_params_init(mc, data);
+ data = data_generic_valid[i];
+ unsupported_params_init(mc, &data);
/* when dies parameter is omitted, it will be set as 1 */
- data->expect_prefer_sockets.dies = 1;
- data->expect_prefer_cores.dies = 1;
+ data.expect_prefer_sockets.dies = 1;
+ data.expect_prefer_cores.dies = 1;
- smp_parse_test(ms, data, true);
+ smp_parse_test(ms, &data, true);
/* when dies parameter is specified */
- data->config.has_dies = true;
- data->config.dies = num_dies;
- if (data->config.has_cpus) {
- data->config.cpus *= num_dies;
+ data.config.has_dies = true;
+ data.config.dies = num_dies;
+ if (data.config.has_cpus) {
+ data.config.cpus *= num_dies;
}
- if (data->config.has_maxcpus) {
- data->config.maxcpus *= num_dies;
+ if (data.config.has_maxcpus) {
+ data.config.maxcpus *= num_dies;
}
- data->expect_prefer_sockets.dies = num_dies;
- data->expect_prefer_sockets.cpus *= num_dies;
- data->expect_prefer_sockets.max_cpus *= num_dies;
- data->expect_prefer_cores.dies = num_dies;
- data->expect_prefer_cores.cpus *= num_dies;
- data->expect_prefer_cores.max_cpus *= num_dies;
+ data.expect_prefer_sockets.dies = num_dies;
+ data.expect_prefer_sockets.cpus *= num_dies;
+ data.expect_prefer_sockets.max_cpus *= num_dies;
+ data.expect_prefer_cores.dies = num_dies;
+ data.expect_prefer_cores.cpus *= num_dies;
+ data.expect_prefer_cores.max_cpus *= num_dies;
- smp_parse_test(ms, data, true);
+ smp_parse_test(ms, &data, true);
}
for (i = 0; i < ARRAY_SIZE(data_with_dies_invalid); i++) {
- *data = data_with_dies_invalid[i];
- unsupported_params_init(mc, data);
+ data = data_with_dies_invalid[i];
+ unsupported_params_init(mc, &data);
- smp_parse_test(ms, data, false);
+ smp_parse_test(ms, &data, false);
}
object_unref(obj);
--
2.27.0

View File

@ -0,0 +1,71 @@
From fad259cf9996dbc4001cb94ec3c846d649401027 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <philmd@redhat.com>
Date: Mon, 15 Nov 2021 12:35:43 +0100
Subject: [PATCH 03/24] tests/unit/test-smp-parse: Split the 'generic' test in
valid / invalid
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Split the 'generic' test in two tests: 'valid' and 'invalid'.
This will allow us to remove the hack which modifies the
MachineClass internal state.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Yanan Wang <wangyanan55@huawei.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20211216132015.815493-3-philmd@redhat.com>
---
tests/unit/test-smp-parse.c | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c
index 37c6b4981d..425ed6b6b9 100644
--- a/tests/unit/test-smp-parse.c
+++ b/tests/unit/test-smp-parse.c
@@ -487,7 +487,7 @@ static void machine_base_class_init(ObjectClass *oc, void *data)
mc->name = g_strdup(SMP_MACHINE_NAME);
}
-static void test_generic(const void *opaque)
+static void test_generic_valid(const void *opaque)
{
const char *machine_type = opaque;
Object *obj = object_new(machine_type);
@@ -508,6 +508,18 @@ static void test_generic(const void *opaque)
smp_parse_test(ms, data, true);
}
+ object_unref(obj);
+}
+
+static void test_generic_invalid(const void *opaque)
+{
+ const char *machine_type = opaque;
+ Object *obj = object_new(machine_type);
+ MachineState *ms = MACHINE(obj);
+ MachineClass *mc = MACHINE_GET_CLASS(obj);
+ SMPTestData *data = &(SMPTestData){};
+ int i;
+
/* Force invalid min CPUs and max CPUs */
mc->min_cpus = 2;
mc->max_cpus = 511;
@@ -601,9 +613,12 @@ int main(int argc, char *argv[])
g_test_init(&argc, &argv, NULL);
- g_test_add_data_func("/test-smp-parse/generic",
+ g_test_add_data_func("/test-smp-parse/generic/valid",
+ TYPE_MACHINE,
+ test_generic_valid);
+ g_test_add_data_func("/test-smp-parse/generic/invalid",
TYPE_MACHINE,
- test_generic);
+ test_generic_invalid);
g_test_add_data_func("/test-smp-parse/with_dies",
TYPE_MACHINE,
test_with_dies);
--
2.27.0