* Fix loongarch64 avocado test

* Make qtests more flexible with regards to non-available CPU models
 * Improvements for the test-smp-parse unit test
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCAAvFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAmZpoEoRHHRodXRoQHJl
 ZGhhdC5jb20ACgkQLtnXdP5wLbVF6g/+JYTRKmaIduQIP9g2+NkM+qMTbjI9Ow47
 8Vdj/ePMXNWOZsgMPkCUdisYeMZEC+XMcDN1xvwZXwLTMTJRacZCSFRpeN4P0m0W
 6aQ28+tPNgx+B9Eh2kc4TpxbiqSH8u5u4GEN4Y07rcX/3YbYyjFgZD8orRu/nJ+H
 0wV7Riq9csi1BkLxrgKaHocFSOl4eOga4OFi+u4wIn/xoW3MN0laxe4iuoQRMZPf
 gJLPRhEija4lto8iIKNxJbTABB0wEcWRWtgqcbHxdatqh1lPTPBpWxmdD/v1LJn+
 H/eO+oh05NQdlhw7+xfWF9PD+MpIePbZ28oNb3X3uURROTdcxpBAgpPipv07FsT4
 LmU2nIBQ4FcpDOkhLnLmBmFBNO6uDCzuGzxFRhX1SIiGMABqTDOKynBQSgQI2iB0
 5J47XUwHtnOoCvf4SRA/MZG8zNSQZdJbnuOBLgZ+vsCG14mWM2NbfSUwRkH6pd/J
 fEbODuzHZoYgUTxjR9+WMbINAbNjMy+SP2sGZIBzcAIIkybKynOy58LoCyNT684U
 ean9bnc65908PJxEfsQ6k9kNwkK4GwOqZi+X383nVgMJ9+3dDw8M76IVU59hsq1n
 wnz4VgFcRdXMYhj9zghaCgH2Ezw8gZHILXH+RlX0Bav4LQ5vSZQ6tRNwM4+rfXBe
 okF1Sxmz31U=
 =s7+V
 -----END PGP SIGNATURE-----

Merge tag 'pull-request-2024-06-12' of https://gitlab.com/thuth/qemu into staging

* Fix loongarch64 avocado test
* Make qtests more flexible with regards to non-available CPU models
* Improvements for the test-smp-parse unit test

# -----BEGIN PGP SIGNATURE-----
#
# iQJFBAABCAAvFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAmZpoEoRHHRodXRoQHJl
# ZGhhdC5jb20ACgkQLtnXdP5wLbVF6g/+JYTRKmaIduQIP9g2+NkM+qMTbjI9Ow47
# 8Vdj/ePMXNWOZsgMPkCUdisYeMZEC+XMcDN1xvwZXwLTMTJRacZCSFRpeN4P0m0W
# 6aQ28+tPNgx+B9Eh2kc4TpxbiqSH8u5u4GEN4Y07rcX/3YbYyjFgZD8orRu/nJ+H
# 0wV7Riq9csi1BkLxrgKaHocFSOl4eOga4OFi+u4wIn/xoW3MN0laxe4iuoQRMZPf
# gJLPRhEija4lto8iIKNxJbTABB0wEcWRWtgqcbHxdatqh1lPTPBpWxmdD/v1LJn+
# H/eO+oh05NQdlhw7+xfWF9PD+MpIePbZ28oNb3X3uURROTdcxpBAgpPipv07FsT4
# LmU2nIBQ4FcpDOkhLnLmBmFBNO6uDCzuGzxFRhX1SIiGMABqTDOKynBQSgQI2iB0
# 5J47XUwHtnOoCvf4SRA/MZG8zNSQZdJbnuOBLgZ+vsCG14mWM2NbfSUwRkH6pd/J
# fEbODuzHZoYgUTxjR9+WMbINAbNjMy+SP2sGZIBzcAIIkybKynOy58LoCyNT684U
# ean9bnc65908PJxEfsQ6k9kNwkK4GwOqZi+X383nVgMJ9+3dDw8M76IVU59hsq1n
# wnz4VgFcRdXMYhj9zghaCgH2Ezw8gZHILXH+RlX0Bav4LQ5vSZQ6tRNwM4+rfXBe
# okF1Sxmz31U=
# =s7+V
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 12 Jun 2024 06:19:06 AM PDT
# gpg:                using RSA key 27B88847EEE0250118F3EAB92ED9D774FE702DB5
# gpg:                issuer "thuth@redhat.com"
# gpg: Good signature from "Thomas Huth <th.huth@gmx.de>" [full]
# gpg:                 aka "Thomas Huth <thuth@redhat.com>" [full]
# gpg:                 aka "Thomas Huth <th.huth@posteo.de>" [unknown]
# gpg:                 aka "Thomas Huth <huth@tuxfamily.org>" [full]

* tag 'pull-request-2024-06-12' of https://gitlab.com/thuth/qemu:
  tests/tcg/s390x: Allow specifying extra QEMU options on the command line
  tests/unit/test-smp-parse: Test the full 8-levels topology hierarchy
  tests/unit/test-smp-parse: Test "modules" and "dies" combination case
  tests/unit/test-smp-parse: Test "modules" parameter in -smp
  tests/unit/test-smp-parse: Make test cases aware of module level
  tests/unit/test-smp-parse: Use default parameters=0 when not set in -smp
  tests/unit/test-smp-parse: Fix an invalid topology case
  tests/unit/test-smp-parse: Fix comment of parameters=1 case
  tests/unit/test-smp-parse: Fix comments of drawers and books case
  test: Remove libibumad dependence
  meson: Remove libibumad dependence
  tests/qtest/x86: check for availability of older cpu models before running tests
  tests/qtest/libqtest: add qtest_has_cpu_model() api
  qtest/x86/numa-test: do not use the obsolete 'pentium' cpu
  tests/avocado: Update LoongArch bios file

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2024-06-13 07:51:58 -07:00
commit 046a64b980
22 changed files with 518 additions and 147 deletions

View file

@ -1885,11 +1885,9 @@ endif
rdma = not_found rdma = not_found
if not get_option('rdma').auto() or have_system if not get_option('rdma').auto() or have_system
libumad = cc.find_library('ibumad', required: get_option('rdma'))
rdma_libs = [cc.find_library('rdmacm', has_headers: ['rdma/rdma_cma.h'], rdma_libs = [cc.find_library('rdmacm', has_headers: ['rdma/rdma_cma.h'],
required: get_option('rdma')), required: get_option('rdma')),
cc.find_library('ibverbs', required: get_option('rdma')), cc.find_library('ibverbs', required: get_option('rdma'))]
libumad]
rdma = declare_dependency(dependencies: rdma_libs) rdma = declare_dependency(dependencies: rdma_libs)
foreach lib: rdma_libs foreach lib: rdma_libs
if not lib.found() if not lib.found()

View file

@ -49,7 +49,6 @@ packages:
- libglusterfs-dev - libglusterfs-dev
- libgnutls28-dev - libgnutls28-dev
- libgtk-3-dev - libgtk-3-dev
- libibumad-dev
- libibverbs-dev - libibverbs-dev
- libiscsi-dev - libiscsi-dev
- libjemalloc-dev - libjemalloc-dev

View file

@ -49,7 +49,6 @@ packages:
- libglusterfs-dev - libglusterfs-dev
- libgnutls28-dev - libgnutls28-dev
- libgtk-3-dev - libgtk-3-dev
- libibumad-dev
- libibverbs-dev - libibverbs-dev
- libiscsi-dev - libiscsi-dev
- libjemalloc-dev - libjemalloc-dev

View file

@ -27,18 +27,18 @@ class LoongArchMachine(QemuSystemTest):
""" """
kernel_url = ('https://github.com/yangxiaojuan-loongson/qemu-binary/' kernel_url = ('https://github.com/yangxiaojuan-loongson/qemu-binary/'
'releases/download/binary-files/vmlinuz.efi') 'releases/download/2024-05-30/vmlinuz.efi')
kernel_hash = '951b485b16e3788b6db03a3e1793c067009e31a2' kernel_hash = '951b485b16e3788b6db03a3e1793c067009e31a2'
kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
initrd_url = ('https://github.com/yangxiaojuan-loongson/qemu-binary/' initrd_url = ('https://github.com/yangxiaojuan-loongson/qemu-binary/'
'releases/download/binary-files/ramdisk') 'releases/download/2024-05-30/ramdisk')
initrd_hash = 'c67658d9b2a447ce7db2f73ba3d373c9b2b90ab2' initrd_hash = 'c67658d9b2a447ce7db2f73ba3d373c9b2b90ab2'
initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash) initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
bios_url = ('https://github.com/yangxiaojuan-loongson/qemu-binary/' bios_url = ('https://github.com/yangxiaojuan-loongson/qemu-binary/'
'releases/download/binary-files/QEMU_EFI.fd') 'releases/download/2024-05-30/QEMU_EFI.fd')
bios_hash = ('dfc1bfba4853cd763b9d392d0031827e8addbca8') bios_hash = ('f4d0966b5117d4cd82327c050dd668741046be69')
bios_path = self.fetch_asset(bios_url, asset_hash=bios_hash) bios_path = self.fetch_asset(bios_url, asset_hash=bios_hash)
self.vm.set_console() self.vm.set_console()

View file

@ -105,7 +105,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libglusterfs-dev:amd64 \ libglusterfs-dev:amd64 \
libgnutls28-dev:amd64 \ libgnutls28-dev:amd64 \
libgtk-3-dev:amd64 \ libgtk-3-dev:amd64 \
libibumad-dev:amd64 \
libibverbs-dev:amd64 \ libibverbs-dev:amd64 \
libiscsi-dev:amd64 \ libiscsi-dev:amd64 \
libjemalloc-dev:amd64 \ libjemalloc-dev:amd64 \

View file

