These machines can't be used reliably for migration anymore, quoting https://lists.gnu.org/archive/html/qemu-devel/2018-12/msg04516.html : " due to the introduction of the memory API, the firmware is not migrated correctly from source to destination. On QEMU <1.3 the 0xf0000-0xfffff area is basically a copy of the higher 0xffff0000-0xffffffff area, while on more recent versions it is initialized with zeroes and the firmware copies from 0xffff0000 to 0xf0000. When you migrate from old to new QEMU, after reboot there's nothing at 0xf0000 and bugs ensue. " The pc-0.x machines have been marked as deprecated since QEMU v4.0, so it is time to remove them now. And while we're at it, mark the remaining pc-1.x machine types as deprecated now, too, so that we finally only have "pc-i440fx" and "pc-q35" machine types left (apart from the non-versioned "isapc" and "microvm") once we remove them in a couple of releases. Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Signed-off-by: Thomas Huth <thuth@redhat.com> Message-Id: <20191209125248.5849-2-thuth@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
258 lines
7.9 KiB
C
258 lines
7.9 KiB
C
/*
|
|
* QTest testcase for CPU plugging
|
|
*
|
|
* Copyright (c) 2015 SUSE Linux GmbH
|
|
*
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
|
* See the COPYING file in the top-level directory.
|
|
*/
|
|
|
|
#include "qemu/osdep.h"
|
|
|
|
#include "qemu-common.h"
|
|
#include "libqtest-single.h"
|
|
#include "qapi/qmp/qdict.h"
|
|
#include "qapi/qmp/qlist.h"
|
|
|
|
struct PlugTestData {
|
|
char *machine;
|
|
const char *cpu_model;
|
|
char *device_model;
|
|
unsigned sockets;
|
|
unsigned cores;
|
|
unsigned threads;
|
|
unsigned maxcpus;
|
|
};
|
|
typedef struct PlugTestData PlugTestData;
|
|
|
|
static void test_plug_with_cpu_add(gconstpointer data)
|
|
{
|
|
const PlugTestData *s = data;
|
|
char *args;
|
|
QDict *response;
|
|
unsigned int i;
|
|
|
|
args = g_strdup_printf("-machine %s -cpu %s "
|
|
"-smp 1,sockets=%u,cores=%u,threads=%u,maxcpus=%u",
|
|
s->machine, s->cpu_model,
|
|
s->sockets, s->cores, s->threads, s->maxcpus);
|
|
qtest_start(args);
|
|
|
|
for (i = 1; i < s->maxcpus; i++) {
|
|
response = qmp("{ 'execute': 'cpu-add',"
|
|
" 'arguments': { 'id': %d } }", i);
|
|
g_assert(response);
|
|
g_assert(!qdict_haskey(response, "error"));
|
|
qobject_unref(response);
|
|
}
|
|
|
|
qtest_end();
|
|
g_free(args);
|
|
}
|
|
|
|
static void test_plug_without_cpu_add(gconstpointer data)
|
|
{
|
|
const PlugTestData *s = data;
|
|
char *args;
|
|
QDict *response;
|
|
|
|
args = g_strdup_printf("-machine %s -cpu %s "
|
|
"-smp 1,sockets=%u,cores=%u,threads=%u,maxcpus=%u",
|
|
s->machine, s->cpu_model,
|
|
s->sockets, s->cores, s->threads, s->maxcpus);
|
|
qtest_start(args);
|
|
|
|
response = qmp("{ 'execute': 'cpu-add',"
|
|
" 'arguments': { 'id': %d } }",
|
|
s->sockets * s->cores * s->threads);
|
|
g_assert(response);
|
|
g_assert(qdict_haskey(response, "error"));
|
|
qobject_unref(response);
|
|
|
|
qtest_end();
|
|
g_free(args);
|
|
}
|
|
|
|
static void test_plug_with_device_add(gconstpointer data)
|
|
{
|
|
const PlugTestData *td = data;
|
|
char *args;
|
|
QTestState *qts;
|
|
QDict *resp;
|
|
QList *cpus;
|
|
QObject *e;
|
|
int hotplugged = 0;
|
|
|
|
args = g_strdup_printf("-machine %s -cpu %s "
|
|
"-smp 1,sockets=%u,cores=%u,threads=%u,maxcpus=%u",
|
|
td->machine, td->cpu_model,
|
|
td->sockets, td->cores, td->threads, td->maxcpus);
|
|
qts = qtest_init(args);
|
|
|
|
resp = qtest_qmp(qts, "{ 'execute': 'query-hotpluggable-cpus'}");
|
|
g_assert(qdict_haskey(resp, "return"));
|
|
cpus = qdict_get_qlist(resp, "return");
|
|
g_assert(cpus);
|
|
|
|
while ((e = qlist_pop(cpus))) {
|
|
const QDict *cpu, *props;
|
|
|
|
cpu = qobject_to(QDict, e);
|
|
if (qdict_haskey(cpu, "qom-path")) {
|
|
qobject_unref(e);
|
|
continue;
|
|
}
|
|
|
|
g_assert(qdict_haskey(cpu, "props"));
|
|
props = qdict_get_qdict(cpu, "props");
|
|
|
|
qtest_qmp_device_add_qdict(qts, td->device_model, props);
|
|
hotplugged++;
|
|
qobject_unref(e);
|
|
}
|
|
|
|
/* make sure that there were hotplugged CPUs */
|
|
g_assert(hotplugged);
|
|
qobject_unref(resp);
|
|
qtest_quit(qts);
|
|
g_free(args);
|
|
}
|
|
|
|
static void test_data_free(gpointer data)
|
|
{
|
|
PlugTestData *pc = data;
|
|
|
|
g_free(pc->machine);
|
|
g_free(pc->device_model);
|
|
g_free(pc);
|
|
}
|
|
|
|
static void add_pc_test_case(const char *mname)
|
|
{
|
|
char *path;
|
|
PlugTestData *data;
|
|
|
|
if (!g_str_has_prefix(mname, "pc-")) {
|
|
return;
|
|
}
|
|
data = g_new(PlugTestData, 1);
|
|
data->machine = g_strdup(mname);
|
|
data->cpu_model = "Haswell"; /* 1.3+ theoretically */
|
|
data->device_model = g_strdup_printf("%s-%s-cpu", data->cpu_model,
|
|
qtest_get_arch());
|
|
data->sockets = 1;
|
|
data->cores = 3;
|
|
data->threads = 2;
|
|
data->maxcpus = data->sockets * data->cores * data->threads;
|
|
if (g_str_has_suffix(mname, "-1.4") ||
|
|
(strcmp(mname, "pc-1.3") == 0) ||
|
|
(strcmp(mname, "pc-1.2") == 0) ||
|
|
(strcmp(mname, "pc-1.1") == 0) ||
|
|
(strcmp(mname, "pc-1.0") == 0)) {
|
|
path = g_strdup_printf("cpu-plug/%s/init/%ux%ux%u&maxcpus=%u",
|
|
mname, data->sockets, data->cores,
|
|
data->threads, data->maxcpus);
|
|
qtest_add_data_func_full(path, data, test_plug_without_cpu_add,
|
|
test_data_free);
|
|
g_free(path);
|
|
} else {
|
|
PlugTestData *data2 = g_memdup(data, sizeof(PlugTestData));
|
|
|
|
data2->machine = g_strdup(data->machine);
|
|
data2->device_model = g_strdup(data->device_model);
|
|
|
|
path = g_strdup_printf("cpu-plug/%s/cpu-add/%ux%ux%u&maxcpus=%u",
|
|
mname, data->sockets, data->cores,
|
|
data->threads, data->maxcpus);
|
|
qtest_add_data_func_full(path, data, test_plug_with_cpu_add,
|
|
test_data_free);
|
|
g_free(path);
|
|
path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u",
|
|
mname, data2->sockets, data2->cores,
|
|
data2->threads, data2->maxcpus);
|
|
qtest_add_data_func_full(path, data2, test_plug_with_device_add,
|
|
test_data_free);
|
|
g_free(path);
|
|
}
|
|
}
|
|
|
|
static void add_pseries_test_case(const char *mname)
|
|
{
|
|
char *path;
|
|
PlugTestData *data;
|
|
|
|
if (!g_str_has_prefix(mname, "pseries-") ||
|
|
(g_str_has_prefix(mname, "pseries-2.") && atoi(&mname[10]) < 7)) {
|
|
return;
|
|
}
|
|
data = g_new(PlugTestData, 1);
|
|
data->machine = g_strdup(mname);
|
|
data->cpu_model = "power8_v2.0";
|
|
data->device_model = g_strdup("power8_v2.0-spapr-cpu-core");
|
|
data->sockets = 2;
|
|
data->cores = 3;
|
|
data->threads = 1;
|
|
data->maxcpus = data->sockets * data->cores * data->threads;
|
|
|
|
path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u",
|
|
mname, data->sockets, data->cores,
|
|
data->threads, data->maxcpus);
|
|
qtest_add_data_func_full(path, data, test_plug_with_device_add,
|
|
test_data_free);
|
|
g_free(path);
|
|
}
|
|
|
|
static void add_s390x_test_case(const char *mname)
|
|
{
|
|
char *path;
|
|
PlugTestData *data, *data2;
|
|
|
|
if (!g_str_has_prefix(mname, "s390-ccw-virtio-")) {
|
|
return;
|
|
}
|
|
|
|
data = g_new(PlugTestData, 1);
|
|
data->machine = g_strdup(mname);
|
|
data->cpu_model = "qemu";
|
|
data->device_model = g_strdup("qemu-s390x-cpu");
|
|
data->sockets = 1;
|
|
data->cores = 3;
|
|
data->threads = 1;
|
|
data->maxcpus = data->sockets * data->cores * data->threads;
|
|
|
|
data2 = g_memdup(data, sizeof(PlugTestData));
|
|
data2->machine = g_strdup(data->machine);
|
|
data2->device_model = g_strdup(data->device_model);
|
|
|
|
path = g_strdup_printf("cpu-plug/%s/cpu-add/%ux%ux%u&maxcpus=%u",
|
|
mname, data->sockets, data->cores,
|
|
data->threads, data->maxcpus);
|
|
qtest_add_data_func_full(path, data, test_plug_with_cpu_add,
|
|
test_data_free);
|
|
g_free(path);
|
|
|
|
path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u",
|
|
mname, data2->sockets, data2->cores,
|
|
data2->threads, data2->maxcpus);
|
|
qtest_add_data_func_full(path, data2, test_plug_with_device_add,
|
|
test_data_free);
|
|
g_free(path);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
const char *arch = qtest_get_arch();
|
|
|
|
g_test_init(&argc, &argv, NULL);
|
|
|
|
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
|
|
qtest_cb_for_every_machine(add_pc_test_case, g_test_quick());
|
|
} else if (g_str_equal(arch, "ppc64")) {
|
|
qtest_cb_for_every_machine(add_pseries_test_case, g_test_quick());
|
|
} else if (g_str_equal(arch, "s390x")) {
|
|
qtest_cb_for_every_machine(add_s390x_test_case, g_test_quick());
|
|
}
|
|
|
|
return g_test_run();
|
|
}
|