@ -105,7 +105,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libglusterfs-dev:arm64 \ libglusterfs-dev:arm64 \
libgnutls28-dev:arm64 \ libgnutls28-dev:arm64 \
libgtk-3-dev:arm64 \ libgtk-3-dev:arm64 \
libibumad-dev:arm64 \
libibverbs-dev:arm64 \ libibverbs-dev:arm64 \
libiscsi-dev:arm64 \ libiscsi-dev:arm64 \
libjemalloc-dev:arm64 \ libjemalloc-dev:arm64 \

View file

@ -108,7 +108,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libglusterfs-dev:armel \ libglusterfs-dev:armel \
libgnutls28-dev:armel \ libgnutls28-dev:armel \
libgtk-3-dev:armel \ libgtk-3-dev:armel \
libibumad-dev:armel \
libibverbs-dev:armel \ libibverbs-dev:armel \
libiscsi-dev:armel \ libiscsi-dev:armel \
libjemalloc-dev:armel \ libjemalloc-dev:armel \

View file

@ -105,7 +105,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libglusterfs-dev:armhf \ libglusterfs-dev:armhf \
libgnutls28-dev:armhf \ libgnutls28-dev:armhf \
libgtk-3-dev:armhf \ libgtk-3-dev:armhf \
libibumad-dev:armhf \
libibverbs-dev:armhf \ libibverbs-dev:armhf \
libiscsi-dev:armhf \ libiscsi-dev:armhf \
libjemalloc-dev:armhf \ libjemalloc-dev:armhf \

View file

@ -108,7 +108,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libglusterfs-dev:i386 \ libglusterfs-dev:i386 \
libgnutls28-dev:i386 \ libgnutls28-dev:i386 \
libgtk-3-dev:i386 \ libgtk-3-dev:i386 \
libibumad-dev:i386 \
libibverbs-dev:i386 \ libibverbs-dev:i386 \
libiscsi-dev:i386 \ libiscsi-dev:i386 \
libjemalloc-dev:i386 \ libjemalloc-dev:i386 \

View file

@ -107,7 +107,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libglusterfs-dev:mips64el \ libglusterfs-dev:mips64el \
libgnutls28-dev:mips64el \ libgnutls28-dev:mips64el \
libgtk-3-dev:mips64el \ libgtk-3-dev:mips64el \
libibumad-dev:mips64el \
libibverbs-dev:mips64el \ libibverbs-dev:mips64el \
libiscsi-dev:mips64el \ libiscsi-dev:mips64el \
libjemalloc-dev:mips64el \ libjemalloc-dev:mips64el \

View file

@ -107,7 +107,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libglusterfs-dev:mipsel \ libglusterfs-dev:mipsel \
libgnutls28-dev:mipsel \ libgnutls28-dev:mipsel \
libgtk-3-dev:mipsel \ libgtk-3-dev:mipsel \
libibumad-dev:mipsel \
libibverbs-dev:mipsel \ libibverbs-dev:mipsel \
libiscsi-dev:mipsel \ libiscsi-dev:mipsel \
libjemalloc-dev:mipsel \ libjemalloc-dev:mipsel \

View file

@ -105,7 +105,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libglusterfs-dev:ppc64el \ libglusterfs-dev:ppc64el \
libgnutls28-dev:ppc64el \ libgnutls28-dev:ppc64el \
libgtk-3-dev:ppc64el \ libgtk-3-dev:ppc64el \
libibumad-dev:ppc64el \
libibverbs-dev:ppc64el \ libibverbs-dev:ppc64el \
libiscsi-dev:ppc64el \ libiscsi-dev:ppc64el \
libjemalloc-dev:ppc64el \ libjemalloc-dev:ppc64el \

View file

@ -105,7 +105,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libglusterfs-dev:s390x \ libglusterfs-dev:s390x \
libgnutls28-dev:s390x \ libgnutls28-dev:s390x \
libgtk-3-dev:s390x \ libgtk-3-dev:s390x \
libibumad-dev:s390x \
libibverbs-dev:s390x \ libibverbs-dev:s390x \
libiscsi-dev:s390x \ libiscsi-dev:s390x \
libjemalloc-dev:s390x \ libjemalloc-dev:s390x \

View file

@ -55,7 +55,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libglusterfs-dev \ libglusterfs-dev \
libgnutls28-dev \ libgnutls28-dev \
libgtk-3-dev \ libgtk-3-dev \
libibumad-dev \
libibverbs-dev \ libibverbs-dev \
libiscsi-dev \ libiscsi-dev \
libjemalloc-dev \ libjemalloc-dev \

View file

@ -55,7 +55,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libglusterfs-dev \ libglusterfs-dev \
libgnutls28-dev \ libgnutls28-dev \
libgtk-3-dev \ libgtk-3-dev \
libibumad-dev \
libibverbs-dev \ libibverbs-dev \
libiscsi-dev \ libiscsi-dev \
libjemalloc-dev \ libjemalloc-dev \

View file

@ -47,7 +47,6 @@ packages:
- libfdt - libfdt
- libffi - libffi
- libgcrypt - libgcrypt
- libibumad
- libibverbs - libibverbs
- libiscsi - libiscsi
- libjemalloc - libjemalloc

View file

@ -37,6 +37,7 @@
#include "qapi/qmp/qjson.h" #include "qapi/qmp/qjson.h"
#include "qapi/qmp/qlist.h" #include "qapi/qmp/qlist.h"
#include "qapi/qmp/qstring.h" #include "qapi/qmp/qstring.h"
#include "qapi/qmp/qbool.h"
#define MAX_IRQ 256 #define MAX_IRQ 256
@ -1471,6 +1472,12 @@ struct MachInfo {
char *alias; char *alias;
}; };
struct CpuModel {
char *name;
char *alias_of;
bool deprecated;
};
static void qtest_free_machine_list(struct MachInfo *machines) static void qtest_free_machine_list(struct MachInfo *machines)
{ {
if (machines) { if (machines) {
@ -1550,6 +1557,82 @@ static struct MachInfo *qtest_get_machines(const char *var)
return machines; return machines;
} }
static struct CpuModel *qtest_get_cpu_models(void)
{
static struct CpuModel *cpus;
QDict *response, *minfo;
QList *list;
const QListEntry *p;
QObject *qobj;
QString *qstr;
QBool *qbool;
QTestState *qts;
int idx;
if (cpus) {
return cpus;
}
silence_spawn_log = !g_test_verbose();
qts = qtest_init_with_env(NULL, "-machine none");
response = qtest_qmp(qts, "{ 'execute': 'query-cpu-definitions' }");
g_assert(response);
list = qdict_get_qlist(response, "return");
g_assert(list);
cpus = g_new0(struct CpuModel, qlist_size(list) + 1);
for (p = qlist_first(list), idx = 0; p; p = qlist_next(p), idx++) {
minfo = qobject_to(QDict, qlist_entry_obj(p));
g_assert(minfo);
qobj = qdict_get(minfo, "name");
g_assert(qobj);
qstr = qobject_to(QString, qobj);
g_assert(qstr);
cpus[idx].name = g_strdup(qstring_get_str(qstr));
qobj = qdict_get(minfo, "alias_of");
if (qobj) { /* old machines do not report aliases */
qstr = qobject_to(QString, qobj);
g_assert(qstr);
cpus[idx].alias_of = g_strdup(qstring_get_str(qstr));
} else {
cpus[idx].alias_of = NULL;
}
qobj = qdict_get(minfo, "deprecated");
qbool = qobject_to(QBool, qobj);
g_assert(qbool);
cpus[idx].deprecated = qbool_get_bool(qbool);
}
qtest_quit(qts);
qobject_unref(response);
silence_spawn_log = false;
return cpus;
}
bool qtest_has_cpu_model(const char *cpu)
{
struct CpuModel *cpus;
int i;
cpus = qtest_get_cpu_models();
for (i = 0; cpus[i].name != NULL; i++) {
if (g_str_equal(cpu, cpus[i].name) ||
(cpus[i].alias_of && g_str_equal(cpu, cpus[i].alias_of))) {
return true;
}
}
return false;
}
void qtest_cb_for_every_machine(void (*cb)(const char *machine), void qtest_cb_for_every_machine(void (*cb)(const char *machine),
bool skip_old_versioned) bool skip_old_versioned)
{ {

View file

@ -949,6 +949,14 @@ bool qtest_has_machine(const char *machine);
*/ */
bool qtest_has_machine_with_env(const char *var, const char *machine); bool qtest_has_machine_with_env(const char *var, const char *machine);
/**
* qtest_has_cpu_model:
* @cpu: The cpu to look for
*
* Returns: true if the cpu is available in the target binary.
*/
bool qtest_has_cpu_model(const char *cpu);
/** /**
* qtest_has_device: * qtest_has_device:
* @device: The device to look for * @device: The device to look for

View file

@ -125,7 +125,8 @@ static void pc_numa_cpu(const void *data)
QTestState *qts; QTestState *qts;
g_autofree char *cli = NULL; g_autofree char *cli = NULL;
cli = make_cli(data, "-cpu pentium -machine smp.cpus=8,smp.sockets=2,smp.cores=2,smp.threads=2 " cli = make_cli(data,
"-cpu max -machine smp.cpus=8,smp.sockets=2,smp.cores=2,smp.threads=2 "
"-numa node,nodeid=0,memdev=ram -numa node,nodeid=1 " "-numa node,nodeid=0,memdev=ram -numa node,nodeid=1 "
"-numa cpu,node-id=1,socket-id=0 " "-numa cpu,node-id=1,socket-id=0 "
"-numa cpu,node-id=0,socket-id=1,core-id=0 " "-numa cpu,node-id=0,socket-id=1,core-id=0 "

View file

@ -67,10 +67,29 @@ static void test_cpuid_prop(const void *data)
g_free(path); g_free(path);
} }
static void add_cpuid_test(const char *name, const char *cmdline, static void add_cpuid_test(const char *name, const char *cpu,
const char *cpufeat, const char *machine,
const char *property, int64_t expected_value) const char *property, int64_t expected_value)
{ {
CpuidTestArgs *args = g_new0(CpuidTestArgs, 1); CpuidTestArgs *args = g_new0(CpuidTestArgs, 1);
char *cmdline;
char *save;
if (!qtest_has_cpu_model(cpu)) {
return;
}
cmdline = g_strdup_printf("-cpu %s", cpu);
if (cpufeat) {
save = cmdline;
cmdline = g_strdup_printf("%s,%s", cmdline, cpufeat);
g_free(save);
}
if (machine) {
save = cmdline;
cmdline = g_strdup_printf("-machine %s %s", machine, cmdline);
g_free(save);
}
args->cmdline = cmdline; args->cmdline = cmdline;
args->property = property; args->property = property;
args->expected_value = expected_value; args->expected_value = expected_value;
@ -149,12 +168,24 @@ static void test_feature_flag(const void *data)
* either "feature-words" or "filtered-features", when running QEMU * either "feature-words" or "filtered-features", when running QEMU
* using cmdline * using cmdline
*/ */
static FeatureTestArgs *add_feature_test(const char *name, const char *cmdline, static void add_feature_test(const char *name, const char *cpu,
uint32_t eax, uint32_t ecx, const char *cpufeat, uint32_t eax,
const char *reg, int bitnr, uint32_t ecx, const char *reg,
bool expected_value) int bitnr, bool expected_value)
{ {
FeatureTestArgs *args = g_new0(FeatureTestArgs, 1); FeatureTestArgs *args = g_new0(FeatureTestArgs, 1);
char *cmdline;
if (!qtest_has_cpu_model(cpu)) {
return;
}
if (cpufeat) {
cmdline = g_strdup_printf("-cpu %s,%s", cpu, cpufeat);
} else {
cmdline = g_strdup_printf("-cpu %s", cpu);
}
args->cmdline = cmdline; args->cmdline = cmdline;
args->in_eax = eax; args->in_eax = eax;
args->in_ecx = ecx; args->in_ecx = ecx;
@ -162,13 +193,17 @@ static FeatureTestArgs *add_feature_test(const char *name, const char *cmdline,
args->bitnr = bitnr; args->bitnr = bitnr;
args->expected_value = expected_value; args->expected_value = expected_value;
qtest_add_data_func(name, args, test_feature_flag); qtest_add_data_func(name, args, test_feature_flag);
return args; return;
} }
static void test_plus_minus_subprocess(void) static void test_plus_minus_subprocess(void)
{ {
char *path; char *path;
if (!qtest_has_cpu_model("pentium")) {
return;
}
/* Rules: /* Rules:
* 1)"-foo" overrides "+foo" * 1)"-foo" overrides "+foo"
* 2) "[+-]foo" overrides "foo=..." * 2) "[+-]foo" overrides "foo=..."
@ -198,6 +233,10 @@ static void test_plus_minus_subprocess(void)
static void test_plus_minus(void) static void test_plus_minus(void)
{ {
if (!qtest_has_cpu_model("pentium")) {
return;
}
g_test_trap_subprocess("/x86/cpuid/parsing-plus-minus/subprocess", 0, 0); g_test_trap_subprocess("/x86/cpuid/parsing-plus-minus/subprocess", 0, 0);
g_test_trap_assert_passed(); g_test_trap_assert_passed();
g_test_trap_assert_stderr("*Ambiguous CPU model string. " g_test_trap_assert_stderr("*Ambiguous CPU model string. "
@ -217,99 +256,105 @@ int main(int argc, char **argv)
/* Original level values for CPU models: */ /* Original level values for CPU models: */
add_cpuid_test("x86/cpuid/phenom/level", add_cpuid_test("x86/cpuid/phenom/level",
"-cpu phenom", "level", 5); "phenom", NULL, NULL, "level", 5);
add_cpuid_test("x86/cpuid/Conroe/level", add_cpuid_test("x86/cpuid/Conroe/level",
"-cpu Conroe", "level", 10); "Conroe", NULL, NULL, "level", 10);
add_cpuid_test("x86/cpuid/SandyBridge/level", add_cpuid_test("x86/cpuid/SandyBridge/level",
"-cpu SandyBridge", "level", 0xd); "SandyBridge", NULL, NULL, "level", 0xd);
add_cpuid_test("x86/cpuid/486/xlevel", add_cpuid_test("x86/cpuid/486/xlevel",
"-cpu 486", "xlevel", 0); "486", NULL, NULL, "xlevel", 0);
add_cpuid_test("x86/cpuid/core2duo/xlevel", add_cpuid_test("x86/cpuid/core2duo/xlevel",
"-cpu core2duo", "xlevel", 0x80000008); "core2duo", NULL, NULL, "xlevel", 0x80000008);
add_cpuid_test("x86/cpuid/phenom/xlevel", add_cpuid_test("x86/cpuid/phenom/xlevel",
"-cpu phenom", "xlevel", 0x8000001A); "phenom", NULL, NULL, "xlevel", 0x8000001A);
add_cpuid_test("x86/cpuid/athlon/xlevel", add_cpuid_test("x86/cpuid/athlon/xlevel",
"-cpu athlon", "xlevel", 0x80000008); "athlon", NULL, NULL, "xlevel", 0x80000008);
/* If level is not large enough, it should increase automatically: */ /* If level is not large enough, it should increase automatically: */
/* CPUID[6].EAX: */ /* CPUID[6].EAX: */
add_cpuid_test("x86/cpuid/auto-level/phenom/arat", add_cpuid_test("x86/cpuid/auto-level/486/arat",
"-cpu 486,arat=on", "level", 6); "486", "arat=on", NULL, "level", 6);
/* CPUID[EAX=7,ECX=0].EBX: */ /* CPUID[EAX=7,ECX=0].EBX: */
add_cpuid_test("x86/cpuid/auto-level/phenom/fsgsbase", add_cpuid_test("x86/cpuid/auto-level/phenom/fsgsbase",
"-cpu phenom,fsgsbase=on", "level", 7); "phenom", "fsgsbase=on", NULL, "level", 7);
/* CPUID[EAX=7,ECX=0].ECX: */ /* CPUID[EAX=7,ECX=0].ECX: */
add_cpuid_test("x86/cpuid/auto-level/phenom/avx512vbmi", add_cpuid_test("x86/cpuid/auto-level/phenom/avx512vbmi",
"-cpu phenom,avx512vbmi=on", "level", 7); "phenom", "avx512vbmi=on", NULL, "level", 7);
/* CPUID[EAX=0xd,ECX=1].EAX: */ /* CPUID[EAX=0xd,ECX=1].EAX: */
add_cpuid_test("x86/cpuid/auto-level/phenom/xsaveopt", add_cpuid_test("x86/cpuid/auto-level/phenom/xsaveopt",
"-cpu phenom,xsaveopt=on", "level", 0xd); "phenom", "xsaveopt=on", NULL, "level", 0xd);
/* CPUID[8000_0001].EDX: */ /* CPUID[8000_0001].EDX: */
add_cpuid_test("x86/cpuid/auto-xlevel/486/3dnow", add_cpuid_test("x86/cpuid/auto-xlevel/486/3dnow",
"-cpu 486,3dnow=on", "xlevel", 0x80000001); "486", "3dnow=on", NULL, "xlevel", 0x80000001);
/* CPUID[8000_0001].ECX: */ /* CPUID[8000_0001].ECX: */
add_cpuid_test("x86/cpuid/auto-xlevel/486/sse4a", add_cpuid_test("x86/cpuid/auto-xlevel/486/sse4a",
"-cpu 486,sse4a=on", "xlevel", 0x80000001); "486", "sse4a=on", NULL, "xlevel", 0x80000001);
/* CPUID[8000_0007].EDX: */ /* CPUID[8000_0007].EDX: */
add_cpuid_test("x86/cpuid/auto-xlevel/486/invtsc", add_cpuid_test("x86/cpuid/auto-xlevel/486/invtsc",
"-cpu 486,invtsc=on", "xlevel", 0x80000007); "486", "invtsc=on", NULL, "xlevel", 0x80000007);
/* CPUID[8000_000A].EDX: */ /* CPUID[8000_000A].EDX: */
add_cpuid_test("x86/cpuid/auto-xlevel/486/npt", add_cpuid_test("x86/cpuid/auto-xlevel/486/npt",
"-cpu 486,svm=on,npt=on", "xlevel", 0x8000000A); "486", "svm=on,npt=on", NULL, "xlevel", 0x8000000A);
/* CPUID[C000_0001].EDX: */ /* CPUID[C000_0001].EDX: */
add_cpuid_test("x86/cpuid/auto-xlevel2/phenom/xstore", add_cpuid_test("x86/cpuid/auto-xlevel2/phenom/xstore",
"-cpu phenom,xstore=on", "xlevel2", 0xC0000001); "phenom", "xstore=on", NULL, "xlevel2", 0xC0000001);
/* SVM needs CPUID[0x8000000A] */ /* SVM needs CPUID[0x8000000A] */
add_cpuid_test("x86/cpuid/auto-xlevel/athlon/svm", add_cpuid_test("x86/cpuid/auto-xlevel/athlon/svm",
"-cpu athlon,svm=on", "xlevel", 0x8000000A); "athlon", "svm=on", NULL, "xlevel", 0x8000000A);
/* If level is already large enough, it shouldn't change: */ /* If level is already large enough, it shouldn't change: */
add_cpuid_test("x86/cpuid/auto-level/SandyBridge/multiple", add_cpuid_test("x86/cpuid/auto-level/SandyBridge/multiple",
"-cpu SandyBridge,arat=on,fsgsbase=on,avx512vbmi=on", "SandyBridge", "arat=on,fsgsbase=on,avx512vbmi=on",
"level", 0xd); NULL, "level", 0xd);
/* If level is explicitly set, it shouldn't change: */ /* If level is explicitly set, it shouldn't change: */
add_cpuid_test("x86/cpuid/auto-level/486/fixed/0xF", add_cpuid_test("x86/cpuid/auto-level/486/fixed/0xF",
"-cpu 486,level=0xF,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", "486",
"level", 0xF); "level=0xF,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on",
NULL, "level", 0xF);
add_cpuid_test("x86/cpuid/auto-level/486/fixed/2", add_cpuid_test("x86/cpuid/auto-level/486/fixed/2",
"-cpu 486,level=2,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", "486",
"level", 2); "level=2,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on",
NULL, "level", 2);
add_cpuid_test("x86/cpuid/auto-level/486/fixed/0", add_cpuid_test("x86/cpuid/auto-level/486/fixed/0",
"-cpu 486,level=0,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", "486",
"level", 0); "level=0,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on",
NULL, "level", 0);
/* if xlevel is already large enough, it shouldn't change: */ /* if xlevel is already large enough, it shouldn't change: */
add_cpuid_test("x86/cpuid/auto-xlevel/phenom/3dnow", add_cpuid_test("x86/cpuid/auto-xlevel/phenom/3dnow",
"-cpu phenom,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", "phenom", "3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on",
"xlevel", 0x8000001A); NULL, "xlevel", 0x8000001A);
/* If xlevel is explicitly set, it shouldn't change: */ /* If xlevel is explicitly set, it shouldn't change: */
add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/80000002", add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/80000002",
"-cpu 486,xlevel=0x80000002,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", "486",
"xlevel", 0x80000002); "xlevel=0x80000002,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on",
NULL, "xlevel", 0x80000002);
add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/8000001A", add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/8000001A",
"-cpu 486,xlevel=0x8000001A,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", "486",
"xlevel", 0x8000001A); "xlevel=0x8000001A,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on",
NULL, "xlevel", 0x8000001A);
add_cpuid_test("x86/cpuid/auto-xlevel/phenom/fixed/0", add_cpuid_test("x86/cpuid/auto-xlevel/phenom/fixed/0",
"-cpu 486,xlevel=0,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", "486",
"xlevel", 0); "xlevel=0,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on",
NULL, "xlevel", 0);
/* if xlevel2 is already large enough, it shouldn't change: */ /* if xlevel2 is already large enough, it shouldn't change: */
add_cpuid_test("x86/cpuid/auto-xlevel2/486/fixed", add_cpuid_test("x86/cpuid/auto-xlevel2/486/fixed",
"-cpu 486,xlevel2=0xC0000002,xstore=on", "486", "xlevel2=0xC0000002,xstore=on",
"xlevel2", 0xC0000002); NULL, "xlevel2", 0xC0000002);
/* Check compatibility of old machine-types that didn't /* Check compatibility of old machine-types that didn't
* auto-increase level/xlevel/xlevel2: */ * auto-increase level/xlevel/xlevel2: */
if (qtest_has_machine("pc-i440fx-2.7")) { if (qtest_has_machine("pc-i440fx-2.7")) {
add_cpuid_test("x86/cpuid/auto-level/pc-2.7", add_cpuid_test("x86/cpuid/auto-level/pc-2.7",
"-machine pc-i440fx-2.7 -cpu 486,arat=on,avx512vbmi=on,xsaveopt=on", "486", "arat=on,avx512vbmi=on,xsaveopt=on",
"level", 1); "pc-i440fx-2.7", "level", 1);
add_cpuid_test("x86/cpuid/auto-xlevel/pc-2.7", add_cpuid_test("x86/cpuid/auto-xlevel/pc-2.7",
"-machine pc-i440fx-2.7 -cpu 486,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", "486", "3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on",
"xlevel", 0); "pc-i440fx-2.7", "xlevel", 0);
add_cpuid_test("x86/cpuid/auto-xlevel2/pc-2.7", add_cpuid_test("x86/cpuid/auto-xlevel2/pc-2.7",
"-machine pc-i440fx-2.7 -cpu 486,xstore=on", "486", "xstore=on", "pc-i440fx-2.7",
"xlevel2", 0); "xlevel2", 0);
} }
/* /*
@ -319,18 +364,18 @@ int main(int argc, char **argv)
*/ */
if (qtest_has_machine("pc-i440fx-2.3")) { if (qtest_has_machine("pc-i440fx-2.3")) {
add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.3/off", add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.3/off",
"-machine pc-i440fx-2.3 -cpu Penryn", "Penryn", NULL, "pc-i440fx-2.3",
"level", 4); "level", 4);
add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.3/on", add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.3/on",
"-machine pc-i440fx-2.3 -cpu Penryn,erms=on", "Penryn", "erms=on", "pc-i440fx-2.3",
"level", 7); "level", 7);
} }
if (qtest_has_machine("pc-i440fx-2.9")) { if (qtest_has_machine("pc-i440fx-2.9")) {
add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.9/off", add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.9/off",
"-machine pc-i440fx-2.9 -cpu Conroe", "Conroe", NULL, "pc-i440fx-2.9",
"level", 10); "level", 10);
add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.9/on", add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.9/on",
"-machine pc-i440fx-2.9 -cpu Conroe,erms=on", "Conroe", "erms=on", "pc-i440fx-2.9",
"level", 10); "level", 10);
} }
@ -341,42 +386,43 @@ int main(int argc, char **argv)
*/ */
if (qtest_has_machine("pc-i440fx-2.3")) { if (qtest_has_machine("pc-i440fx-2.3")) {
add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.3", add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.3",
"-machine pc-i440fx-2.3 -cpu SandyBridge", "SandyBridge", NULL, "pc-i440fx-2.3",
"xlevel", 0x8000000a); "xlevel", 0x8000000a);
} }
if (qtest_has_machine("pc-i440fx-2.4")) { if (qtest_has_machine("pc-i440fx-2.4")) {
add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.4/npt-off", add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.4/npt-off",
"-machine pc-i440fx-2.4 -cpu SandyBridge,", "SandyBridge", NULL, "pc-i440fx-2.4",
"xlevel", 0x80000008); "xlevel", 0x80000008);
add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.4/npt-on", add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.4/npt-on",
"-machine pc-i440fx-2.4 -cpu SandyBridge,svm=on,npt=on", "SandyBridge", "svm=on,npt=on", "pc-i440fx-2.4",
"xlevel", 0x80000008); "xlevel", 0x80000008);
} }
/* Test feature parsing */ /* Test feature parsing */
add_feature_test("x86/cpuid/features/plus", add_feature_test("x86/cpuid/features/plus",
"-cpu 486,+arat", "486", "+arat",
6, 0, "EAX", 2, true); 6, 0, "EAX", 2, true);
add_feature_test("x86/cpuid/features/minus", add_feature_test("x86/cpuid/features/minus",
"-cpu pentium,-mmx", "pentium", "-mmx",
1, 0, "EDX", 23, false); 1, 0, "EDX", 23, false);
add_feature_test("x86/cpuid/features/on", add_feature_test("x86/cpuid/features/on",
"-cpu 486,arat=on", "486", "arat=on",
6, 0, "EAX", 2, true); 6, 0, "EAX", 2, true);
add_feature_test("x86/cpuid/features/off", add_feature_test("x86/cpuid/features/off",
"-cpu pentium,mmx=off", "pentium", "mmx=off",
1, 0, "EDX", 23, false); 1, 0, "EDX", 23, false);
add_feature_test("x86/cpuid/features/max-plus-invtsc", add_feature_test("x86/cpuid/features/max-plus-invtsc",
"-cpu max,+invtsc", "max" , "+invtsc",
0x80000007, 0, "EDX", 8, true); 0x80000007, 0, "EDX", 8, true);
add_feature_test("x86/cpuid/features/max-invtsc-on", add_feature_test("x86/cpuid/features/max-invtsc-on",
"-cpu max,invtsc=on", "max", "invtsc=on",
0x80000007, 0, "EDX", 8, true); 0x80000007, 0, "EDX", 8, true);
add_feature_test("x86/cpuid/features/max-minus-mmx", add_feature_test("x86/cpuid/features/max-minus-mmx",
"-cpu max,-mmx", "max", "-mmx",
1, 0, "EDX", 23, false); 1, 0, "EDX", 23, false);
add_feature_test("x86/cpuid/features/max-invtsc-on,mmx=off", add_feature_test("x86/cpuid/features/max-invtsc-on,mmx=off",
"-cpu max,mmx=off", "max", "mmx=off",
1, 0, "EDX", 23, false); 1, 0, "EDX", 23, false);
return g_test_run(); return g_test_run();

View file

@ -1,6 +1,6 @@
S390X_SRC=$(SRC_PATH)/tests/tcg/s390x S390X_SRC=$(SRC_PATH)/tests/tcg/s390x
VPATH+=$(S390X_SRC) VPATH+=$(S390X_SRC)
QEMU_OPTS=-action panic=exit-failure -nographic -kernel QEMU_OPTS+=-action panic=exit-failure -nographic $(EXTFLAGS) -kernel
LINK_SCRIPT=$(S390X_SRC)/softmmu.ld LINK_SCRIPT=$(S390X_SRC)/softmmu.ld
CFLAGS+=-ggdb -O0 CFLAGS+=-ggdb -O0
LDFLAGS=-nostdlib -static LDFLAGS=-nostdlib -static

View file

@ -48,17 +48,19 @@
} }
/* /*
* Currently a 4-level topology hierarchy is supported on PC machines * Currently a 5-level topology hierarchy is supported on PC machines
* -sockets/dies/cores/threads * -sockets/dies/modules/cores/threads
*/ */
#define SMP_CONFIG_WITH_DIES(ha, a, hb, b, hc, c, hd, d, he, e, hf, f) \ #define SMP_CONFIG_WITH_MODS_DIES(ha, a, hb, b, hc, c, hd, d, \
he, e, hf, f, hg, g) \
{ \ { \
.has_cpus = ha, .cpus = a, \ .has_cpus = ha, .cpus = a, \
.has_sockets = hb, .sockets = b, \ .has_sockets = hb, .sockets = b, \
.has_dies = hc, .dies = c, \ .has_dies = hc, .dies = c, \
.has_cores = hd, .cores = d, \ .has_modules = hd, .modules = d, \
.has_threads = he, .threads = e, \ .has_cores = he, .cores = e, \
.has_maxcpus = hf, .maxcpus = f, \ .has_threads = hf, .threads = f, \
.has_maxcpus = hg, .maxcpus = g, \
} }
/* /*
@ -92,11 +94,11 @@
} }
/* /*
* Currently QEMU supports up to a 7-level topology hierarchy, which is the * Currently QEMU supports up to a 8-level topology hierarchy, which is the
* QEMU's unified abstract representation of CPU topology. * QEMU's unified abstract representation of CPU topology.
* -drawers/books/sockets/dies/clusters/cores/threads * -drawers/books/sockets/dies/clusters/modules/cores/threads
*/ */
#define SMP_CONFIG_WITH_FULL_TOPO(a, b, c, d, e, f, g, h, i) \ #define SMP_CONFIG_WITH_FULL_TOPO(a, b, c, d, e, f, g, h, i, j) \
{ \ { \
.has_cpus = true, .cpus = a, \ .has_cpus = true, .cpus = a, \
.has_drawers = true, .drawers = b, \ .has_drawers = true, .drawers = b, \
@ -104,9 +106,10 @@
.has_sockets = true, .sockets = d, \ .has_sockets = true, .sockets = d, \
.has_dies = true, .dies = e, \ .has_dies = true, .dies = e, \
.has_clusters = true, .clusters = f, \ .has_clusters = true, .clusters = f, \
.has_cores = true, .cores = g, \ .has_modules = true, .modules = g, \
.has_threads = true, .threads = h, \ .has_cores = true, .cores = h, \
.has_maxcpus = true, .maxcpus = i, \ .has_threads = true, .threads = i, \
.has_maxcpus = true, .maxcpus = j, \
} }
/** /**
@ -333,9 +336,11 @@ static const struct SMPTestData data_generic_valid[] = {
}, { }, {
/* /*
* Unsupported parameters are always allowed to be set to '1' * Unsupported parameters are always allowed to be set to '1'
* config: -smp 8,books=1,drawers=1,sockets=2,modules=1,dies=1,cores=2,threads=2,maxcpus=8 * config:
* -smp 8,drawers=1,books=1,sockets=2,dies=1,clusters=1,modules=1,\
* cores=2,threads=2,maxcpus=8
* expect: cpus=8,sockets=2,cores=2,threads=2,maxcpus=8 */ * expect: cpus=8,sockets=2,cores=2,threads=2,maxcpus=8 */
.config = SMP_CONFIG_WITH_FULL_TOPO(8, 1, 1, 2, 1, 1, 2, 2, 8), .config = SMP_CONFIG_WITH_FULL_TOPO(8, 1, 1, 2, 1, 1, 1, 2, 2, 8),
.expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 2, 2, 8), .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 2, 2, 8),
.expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 2, 2, 8), .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 2, 2, 8),
}, },
@ -343,8 +348,14 @@ static const struct SMPTestData data_generic_valid[] = {
static const struct SMPTestData data_generic_invalid[] = { static const struct SMPTestData data_generic_invalid[] = {
{ {
/* config: -smp 2,modules=2 */
.config = SMP_CONFIG_WITH_MODS_DIES(T, 2, F, 0, F, 0, T, 2,
F, 0, F, 0, F, 0),
.expect_error = "modules > 1 not supported by this machine's CPU topology",
}, {
/* config: -smp 2,dies=2 */ /* config: -smp 2,dies=2 */
.config = SMP_CONFIG_WITH_DIES(T, 2, F, 0, T, 2, F, 0, F, 0, F, 0), .config = SMP_CONFIG_WITH_MODS_DIES(T, 2, F, 0, T, 2, F, 0,
F, 0, F, 0, F, 0),
.expect_error = "dies > 1 not supported by this machine's CPU topology", .expect_error = "dies > 1 not supported by this machine's CPU topology",
}, { }, {
/* config: -smp 2,clusters=2 */ /* config: -smp 2,clusters=2 */
@ -395,17 +406,39 @@ static const struct SMPTestData data_generic_invalid[] = {
}, },
}; };
static const struct SMPTestData data_with_modules_invalid[] = {
{
/* config: -smp 16,sockets=2,modules=2,cores=4,threads=2,maxcpus=16 */
.config = SMP_CONFIG_WITH_MODS_DIES(T, 16, T, 2, F, 0, T, 2,
T, 4, T, 2, T, 16),
.expect_error = "Invalid CPU topology: "
"product of the hierarchy must match maxcpus: "
"sockets (2) * modules (2) * cores (4) * threads (2) "
"!= maxcpus (16)",
}, {
/* config: -smp 34,sockets=2,modules=2,cores=4,threads=2,maxcpus=32 */
.config = SMP_CONFIG_WITH_MODS_DIES(T, 34, T, 2, F, 0, T, 2,
T, 4, T, 2, T, 32),
.expect_error = "Invalid CPU topology: "
"maxcpus must be equal to or greater than smp: "
"sockets (2) * modules (2) * cores (4) * threads (2) "
"== maxcpus (32) < smp_cpus (34)",
},
};
static const 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 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), .config = SMP_CONFIG_WITH_MODS_DIES(T, 16, T, 2, T, 2, F, 0,
T, 4, T, 2, T, 16),
.expect_error = "Invalid CPU topology: " .expect_error = "Invalid CPU topology: "
"product of the hierarchy must match maxcpus: " "product of the hierarchy must match maxcpus: "
"sockets (2) * dies (2) * cores (4) * threads (2) " "sockets (2) * dies (2) * cores (4) * threads (2) "
"!= maxcpus (16)", "!= maxcpus (16)",
}, { }, {
/* config: -smp 34,sockets=2,dies=2,cores=4,threads=2,maxcpus=32 */ /* config: -smp 34,sockets=2,dies=2,cores=4,threads=2,maxcpus=32 */
.config = SMP_CONFIG_WITH_DIES(T, 34, T, 2, T, 2, T, 4, T, 2, T, 32), .config = SMP_CONFIG_WITH_MODS_DIES(T, 34, T, 2, T, 2, F, 0,
T, 4, T, 2, T, 32),
.expect_error = "Invalid CPU topology: " .expect_error = "Invalid CPU topology: "
"maxcpus must be equal to or greater than smp: " "maxcpus must be equal to or greater than smp: "
"sockets (2) * dies (2) * cores (4) * threads (2) " "sockets (2) * dies (2) * cores (4) * threads (2) "
@ -413,6 +446,33 @@ static const struct SMPTestData data_with_dies_invalid[] = {
}, },
}; };
static const struct SMPTestData data_with_modules_dies_invalid[] = {
{
/*
* config: -smp 200,sockets=3,dies=5,modules=2,cores=4,\
* threads=2,maxcpus=200
*/
.config = SMP_CONFIG_WITH_MODS_DIES(T, 200, T, 3, T, 5, T,
2, T, 4, T, 2, T, 200),
.expect_error = "Invalid CPU topology: "
"product of the hierarchy must match maxcpus: "
"sockets (3) * dies (5) * modules (2) * "
"cores (4) * threads (2) != maxcpus (200)",
}, {
/*
* config: -smp 242,sockets=3,dies=5,modules=2,cores=4,\
* threads=2,maxcpus=240
*/
.config = SMP_CONFIG_WITH_MODS_DIES(T, 242, T, 3, T, 5, T,
2, T, 4, T, 2, T, 240),
.expect_error = "Invalid CPU topology: "
"maxcpus must be equal to or greater than smp: "
"sockets (3) * dies (5) * modules (2) * "
"cores (4) * threads (2) "
"== maxcpus (240) < smp_cpus (242)",
},
};
static const struct SMPTestData data_with_clusters_invalid[] = { static const struct SMPTestData data_with_clusters_invalid[] = {
{ {
/* config: -smp 16,sockets=2,clusters=2,cores=4,threads=2,maxcpus=16 */ /* config: -smp 16,sockets=2,clusters=2,cores=4,threads=2,maxcpus=16 */
@ -434,7 +494,7 @@ static const struct SMPTestData data_with_clusters_invalid[] = {
static const struct SMPTestData data_with_books_invalid[] = { static const struct SMPTestData data_with_books_invalid[] = {
{ {
/* config: -smp 16,books=2,sockets=2,cores=4,threads=2,maxcpus=16 */ /* config: -smp 16,books=2,sockets=2,cores=4,threads=2,maxcpus=16 */
.config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 16, F, 1, T, 2, T, .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 16, F, 0, T, 2, T,
2, T, 4, T, 2, T, 16), 2, T, 4, T, 2, T, 16),
.expect_error = "Invalid CPU topology: " .expect_error = "Invalid CPU topology: "
"product of the hierarchy must match maxcpus: " "product of the hierarchy must match maxcpus: "
@ -442,7 +502,7 @@ static const struct SMPTestData data_with_books_invalid[] = {
"!= maxcpus (16)", "!= maxcpus (16)",
}, { }, {
/* config: -smp 34,books=2,sockets=2,cores=4,threads=2,maxcpus=32 */ /* config: -smp 34,books=2,sockets=2,cores=4,threads=2,maxcpus=32 */
.config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 34, F, 1, T, 2, T, .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 34, F, 0, T, 2, T,
2, T, 4, T, 2, T, 32), 2, T, 4, T, 2, T, 32),
.expect_error = "Invalid CPU topology: " .expect_error = "Invalid CPU topology: "
"maxcpus must be equal to or greater than smp: " "maxcpus must be equal to or greater than smp: "
@ -454,7 +514,7 @@ static const struct SMPTestData data_with_books_invalid[] = {
static const struct SMPTestData data_with_drawers_invalid[] = { static const struct SMPTestData data_with_drawers_invalid[] = {
{ {
/* config: -smp 16,drawers=2,sockets=2,cores=4,threads=2,maxcpus=16 */ /* config: -smp 16,drawers=2,sockets=2,cores=4,threads=2,maxcpus=16 */
.config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 16, T, 2, F, 1, T, .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 16, T, 2, F, 0, T,
2, T, 4, T, 2, T, 16), 2, T, 4, T, 2, T, 16),
.expect_error = "Invalid CPU topology: " .expect_error = "Invalid CPU topology: "
"product of the hierarchy must match maxcpus: " "product of the hierarchy must match maxcpus: "
@ -462,7 +522,7 @@ static const struct SMPTestData data_with_drawers_invalid[] = {
"!= maxcpus (16)", "!= maxcpus (16)",
}, { }, {
/* config: -smp 34,drawers=2,sockets=2,cores=4,threads=2,maxcpus=32 */ /* config: -smp 34,drawers=2,sockets=2,cores=4,threads=2,maxcpus=32 */
.config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 34, T, 2, F, 1, T, .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 34, T, 2, F, 0, T,
2, T, 4, T, 2, T, 32), 2, T, 4, T, 2, T, 32),
.expect_error = "Invalid CPU topology: " .expect_error = "Invalid CPU topology: "
"maxcpus must be equal to or greater than smp: " "maxcpus must be equal to or greater than smp: "
@ -474,7 +534,7 @@ static const struct SMPTestData data_with_drawers_invalid[] = {
static const struct SMPTestData data_with_drawers_books_invalid[] = { static const struct SMPTestData data_with_drawers_books_invalid[] = {
{ {
/* /*
* config: -smp 200,drawers=2,books=2,sockets=2,cores=4,\ * config: -smp 200,drawers=3,books=5,sockets=2,cores=4,\
* threads=2,maxcpus=200 * threads=2,maxcpus=200
*/ */
.config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 200, T, 3, T, 5, T, .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 200, T, 3, T, 5, T,
@ -485,7 +545,7 @@ static const struct SMPTestData data_with_drawers_books_invalid[] = {
"cores (4) * threads (2) != maxcpus (200)", "cores (4) * threads (2) != maxcpus (200)",
}, { }, {
/* /*
* config: -smp 242,drawers=2,books=2,sockets=2,cores=4,\ * config: -smp 242,drawers=3,books=5,sockets=2,cores=4,\
* threads=2,maxcpus=240 * threads=2,maxcpus=240
*/ */
.config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 242, T, 3, T, 5, T, .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 242, T, 3, T, 5, T,
@ -502,32 +562,37 @@ static const struct SMPTestData data_full_topo_invalid[] = {
{ {
/* /*
* config: -smp 200,drawers=3,books=5,sockets=2,dies=4,\ * config: -smp 200,drawers=3,books=5,sockets=2,dies=4,\
* clusters=2,cores=7,threads=2,maxcpus=200 * clusters=2,modules=3,cores=7,threads=2,\
* maxcpus=200
*/ */
.config = SMP_CONFIG_WITH_FULL_TOPO(200, 3, 5, 2, 4, 2, 7, 2, 200), .config = SMP_CONFIG_WITH_FULL_TOPO(200, 3, 5, 2, 4, 2, 3, 7, 2, 200),
.expect_error = "Invalid CPU topology: " .expect_error = "Invalid CPU topology: "
"product of the hierarchy must match maxcpus: " "product of the hierarchy must match maxcpus: "
"drawers (3) * books (5) * sockets (2) * dies (4) * " "drawers (3) * books (5) * sockets (2) * dies (4) * "
"clusters (2) * cores (7) * threads (2) " "clusters (2) * modules (3) * cores (7) * threads (2) "
"!= maxcpus (200)", "!= maxcpus (200)",
}, { }, {
/* /*
* config: -smp 3361,drawers=3,books=5,sockets=2,dies=4,\ * config: -smp 2881,drawers=3,books=5,sockets=2,dies=4,\
* clusters=2,cores=7,threads=2,maxcpus=3360 * clusters=2,modules=3,cores=2,threads=2,
* maxcpus=2880
*/ */
.config = SMP_CONFIG_WITH_FULL_TOPO(3361, 3, 5, 2, 4, 2, 7, 2, 3360), .config = SMP_CONFIG_WITH_FULL_TOPO(2881, 3, 5, 2, 4,
2, 3, 2, 2, 2880),
.expect_error = "Invalid CPU topology: " .expect_error = "Invalid CPU topology: "
"maxcpus must be equal to or greater than smp: " "maxcpus must be equal to or greater than smp: "
"drawers (3) * books (5) * sockets (2) * dies (4) * " "drawers (3) * books (5) * sockets (2) * "
"clusters (2) * cores (7) * threads (2) " "dies (4) * clusters (2) * modules (3) * "
"== maxcpus (3360) < smp_cpus (3361)", "cores (2) * threads (2) == maxcpus (2880) "
"< smp_cpus (2881)",
}, { }, {
/* /*
* config: -smp 1,drawers=3,books=5,sockets=2,dies=4,\ * config: -smp 1,drawers=3,books=5,sockets=2,dies=4,\
* clusters=2,cores=7,threads=3,maxcpus=5040 * clusters=2,modules=3,cores=3,threads=3,\
* maxcpus=6480
*/ */
.config = SMP_CONFIG_WITH_FULL_TOPO(3361, 3, 5, 2, 4, 2, 7, 3, 5040), .config = SMP_CONFIG_WITH_FULL_TOPO(1, 3, 5, 2, 4, 2, 3, 3, 3, 6480),
.expect_error = "Invalid SMP CPUs 5040. The max CPUs supported " .expect_error = "Invalid SMP CPUs 6480. The max CPUs supported "
"by machine '" SMP_MACHINE_NAME "' is 4096", "by machine '" SMP_MACHINE_NAME "' is 4096",
}, },
}; };
@ -537,81 +602,100 @@ static const struct SMPTestData data_zero_topo_invalid[] = {
/* /*
* Test "cpus=0". * Test "cpus=0".
* config: -smp 0,drawers=1,books=1,sockets=1,dies=1,\ * config: -smp 0,drawers=1,books=1,sockets=1,dies=1,\
* clusters=1,cores=1,threads=1,maxcpus=1 * clusters=1,modules=1,cores=1,threads=1,\
* maxcpus=1
*/ */
.config = SMP_CONFIG_WITH_FULL_TOPO(0, 1, 1, 1, 1, 1, 1, 1, 1), .config = SMP_CONFIG_WITH_FULL_TOPO(0, 1, 1, 1, 1, 1, 1, 1, 1, 1),
.expect_error = "Invalid CPU topology: CPU topology parameters must " .expect_error = "Invalid CPU topology: CPU topology parameters must "
"be greater than zero", "be greater than zero",
}, { }, {
/* /*
* Test "drawers=0". * Test "drawers=0".
* config: -smp 1,drawers=0,books=1,sockets=1,dies=1,\ * config: -smp 1,drawers=0,books=1,sockets=1,dies=1,\
* clusters=1,cores=1,threads=1,maxcpus=1 * clusters=1,modules=1,cores=1,threads=1,\
* maxcpus=1
*/ */
.config = SMP_CONFIG_WITH_FULL_TOPO(1, 0, 1, 1, 1, 1, 1, 1, 1), .config = SMP_CONFIG_WITH_FULL_TOPO(1, 0, 1, 1, 1, 1, 1, 1, 1, 1),
.expect_error = "Invalid CPU topology: CPU topology parameters must " .expect_error = "Invalid CPU topology: CPU topology parameters must "
"be greater than zero", "be greater than zero",
}, { }, {
/* /*
* Test "books=0". * Test "books=0".
* config: -smp 1,drawers=1,books=0,sockets=1,dies=1,\ * config: -smp 1,drawers=1,books=0,sockets=1,dies=1,\
* clusters=1,cores=1,threads=1,maxcpus=1 * clusters=1,modules=1,cores=1,threads=1,\
* maxcpus=1
*/ */
.config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 0, 1, 1, 1, 1, 1, 1), .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 0, 1, 1, 1, 1, 1, 1, 1),
.expect_error = "Invalid CPU topology: CPU topology parameters must " .expect_error = "Invalid CPU topology: CPU topology parameters must "
"be greater than zero", "be greater than zero",
}, { }, {
/* /*
* Test "sockets=0". * Test "sockets=0".
* config: -smp 1,drawers=1,books=1,sockets=0,dies=1,\ * config: -smp 1,drawers=1,books=1,sockets=0,dies=1,\
* clusters=1,cores=1,threads=1,maxcpus=1 * clusters=1,modules=1,cores=1,threads=1,
* maxcpus=1
*/ */
.config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 0, 1, 1, 1, 1, 1), .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 0, 1, 1, 1, 1, 1, 1),
.expect_error = "Invalid CPU topology: CPU topology parameters must " .expect_error = "Invalid CPU topology: CPU topology parameters must "
"be greater than zero", "be greater than zero",
}, { }, {
/* /*
* Test "dies=0". * Test "dies=0".
* config: -smp 1,drawers=1,books=1,sockets=1,dies=0,\ * config: -smp 1,drawers=1,books=1,sockets=1,dies=0,\
* clusters=1,cores=1,threads=1,maxcpus=1 * clusters=1,modules=1,cores=1,threads=1,\
* maxcpus=1
*/ */
.config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 0, 1, 1, 1, 1), .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 0, 1, 1, 1, 1, 1),
.expect_error = "Invalid CPU topology: CPU topology parameters must " .expect_error = "Invalid CPU topology: CPU topology parameters must "
"be greater than zero", "be greater than zero",
}, { }, {
/* /*
* Test "clusters=0". * Test "clusters=0".
* config: -smp 1,drawers=1,books=1,sockets=1,dies=1,\ * config: -smp 1,drawers=1,books=1,sockets=1,dies=1,\
* clusters=0,cores=1,threads=1,maxcpus=1 * clusters=0,modules=1,cores=1,threads=1,\
* maxcpus=1
*/ */
.config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 0, 1, 1, 1), .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 0, 1, 1, 1, 1),
.expect_error = "Invalid CPU topology: CPU topology parameters must "
"be greater than zero",
}, {
/*
* Test "modules=0".
* config: -smp 1,drawers=1,books=1,sockets=1,dies=1,\
* clusters=1,modules=0,cores=1,threads=1,\
* maxcpus=1
*/
.config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 1, 0, 1, 1, 1),
.expect_error = "Invalid CPU topology: CPU topology parameters must " .expect_error = "Invalid CPU topology: CPU topology parameters must "
"be greater than zero", "be greater than zero",
}, { }, {
/* /*
* Test "cores=0". * Test "cores=0".
* config: -smp 1,drawers=1,books=1,sockets=1,dies=1,\ * config: -smp 1,drawers=1,books=1,sockets=1,dies=1,\
* clusters=1,cores=0,threads=1,maxcpus=1 * clusters=1,modules=1,cores=0,threads=1,
* maxcpus=1
*/ */
.config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 1, 0, 1, 1), .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 1, 1, 0, 1, 1),
.expect_error = "Invalid CPU topology: CPU topology parameters must " .expect_error = "Invalid CPU topology: CPU topology parameters must "
"be greater than zero", "be greater than zero",
}, { }, {
/* /*
* Test "threads=0". * Test "threads=0".
* config: -smp 1,drawers=1,books=1,sockets=1,dies=1,\ * config: -smp 1,drawers=1,books=1,sockets=1,dies=1,\
* clusters=1,cores=1,threads=0,maxcpus=1 * clusters=1,modules=1,cores=1,threads=0,\
* maxcpus=1
*/ */
.config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 1, 1, 0, 1), .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 1, 1, 1, 0, 1),
.expect_error = "Invalid CPU topology: CPU topology parameters must " .expect_error = "Invalid CPU topology: CPU topology parameters must "
"be greater than zero", "be greater than zero",
}, { }, {
/* /*
* Test "maxcpus=0". * Test "maxcpus=0".
* config: -smp 1,drawers=1,books=1,sockets=1,dies=1,\ * config: -smp 1,drawers=1,books=1,sockets=1,dies=1,\
* clusters=1,cores=1,threads=1,maxcpus=0 * clusters=1,modules=1,cores=1,threads=1,\
* maxcpus=0
*/ */
.config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 1, 1, 1, 0), .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 1, 1, 1, 1, 0),
.expect_error = "Invalid CPU topology: CPU topology parameters must " .expect_error = "Invalid CPU topology: CPU topology parameters must "
"be greater than zero", "be greater than zero",
}, },
@ -627,6 +711,7 @@ static char *smp_config_to_string(const SMPConfiguration *config)
" .has_sockets = %5s, sockets = %" PRId64 ",\n" " .has_sockets = %5s, sockets = %" PRId64 ",\n"
" .has_dies = %5s, dies = %" PRId64 ",\n" " .has_dies = %5s, dies = %" PRId64 ",\n"
" .has_clusters = %5s, clusters = %" PRId64 ",\n" " .has_clusters = %5s, clusters = %" PRId64 ",\n"
" .has_modules = %5s, modules = %" PRId64 ",\n"
" .has_cores = %5s, cores = %" PRId64 ",\n" " .has_cores = %5s, cores = %" PRId64 ",\n"
" .has_threads = %5s, threads = %" PRId64 ",\n" " .has_threads = %5s, threads = %" PRId64 ",\n"
" .has_maxcpus = %5s, maxcpus = %" PRId64 ",\n" " .has_maxcpus = %5s, maxcpus = %" PRId64 ",\n"
@ -637,6 +722,7 @@ static char *smp_config_to_string(const SMPConfiguration *config)
config->has_sockets ? "true" : "false", config->sockets, config->has_sockets ? "true" : "false", config->sockets,
config->has_dies ? "true" : "false", config->dies, config->has_dies ? "true" : "false", config->dies,
config->has_clusters ? "true" : "false", config->clusters, config->has_clusters ? "true" : "false", config->clusters,
config->has_modules ? "true" : "false", config->modules,
config->has_cores ? "true" : "false", config->cores, config->has_cores ? "true" : "false", config->cores,
config->has_threads ? "true" : "false", config->threads, config->has_threads ? "true" : "false", config->threads,
config->has_maxcpus ? "true" : "false", config->maxcpus); config->has_maxcpus ? "true" : "false", config->maxcpus);
@ -677,6 +763,7 @@ static char *cpu_topology_to_string(const CpuTopology *topo,
" .sockets = %u,\n" " .sockets = %u,\n"
" .dies = %u,\n" " .dies = %u,\n"
" .clusters = %u,\n" " .clusters = %u,\n"
" .modules = %u,\n"
" .cores = %u,\n" " .cores = %u,\n"
" .threads = %u,\n" " .threads = %u,\n"
" .max_cpus = %u,\n" " .max_cpus = %u,\n"
@ -686,8 +773,8 @@ static char *cpu_topology_to_string(const CpuTopology *topo,
"}", "}",
topo->cpus, topo->drawers, topo->books, topo->cpus, topo->drawers, topo->books,
topo->sockets, topo->dies, topo->clusters, topo->sockets, topo->dies, topo->clusters,
topo->cores, topo->threads, topo->max_cpus, topo->modules, topo->cores, topo->threads,
threads_per_socket, cores_per_socket, topo->max_cpus, threads_per_socket, cores_per_socket,
has_clusters ? "true" : "false"); has_clusters ? "true" : "false");
} }
@ -730,6 +817,7 @@ static void check_parse(MachineState *ms, const SMPConfiguration *config,
(ms->smp.sockets == expect_topo->sockets) && (ms->smp.sockets == expect_topo->sockets) &&
(ms->smp.dies == expect_topo->dies) && (ms->smp.dies == expect_topo->dies) &&
(ms->smp.clusters == expect_topo->clusters) && (ms->smp.clusters == expect_topo->clusters) &&
(ms->smp.modules == expect_topo->modules) &&
(ms->smp.cores == expect_topo->cores) && (ms->smp.cores == expect_topo->cores) &&
(ms->smp.threads == expect_topo->threads) && (ms->smp.threads == expect_topo->threads) &&
(ms->smp.max_cpus == expect_topo->max_cpus) && (ms->smp.max_cpus == expect_topo->max_cpus) &&
@ -810,6 +898,11 @@ static void smp_parse_test(MachineState *ms, SMPTestData *data, bool is_valid)
/* The parsed results of the unsupported parameters should be 1 */ /* The parsed results of the unsupported parameters should be 1 */
static void unsupported_params_init(const MachineClass *mc, SMPTestData *data) static void unsupported_params_init(const MachineClass *mc, SMPTestData *data)
{ {
if (!mc->smp_props.modules_supported) {
data->expect_prefer_sockets.modules = 1;
data->expect_prefer_cores.modules = 1;
}
if (!mc->smp_props.dies_supported) { if (!mc->smp_props.dies_supported) {
data->expect_prefer_sockets.dies = 1; data->expect_prefer_sockets.dies = 1;
data->expect_prefer_cores.dies = 1; data->expect_prefer_cores.dies = 1;
@ -850,6 +943,13 @@ static void machine_generic_invalid_class_init(ObjectClass *oc, void *data)
mc->max_cpus = MAX_CPUS - 1; mc->max_cpus = MAX_CPUS - 1;
} }
static void machine_with_modules_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
mc->smp_props.modules_supported = true;
}
static void machine_with_dies_class_init(ObjectClass *oc, void *data) static void machine_with_dies_class_init(ObjectClass *oc, void *data)
{ {
MachineClass *mc = MACHINE_CLASS(oc); MachineClass *mc = MACHINE_CLASS(oc);
@ -857,6 +957,14 @@ static void machine_with_dies_class_init(ObjectClass *oc, void *data)
mc->smp_props.dies_supported = true; mc->smp_props.dies_supported = true;
} }
static void machine_with_modules_dies_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
mc->smp_props.modules_supported = true;
mc->smp_props.dies_supported = true;
}
static void machine_with_clusters_class_init(ObjectClass *oc, void *data) static void machine_with_clusters_class_init(ObjectClass *oc, void *data)
{ {
MachineClass *mc = MACHINE_CLASS(oc); MachineClass *mc = MACHINE_CLASS(oc);
@ -894,6 +1002,7 @@ static void machine_full_topo_class_init(ObjectClass *oc, void *data)
mc->smp_props.books_supported = true; mc->smp_props.books_supported = true;
mc->smp_props.dies_supported = true; mc->smp_props.dies_supported = true;
mc->smp_props.clusters_supported = true; mc->smp_props.clusters_supported = true;
mc->smp_props.modules_supported = true;
} }
static void test_generic_valid(const void *opaque) static void test_generic_valid(const void *opaque)
@ -934,6 +1043,56 @@ static void test_generic_invalid(const void *opaque)
object_unref(obj); object_unref(obj);
} }
static void test_with_modules(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_modules = 2;
int i;
for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
data = data_generic_valid[i];
unsupported_params_init(mc, &data);
/* when modules parameter is omitted, it will be set as 1 */
data.expect_prefer_sockets.modules = 1;
data.expect_prefer_cores.modules = 1;
smp_parse_test(ms, &data, true);
/* when modules parameter is specified */
data.config.has_modules = true;
data.config.modules = num_modules;
if (data.config.has_cpus) {
data.config.cpus *= num_modules;
}
if (data.config.has_maxcpus) {
data.config.maxcpus *= num_modules;
}
data.expect_prefer_sockets.modules = num_modules;
data.expect_prefer_sockets.cpus *= num_modules;
data.expect_prefer_sockets.max_cpus *= num_modules;
data.expect_prefer_cores.modules = num_modules;
data.expect_prefer_cores.cpus *= num_modules;
data.expect_prefer_cores.max_cpus *= num_modules;
smp_parse_test(ms, &data, true);
}
for (i = 0; i < ARRAY_SIZE(data_with_modules_invalid); i++) {
data = data_with_modules_invalid[i];
unsupported_params_init(mc, &data);
smp_parse_test(ms, &data, false);
}
object_unref(obj);
}
static void test_with_dies(const void *opaque) static void test_with_dies(const void *opaque)
{ {
const char *machine_type = opaque; const char *machine_type = opaque;
@ -984,6 +1143,67 @@ static void test_with_dies(const void *opaque)
object_unref(obj); object_unref(obj);
} }
static void test_with_modules_dies(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_modules = 5, num_dies = 3;
int i;
for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
data = data_generic_valid[i];
unsupported_params_init(mc, &data);
/*
* when modules and dies parameters are omitted, they will
* be both set as 1.
*/
data.expect_prefer_sockets.modules = 1;
data.expect_prefer_sockets.dies = 1;
data.expect_prefer_cores.modules = 1;
data.expect_prefer_cores.dies = 1;
smp_parse_test(ms, &data, true);
/* when modules and dies parameters are both specified */
data.config.has_modules = true;
data.config.modules = num_modules;
data.config.has_dies = true;
data.config.dies = num_dies;
if (data.config.has_cpus) {
data.config.cpus *= num_modules * num_dies;
}
if (data.config.has_maxcpus) {
data.config.maxcpus *= num_modules * num_dies;
}
data.expect_prefer_sockets.modules = num_modules;
data.expect_prefer_sockets.dies = num_dies;
data.expect_prefer_sockets.cpus *= num_modules * num_dies;
data.expect_prefer_sockets.max_cpus *= num_modules * num_dies;
data.expect_prefer_cores.modules = num_modules;
data.expect_prefer_cores.dies = num_dies;
data.expect_prefer_cores.cpus *= num_modules * num_dies;
data.expect_prefer_cores.max_cpus *= num_modules * num_dies;
smp_parse_test(ms, &data, true);
}
for (i = 0; i < ARRAY_SIZE(data_with_modules_dies_invalid); i++) {
data = data_with_modules_dies_invalid[i];
unsupported_params_init(mc, &data);
smp_parse_test(ms, &data, false);
}
object_unref(obj);
}
static void test_with_clusters(const void *opaque) static void test_with_clusters(const void *opaque)
{ {
const char *machine_type = opaque; const char *machine_type = opaque;
@ -1202,30 +1422,41 @@ static void test_full_topo(const void *opaque)
MachineState *ms = MACHINE(obj); MachineState *ms = MACHINE(obj);
MachineClass *mc = MACHINE_GET_CLASS(obj); MachineClass *mc = MACHINE_GET_CLASS(obj);
SMPTestData data = {}; SMPTestData data = {};
unsigned int drawers = 5, books = 3, dies = 2, clusters = 7, multiplier; unsigned int drawers, books, dies, clusters, modules, multiplier;
int i; int i;
multiplier = drawers * books * dies * clusters; drawers = 5;
books = 3;
dies = 2;
clusters = 3;
modules = 2;
multiplier = drawers * books * dies * clusters * modules;
for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) { for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
data = data_generic_valid[i]; data = data_generic_valid[i];
unsupported_params_init(mc, &data); unsupported_params_init(mc, &data);
/* /*
* when drawers, books, dies and clusters parameters are omitted, * when drawers, books, dies, clusters and modules parameters are
* they will be set as 1. * omitted, they will be set as 1.
*/ */
data.expect_prefer_sockets.drawers = 1; data.expect_prefer_sockets.drawers = 1;
data.expect_prefer_sockets.books = 1; data.expect_prefer_sockets.books = 1;
data.expect_prefer_sockets.dies = 1; data.expect_prefer_sockets.dies = 1;
data.expect_prefer_sockets.clusters = 1; data.expect_prefer_sockets.clusters = 1;
data.expect_prefer_sockets.modules = 1;
data.expect_prefer_cores.drawers = 1; data.expect_prefer_cores.drawers = 1;
data.expect_prefer_cores.books = 1; data.expect_prefer_cores.books = 1;
data.expect_prefer_cores.dies = 1; data.expect_prefer_cores.dies = 1;
data.expect_prefer_cores.clusters = 1; data.expect_prefer_cores.clusters = 1;
data.expect_prefer_cores.modules = 1;
smp_parse_test(ms, &data, true); smp_parse_test(ms, &data, true);
/* when drawers, books, dies and clusters parameters are specified. */ /*
* when drawers, books, dies, clusters and modules parameters
* are specified.
*/
data.config.has_drawers = true; data.config.has_drawers = true;
data.config.drawers = drawers; data.config.drawers = drawers;
data.config.has_books = true; data.config.has_books = true;
@ -1234,6 +1465,8 @@ static void test_full_topo(const void *opaque)
data.config.dies = dies; data.config.dies = dies;
data.config.has_clusters = true; data.config.has_clusters = true;
data.config.clusters = clusters; data.config.clusters = clusters;
data.config.has_modules = true;
data.config.modules = modules;
if (data.config.has_cpus) { if (data.config.has_cpus) {
data.config.cpus *= multiplier; data.config.cpus *= multiplier;
@ -1246,6 +1479,7 @@ static void test_full_topo(const void *opaque)
data.expect_prefer_sockets.books = books; data.expect_prefer_sockets.books = books;
data.expect_prefer_sockets.dies = dies; data.expect_prefer_sockets.dies = dies;
data.expect_prefer_sockets.clusters = clusters; data.expect_prefer_sockets.clusters = clusters;
data.expect_prefer_sockets.modules = modules;
data.expect_prefer_sockets.cpus *= multiplier; data.expect_prefer_sockets.cpus *= multiplier;
data.expect_prefer_sockets.max_cpus *= multiplier; data.expect_prefer_sockets.max_cpus *= multiplier;
@ -1253,6 +1487,7 @@ static void test_full_topo(const void *opaque)
data.expect_prefer_cores.books = books; data.expect_prefer_cores.books = books;
data.expect_prefer_cores.dies = dies; data.expect_prefer_cores.dies = dies;
data.expect_prefer_cores.clusters = clusters; data.expect_prefer_cores.clusters = clusters;
data.expect_prefer_cores.modules = modules;
data.expect_prefer_cores.cpus *= multiplier; data.expect_prefer_cores.cpus *= multiplier;
data.expect_prefer_cores.max_cpus *= multiplier; data.expect_prefer_cores.max_cpus *= multiplier;
@ -1292,10 +1527,18 @@ static const TypeInfo smp_machine_types[] = {
.name = MACHINE_TYPE_NAME("smp-generic-invalid"), .name = MACHINE_TYPE_NAME("smp-generic-invalid"),
.parent = TYPE_MACHINE, .parent = TYPE_MACHINE,
.class_init = machine_generic_invalid_class_init, .class_init = machine_generic_invalid_class_init,
}, {
.name = MACHINE_TYPE_NAME("smp-with-modules"),
.parent = TYPE_MACHINE,
.class_init = machine_with_modules_class_init,
}, { }, {
.name = MACHINE_TYPE_NAME("smp-with-dies"), .name = MACHINE_TYPE_NAME("smp-with-dies"),
.parent = TYPE_MACHINE, .parent = TYPE_MACHINE,
.class_init = machine_with_dies_class_init, .class_init = machine_with_dies_class_init,
}, {
.name = MACHINE_TYPE_NAME("smp-with-modules-dies"),
.parent = TYPE_MACHINE,
.class_init = machine_with_modules_dies_class_init,
}, { }, {
.name = MACHINE_TYPE_NAME("smp-with-clusters"), .name = MACHINE_TYPE_NAME("smp-with-clusters"),
.parent = TYPE_MACHINE, .parent = TYPE_MACHINE,
@ -1333,9 +1576,15 @@ int main(int argc, char *argv[])
g_test_add_data_func("/test-smp-parse/generic/invalid", g_test_add_data_func("/test-smp-parse/generic/invalid",
MACHINE_TYPE_NAME("smp-generic-invalid"), MACHINE_TYPE_NAME("smp-generic-invalid"),
test_generic_invalid); test_generic_invalid);
g_test_add_data_func("/test-smp-parse/with_modules",
MACHINE_TYPE_NAME("smp-with-modules"),
test_with_modules);
g_test_add_data_func("/test-smp-parse/with_dies", g_test_add_data_func("/test-smp-parse/with_dies",
MACHINE_TYPE_NAME("smp-with-dies"), MACHINE_TYPE_NAME("smp-with-dies"),
test_with_dies); test_with_dies);
g_test_add_data_func("/test-smp-parse/with_modules_dies",
MACHINE_TYPE_NAME("smp-with-modules-dies"),
test_with_modules_dies);
g_test_add_data_func("/test-smp-parse/with_clusters", g_test_add_data_func("/test-smp-parse/with_clusters",
MACHINE_TYPE_NAME("smp-with-clusters"), MACHINE_TYPE_NAME("smp-with-clusters"),
test_with_clusters); test_with_clusters);