Machine and x86 queue, 2019-07-05
* CPU die topology support (Like Xu) * Deprecation of features (Igor Mammedov): * 'mem' parameter of '-numa node' option * implict memory distribution between NUMA nodes * deprecate -mem-path fallback to anonymous RAM * x86 versioned CPU models (Eduardo Habkost) * SnowRidge CPU model (Paul Lai) * Add deprecation information to query-machines (Eduardo Habkost) * Other i386 fixes -----BEGIN PGP SIGNATURE----- iQJIBAABCAAyFiEEWjIv1avE09usz9GqKAeTb5hNxaYFAl0fyzkUHGVoYWJrb3N0 QHJlZGhhdC5jb20ACgkQKAeTb5hNxaZoghAAtj2RFifkZ3gueqEbbfEaqkuie+yH rZ+vC9OZE5Ok7l+J0PtS+IzJNfXP+UIbLDyIJfpVMOOKDSxAobmELOLHlxp/n/jl e+nbgAEydrflLTC/yr6oRmS0H3o45YvjXehIiYhLAiJ86pxs4xuzQcC70ngLGb+y qiq1WDG0i/roZj0ng/+OUIy6qB3/Rrq/HBlCIeL9AKaXax7TEcgPuyjwmwXOVOMs Et2yaSRdfEj7RvrvpZDvT7SDTyrvdII4vSPqEos3/Sb41iF6JIDt7ISYcK1+gNzU xtVg1xxPqzKSEmfLQmYgjhDpCgN+I3DMwk8CSVB7GD5tn1PhCXkZD8iOGfkjq8QM fjRvoFNZw/xDIHBl2ubovq/Uzsmb5yJ96r8WEykjU8P2nnSdPaN2FNq3ELBVibPz Kut1ulEAFeTVhhvfrMOD80eDFyv5llksskSFfhHw4lAVurN6CV79rg6O+yRtS2tC jB9RCb+KUilOkgvMqFrom+vHppO6IHbGGXzTz3hMAgDAngPms1qEQ2XLuw/Zi9V7 dNByeilE88WIoJrAYswJFdGddZWzayHntiOuO2nvaXBLURZ7UREQRRMyz1bFo59G zXPv6exgSqc/mlse2dCXK7iVRL/B68euDq91xjfN/wlxGZEuZ6iaaeiuKbF62b5Q M/wfvuogD5DWgsw= =NAyM -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/ehabkost/tags/machine-next-pull-request' into staging Machine and x86 queue, 2019-07-05 * CPU die topology support (Like Xu) * Deprecation of features (Igor Mammedov): * 'mem' parameter of '-numa node' option * implict memory distribution between NUMA nodes * deprecate -mem-path fallback to anonymous RAM * x86 versioned CPU models (Eduardo Habkost) * SnowRidge CPU model (Paul Lai) * Add deprecation information to query-machines (Eduardo Habkost) * Other i386 fixes # gpg: Signature made Fri 05 Jul 2019 23:12:09 BST # gpg: using RSA key 5A322FD5ABC4D3DBACCFD1AA2807936F984DC5A6 # gpg: issuer "ehabkost@redhat.com" # gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>" [full] # Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF D1AA 2807 936F 984D C5A6 * remotes/ehabkost/tags/machine-next-pull-request: (42 commits) tests: use -numa memdev option in tests instead of legacy 'mem' option numa: allow memory-less nodes when using memdev as backend numa: Make deprecation warnings conditional on !qtest_enabled() i386: Add Cascadelake-Server-v2 CPU model docs: Deprecate CPU model runnability guarantees i386: Make unversioned CPU models be aliases i386: Replace -noTSX, -IBRS, -IBPB CPU models with aliases i386: Define -IBRS, -noTSX, -IBRS versions of CPU models i386: Register versioned CPU models i386: Get model-id from CPU object on "-cpu help" i386: Add x-force-features option for testing qmp: Add "alias-of" field to query-cpu-definitions i386: Introduce SnowRidge CPU model qmp: Add deprecation information to query-machines vl.c: Add -smp, dies=* command line support and update doc machine: Refactor smp_parse() in vl.c as MachineClass::smp_parse() target/i386: Add CPUID.1F generation support for multi-dies PCMachine i386: Remove unused host_cpudef variable x86/cpu: use FeatureWordArray to define filtered_features i386: make 'hv-spinlocks' a regular uint32 property ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
3a1acf5d47
@ -1542,8 +1542,8 @@ static int kvm_init(MachineState *ms)
|
||||
const char *name;
|
||||
int num;
|
||||
} num_cpus[] = {
|
||||
{ "SMP", smp_cpus },
|
||||
{ "hotpluggable", max_cpus },
|
||||
{ "SMP", ms->smp.cpus },
|
||||
{ "hotpluggable", ms->smp.max_cpus },
|
||||
{ NULL, }
|
||||
}, *nc = num_cpus;
|
||||
int soft_vcpus_limit, hard_vcpus_limit;
|
||||
|
@ -222,6 +222,7 @@ static void host_memory_backend_set_prealloc(Object *obj, bool value,
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
|
||||
if (backend->force_prealloc) {
|
||||
if (value) {
|
||||
@ -241,7 +242,7 @@ static void host_memory_backend_set_prealloc(Object *obj, bool value,
|
||||
void *ptr = memory_region_get_ram_ptr(&backend->mr);
|
||||
uint64_t sz = memory_region_size(&backend->mr);
|
||||
|
||||
os_mem_prealloc(fd, ptr, sz, smp_cpus, &local_err);
|
||||
os_mem_prealloc(fd, ptr, sz, ms->smp.cpus, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
@ -311,6 +312,7 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
|
||||
{
|
||||
HostMemoryBackend *backend = MEMORY_BACKEND(uc);
|
||||
HostMemoryBackendClass *bc = MEMORY_BACKEND_GET_CLASS(uc);
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
Error *local_err = NULL;
|
||||
void *ptr;
|
||||
uint64_t sz;
|
||||
@ -375,7 +377,7 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
|
||||
*/
|
||||
if (backend->prealloc) {
|
||||
os_mem_prealloc(memory_region_get_fd(&backend->mr), ptr, sz,
|
||||
smp_cpus, &local_err);
|
||||
ms->smp.cpus, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
|
7
cpus.c
7
cpus.c
@ -54,6 +54,7 @@
|
||||
#include "tcg.h"
|
||||
#include "hw/nmi.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "hw/boards.h"
|
||||
|
||||
#ifdef CONFIG_LINUX
|
||||
|
||||
@ -2075,8 +2076,10 @@ static void qemu_dummy_start_vcpu(CPUState *cpu)
|
||||
|
||||
void qemu_init_vcpu(CPUState *cpu)
|
||||
{
|
||||
cpu->nr_cores = smp_cores;
|
||||
cpu->nr_threads = smp_threads;
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
|
||||
cpu->nr_cores = ms->smp.cores;
|
||||
cpu->nr_threads = ms->smp.threads;
|
||||
cpu->stopped = true;
|
||||
cpu->random_seed = qemu_guest_random_seed_thread_part1();
|
||||
|
||||
|
3
exec.c
3
exec.c
@ -1874,6 +1874,7 @@ static void *file_ram_alloc(RAMBlock *block,
|
||||
bool truncate,
|
||||
Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
void *area;
|
||||
|
||||
block->page_size = qemu_fd_getpagesize(fd);
|
||||
@ -1930,7 +1931,7 @@ static void *file_ram_alloc(RAMBlock *block,
|
||||
}
|
||||
|
||||
if (mem_prealloc) {
|
||||
os_mem_prealloc(fd, area, memory, smp_cpus, errp);
|
||||
os_mem_prealloc(fd, area, memory, ms->smp.cpus, errp);
|
||||
if (errp && *errp) {
|
||||
qemu_ram_munmap(fd, area, memory);
|
||||
return NULL;
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "exec/gdbstub.h"
|
||||
#include "hw/cpu/cluster.h"
|
||||
#include "hw/boards.h"
|
||||
#endif
|
||||
|
||||
#define MAX_PACKET_LENGTH 4096
|
||||
@ -1171,6 +1172,9 @@ static int gdb_handle_vcont(GDBState *s, const char *p)
|
||||
CPU_FOREACH(cpu) {
|
||||
max_cpus = max_cpus <= cpu->cpu_index ? cpu->cpu_index + 1 : max_cpus;
|
||||
}
|
||||
#else
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
unsigned int max_cpus = ms->smp.max_cpus;
|
||||
#endif
|
||||
/* uninitialised CPUs stay 0 */
|
||||
newstates = g_new0(char, max_cpus);
|
||||
|
@ -63,6 +63,7 @@ static void clipper_init(MachineState *machine)
|
||||
char *palcode_filename;
|
||||
uint64_t palcode_entry, palcode_low, palcode_high;
|
||||
uint64_t kernel_entry, kernel_low, kernel_high;
|
||||
unsigned int smp_cpus = machine->smp.cpus;
|
||||
|
||||
/* Create up to 4 cpus. */
|
||||
memset(cpus, 0, sizeof(cpus));
|
||||
|
@ -187,7 +187,7 @@ static void aspeed_board_init(MachineState *machine,
|
||||
&error_abort);
|
||||
object_property_set_int(OBJECT(&bmc->soc), cfg->num_cs, "num-cs",
|
||||
&error_abort);
|
||||
object_property_set_int(OBJECT(&bmc->soc), smp_cpus, "num-cpus",
|
||||
object_property_set_int(OBJECT(&bmc->soc), machine->smp.cpus, "num-cpus",
|
||||
&error_abort);
|
||||
if (machine->kernel_filename) {
|
||||
/*
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/arm/fsl-imx6.h"
|
||||
#include "hw/boards.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "chardev/char.h"
|
||||
#include "qemu/error-report.h"
|
||||
@ -33,11 +34,12 @@
|
||||
|
||||
static void fsl_imx6_init(Object *obj)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
FslIMX6State *s = FSL_IMX6(obj);
|
||||
char name[NAME_SIZE];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MIN(smp_cpus, FSL_IMX6_NUM_CPUS); i++) {
|
||||
for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX6_NUM_CPUS); i++) {
|
||||
snprintf(name, NAME_SIZE, "cpu%d", i);
|
||||
object_initialize_child(obj, name, &s->cpu[i], sizeof(s->cpu[i]),
|
||||
"cortex-a9-" TYPE_ARM_CPU, &error_abort, NULL);
|
||||
@ -93,9 +95,11 @@ static void fsl_imx6_init(Object *obj)
|
||||
|
||||
static void fsl_imx6_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
FslIMX6State *s = FSL_IMX6(dev);
|
||||
uint16_t i;
|
||||
Error *err = NULL;
|
||||
unsigned int smp_cpus = ms->smp.cpus;
|
||||
|
||||
if (smp_cpus > FSL_IMX6_NUM_CPUS) {
|
||||
error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "qapi/error.h"
|
||||
#include "hw/arm/fsl-imx6ul.h"
|
||||
#include "hw/misc/unimp.h"
|
||||
#include "hw/boards.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/module.h"
|
||||
@ -28,11 +29,12 @@
|
||||
|
||||
static void fsl_imx6ul_init(Object *obj)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
FslIMX6ULState *s = FSL_IMX6UL(obj);
|
||||
char name[NAME_SIZE];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MIN(smp_cpus, FSL_IMX6UL_NUM_CPUS); i++) {
|
||||
for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX6UL_NUM_CPUS); i++) {
|
||||
snprintf(name, NAME_SIZE, "cpu%d", i);
|
||||
object_initialize_child(obj, name, &s->cpu[i], sizeof(s->cpu[i]),
|
||||
"cortex-a7-" TYPE_ARM_CPU, &error_abort, NULL);
|
||||
@ -156,10 +158,12 @@ static void fsl_imx6ul_init(Object *obj)
|
||||
|
||||
static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
FslIMX6ULState *s = FSL_IMX6UL(dev);
|
||||
int i;
|
||||
qemu_irq irq;
|
||||
char name[NAME_SIZE];
|
||||
unsigned int smp_cpus = ms->smp.cpus;
|
||||
|
||||
if (smp_cpus > FSL_IMX6UL_NUM_CPUS) {
|
||||
error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "qapi/error.h"
|
||||
#include "hw/arm/fsl-imx7.h"
|
||||
#include "hw/misc/unimp.h"
|
||||
#include "hw/boards.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/module.h"
|
||||
@ -30,12 +31,12 @@
|
||||
|
||||
static void fsl_imx7_init(Object *obj)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
FslIMX7State *s = FSL_IMX7(obj);
|
||||
char name[NAME_SIZE];
|
||||
int i;
|
||||
|
||||
|
||||
for (i = 0; i < MIN(smp_cpus, FSL_IMX7_NUM_CPUS); i++) {
|
||||
for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX7_NUM_CPUS); i++) {
|
||||
snprintf(name, NAME_SIZE, "cpu%d", i);
|
||||
object_initialize_child(obj, name, &s->cpu[i], sizeof(s->cpu[i]),
|
||||
ARM_CPU_TYPE_NAME("cortex-a7"), &error_abort,
|
||||
@ -155,11 +156,13 @@ static void fsl_imx7_init(Object *obj)
|
||||
|
||||
static void fsl_imx7_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
FslIMX7State *s = FSL_IMX7(dev);
|
||||
Object *o;
|
||||
int i;
|
||||
qemu_irq irq;
|
||||
char name[NAME_SIZE];
|
||||
unsigned int smp_cpus = ms->smp.cpus;
|
||||
|
||||
if (smp_cpus > FSL_IMX7_NUM_CPUS) {
|
||||
error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
|
||||
|
@ -241,6 +241,7 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
|
||||
SysBusDevice *busdev;
|
||||
qemu_irq pic[128];
|
||||
int n;
|
||||
unsigned int smp_cpus = machine->smp.cpus;
|
||||
qemu_irq cpu_irq[4];
|
||||
qemu_irq cpu_fiq[4];
|
||||
qemu_irq cpu_virq[4];
|
||||
|
@ -42,7 +42,7 @@ static void mcimx6ul_evk_init(MachineState *machine)
|
||||
.kernel_filename = machine->kernel_filename,
|
||||
.kernel_cmdline = machine->kernel_cmdline,
|
||||
.initrd_filename = machine->initrd_filename,
|
||||
.nb_cpus = smp_cpus,
|
||||
.nb_cpus = machine->smp.cpus,
|
||||
};
|
||||
|
||||
object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc),
|
||||
|
@ -45,7 +45,7 @@ static void mcimx7d_sabre_init(MachineState *machine)
|
||||
.kernel_filename = machine->kernel_filename,
|
||||
.kernel_cmdline = machine->kernel_cmdline,
|
||||
.initrd_filename = machine->initrd_filename,
|
||||
.nb_cpus = smp_cpus,
|
||||
.nb_cpus = machine->smp.cpus,
|
||||
};
|
||||
|
||||
object_initialize(&s->soc, sizeof(s->soc), TYPE_FSL_IMX7);
|
||||
|
@ -116,7 +116,7 @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
|
||||
|
||||
binfo.board_id = raspi_boardid[version];
|
||||
binfo.ram_size = ram_size;
|
||||
binfo.nb_cpus = smp_cpus;
|
||||
binfo.nb_cpus = machine->smp.cpus;
|
||||
|
||||
if (version <= 2) {
|
||||
/* The rpi1 and 2 require some custom setup code to run in Secure
|
||||
@ -194,7 +194,7 @@ static void raspi_init(MachineState *machine, int version)
|
||||
/* Setup the SOC */
|
||||
object_property_add_const_link(OBJECT(&s->soc), "ram", OBJECT(&s->ram),
|
||||
&error_abort);
|
||||
object_property_set_int(OBJECT(&s->soc), smp_cpus, "enabled-cpus",
|
||||
object_property_set_int(OBJECT(&s->soc), machine->smp.cpus, "enabled-cpus",
|
||||
&error_abort);
|
||||
int board_rev = version == 3 ? 0xa02082 : 0xa21041;
|
||||
object_property_set_int(OBJECT(&s->soc), board_rev, "board-rev",
|
||||
|
@ -69,6 +69,7 @@ static void realview_init(MachineState *machine,
|
||||
NICInfo *nd;
|
||||
I2CBus *i2c;
|
||||
int n;
|
||||
unsigned int smp_cpus = machine->smp.cpus;
|
||||
int done_nic = 0;
|
||||
qemu_irq cpu_irq[4];
|
||||
int is_mpcore = 0;
|
||||
|
@ -105,7 +105,7 @@ static void sabrelite_init(MachineState *machine)
|
||||
sabrelite_binfo.kernel_filename = machine->kernel_filename;
|
||||
sabrelite_binfo.kernel_cmdline = machine->kernel_cmdline;
|
||||
sabrelite_binfo.initrd_filename = machine->initrd_filename;
|
||||
sabrelite_binfo.nb_cpus = smp_cpus;
|
||||
sabrelite_binfo.nb_cpus = machine->smp.cpus;
|
||||
sabrelite_binfo.secure_boot = true;
|
||||
sabrelite_binfo.write_secondary_boot = sabrelite_write_secondary;
|
||||
sabrelite_binfo.secondary_cpu_reset_hook = sabrelite_reset_secondary;
|
||||
|
@ -328,6 +328,7 @@ static void create_secure_ram(SBSAMachineState *sms,
|
||||
|
||||
static void create_gic(SBSAMachineState *sms, qemu_irq *pic)
|
||||
{
|
||||
unsigned int smp_cpus = MACHINE(sms)->smp.cpus;
|
||||
DeviceState *gicdev;
|
||||
SysBusDevice *gicbusdev;
|
||||
const char *gictype;
|
||||
@ -585,6 +586,8 @@ static void *sbsa_ref_dtb(const struct arm_boot_info *binfo, int *fdt_size)
|
||||
|
||||
static void sbsa_ref_init(MachineState *machine)
|
||||
{
|
||||
unsigned int smp_cpus = machine->smp.cpus;
|
||||
unsigned int max_cpus = machine->smp.max_cpus;
|
||||
SBSAMachineState *sms = SBSA_MACHINE(machine);
|
||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||
MemoryRegion *sysmem = get_system_memory();
|
||||
@ -727,6 +730,7 @@ static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, int idx)
|
||||
|
||||
static const CPUArchIdList *sbsa_ref_possible_cpu_arch_ids(MachineState *ms)
|
||||
{
|
||||
unsigned int max_cpus = ms->smp.max_cpus;
|
||||
SBSAMachineState *sms = SBSA_MACHINE(ms);
|
||||
int n;
|
||||
|
||||
|
@ -203,12 +203,14 @@ struct VEDBoardInfo {
|
||||
DBoardInitFn *init;
|
||||
};
|
||||
|
||||
static void init_cpus(const char *cpu_type, const char *privdev,
|
||||
hwaddr periphbase, qemu_irq *pic, bool secure, bool virt)
|
||||
static void init_cpus(MachineState *ms, const char *cpu_type,
|
||||
const char *privdev, hwaddr periphbase,
|
||||
qemu_irq *pic, bool secure, bool virt)
|
||||
{
|
||||
DeviceState *dev;
|
||||
SysBusDevice *busdev;
|
||||
int n;
|
||||
unsigned int smp_cpus = ms->smp.cpus;
|
||||
|
||||
/* Create the actual CPUs */
|
||||
for (n = 0; n < smp_cpus; n++) {
|
||||
@ -269,6 +271,7 @@ static void a9_daughterboard_init(const VexpressMachineState *vms,
|
||||
const char *cpu_type,
|
||||
qemu_irq *pic)
|
||||
{
|
||||
MachineState *machine = MACHINE(vms);
|
||||
MemoryRegion *sysmem = get_system_memory();
|
||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *lowram = g_new(MemoryRegion, 1);
|
||||
@ -295,7 +298,7 @@ static void a9_daughterboard_init(const VexpressMachineState *vms,
|
||||
memory_region_add_subregion(sysmem, 0x60000000, ram);
|
||||
|
||||
/* 0x1e000000 A9MPCore (SCU) private memory region */
|
||||
init_cpus(cpu_type, TYPE_A9MPCORE_PRIV, 0x1e000000, pic,
|
||||
init_cpus(machine, cpu_type, TYPE_A9MPCORE_PRIV, 0x1e000000, pic,
|
||||
vms->secure, vms->virt);
|
||||
|
||||
/* Daughterboard peripherals : 0x10020000 .. 0x20000000 */
|
||||
@ -355,6 +358,7 @@ static void a15_daughterboard_init(const VexpressMachineState *vms,
|
||||
const char *cpu_type,
|
||||
qemu_irq *pic)
|
||||
{
|
||||
MachineState *machine = MACHINE(vms);
|
||||
MemoryRegion *sysmem = get_system_memory();
|
||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *sram = g_new(MemoryRegion, 1);
|
||||
@ -377,8 +381,8 @@ static void a15_daughterboard_init(const VexpressMachineState *vms,
|
||||
memory_region_add_subregion(sysmem, 0x80000000, ram);
|
||||
|
||||
/* 0x2c000000 A15MPCore private memory region (GIC) */
|
||||
init_cpus(cpu_type, TYPE_A15MPCORE_PRIV, 0x2c000000, pic, vms->secure,
|
||||
vms->virt);
|
||||
init_cpus(machine, cpu_type, TYPE_A15MPCORE_PRIV,
|
||||
0x2c000000, pic, vms->secure, vms->virt);
|
||||
|
||||
/* A15 daughterboard peripherals: */
|
||||
|
||||
@ -706,7 +710,7 @@ static void vexpress_common_init(MachineState *machine)
|
||||
daughterboard->bootinfo.kernel_filename = machine->kernel_filename;
|
||||
daughterboard->bootinfo.kernel_cmdline = machine->kernel_cmdline;
|
||||
daughterboard->bootinfo.initrd_filename = machine->initrd_filename;
|
||||
daughterboard->bootinfo.nb_cpus = smp_cpus;
|
||||
daughterboard->bootinfo.nb_cpus = machine->smp.cpus;
|
||||
daughterboard->bootinfo.board_id = VEXPRESS_BOARD_ID;
|
||||
daughterboard->bootinfo.loader_start = daughterboard->loader_start;
|
||||
daughterboard->bootinfo.smp_loader_start = map[VE_SRAM];
|
||||
|
@ -559,11 +559,13 @@ static void create_v2m(VirtMachineState *vms, qemu_irq *pic)
|
||||
|
||||
static void create_gic(VirtMachineState *vms, qemu_irq *pic)
|
||||
{
|
||||
MachineState *ms = MACHINE(vms);
|
||||
/* We create a standalone GIC */
|
||||
DeviceState *gicdev;
|
||||
SysBusDevice *gicbusdev;
|
||||
const char *gictype;
|
||||
int type = vms->gic_version, i;
|
||||
unsigned int smp_cpus = ms->smp.cpus;
|
||||
uint32_t nb_redist_regions = 0;
|
||||
|
||||
gictype = (type == 3) ? gicv3_class_name() : gic_class_name();
|
||||
@ -1039,13 +1041,14 @@ static bool virt_firmware_init(VirtMachineState *vms,
|
||||
|
||||
static FWCfgState *create_fw_cfg(const VirtMachineState *vms, AddressSpace *as)
|
||||
{
|
||||
MachineState *ms = MACHINE(vms);
|
||||
hwaddr base = vms->memmap[VIRT_FW_CFG].base;
|
||||
hwaddr size = vms->memmap[VIRT_FW_CFG].size;
|
||||
FWCfgState *fw_cfg;
|
||||
char *nodename;
|
||||
|
||||
fw_cfg = fw_cfg_init_mem_wide(base + 8, base, 8, base + 16, as);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)ms->smp.cpus);
|
||||
|
||||
nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base);
|
||||
qemu_fdt_add_subnode(vms->fdt, nodename);
|
||||
@ -1345,7 +1348,7 @@ static void virt_build_smbios(VirtMachineState *vms)
|
||||
vmc->smbios_old_sys_ver ? "1.0" : mc->name, false,
|
||||
true, SMBIOS_ENTRY_POINT_30);
|
||||
|
||||
smbios_get_tables(NULL, 0, &smbios_tables, &smbios_tables_len,
|
||||
smbios_get_tables(MACHINE(vms), NULL, 0, &smbios_tables, &smbios_tables_len,
|
||||
&smbios_anchor, &smbios_anchor_len);
|
||||
|
||||
if (smbios_anchor) {
|
||||
@ -1478,6 +1481,8 @@ static void machvirt_init(MachineState *machine)
|
||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||
bool firmware_loaded;
|
||||
bool aarch64 = true;
|
||||
unsigned int smp_cpus = machine->smp.cpus;
|
||||
unsigned int max_cpus = machine->smp.max_cpus;
|
||||
|
||||
/*
|
||||
* In accelerated mode, the memory map is computed earlier in kvm_type()
|
||||
@ -1845,6 +1850,7 @@ static int64_t virt_get_default_cpu_node_id(const MachineState *ms, int idx)
|
||||
static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
|
||||
{
|
||||
int n;
|
||||
unsigned int max_cpus = ms->smp.max_cpus;
|
||||
VirtMachineState *vms = VIRT_MACHINE(ms);
|
||||
|
||||
if (ms->possible_cpus) {
|
||||
@ -1946,6 +1952,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
|
||||
assert(!mc->get_hotplug_handler);
|
||||
mc->get_hotplug_handler = virt_machine_get_hotplug_handler;
|
||||
hc->plug = virt_machine_device_plug_cb;
|
||||
mc->numa_mem_supported = true;
|
||||
}
|
||||
|
||||
static void virt_instance_init(Object *obj)
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "cpu.h"
|
||||
#include "hw/arm/xlnx-zynqmp.h"
|
||||
#include "hw/intc/arm_gic_common.h"
|
||||
#include "hw/boards.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "kvm_arm.h"
|
||||
@ -171,12 +172,13 @@ static inline int arm_gic_ppi_index(int cpu_nr, int ppi_index)
|
||||
return GIC_NUM_SPI_INTR + cpu_nr * GIC_INTERNAL + ppi_index;
|
||||
}
|
||||
|
||||
static void xlnx_zynqmp_create_rpu(XlnxZynqMPState *s, const char *boot_cpu,
|
||||
Error **errp)
|
||||
static void xlnx_zynqmp_create_rpu(MachineState *ms, XlnxZynqMPState *s,
|
||||
const char *boot_cpu, Error **errp)
|
||||
{
|
||||
Error *err = NULL;
|
||||
int i;
|
||||
int num_rpus = MIN(smp_cpus - XLNX_ZYNQMP_NUM_APU_CPUS, XLNX_ZYNQMP_NUM_RPU_CPUS);
|
||||
int num_rpus = MIN(ms->smp.cpus - XLNX_ZYNQMP_NUM_APU_CPUS,
|
||||
XLNX_ZYNQMP_NUM_RPU_CPUS);
|
||||
|
||||
if (num_rpus <= 0) {
|
||||
/* Don't create rpu-cluster object if there's nothing to put in it */
|
||||
@ -221,9 +223,10 @@ static void xlnx_zynqmp_create_rpu(XlnxZynqMPState *s, const char *boot_cpu,
|
||||
|
||||
static void xlnx_zynqmp_init(Object *obj)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
XlnxZynqMPState *s = XLNX_ZYNQMP(obj);
|
||||
int i;
|
||||
int num_apus = MIN(smp_cpus, XLNX_ZYNQMP_NUM_APU_CPUS);
|
||||
int num_apus = MIN(ms->smp.cpus, XLNX_ZYNQMP_NUM_APU_CPUS);
|
||||
|
||||
object_initialize_child(obj, "apu-cluster", &s->apu_cluster,
|
||||
sizeof(s->apu_cluster), TYPE_CPU_CLUSTER,
|
||||
@ -290,11 +293,12 @@ static void xlnx_zynqmp_init(Object *obj)
|
||||
|
||||
static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
XlnxZynqMPState *s = XLNX_ZYNQMP(dev);
|
||||
MemoryRegion *system_memory = get_system_memory();
|
||||
uint8_t i;
|
||||
uint64_t ram_size;
|
||||
int num_apus = MIN(smp_cpus, XLNX_ZYNQMP_NUM_APU_CPUS);
|
||||
int num_apus = MIN(ms->smp.cpus, XLNX_ZYNQMP_NUM_APU_CPUS);
|
||||
const char *boot_cpu = s->boot_cpu ? s->boot_cpu : "apu-cpu[0]";
|
||||
ram_addr_t ddr_low_size, ddr_high_size;
|
||||
qemu_irq gic_spi[GIC_NUM_SPI_INTR];
|
||||
@ -456,7 +460,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
|
||||
"RPUs just use -smp 6.");
|
||||
}
|
||||
|
||||
xlnx_zynqmp_create_rpu(s, boot_cpu, &err);
|
||||
xlnx_zynqmp_create_rpu(ms, s, boot_cpu, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
|
@ -86,6 +86,9 @@ void hmp_hotpluggable_cpus(Monitor *mon, const QDict *qdict)
|
||||
if (c->has_socket_id) {
|
||||
monitor_printf(mon, " socket-id: \"%" PRIu64 "\"\n", c->socket_id);
|
||||
}
|
||||
if (c->has_die_id) {
|
||||
monitor_printf(mon, " die-id: \"%" PRIu64 "\"\n", c->die_id);
|
||||
}
|
||||
if (c->has_core_id) {
|
||||
monitor_printf(mon, " core-id: \"%" PRIu64 "\"\n", c->core_id);
|
||||
}
|
||||
|
@ -226,6 +226,8 @@ MachineInfoList *qmp_query_machines(Error **errp)
|
||||
info->name = g_strdup(mc->name);
|
||||
info->cpu_max = !mc->max_cpus ? 1 : mc->max_cpus;
|
||||
info->hotpluggable_cpus = mc->has_hotpluggable_cpus;
|
||||
info->numa_mem_supported = mc->numa_mem_supported;
|
||||
info->deprecated = !!mc->deprecation_reason;
|
||||
|
||||
entry = g_malloc0(sizeof(*entry));
|
||||
entry->value = info;
|
||||
@ -264,7 +266,7 @@ void qmp_cpu_add(int64_t id, Error **errp)
|
||||
|
||||
mc = MACHINE_GET_CLASS(current_machine);
|
||||
if (mc->hot_add_cpu) {
|
||||
mc->hot_add_cpu(id, errp);
|
||||
mc->hot_add_cpu(current_machine, id, errp);
|
||||
} else {
|
||||
error_setg(errp, "Not supported");
|
||||
}
|
||||
|
@ -11,6 +11,9 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "qemu/units.h"
|
||||
#include "hw/boards.h"
|
||||
#include "qapi/error.h"
|
||||
@ -683,6 +686,11 @@ void machine_set_cpu_numa_node(MachineState *machine,
|
||||
return;
|
||||
}
|
||||
|
||||
if (props->has_die_id && !slot->props.has_die_id) {
|
||||
error_setg(errp, "die-id is not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
/* skip slots with explicit mismatch */
|
||||
if (props->has_thread_id && props->thread_id != slot->props.thread_id) {
|
||||
continue;
|
||||
@ -692,6 +700,10 @@ void machine_set_cpu_numa_node(MachineState *machine,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (props->has_die_id && props->die_id != slot->props.die_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (props->has_socket_id && props->socket_id != slot->props.socket_id) {
|
||||
continue;
|
||||
}
|
||||
@ -717,6 +729,78 @@ void machine_set_cpu_numa_node(MachineState *machine,
|
||||
}
|
||||
}
|
||||
|
||||
static void smp_parse(MachineState *ms, QemuOpts *opts)
|
||||
{
|
||||
if (opts) {
|
||||
unsigned cpus = qemu_opt_get_number(opts, "cpus", 0);
|
||||
unsigned sockets = qemu_opt_get_number(opts, "sockets", 0);
|
||||
unsigned cores = qemu_opt_get_number(opts, "cores", 0);
|
||||
unsigned threads = qemu_opt_get_number(opts, "threads", 0);
|
||||
|
||||
/* compute missing values, prefer sockets over cores over threads */
|
||||
if (cpus == 0 || sockets == 0) {
|
||||
cores = cores > 0 ? cores : 1;
|
||||
threads = threads > 0 ? threads : 1;
|
||||
if (cpus == 0) {
|
||||
sockets = sockets > 0 ? sockets : 1;
|
||||
cpus = cores * threads * sockets;
|
||||
} else {
|
||||
ms->smp.max_cpus =
|
||||
qemu_opt_get_number(opts, "maxcpus", cpus);
|
||||
sockets = ms->smp.max_cpus / (cores * threads);
|
||||
}
|
||||
} else if (cores == 0) {
|
||||
threads = threads > 0 ? threads : 1;
|
||||
cores = cpus / (sockets * threads);
|
||||
cores = cores > 0 ? cores : 1;
|
||||
} else if (threads == 0) {
|
||||
threads = cpus / (cores * sockets);
|
||||
threads = threads > 0 ? threads : 1;
|
||||
} else if (sockets * cores * threads < cpus) {
|
||||
error_report("cpu topology: "
|
||||
"sockets (%u) * cores (%u) * threads (%u) < "
|
||||
"smp_cpus (%u)",
|
||||
sockets, cores, threads, cpus);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ms->smp.max_cpus =
|
||||
qemu_opt_get_number(opts, "maxcpus", cpus);
|
||||
|
||||
if (ms->smp.max_cpus < cpus) {
|
||||
error_report("maxcpus must be equal to or greater than smp");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (sockets * cores * threads > ms->smp.max_cpus) {
|
||||
error_report("cpu topology: "
|
||||
"sockets (%u) * cores (%u) * threads (%u) > "
|
||||
"maxcpus (%u)",
|
||||
sockets, cores, threads,
|
||||
ms->smp.max_cpus);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (sockets * cores * threads != ms->smp.max_cpus) {
|
||||
warn_report("Invalid CPU topology deprecated: "
|
||||
"sockets (%u) * cores (%u) * threads (%u) "
|
||||
"!= maxcpus (%u)",
|
||||
sockets, cores, threads,
|
||||
ms->smp.max_cpus);
|
||||
}
|
||||
|
||||
ms->smp.cpus = cpus;
|
||||
ms->smp.cores = cores;
|
||||
ms->smp.threads = threads;
|
||||
}
|
||||
|
||||
if (ms->smp.cpus > 1) {
|
||||
Error *blocker = NULL;
|
||||
error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, "smp");
|
||||
replay_add_blocker(blocker);
|
||||
}
|
||||
}
|
||||
|
||||
static void machine_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
@ -724,6 +808,7 @@ static void machine_class_init(ObjectClass *oc, void *data)
|
||||
/* Default 128 MB as guest ram size */
|
||||
mc->default_ram_size = 128 * MiB;
|
||||
mc->rom_file_has_mr = true;
|
||||
mc->smp_parse = smp_parse;
|
||||
|
||||
/* numa node memory size aligned on 8MB by default.
|
||||
* On Linux, each node's border has to be 8MB aligned
|
||||
@ -949,6 +1034,9 @@ static char *cpu_slot_to_string(const CPUArchId *cpu)
|
||||
if (cpu->props.has_socket_id) {
|
||||
g_string_append_printf(s, "socket-id: %"PRId64, cpu->props.socket_id);
|
||||
}
|
||||
if (cpu->props.has_die_id) {
|
||||
g_string_append_printf(s, "die-id: %"PRId64, cpu->props.die_id);
|
||||
}
|
||||
if (cpu->props.has_core_id) {
|
||||
if (s->len) {
|
||||
g_string_append_printf(s, ", ");
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/opts-visitor.h"
|
||||
#include "qapi/qapi-visit-machine.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "hw/mem/pc-dimm.h"
|
||||
#include "hw/mem/memory-device.h"
|
||||
#include "qemu/option.h"
|
||||
@ -44,7 +45,8 @@ QemuOptsList qemu_numa_opts = {
|
||||
.desc = { { 0 } } /* validated with OptsVisitor */
|
||||
};
|
||||
|
||||
static int have_memdevs = -1;
|
||||
static int have_memdevs;
|
||||
static int have_mem;
|
||||
static int max_numa_nodeid; /* Highest specified NUMA node ID, plus one.
|
||||
* For all nodes, nodeid < max_numa_nodeid
|
||||
*/
|
||||
@ -60,6 +62,7 @@ static void parse_numa_node(MachineState *ms, NumaNodeOptions *node,
|
||||
uint16_t nodenr;
|
||||
uint16List *cpus = NULL;
|
||||
MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||
unsigned int max_cpus = ms->smp.max_cpus;
|
||||
|
||||
if (node->has_nodeid) {
|
||||
nodenr = node->nodeid;
|
||||
@ -101,22 +104,20 @@ static void parse_numa_node(MachineState *ms, NumaNodeOptions *node,
|
||||
}
|
||||
}
|
||||
|
||||
if (node->has_mem && node->has_memdev) {
|
||||
error_setg(errp, "cannot specify both mem= and memdev=");
|
||||
return;
|
||||
}
|
||||
|
||||
if (have_memdevs == -1) {
|
||||
have_memdevs = node->has_memdev;
|
||||
}
|
||||
if (node->has_memdev != have_memdevs) {
|
||||
error_setg(errp, "memdev option must be specified for either "
|
||||
"all or no nodes");
|
||||
have_memdevs = have_memdevs ? : node->has_memdev;
|
||||
have_mem = have_mem ? : node->has_mem;
|
||||
if ((node->has_mem && have_memdevs) || (node->has_memdev && have_mem)) {
|
||||
error_setg(errp, "numa configuration should use either mem= or memdev=,"
|
||||
"mixing both is not allowed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (node->has_mem) {
|
||||
numa_info[nodenr].node_mem = node->mem;
|
||||
if (!qtest_enabled()) {
|
||||
warn_report("Parameter -numa node,mem is deprecated,"
|
||||
" use -numa node,memdev instead");
|
||||
}
|
||||
}
|
||||
if (node->has_memdev) {
|
||||
Object *o;
|
||||
@ -402,6 +403,11 @@ void numa_complete_configuration(MachineState *ms)
|
||||
if (i == nb_numa_nodes) {
|
||||
assert(mc->numa_auto_assign_ram);
|
||||
mc->numa_auto_assign_ram(mc, numa_info, nb_numa_nodes, ram_size);
|
||||
if (!qtest_enabled()) {
|
||||
warn_report("Default splitting of RAM between nodes is deprecated,"
|
||||
" Use '-numa node,memdev' to explictly define RAM"
|
||||
" allocation per node");
|
||||
}
|
||||
}
|
||||
|
||||
numa_total = 0;
|
||||
@ -473,8 +479,10 @@ static void allocate_system_memory_nonnuma(MemoryRegion *mr, Object *owner,
|
||||
if (mem_prealloc) {
|
||||
exit(1);
|
||||
}
|
||||
error_report("falling back to regular RAM allocation.");
|
||||
|
||||
warn_report("falling back to regular RAM allocation");
|
||||
error_printf("This is deprecated. Make sure that -mem-path "
|
||||
" specified path has sufficient resources to allocate"
|
||||
" -m specified RAM amount");
|
||||
/* Legacy behavior: if allocation failed, fall back to
|
||||
* regular RAM allocation.
|
||||
*/
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "qemu/module.h"
|
||||
#include "qapi/error.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "hw/boards.h"
|
||||
|
||||
static void core_prop_get_core_id(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
@ -71,13 +72,14 @@ static void core_prop_set_nr_threads(Object *obj, Visitor *v, const char *name,
|
||||
|
||||
static void cpu_core_instance_init(Object *obj)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
CPUCore *core = CPU_CORE(obj);
|
||||
|
||||
object_property_add(obj, "core-id", "int", core_prop_get_core_id,
|
||||
core_prop_set_core_id, NULL, NULL, NULL);
|
||||
object_property_add(obj, "nr-threads", "int", core_prop_get_nr_threads,
|
||||
core_prop_set_nr_threads, NULL, NULL, NULL);
|
||||
core->nr_threads = smp_threads;
|
||||
core->nr_threads = ms->smp.threads;
|
||||
}
|
||||
|
||||
static void cpu_core_class_init(ObjectClass *oc, void *data)
|
||||
|
@ -72,6 +72,7 @@ static void machine_hppa_init(MachineState *machine)
|
||||
MemoryRegion *ram_region;
|
||||
MemoryRegion *cpu_region;
|
||||
long i;
|
||||
unsigned int smp_cpus = machine->smp.cpus;
|
||||
|
||||
ram_size = machine->ram_size;
|
||||
|
||||
@ -240,8 +241,9 @@ static void machine_hppa_init(MachineState *machine)
|
||||
cpu[0]->env.gr[21] = smp_cpus;
|
||||
}
|
||||
|
||||
static void hppa_machine_reset(void)
|
||||
static void hppa_machine_reset(MachineState *ms)
|
||||
{
|
||||
unsigned int smp_cpus = ms->smp.cpus;
|
||||
int i;
|
||||
|
||||
qemu_devices_reset();
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "sysemu/tpm.h"
|
||||
#include "hw/acpi/tpm.h"
|
||||
#include "hw/acpi/vmgenid.h"
|
||||
#include "hw/boards.h"
|
||||
#include "sysemu/tpm_backend.h"
|
||||
#include "hw/timer/mc146818rtc_regs.h"
|
||||
#include "hw/mem/memory-device.h"
|
||||
@ -123,7 +124,8 @@ typedef struct FwCfgTPMConfig {
|
||||
|
||||
static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg);
|
||||
|
||||
static void init_common_fadt_data(Object *o, AcpiFadtData *data)
|
||||
static void init_common_fadt_data(MachineState *ms, Object *o,
|
||||
AcpiFadtData *data)
|
||||
{
|
||||
uint32_t io = object_property_get_uint(o, ACPI_PM_PROP_PM_IO_BASE, NULL);
|
||||
AmlAddressSpace as = AML_AS_SYSTEM_IO;
|
||||
@ -139,7 +141,8 @@ static void init_common_fadt_data(Object *o, AcpiFadtData *data)
|
||||
* CPUs for more than 8 CPUs, "Clustered Logical" mode has to be
|
||||
* used
|
||||
*/
|
||||
((max_cpus > 8) ? (1 << ACPI_FADT_F_FORCE_APIC_CLUSTER_MODEL) : 0),
|
||||
((ms->smp.max_cpus > 8) ?
|
||||
(1 << ACPI_FADT_F_FORCE_APIC_CLUSTER_MODEL) : 0),
|
||||
.int_model = 1 /* Multiple APIC */,
|
||||
.rtc_century = RTC_CENTURY,
|
||||
.plvl2_lat = 0xfff /* C2 state not supported */,
|
||||
@ -173,7 +176,7 @@ static Object *object_resolve_type_unambiguous(const char *typename)
|
||||
return o;
|
||||
}
|
||||
|
||||
static void acpi_get_pm_info(AcpiPmInfo *pm)
|
||||
static void acpi_get_pm_info(MachineState *machine, AcpiPmInfo *pm)
|
||||
{
|
||||
Object *piix = object_resolve_type_unambiguous(TYPE_PIIX4_PM);
|
||||
Object *lpc = object_resolve_type_unambiguous(TYPE_ICH9_LPC_DEVICE);
|
||||
@ -184,7 +187,7 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
|
||||
pm->pcihp_io_len = 0;
|
||||
|
||||
assert(obj);
|
||||
init_common_fadt_data(obj, &pm->fadt);
|
||||
init_common_fadt_data(machine, obj, &pm->fadt);
|
||||
if (piix) {
|
||||
/* w2k requires FADT(rev1) or it won't boot, keep PC compatible */
|
||||
pm->fadt.rev = 1;
|
||||
@ -2612,7 +2615,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
|
||||
AcpiSlicOem slic_oem = { .id = NULL, .table_id = NULL };
|
||||
Object *vmgenid_dev;
|
||||
|
||||
acpi_get_pm_info(&pm);
|
||||
acpi_get_pm_info(machine, &pm);
|
||||
acpi_get_misc_info(&misc);
|
||||
acpi_get_pci_holes(&pci_hole, &pci_hole64);
|
||||
acpi_get_slic_oem(&slic_oem);
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "sysemu/kvm.h"
|
||||
#include "hw/i386/apic_internal.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/boards.h"
|
||||
#include "tcg/tcg.h"
|
||||
|
||||
#define VAPIC_IO_PORT 0x7e
|
||||
@ -442,11 +443,12 @@ static void do_patch_instruction(CPUState *cs, run_on_cpu_data data)
|
||||
|
||||
static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
CPUState *cs = CPU(cpu);
|
||||
VAPICHandlers *handlers;
|
||||
PatchInfo *info;
|
||||
|
||||
if (smp_cpus == 1) {
|
||||
if (ms->smp.cpus == 1) {
|
||||
handlers = &s->rom_state.up;
|
||||
} else {
|
||||
handlers = &s->rom_state.mp;
|
||||
@ -747,6 +749,7 @@ static void do_vapic_enable(CPUState *cs, run_on_cpu_data data)
|
||||
static void kvmvapic_vm_state_change(void *opaque, int running,
|
||||
RunState state)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
VAPICROMState *s = opaque;
|
||||
uint8_t *zero;
|
||||
|
||||
@ -755,7 +758,7 @@ static void kvmvapic_vm_state_change(void *opaque, int running,
|
||||
}
|
||||
|
||||
if (s->state == VAPIC_ACTIVE) {
|
||||
if (smp_cpus == 1) {
|
||||
if (ms->smp.cpus == 1) {
|
||||
run_on_cpu(first_cpu, do_vapic_enable, RUN_ON_CPU_HOST_PTR(s));
|
||||
} else {
|
||||
zero = g_malloc0(s->rom_state.vapic_size);
|
||||
|
178
hw/i386/pc.c
178
hw/i386/pc.c
@ -81,6 +81,8 @@
|
||||
#include "standard-headers/asm-x86/bootparam.h"
|
||||
#include "hw/virtio/virtio-pmem-pci.h"
|
||||
#include "hw/mem/memory-device.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
|
||||
/* debug PC/ISA interrupts */
|
||||
//#define DEBUG_IRQ
|
||||
@ -925,11 +927,13 @@ bool e820_get_entry(int idx, uint32_t type, uint64_t *address, uint64_t *length)
|
||||
static uint32_t x86_cpu_apic_id_from_index(PCMachineState *pcms,
|
||||
unsigned int cpu_index)
|
||||
{
|
||||
MachineState *ms = MACHINE(pcms);
|
||||
PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
|
||||
uint32_t correct_id;
|
||||
static bool warned;
|
||||
|
||||
correct_id = x86_apicid_from_cpu_idx(smp_cores, smp_threads, cpu_index);
|
||||
correct_id = x86_apicid_from_cpu_idx(pcms->smp_dies, ms->smp.cores,
|
||||
ms->smp.threads, cpu_index);
|
||||
if (pcmc->compat_apic_id_mode) {
|
||||
if (cpu_index != correct_id && !warned && !qtest_enabled()) {
|
||||
error_report("APIC IDs set in compatibility mode, "
|
||||
@ -954,7 +958,7 @@ static void pc_build_smbios(PCMachineState *pcms)
|
||||
/* tell smbios about cpuid version and features */
|
||||
smbios_set_cpuid(cpu->env.cpuid_version, cpu->env.features[FEAT_1_EDX]);
|
||||
|
||||
smbios_tables = smbios_get_table_legacy(&smbios_tables_len);
|
||||
smbios_tables = smbios_get_table_legacy(ms, &smbios_tables_len);
|
||||
if (smbios_tables) {
|
||||
fw_cfg_add_bytes(pcms->fw_cfg, FW_CFG_SMBIOS_ENTRIES,
|
||||
smbios_tables, smbios_tables_len);
|
||||
@ -971,7 +975,7 @@ static void pc_build_smbios(PCMachineState *pcms)
|
||||
array_count++;
|
||||
}
|
||||
}
|
||||
smbios_get_tables(mem_array, array_count,
|
||||
smbios_get_tables(ms, mem_array, array_count,
|
||||
&smbios_tables, &smbios_tables_len,
|
||||
&smbios_anchor, &smbios_anchor_len);
|
||||
g_free(mem_array);
|
||||
@ -1512,12 +1516,16 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
|
||||
}
|
||||
}
|
||||
|
||||
static void pc_new_cpu(const char *typename, int64_t apic_id, Error **errp)
|
||||
static void pc_new_cpu(PCMachineState *pcms, int64_t apic_id, Error **errp)
|
||||
{
|
||||
Object *cpu = NULL;
|
||||
Error *local_err = NULL;
|
||||
CPUX86State *env = NULL;
|
||||
|
||||
cpu = object_new(typename);
|
||||
cpu = object_new(MACHINE(pcms)->cpu_type);
|
||||
|
||||
env = &X86_CPU(cpu)->env;
|
||||
env->nr_dies = pcms->smp_dies;
|
||||
|
||||
object_property_set_uint(cpu, apic_id, "apic-id", &local_err);
|
||||
object_property_set_bool(cpu, true, "realized", &local_err);
|
||||
@ -1526,9 +1534,88 @@ static void pc_new_cpu(const char *typename, int64_t apic_id, Error **errp)
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
|
||||
void pc_hot_add_cpu(const int64_t id, Error **errp)
|
||||
/*
|
||||
* This function is very similar to smp_parse()
|
||||
* in hw/core/machine.c but includes CPU die support.
|
||||
*/
|
||||
void pc_smp_parse(MachineState *ms, QemuOpts *opts)
|
||||
{
|
||||
PCMachineState *pcms = PC_MACHINE(ms);
|
||||
|
||||
if (opts) {
|
||||
unsigned cpus = qemu_opt_get_number(opts, "cpus", 0);
|
||||
unsigned sockets = qemu_opt_get_number(opts, "sockets", 0);
|
||||
unsigned dies = qemu_opt_get_number(opts, "dies", 1);
|
||||
unsigned cores = qemu_opt_get_number(opts, "cores", 0);
|
||||
unsigned threads = qemu_opt_get_number(opts, "threads", 0);
|
||||
|
||||
/* compute missing values, prefer sockets over cores over threads */
|
||||
if (cpus == 0 || sockets == 0) {
|
||||
cores = cores > 0 ? cores : 1;
|
||||
threads = threads > 0 ? threads : 1;
|
||||
if (cpus == 0) {
|
||||
sockets = sockets > 0 ? sockets : 1;
|
||||
cpus = cores * threads * dies * sockets;
|
||||
} else {
|
||||
ms->smp.max_cpus =
|
||||
qemu_opt_get_number(opts, "maxcpus", cpus);
|
||||
sockets = ms->smp.max_cpus / (cores * threads * dies);
|
||||
}
|
||||
} else if (cores == 0) {
|
||||
threads = threads > 0 ? threads : 1;
|
||||
cores = cpus / (sockets * dies * threads);
|
||||
cores = cores > 0 ? cores : 1;
|
||||
} else if (threads == 0) {
|
||||
threads = cpus / (cores * dies * sockets);
|
||||
threads = threads > 0 ? threads : 1;
|
||||
} else if (sockets * dies * cores * threads < cpus) {
|
||||
error_report("cpu topology: "
|
||||
"sockets (%u) * dies (%u) * cores (%u) * threads (%u) < "
|
||||
"smp_cpus (%u)",
|
||||
sockets, dies, cores, threads, cpus);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ms->smp.max_cpus =
|
||||
qemu_opt_get_number(opts, "maxcpus", cpus);
|
||||
|
||||
if (ms->smp.max_cpus < cpus) {
|
||||
error_report("maxcpus must be equal to or greater than smp");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (sockets * dies * cores * threads > ms->smp.max_cpus) {
|
||||
error_report("cpu topology: "
|
||||
"sockets (%u) * dies (%u) * cores (%u) * threads (%u) > "
|
||||
"maxcpus (%u)",
|
||||
sockets, dies, cores, threads,
|
||||
ms->smp.max_cpus);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (sockets * dies * cores * threads != ms->smp.max_cpus) {
|
||||
warn_report("Invalid CPU topology deprecated: "
|
||||
"sockets (%u) * dies (%u) * cores (%u) * threads (%u) "
|
||||
"!= maxcpus (%u)",
|
||||
sockets, dies, cores, threads,
|
||||
ms->smp.max_cpus);
|
||||
}
|
||||
|
||||
ms->smp.cpus = cpus;
|
||||
ms->smp.cores = cores;
|
||||
ms->smp.threads = threads;
|
||||
pcms->smp_dies = dies;
|
||||
}
|
||||
|
||||
if (ms->smp.cpus > 1) {
|
||||
Error *blocker = NULL;
|
||||
error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, "smp");
|
||||
replay_add_blocker(blocker);
|
||||
}
|
||||
}
|
||||
|
||||
void pc_hot_add_cpu(MachineState *ms, const int64_t id, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
PCMachineState *pcms = PC_MACHINE(ms);
|
||||
int64_t apic_id = x86_cpu_apic_id_from_index(pcms, id);
|
||||
Error *local_err = NULL;
|
||||
@ -1545,7 +1632,7 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
pc_new_cpu(ms->cpu_type, apic_id, &local_err);
|
||||
pc_new_cpu(PC_MACHINE(ms), apic_id, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
@ -1558,6 +1645,9 @@ void pc_cpus_init(PCMachineState *pcms)
|
||||
const CPUArchIdList *possible_cpus;
|
||||
MachineState *ms = MACHINE(pcms);
|
||||
MachineClass *mc = MACHINE_GET_CLASS(pcms);
|
||||
PCMachineClass *pcmc = PC_MACHINE_CLASS(mc);
|
||||
|
||||
x86_cpu_set_default_version(pcmc->default_cpu_version);
|
||||
|
||||
/* Calculates the limit to CPU APIC ID values
|
||||
*
|
||||
@ -1566,11 +1656,11 @@ void pc_cpus_init(PCMachineState *pcms)
|
||||
*
|
||||
* This is used for FW_CFG_MAX_CPUS. See comments on bochs_bios_init().
|
||||
*/
|
||||
pcms->apic_id_limit = x86_cpu_apic_id_from_index(pcms, max_cpus - 1) + 1;
|
||||
pcms->apic_id_limit = x86_cpu_apic_id_from_index(pcms,
|
||||
ms->smp.max_cpus - 1) + 1;
|
||||
possible_cpus = mc->possible_cpu_arch_ids(ms);
|
||||
for (i = 0; i < smp_cpus; i++) {
|
||||
pc_new_cpu(possible_cpus->cpus[i].type, possible_cpus->cpus[i].arch_id,
|
||||
&error_fatal);
|
||||
for (i = 0; i < ms->smp.cpus; i++) {
|
||||
pc_new_cpu(pcms, possible_cpus->cpus[i].arch_id, &error_fatal);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2290,8 +2380,11 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
||||
CPUArchId *cpu_slot;
|
||||
X86CPUTopoInfo topo;
|
||||
X86CPU *cpu = X86_CPU(dev);
|
||||
CPUX86State *env = &cpu->env;
|
||||
MachineState *ms = MACHINE(hotplug_dev);
|
||||
PCMachineState *pcms = PC_MACHINE(hotplug_dev);
|
||||
unsigned int smp_cores = ms->smp.cores;
|
||||
unsigned int smp_threads = ms->smp.threads;
|
||||
|
||||
if(!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) {
|
||||
error_setg(errp, "Invalid CPU type, expected cpu type: '%s'",
|
||||
@ -2299,9 +2392,15 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
||||
return;
|
||||
}
|
||||
|
||||
/* if APIC ID is not set, set it based on socket/core/thread properties */
|
||||
env->nr_dies = pcms->smp_dies;
|
||||
|
||||
/*
|
||||
* If APIC ID is not set,
|
||||
* set it based on socket/die/core/thread properties.
|
||||
*/
|
||||
if (cpu->apic_id == UNASSIGNED_APIC_ID) {
|
||||
int max_socket = (max_cpus - 1) / smp_threads / smp_cores;
|
||||
int max_socket = (ms->smp.max_cpus - 1) /
|
||||
smp_threads / smp_cores / pcms->smp_dies;
|
||||
|
||||
if (cpu->socket_id < 0) {
|
||||
error_setg(errp, "CPU socket-id is not set");
|
||||
@ -2310,6 +2409,10 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
||||
error_setg(errp, "Invalid CPU socket-id: %u must be in range 0:%u",
|
||||
cpu->socket_id, max_socket);
|
||||
return;
|
||||
} else if (cpu->die_id > pcms->smp_dies - 1) {
|
||||
error_setg(errp, "Invalid CPU die-id: %u must be in range 0:%u",
|
||||
cpu->die_id, max_socket);
|
||||
return;
|
||||
}
|
||||
if (cpu->core_id < 0) {
|
||||
error_setg(errp, "CPU core-id is not set");
|
||||
@ -2329,20 +2432,24 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
||||
}
|
||||
|
||||
topo.pkg_id = cpu->socket_id;
|
||||
topo.die_id = cpu->die_id;
|
||||
topo.core_id = cpu->core_id;
|
||||
topo.smt_id = cpu->thread_id;
|
||||
cpu->apic_id = apicid_from_topo_ids(smp_cores, smp_threads, &topo);
|
||||
cpu->apic_id = apicid_from_topo_ids(pcms->smp_dies, smp_cores,
|
||||
smp_threads, &topo);
|
||||
}
|
||||
|
||||
cpu_slot = pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, &idx);
|
||||
if (!cpu_slot) {
|
||||
MachineState *ms = MACHINE(pcms);
|
||||
|
||||
x86_topo_ids_from_apicid(cpu->apic_id, smp_cores, smp_threads, &topo);
|
||||
error_setg(errp, "Invalid CPU [socket: %u, core: %u, thread: %u] with"
|
||||
" APIC ID %" PRIu32 ", valid index range 0:%d",
|
||||
topo.pkg_id, topo.core_id, topo.smt_id, cpu->apic_id,
|
||||
ms->possible_cpus->len - 1);
|
||||
x86_topo_ids_from_apicid(cpu->apic_id, pcms->smp_dies,
|
||||
smp_cores, smp_threads, &topo);
|
||||
error_setg(errp,
|
||||
"Invalid CPU [socket: %u, die: %u, core: %u, thread: %u] with"
|
||||
" APIC ID %" PRIu32 ", valid index range 0:%d",
|
||||
topo.pkg_id, topo.die_id, topo.core_id, topo.smt_id,
|
||||
cpu->apic_id, ms->possible_cpus->len - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2358,7 +2465,8 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
||||
/* TODO: move socket_id/core_id/thread_id checks into x86_cpu_realizefn()
|
||||
* once -smp refactoring is complete and there will be CPU private
|
||||
* CPUState::nr_cores and CPUState::nr_threads fields instead of globals */
|
||||
x86_topo_ids_from_apicid(cpu->apic_id, smp_cores, smp_threads, &topo);
|
||||
x86_topo_ids_from_apicid(cpu->apic_id, pcms->smp_dies,
|
||||
smp_cores, smp_threads, &topo);
|
||||
if (cpu->socket_id != -1 && cpu->socket_id != topo.pkg_id) {
|
||||
error_setg(errp, "property socket-id: %u doesn't match set apic-id:"
|
||||
" 0x%x (socket-id: %u)", cpu->socket_id, cpu->apic_id, topo.pkg_id);
|
||||
@ -2366,6 +2474,13 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
||||
}
|
||||
cpu->socket_id = topo.pkg_id;
|
||||
|
||||
if (cpu->die_id != -1 && cpu->die_id != topo.die_id) {
|
||||
error_setg(errp, "property die-id: %u doesn't match set apic-id:"
|
||||
" 0x%x (die-id: %u)", cpu->die_id, cpu->apic_id, topo.die_id);
|
||||
return;
|
||||
}
|
||||
cpu->die_id = topo.die_id;
|
||||
|
||||
if (cpu->core_id != -1 && cpu->core_id != topo.core_id) {
|
||||
error_setg(errp, "property core-id: %u doesn't match set apic-id:"
|
||||
" 0x%x (core-id: %u)", cpu->core_id, cpu->apic_id, topo.core_id);
|
||||
@ -2523,7 +2638,11 @@ pc_machine_get_device_memory_region_size(Object *obj, Visitor *v,
|
||||
Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
int64_t value = memory_region_size(&ms->device_memory->mr);
|
||||
int64_t value = 0;
|
||||
|
||||
if (ms->device_memory) {
|
||||
value = memory_region_size(&ms->device_memory->mr);
|
||||
}
|
||||
|
||||
visit_type_int(v, name, &value, errp);
|
||||
}
|
||||
@ -2680,11 +2799,12 @@ static void pc_machine_initfn(Object *obj)
|
||||
pcms->smbus_enabled = true;
|
||||
pcms->sata_enabled = true;
|
||||
pcms->pit_enabled = true;
|
||||
pcms->smp_dies = 1;
|
||||
|
||||
pc_system_flash_create(pcms);
|
||||
}
|
||||
|
||||
static void pc_machine_reset(void)
|
||||
static void pc_machine_reset(MachineState *machine)
|
||||
{
|
||||
CPUState *cs;
|
||||
X86CPU *cpu;
|
||||
@ -2716,10 +2836,12 @@ pc_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
|
||||
static int64_t pc_get_default_cpu_node_id(const MachineState *ms, int idx)
|
||||
{
|
||||
X86CPUTopoInfo topo;
|
||||
PCMachineState *pcms = PC_MACHINE(ms);
|
||||
|
||||
assert(idx < ms->possible_cpus->len);
|
||||
x86_topo_ids_from_apicid(ms->possible_cpus->cpus[idx].arch_id,
|
||||
smp_cores, smp_threads, &topo);
|
||||
pcms->smp_dies, ms->smp.cores,
|
||||
ms->smp.threads, &topo);
|
||||
return topo.pkg_id % nb_numa_nodes;
|
||||
}
|
||||
|
||||
@ -2727,6 +2849,7 @@ static const CPUArchIdList *pc_possible_cpu_arch_ids(MachineState *ms)
|
||||
{
|
||||
PCMachineState *pcms = PC_MACHINE(ms);
|
||||
int i;
|
||||
unsigned int max_cpus = ms->smp.max_cpus;
|
||||
|
||||
if (ms->possible_cpus) {
|
||||
/*
|
||||
@ -2747,9 +2870,12 @@ static const CPUArchIdList *pc_possible_cpu_arch_ids(MachineState *ms)
|
||||
ms->possible_cpus->cpus[i].vcpus_count = 1;
|
||||
ms->possible_cpus->cpus[i].arch_id = x86_cpu_apic_id_from_index(pcms, i);
|
||||
x86_topo_ids_from_apicid(ms->possible_cpus->cpus[i].arch_id,
|
||||
smp_cores, smp_threads, &topo);
|
||||
pcms->smp_dies, ms->smp.cores,
|
||||
ms->smp.threads, &topo);
|
||||
ms->possible_cpus->cpus[i].props.has_socket_id = true;
|
||||
ms->possible_cpus->cpus[i].props.socket_id = topo.pkg_id;
|
||||
ms->possible_cpus->cpus[i].props.has_die_id = true;
|
||||
ms->possible_cpus->cpus[i].props.die_id = topo.die_id;
|
||||
ms->possible_cpus->cpus[i].props.has_core_id = true;
|
||||
ms->possible_cpus->cpus[i].props.core_id = topo.core_id;
|
||||
ms->possible_cpus->cpus[i].props.has_thread_id = true;
|
||||
@ -2805,6 +2931,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
|
||||
mc->has_hotpluggable_cpus = true;
|
||||
mc->default_boot_order = "cad";
|
||||
mc->hot_add_cpu = pc_hot_add_cpu;
|
||||
mc->smp_parse = pc_smp_parse;
|
||||
mc->block_default_type = IF_IDE;
|
||||
mc->max_cpus = 255;
|
||||
mc->reset = pc_machine_reset;
|
||||
@ -2815,6 +2942,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
|
||||
nc->nmi_monitor_handler = x86_nmi;
|
||||
mc->default_cpu_type = TARGET_DEFAULT_CPU_TYPE;
|
||||
mc->nvdimm_supported = true;
|
||||
mc->numa_mem_supported = true;
|
||||
|
||||
object_class_property_add(oc, PC_MACHINE_DEVMEM_REGION_SIZE, "int",
|
||||
pc_machine_get_device_memory_region_size, NULL,
|
||||
|
@ -429,9 +429,11 @@ static void pc_i440fx_machine_options(MachineClass *m)
|
||||
|
||||
static void pc_i440fx_4_1_machine_options(MachineClass *m)
|
||||
{
|
||||
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
|
||||
pc_i440fx_machine_options(m);
|
||||
m->alias = "pc";
|
||||
m->is_default = 1;
|
||||
pcmc->default_cpu_version = 1;
|
||||
}
|
||||
|
||||
DEFINE_I440FX_MACHINE(v4_1, "pc-i440fx-4.1", NULL,
|
||||
@ -439,9 +441,11 @@ DEFINE_I440FX_MACHINE(v4_1, "pc-i440fx-4.1", NULL,
|
||||
|
||||
static void pc_i440fx_4_0_machine_options(MachineClass *m)
|
||||
{
|
||||
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
|
||||
pc_i440fx_4_1_machine_options(m);
|
||||
m->alias = NULL;
|
||||
m->is_default = 0;
|
||||
pcmc->default_cpu_version = CPU_VERSION_LEGACY;
|
||||
compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len);
|
||||
compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len);
|
||||
}
|
||||
|
@ -367,8 +367,10 @@ static void pc_q35_machine_options(MachineClass *m)
|
||||
|
||||
static void pc_q35_4_1_machine_options(MachineClass *m)
|
||||
{
|
||||
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
|
||||
pc_q35_machine_options(m);
|
||||
m->alias = "q35";
|
||||
pcmc->default_cpu_version = 1;
|
||||
}
|
||||
|
||||
DEFINE_Q35_MACHINE(v4_1, "pc-q35-4.1", NULL,
|
||||
@ -376,8 +378,10 @@ DEFINE_Q35_MACHINE(v4_1, "pc-q35-4.1", NULL,
|
||||
|
||||
static void pc_q35_4_0_1_machine_options(MachineClass *m)
|
||||
{
|
||||
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
|
||||
pc_q35_4_1_machine_options(m);
|
||||
m->alias = NULL;
|
||||
pcmc->default_cpu_version = CPU_VERSION_LEGACY;
|
||||
/*
|
||||
* This is the default machine for the 4.0-stable branch. It is basically
|
||||
* a 4.0 that doesn't use split irqchip by default. It MUST hence apply the
|
||||
|
@ -756,6 +756,8 @@ static ioreq_t *cpu_get_ioreq_from_shared_memory(XenIOState *state, int vcpu)
|
||||
/* retval--the number of ioreq packet */
|
||||
static ioreq_t *cpu_get_ioreq(XenIOState *state)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
unsigned int max_cpus = ms->smp.max_cpus;
|
||||
int i;
|
||||
evtchn_port_t port;
|
||||
|
||||
@ -1383,6 +1385,8 @@ static int xen_map_ioreq_server(XenIOState *state)
|
||||
|
||||
void xen_hvm_init(PCMachineState *pcms, MemoryRegion **ram_memory)
|
||||
{
|
||||
MachineState *ms = MACHINE(pcms);
|
||||
unsigned int max_cpus = ms->smp.max_cpus;
|
||||
int i, rc;
|
||||
xen_pfn_t ioreq_pfn;
|
||||
XenIOState *state;
|
||||
|
@ -458,7 +458,7 @@ static void boston_mach_init(MachineState *machine)
|
||||
sizeof(s->cps), TYPE_MIPS_CPS);
|
||||
object_property_set_str(OBJECT(&s->cps), machine->cpu_type, "cpu-type",
|
||||
&err);
|
||||
object_property_set_int(OBJECT(&s->cps), smp_cpus, "num-vp", &err);
|
||||
object_property_set_int(OBJECT(&s->cps), machine->smp.cpus, "num-vp", &err);
|
||||
object_property_set_bool(OBJECT(&s->cps), true, "realized", &err);
|
||||
|
||||
if (err != NULL) {
|
||||
|
@ -1095,6 +1095,8 @@ static int64_t load_kernel (void)
|
||||
|
||||
static void malta_mips_config(MIPSCPU *cpu)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
unsigned int smp_cpus = ms->smp.cpus;
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
CPUState *cs = CPU(cpu);
|
||||
|
||||
@ -1124,15 +1126,15 @@ static void main_cpu_reset(void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
static void create_cpu_without_cps(const char *cpu_type,
|
||||
static void create_cpu_without_cps(MachineState *ms,
|
||||
qemu_irq *cbus_irq, qemu_irq *i8259_irq)
|
||||
{
|
||||
CPUMIPSState *env;
|
||||
MIPSCPU *cpu;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < smp_cpus; i++) {
|
||||
cpu = MIPS_CPU(cpu_create(cpu_type));
|
||||
for (i = 0; i < ms->smp.cpus; i++) {
|
||||
cpu = MIPS_CPU(cpu_create(ms->cpu_type));
|
||||
|
||||
/* Init internal devices */
|
||||
cpu_mips_irq_init_cpu(cpu);
|
||||
@ -1146,15 +1148,15 @@ static void create_cpu_without_cps(const char *cpu_type,
|
||||
*cbus_irq = env->irq[4];
|
||||
}
|
||||
|
||||
static void create_cps(MaltaState *s, const char *cpu_type,
|
||||
static void create_cps(MachineState *ms, MaltaState *s,
|
||||
qemu_irq *cbus_irq, qemu_irq *i8259_irq)
|
||||
{
|
||||
Error *err = NULL;
|
||||
|
||||
sysbus_init_child_obj(OBJECT(s), "cps", OBJECT(&s->cps), sizeof(s->cps),
|
||||
TYPE_MIPS_CPS);
|
||||
object_property_set_str(OBJECT(&s->cps), cpu_type, "cpu-type", &err);
|
||||
object_property_set_int(OBJECT(&s->cps), smp_cpus, "num-vp", &err);
|
||||
object_property_set_str(OBJECT(&s->cps), ms->cpu_type, "cpu-type", &err);
|
||||
object_property_set_int(OBJECT(&s->cps), ms->smp.cpus, "num-vp", &err);
|
||||
object_property_set_bool(OBJECT(&s->cps), true, "realized", &err);
|
||||
if (err != NULL) {
|
||||
error_report("%s", error_get_pretty(err));
|
||||
@ -1167,13 +1169,13 @@ static void create_cps(MaltaState *s, const char *cpu_type,
|
||||
*cbus_irq = NULL;
|
||||
}
|
||||
|
||||
static void mips_create_cpu(MaltaState *s, const char *cpu_type,
|
||||
static void mips_create_cpu(MachineState *ms, MaltaState *s,
|
||||
qemu_irq *cbus_irq, qemu_irq *i8259_irq)
|
||||
{
|
||||
if ((smp_cpus > 1) && cpu_supports_cps_smp(cpu_type)) {
|
||||
create_cps(s, cpu_type, cbus_irq, i8259_irq);
|
||||
if ((ms->smp.cpus > 1) && cpu_supports_cps_smp(ms->cpu_type)) {
|
||||
create_cps(ms, s, cbus_irq, i8259_irq);
|
||||
} else {
|
||||
create_cpu_without_cps(cpu_type, cbus_irq, i8259_irq);
|
||||
create_cpu_without_cps(ms, cbus_irq, i8259_irq);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1217,7 +1219,7 @@ void mips_malta_init(MachineState *machine)
|
||||
qdev_init_nofail(dev);
|
||||
|
||||
/* create CPU */
|
||||
mips_create_cpu(s, machine->cpu_type, &cbus_irq, &i8259_irq);
|
||||
mips_create_cpu(machine, s, &cbus_irq, &i8259_irq);
|
||||
|
||||
/* allocate RAM */
|
||||
if (ram_size > 2 * GiB) {
|
||||
|
@ -130,6 +130,7 @@ static void openrisc_sim_init(MachineState *machine)
|
||||
qemu_irq *cpu_irqs[2];
|
||||
qemu_irq serial_irq;
|
||||
int n;
|
||||
unsigned int smp_cpus = machine->smp.cpus;
|
||||
|
||||
for (n = 0; n < smp_cpus; n++) {
|
||||
cpu = OPENRISC_CPU(cpu_create(machine->cpu_type));
|
||||
|
@ -308,6 +308,7 @@ static int ppce500_load_device_tree(PPCE500MachineState *pms,
|
||||
bool dry_run)
|
||||
{
|
||||
MachineState *machine = MACHINE(pms);
|
||||
unsigned int smp_cpus = machine->smp.cpus;
|
||||
const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(pms);
|
||||
CPUPPCState *env = first_cpu->env_ptr;
|
||||
int ret = -1;
|
||||
@ -735,6 +736,7 @@ static DeviceState *ppce500_init_mpic_qemu(PPCE500MachineState *pms,
|
||||
SysBusDevice *s;
|
||||
int i, j, k;
|
||||
MachineState *machine = MACHINE(pms);
|
||||
unsigned int smp_cpus = machine->smp.cpus;
|
||||
const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(pms);
|
||||
|
||||
dev = qdev_create(NULL, TYPE_OPENPIC);
|
||||
@ -847,6 +849,7 @@ void ppce500_init(MachineState *machine)
|
||||
struct boot_info *boot_info;
|
||||
int dt_size;
|
||||
int i;
|
||||
unsigned int smp_cpus = machine->smp.cpus;
|
||||
/* irq num for pin INTA, INTB, INTC and INTD is 1, 2, 3 and
|
||||
* 4 respectively */
|
||||
unsigned int pci_irq_nrs[PCI_NUM_PINS] = {1, 2, 3, 4};
|
||||
|
@ -136,6 +136,7 @@ static void ppc_core99_init(MachineState *machine)
|
||||
DeviceState *dev, *pic_dev;
|
||||
hwaddr nvram_addr = 0xFFF04000;
|
||||
uint64_t tbfreq;
|
||||
unsigned int smp_cpus = machine->smp.cpus;
|
||||
|
||||
linux_boot = (kernel_filename != NULL);
|
||||
|
||||
@ -463,7 +464,7 @@ static void ppc_core99_init(MachineState *machine)
|
||||
sysbus_mmio_map(s, 1, CFG_ADDR + 2);
|
||||
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)machine->smp.max_cpus);
|
||||
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, machine_arch);
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base);
|
||||
|
@ -101,6 +101,7 @@ static void ppc_heathrow_init(MachineState *machine)
|
||||
DeviceState *dev, *pic_dev;
|
||||
BusState *adb_bus;
|
||||
int bios_size;
|
||||
unsigned int smp_cpus = machine->smp.cpus;
|
||||
uint16_t ppc_boot_device;
|
||||
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
|
||||
void *fw_cfg;
|
||||
@ -324,7 +325,7 @@ static void ppc_heathrow_init(MachineState *machine)
|
||||
sysbus_mmio_map(s, 1, CFG_ADDR + 2);
|
||||
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)machine->smp.max_cpus);
|
||||
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, ARCH_HEATHROW);
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base);
|
||||
|
@ -529,9 +529,8 @@ static void pnv_powerdown_notify(Notifier *n, void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
static void pnv_reset(void)
|
||||
static void pnv_reset(MachineState *machine)
|
||||
{
|
||||
MachineState *machine = MACHINE(qdev_get_machine());
|
||||
PnvMachineState *pnv = PNV_MACHINE(machine);
|
||||
void *fdt;
|
||||
Object *obj;
|
||||
@ -689,7 +688,8 @@ static void pnv_init(MachineState *machine)
|
||||
object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal);
|
||||
object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id",
|
||||
&error_fatal);
|
||||
object_property_set_int(chip, smp_cores, "nr-cores", &error_fatal);
|
||||
object_property_set_int(chip, machine->smp.cores,
|
||||
"nr-cores", &error_fatal);
|
||||
object_property_set_bool(chip, true, "realized", &error_fatal);
|
||||
}
|
||||
g_free(chip_typename);
|
||||
@ -1150,6 +1150,7 @@ static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
|
||||
|
||||
static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
Error *error = NULL;
|
||||
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
|
||||
const char *typename = pnv_chip_core_typename(chip);
|
||||
@ -1183,7 +1184,7 @@ static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
|
||||
snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
|
||||
object_initialize_child(OBJECT(chip), core_name, pnv_core, typesize,
|
||||
typename, &error_fatal, NULL);
|
||||
object_property_set_int(OBJECT(pnv_core), smp_threads, "nr-threads",
|
||||
object_property_set_int(OBJECT(pnv_core), ms->smp.threads, "nr-threads",
|
||||
&error_fatal);
|
||||
object_property_set_int(OBJECT(pnv_core), core_hwid,
|
||||
CPU_CORE_PROP_CORE_ID, &error_fatal);
|
||||
|
@ -428,7 +428,7 @@ static void ppc_prep_init(MachineState *machine)
|
||||
linux_boot = (kernel_filename != NULL);
|
||||
|
||||
/* init CPUs */
|
||||
for (i = 0; i < smp_cpus; i++) {
|
||||
for (i = 0; i < machine->smp.cpus; i++) {
|
||||
cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
|
||||
env = &cpu->env;
|
||||
|
||||
@ -770,7 +770,7 @@ static void ibm_40p_init(MachineState *machine)
|
||||
boot_device = machine->boot_order[0];
|
||||
}
|
||||
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)machine->smp.max_cpus);
|
||||
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)machine->ram_size);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, ARCH_PREP);
|
||||
|
||||
|
@ -106,6 +106,9 @@
|
||||
*/
|
||||
static int spapr_vcpu_id(SpaprMachineState *spapr, int cpu_index)
|
||||
{
|
||||
MachineState *ms = MACHINE(spapr);
|
||||
unsigned int smp_threads = ms->smp.threads;
|
||||
|
||||
assert(spapr->vsmt);
|
||||
return
|
||||
(cpu_index / smp_threads) * spapr->vsmt + cpu_index % smp_threads;
|
||||
@ -153,8 +156,10 @@ static void pre_2_10_vmstate_unregister_dummy_icp(int i)
|
||||
|
||||
int spapr_max_server_number(SpaprMachineState *spapr)
|
||||
{
|
||||
MachineState *ms = MACHINE(spapr);
|
||||
|
||||
assert(spapr->vsmt);
|
||||
return DIV_ROUND_UP(max_cpus * spapr->vsmt, smp_threads);
|
||||
return DIV_ROUND_UP(ms->smp.max_cpus * spapr->vsmt, ms->smp.threads);
|
||||
}
|
||||
|
||||
static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu,
|
||||
@ -287,6 +292,7 @@ static void spapr_populate_pa_features(SpaprMachineState *spapr,
|
||||
|
||||
static int spapr_fixup_cpu_dt(void *fdt, SpaprMachineState *spapr)
|
||||
{
|
||||
MachineState *ms = MACHINE(spapr);
|
||||
int ret = 0, offset, cpus_offset;
|
||||
CPUState *cs;
|
||||
char cpu_model[32];
|
||||
@ -296,7 +302,7 @@ static int spapr_fixup_cpu_dt(void *fdt, SpaprMachineState *spapr)
|
||||
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
||||
DeviceClass *dc = DEVICE_GET_CLASS(cs);
|
||||
int index = spapr_get_vcpu_id(cpu);
|
||||
int compat_smt = MIN(smp_threads, ppc_compat_max_vthreads(cpu));
|
||||
int compat_smt = MIN(ms->smp.threads, ppc_compat_max_vthreads(cpu));
|
||||
|
||||
if (!spapr_is_thread0_in_vcore(spapr, cpu)) {
|
||||
continue;
|
||||
@ -442,6 +448,7 @@ static int spapr_populate_memory(SpaprMachineState *spapr, void *fdt)
|
||||
static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
|
||||
SpaprMachineState *spapr)
|
||||
{
|
||||
MachineState *ms = MACHINE(spapr);
|
||||
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
|
||||
@ -453,7 +460,8 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
|
||||
uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000;
|
||||
uint32_t page_sizes_prop[64];
|
||||
size_t page_sizes_prop_size;
|
||||
uint32_t vcpus_per_socket = smp_threads * smp_cores;
|
||||
unsigned int smp_threads = ms->smp.threads;
|
||||
uint32_t vcpus_per_socket = smp_threads * ms->smp.cores;
|
||||
uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
|
||||
int compat_smt = MIN(smp_threads, ppc_compat_max_vthreads(cpu));
|
||||
SpaprDrc *drc;
|
||||
@ -1026,6 +1034,7 @@ int spapr_h_cas_compose_response(SpaprMachineState *spapr,
|
||||
|
||||
static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt)
|
||||
{
|
||||
MachineState *ms = MACHINE(spapr);
|
||||
int rtas;
|
||||
GString *hypertas = g_string_sized_new(256);
|
||||
GString *qemu_hypertas = g_string_sized_new(256);
|
||||
@ -1036,7 +1045,7 @@ static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt)
|
||||
cpu_to_be32(max_device_addr >> 32),
|
||||
cpu_to_be32(max_device_addr & 0xffffffff),
|
||||
0, cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE),
|
||||
cpu_to_be32(max_cpus / smp_threads),
|
||||
cpu_to_be32(ms->smp.max_cpus / ms->smp.threads),
|
||||
};
|
||||
uint32_t maxdomain = cpu_to_be32(spapr->gpu_numa_id > 1 ? 1 : 0);
|
||||
uint32_t maxdomains[] = {
|
||||
@ -1691,9 +1700,8 @@ static int spapr_reset_drcs(Object *child, void *opaque)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void spapr_machine_reset(void)
|
||||
static void spapr_machine_reset(MachineState *machine)
|
||||
{
|
||||
MachineState *machine = MACHINE(qdev_get_machine());
|
||||
SpaprMachineState *spapr = SPAPR_MACHINE(machine);
|
||||
PowerPCCPU *first_ppc_cpu;
|
||||
uint32_t rtas_limit;
|
||||
@ -2544,7 +2552,7 @@ static void spapr_validate_node_memory(MachineState *machine, Error **errp)
|
||||
/* find cpu slot in machine->possible_cpus by core_id */
|
||||
static CPUArchId *spapr_find_cpu_slot(MachineState *ms, uint32_t id, int *idx)
|
||||
{
|
||||
int index = id / smp_threads;
|
||||
int index = id / ms->smp.threads;
|
||||
|
||||
if (index >= ms->possible_cpus->len) {
|
||||
return NULL;
|
||||
@ -2557,10 +2565,12 @@ static CPUArchId *spapr_find_cpu_slot(MachineState *ms, uint32_t id, int *idx)
|
||||
|
||||
static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(spapr);
|
||||
Error *local_err = NULL;
|
||||
bool vsmt_user = !!spapr->vsmt;
|
||||
int kvm_smt = kvmppc_smt_threads();
|
||||
int ret;
|
||||
unsigned int smp_threads = ms->smp.threads;
|
||||
|
||||
if (!kvm_enabled() && (smp_threads > 1)) {
|
||||
error_setg(&local_err, "TCG cannot support more than 1 thread/core "
|
||||
@ -2634,6 +2644,9 @@ static void spapr_init_cpus(SpaprMachineState *spapr)
|
||||
SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
|
||||
const char *type = spapr_get_cpu_core_type(machine->cpu_type);
|
||||
const CPUArchIdList *possible_cpus;
|
||||
unsigned int smp_cpus = machine->smp.cpus;
|
||||
unsigned int smp_threads = machine->smp.threads;
|
||||
unsigned int max_cpus = machine->smp.max_cpus;
|
||||
int boot_cores_nr = smp_cpus / smp_threads;
|
||||
int i;
|
||||
|
||||
@ -3860,6 +3873,7 @@ static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
const char *type = object_get_typename(OBJECT(dev));
|
||||
CPUArchId *core_slot;
|
||||
int index;
|
||||
unsigned int smp_threads = machine->smp.threads;
|
||||
|
||||
if (dev->hotplugged && !mc->has_hotpluggable_cpus) {
|
||||
error_setg(&local_err, "CPU hotplug not supported for this machine");
|
||||
@ -4125,14 +4139,16 @@ spapr_cpu_index_to_props(MachineState *machine, unsigned cpu_index)
|
||||
|
||||
static int64_t spapr_get_default_cpu_node_id(const MachineState *ms, int idx)
|
||||
{
|
||||
return idx / smp_cores % nb_numa_nodes;
|
||||
return idx / ms->smp.cores % nb_numa_nodes;
|
||||
}
|
||||
|
||||
static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine)
|
||||
{
|
||||
int i;
|
||||
unsigned int smp_threads = machine->smp.threads;
|
||||
unsigned int smp_cpus = machine->smp.cpus;
|
||||
const char *core_type;
|
||||
int spapr_max_cores = max_cpus / smp_threads;
|
||||
int spapr_max_cores = machine->smp.max_cpus / smp_threads;
|
||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||
|
||||
if (!mc->has_hotpluggable_cpus) {
|
||||
@ -4255,6 +4271,7 @@ int spapr_get_vcpu_id(PowerPCCPU *cpu)
|
||||
void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp)
|
||||
{
|
||||
SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
|
||||
MachineState *ms = MACHINE(spapr);
|
||||
int vcpu_id;
|
||||
|
||||
vcpu_id = spapr_vcpu_id(spapr, cpu_index);
|
||||
@ -4263,7 +4280,7 @@ void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp)
|
||||
error_setg(errp, "Can't create CPU with id %d in KVM", vcpu_id);
|
||||
error_append_hint(errp, "Adjust the number of cpus to %d "
|
||||
"or try to raise the number of threads per core\n",
|
||||
vcpu_id * smp_threads / spapr->vsmt);
|
||||
vcpu_id * ms->smp.threads / spapr->vsmt);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4350,6 +4367,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
|
||||
* in which LMBs are represented and hot-added
|
||||
*/
|
||||
mc->numa_mem_align_shift = 28;
|
||||
mc->numa_mem_supported = true;
|
||||
|
||||
smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
|
||||
smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON;
|
||||
|
@ -235,6 +235,8 @@ static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
|
||||
target_ulong args,
|
||||
uint32_t nret, target_ulong rets)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
unsigned int max_cpus = ms->smp.max_cpus;
|
||||
target_ulong parameter = rtas_ld(args, 0);
|
||||
target_ulong buffer = rtas_ld(args, 1);
|
||||
target_ulong length = rtas_ld(args, 2);
|
||||
@ -248,7 +250,7 @@ static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
|
||||
"MaxPlatProcs=%d",
|
||||
max_cpus,
|
||||
current_machine->ram_size / MiB,
|
||||
smp_cpus,
|
||||
ms->smp.cpus,
|
||||
max_cpus);
|
||||
ret = sysparm_st(buffer, length, param_val, strlen(param_val) + 1);
|
||||
g_free(param_val);
|
||||
|
@ -124,6 +124,7 @@ static void riscv_sifive_e_init(MachineState *machine)
|
||||
|
||||
static void riscv_sifive_e_soc_init(Object *obj)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
SiFiveESoCState *s = RISCV_E_SOC(obj);
|
||||
|
||||
object_initialize_child(obj, "cpus", &s->cpus,
|
||||
@ -131,7 +132,7 @@ static void riscv_sifive_e_soc_init(Object *obj)
|
||||
&error_abort, NULL);
|
||||
object_property_set_str(OBJECT(&s->cpus), SIFIVE_E_CPU, "cpu-type",
|
||||
&error_abort);
|
||||
object_property_set_int(OBJECT(&s->cpus), smp_cpus, "num-harts",
|
||||
object_property_set_int(OBJECT(&s->cpus), ms->smp.cpus, "num-harts",
|
||||
&error_abort);
|
||||
sysbus_init_child_obj(obj, "riscv.sifive.e.gpio0",
|
||||
&s->gpio, sizeof(s->gpio),
|
||||
@ -140,6 +141,7 @@ static void riscv_sifive_e_soc_init(Object *obj)
|
||||
|
||||
static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
const struct MemmapEntry *memmap = sifive_e_memmap;
|
||||
Error *err = NULL;
|
||||
|
||||
@ -168,7 +170,7 @@ static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp)
|
||||
SIFIVE_E_PLIC_CONTEXT_STRIDE,
|
||||
memmap[SIFIVE_E_PLIC].size);
|
||||
sifive_clint_create(memmap[SIFIVE_E_CLINT].base,
|
||||
memmap[SIFIVE_E_CLINT].size, smp_cpus,
|
||||
memmap[SIFIVE_E_CLINT].size, ms->smp.cpus,
|
||||
SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE);
|
||||
sifive_mmio_emulate(sys_mem, "riscv.sifive.e.aon",
|
||||
memmap[SIFIVE_E_AON].base, memmap[SIFIVE_E_AON].size);
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/pci/msi.h"
|
||||
#include "hw/boards.h"
|
||||
#include "target/riscv/cpu.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/riscv/sifive_plic.h"
|
||||
@ -439,6 +440,8 @@ static void sifive_plic_irq_request(void *opaque, int irq, int level)
|
||||
|
||||
static void sifive_plic_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
unsigned int smp_cpus = ms->smp.cpus;
|
||||
SiFivePLICState *plic = SIFIVE_PLIC(dev);
|
||||
int i;
|
||||
|
||||
|
@ -315,13 +315,14 @@ static void riscv_sifive_u_init(MachineState *machine)
|
||||
|
||||
static void riscv_sifive_u_soc_init(Object *obj)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
SiFiveUSoCState *s = RISCV_U_SOC(obj);
|
||||
|
||||
object_initialize_child(obj, "cpus", &s->cpus, sizeof(s->cpus),
|
||||
TYPE_RISCV_HART_ARRAY, &error_abort, NULL);
|
||||
object_property_set_str(OBJECT(&s->cpus), SIFIVE_U_CPU, "cpu-type",
|
||||
&error_abort);
|
||||
object_property_set_int(OBJECT(&s->cpus), smp_cpus, "num-harts",
|
||||
object_property_set_int(OBJECT(&s->cpus), ms->smp.cpus, "num-harts",
|
||||
&error_abort);
|
||||
|
||||
sysbus_init_child_obj(obj, "gem", &s->gem, sizeof(s->gem),
|
||||
@ -330,6 +331,7 @@ static void riscv_sifive_u_soc_init(Object *obj)
|
||||
|
||||
static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
SiFiveUSoCState *s = RISCV_U_SOC(dev);
|
||||
const struct MemmapEntry *memmap = sifive_u_memmap;
|
||||
MemoryRegion *system_memory = get_system_memory();
|
||||
@ -351,9 +353,10 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp)
|
||||
mask_rom);
|
||||
|
||||
/* create PLIC hart topology configuration string */
|
||||
plic_hart_config_len = (strlen(SIFIVE_U_PLIC_HART_CONFIG) + 1) * smp_cpus;
|
||||
plic_hart_config_len = (strlen(SIFIVE_U_PLIC_HART_CONFIG) + 1) *
|
||||
ms->smp.cpus;
|
||||
plic_hart_config = g_malloc0(plic_hart_config_len);
|
||||
for (i = 0; i < smp_cpus; i++) {
|
||||
for (i = 0; i < ms->smp.cpus; i++) {
|
||||
if (i != 0) {
|
||||
strncat(plic_hart_config, ",", plic_hart_config_len);
|
||||
}
|
||||
@ -379,7 +382,7 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp)
|
||||
sifive_uart_create(system_memory, memmap[SIFIVE_U_UART1].base,
|
||||
serial_hd(1), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_UART1_IRQ));
|
||||
sifive_clint_create(memmap[SIFIVE_U_CLINT].base,
|
||||
memmap[SIFIVE_U_CLINT].size, smp_cpus,
|
||||
memmap[SIFIVE_U_CLINT].size, ms->smp.cpus,
|
||||
SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE);
|
||||
|
||||
for (i = 0; i < SIFIVE_U_PLIC_NUM_SOURCES; i++) {
|
||||
|
@ -159,6 +159,7 @@ static void spike_board_init(MachineState *machine)
|
||||
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
|
||||
int i;
|
||||
unsigned int smp_cpus = machine->smp.cpus;
|
||||
|
||||
/* Initialize SOC */
|
||||
object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc),
|
||||
@ -241,6 +242,7 @@ static void spike_v1_10_0_board_init(MachineState *machine)
|
||||
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
|
||||
int i;
|
||||
unsigned int smp_cpus = machine->smp.cpus;
|
||||
|
||||
if (!qtest_enabled()) {
|
||||
info_report("The Spike v1.10.0 machine has been deprecated. "
|
||||
@ -329,6 +331,7 @@ static void spike_v1_09_1_board_init(MachineState *machine)
|
||||
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
|
||||
int i;
|
||||
unsigned int smp_cpus = machine->smp.cpus;
|
||||
|
||||
if (!qtest_enabled()) {
|
||||
info_report("The Spike v1.09.1 machine has been deprecated. "
|
||||
|
@ -371,6 +371,7 @@ static void riscv_virt_board_init(MachineState *machine)
|
||||
char *plic_hart_config;
|
||||
size_t plic_hart_config_len;
|
||||
int i;
|
||||
unsigned int smp_cpus = machine->smp.cpus;
|
||||
void *fdt;
|
||||
|
||||
/* Initialize SOC */
|
||||
|
@ -84,7 +84,7 @@ static void s390_init_cpus(MachineState *machine)
|
||||
/* initialize possible_cpus */
|
||||
mc->possible_cpu_arch_ids(machine);
|
||||
|
||||
for (i = 0; i < smp_cpus; i++) {
|
||||
for (i = 0; i < machine->smp.cpus; i++) {
|
||||
s390x_new_cpu(machine->cpu_type, i, &error_fatal);
|
||||
}
|
||||
}
|
||||
@ -339,7 +339,7 @@ static inline void s390_do_cpu_ipl(CPUState *cs, run_on_cpu_data arg)
|
||||
s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu);
|
||||
}
|
||||
|
||||
static void s390_machine_reset(void)
|
||||
static void s390_machine_reset(MachineState *machine)
|
||||
{
|
||||
enum s390_reset reset_type;
|
||||
CPUState *cs, *t;
|
||||
@ -411,6 +411,7 @@ static CpuInstanceProperties s390_cpu_index_to_props(MachineState *ms,
|
||||
static const CPUArchIdList *s390_possible_cpu_arch_ids(MachineState *ms)
|
||||
{
|
||||
int i;
|
||||
unsigned int max_cpus = ms->smp.max_cpus;
|
||||
|
||||
if (ms->possible_cpus) {
|
||||
g_assert(ms->possible_cpus && ms->possible_cpus->len == max_cpus);
|
||||
@ -440,9 +441,9 @@ static HotplugHandler *s390_get_hotplug_handler(MachineState *machine,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void s390_hot_add_cpu(const int64_t id, Error **errp)
|
||||
static void s390_hot_add_cpu(MachineState *machine,
|
||||
const int64_t id, Error **errp)
|
||||
{
|
||||
MachineState *machine = MACHINE(qdev_get_machine());
|
||||
ObjectClass *oc;
|
||||
|
||||
g_assert(machine->possible_cpus->cpus[0].cpu);
|
||||
|
@ -64,7 +64,7 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
|
||||
prepare_cpu_entries(sclp, read_info->entries, &cpu_count);
|
||||
read_info->entries_cpu = cpu_to_be16(cpu_count);
|
||||
read_info->offset_cpu = cpu_to_be16(offsetof(ReadInfo, entries));
|
||||
read_info->highest_cpu = cpu_to_be16(max_cpus - 1);
|
||||
read_info->highest_cpu = cpu_to_be16(machine->smp.max_cpus - 1);
|
||||
|
||||
read_info->ibc_val = cpu_to_be32(s390_get_ibc_val());
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "sysemu/cpus.h"
|
||||
#include "hw/firmware/smbios.h"
|
||||
#include "hw/loader.h"
|
||||
#include "hw/boards.h"
|
||||
#include "exec/cpu-common.h"
|
||||
#include "smbios_build.h"
|
||||
|
||||
@ -341,9 +342,10 @@ static void smbios_register_config(void)
|
||||
|
||||
opts_init(smbios_register_config);
|
||||
|
||||
static void smbios_validate_table(void)
|
||||
static void smbios_validate_table(MachineState *ms)
|
||||
{
|
||||
uint32_t expect_t4_count = smbios_legacy ? smp_cpus : smbios_smp_sockets;
|
||||
uint32_t expect_t4_count = smbios_legacy ?
|
||||
ms->smp.cpus : smbios_smp_sockets;
|
||||
|
||||
if (smbios_type4_count && smbios_type4_count != expect_t4_count) {
|
||||
error_report("Expected %d SMBIOS Type 4 tables, got %d instead",
|
||||
@ -428,7 +430,7 @@ static void smbios_build_type_1_fields(void)
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *smbios_get_table_legacy(size_t *length)
|
||||
uint8_t *smbios_get_table_legacy(MachineState *ms, size_t *length)
|
||||
{
|
||||
if (!smbios_legacy) {
|
||||
*length = 0;
|
||||
@ -438,7 +440,7 @@ uint8_t *smbios_get_table_legacy(size_t *length)
|
||||
if (!smbios_immutable) {
|
||||
smbios_build_type_0_fields();
|
||||
smbios_build_type_1_fields();
|
||||
smbios_validate_table();
|
||||
smbios_validate_table(ms);
|
||||
smbios_immutable = true;
|
||||
}
|
||||
*length = smbios_entries_len;
|
||||
@ -570,7 +572,7 @@ static void smbios_build_type_3_table(void)
|
||||
SMBIOS_BUILD_TABLE_POST;
|
||||
}
|
||||
|
||||
static void smbios_build_type_4_table(unsigned instance)
|
||||
static void smbios_build_type_4_table(MachineState *ms, unsigned instance)
|
||||
{
|
||||
char sock_str[128];
|
||||
|
||||
@ -597,8 +599,8 @@ static void smbios_build_type_4_table(unsigned instance)
|
||||
SMBIOS_TABLE_SET_STR(4, serial_number_str, type4.serial);
|
||||
SMBIOS_TABLE_SET_STR(4, asset_tag_number_str, type4.asset);
|
||||
SMBIOS_TABLE_SET_STR(4, part_number_str, type4.part);
|
||||
t->core_count = t->core_enabled = smp_cores;
|
||||
t->thread_count = smp_threads;
|
||||
t->core_count = t->core_enabled = ms->smp.cores;
|
||||
t->thread_count = ms->smp.threads;
|
||||
t->processor_characteristics = cpu_to_le16(0x02); /* Unknown */
|
||||
t->processor_family2 = cpu_to_le16(0x01); /* Other */
|
||||
|
||||
@ -839,7 +841,8 @@ static void smbios_entry_point_setup(void)
|
||||
}
|
||||
}
|
||||
|
||||
void smbios_get_tables(const struct smbios_phys_mem_area *mem_array,
|
||||
void smbios_get_tables(MachineState *ms,
|
||||
const struct smbios_phys_mem_area *mem_array,
|
||||
const unsigned int mem_array_size,
|
||||
uint8_t **tables, size_t *tables_len,
|
||||
uint8_t **anchor, size_t *anchor_len)
|
||||
@ -858,11 +861,12 @@ void smbios_get_tables(const struct smbios_phys_mem_area *mem_array,
|
||||
smbios_build_type_2_table();
|
||||
smbios_build_type_3_table();
|
||||
|
||||
smbios_smp_sockets = DIV_ROUND_UP(smp_cpus, smp_cores * smp_threads);
|
||||
smbios_smp_sockets = DIV_ROUND_UP(ms->smp.cpus,
|
||||
ms->smp.cores * ms->smp.threads);
|
||||
assert(smbios_smp_sockets >= 1);
|
||||
|
||||
for (i = 0; i < smbios_smp_sockets; i++) {
|
||||
smbios_build_type_4_table(i);
|
||||
smbios_build_type_4_table(ms, i);
|
||||
}
|
||||
|
||||
smbios_build_type_11_table();
|
||||
@ -888,7 +892,7 @@ void smbios_get_tables(const struct smbios_phys_mem_area *mem_array,
|
||||
smbios_build_type_38_table();
|
||||
smbios_build_type_127_table();
|
||||
|
||||
smbios_validate_table();
|
||||
smbios_validate_table(ms);
|
||||
smbios_entry_point_setup();
|
||||
smbios_immutable = true;
|
||||
}
|
||||
|
@ -871,6 +871,8 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef,
|
||||
FWCfgState *fw_cfg;
|
||||
DeviceState *dev;
|
||||
SysBusDevice *s;
|
||||
unsigned int smp_cpus = machine->smp.cpus;
|
||||
unsigned int max_cpus = machine->smp.max_cpus;
|
||||
|
||||
/* init CPUs */
|
||||
for(i = 0; i < smp_cpus; i++) {
|
||||
|
@ -697,8 +697,8 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
|
||||
&FW_CFG_IO(dev)->comb_iomem);
|
||||
|
||||
fw_cfg = FW_CFG(dev);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)machine->smp.cpus);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)machine->smp.max_cpus);
|
||||
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
|
||||
fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
|
||||
fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_entry);
|
||||
|
@ -59,7 +59,7 @@ static void xtensa_sim_init(MachineState *machine)
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
int n;
|
||||
|
||||
for (n = 0; n < smp_cpus; n++) {
|
||||
for (n = 0; n < machine->smp.cpus; n++) {
|
||||
cpu = XTENSA_CPU(cpu_create(machine->cpu_type));
|
||||
env = &cpu->env;
|
||||
|
||||
|
@ -238,6 +238,7 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine)
|
||||
const unsigned system_io_size = 224 * MiB;
|
||||
uint32_t freq = 10000000;
|
||||
int n;
|
||||
unsigned int smp_cpus = machine->smp.cpus;
|
||||
|
||||
if (smp_cpus > 1) {
|
||||
mx_pic = xtensa_mx_pic_init(31);
|
||||
|
@ -160,6 +160,12 @@ typedef struct {
|
||||
* @kvm_type:
|
||||
* Return the type of KVM corresponding to the kvm-type string option or
|
||||
* computed based on other criteria such as the host kernel capabilities.
|
||||
* @numa_mem_supported:
|
||||
* true if '--numa node.mem' option is supported and false otherwise
|
||||
* @smp_parse:
|
||||
* The function pointer to hook different machine specific functions for
|
||||
* parsing "smp-opts" from QemuOpts to MachineState::CpuTopology and more
|
||||
* machine specific topology fields, such as smp_dies for PCMachine.
|
||||
*/
|
||||
struct MachineClass {
|
||||
/*< private >*/
|
||||
@ -173,9 +179,10 @@ struct MachineClass {
|
||||
const char *deprecation_reason;
|
||||
|
||||
void (*init)(MachineState *state);
|
||||
void (*reset)(void);
|
||||
void (*hot_add_cpu)(const int64_t id, Error **errp);
|
||||
void (*reset)(MachineState *state);
|
||||
void (*hot_add_cpu)(MachineState *state, const int64_t id, Error **errp);
|
||||
int (*kvm_type)(MachineState *machine, const char *arg);
|
||||
void (*smp_parse)(MachineState *ms, QemuOpts *opts);
|
||||
|
||||
BlockInterfaceType block_default_type;
|
||||
int units_per_default_bus;
|
||||
@ -212,6 +219,7 @@ struct MachineClass {
|
||||
bool ignore_boot_device_suffixes;
|
||||
bool smbus_no_migration_support;
|
||||
bool nvdimm_supported;
|
||||
bool numa_mem_supported;
|
||||
|
||||
HotplugHandler *(*get_hotplug_handler)(MachineState *machine,
|
||||
DeviceState *dev);
|
||||
@ -232,6 +240,20 @@ typedef struct DeviceMemoryState {
|
||||
MemoryRegion mr;
|
||||
} DeviceMemoryState;
|
||||
|
||||
/**
|
||||
* CpuTopology:
|
||||
* @cpus: the number of present logical processors on the machine
|
||||
* @cores: the number of cores in one package
|
||||
* @threads: the number of threads in one core
|
||||
* @max_cpus: the maximum number of logical processors on the machine
|
||||
*/
|
||||
typedef struct CpuTopology {
|
||||
unsigned int cpus;
|
||||
unsigned int cores;
|
||||
unsigned int threads;
|
||||
unsigned int max_cpus;
|
||||
} CpuTopology;
|
||||
|
||||
/**
|
||||
* MachineState:
|
||||
*/
|
||||
@ -274,6 +296,7 @@ struct MachineState {
|
||||
const char *cpu_type;
|
||||
AccelState *accelerator;
|
||||
CPUArchIdList *possible_cpus;
|
||||
CpuTopology smp;
|
||||
struct NVDIMMState *nvdimms_state;
|
||||
};
|
||||
|
||||
|
@ -268,8 +268,9 @@ void smbios_set_cpuid(uint32_t version, uint32_t features);
|
||||
void smbios_set_defaults(const char *manufacturer, const char *product,
|
||||
const char *version, bool legacy_mode,
|
||||
bool uuid_encoded, SmbiosEntryPointType ep_type);
|
||||
uint8_t *smbios_get_table_legacy(size_t *length);
|
||||
void smbios_get_tables(const struct smbios_phys_mem_area *mem_array,
|
||||
uint8_t *smbios_get_table_legacy(MachineState *ms, size_t *length);
|
||||
void smbios_get_tables(MachineState *ms,
|
||||
const struct smbios_phys_mem_area *mem_array,
|
||||
const unsigned int mem_array_size,
|
||||
uint8_t **tables, size_t *tables_len,
|
||||
uint8_t **anchor, size_t *anchor_len);
|
||||
|
@ -24,6 +24,7 @@
|
||||
* PCMachineState:
|
||||
* @acpi_dev: link to ACPI PM device that performs ACPI hotplug handling
|
||||
* @boot_cpus: number of present VCPUs
|
||||
* @smp_dies: number of dies per one package
|
||||
*/
|
||||
struct PCMachineState {
|
||||
/*< private >*/
|
||||
@ -59,6 +60,7 @@ struct PCMachineState {
|
||||
bool apic_xrupt_override;
|
||||
unsigned apic_id_limit;
|
||||
uint16_t boot_cpus;
|
||||
unsigned smp_dies;
|
||||
|
||||
/* NUMA information: */
|
||||
uint64_t numa_nodes;
|
||||
@ -107,6 +109,9 @@ typedef struct PCMachineClass {
|
||||
|
||||
/* Compat options: */
|
||||
|
||||
/* Default CPU model version. See x86_cpu_set_default_version(). */
|
||||
int default_cpu_version;
|
||||
|
||||
/* ACPI compat: */
|
||||
bool has_acpi_build;
|
||||
bool rsdp_in_ram;
|
||||
@ -189,7 +194,8 @@ void pc_register_ferr_irq(qemu_irq irq);
|
||||
void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
|
||||
|
||||
void pc_cpus_init(PCMachineState *pcms);
|
||||
void pc_hot_add_cpu(const int64_t id, Error **errp);
|
||||
void pc_hot_add_cpu(MachineState *ms, const int64_t id, Error **errp);
|
||||
void pc_smp_parse(MachineState *ms, QemuOpts *opts);
|
||||
|
||||
void pc_guest_info_init(PCMachineState *pcms);
|
||||
|
||||
|
@ -47,6 +47,7 @@ typedef uint32_t apic_id_t;
|
||||
|
||||
typedef struct X86CPUTopoInfo {
|
||||
unsigned pkg_id;
|
||||
unsigned die_id;
|
||||
unsigned core_id;
|
||||
unsigned smt_id;
|
||||
} X86CPUTopoInfo;
|
||||
@ -62,87 +63,120 @@ static unsigned apicid_bitwidth_for_count(unsigned count)
|
||||
|
||||
/* Bit width of the SMT_ID (thread ID) field on the APIC ID
|
||||
*/
|
||||
static inline unsigned apicid_smt_width(unsigned nr_cores, unsigned nr_threads)
|
||||
static inline unsigned apicid_smt_width(unsigned nr_dies,
|
||||
unsigned nr_cores,
|
||||
unsigned nr_threads)
|
||||
{
|
||||
return apicid_bitwidth_for_count(nr_threads);
|
||||
}
|
||||
|
||||
/* Bit width of the Core_ID field
|
||||
*/
|
||||
static inline unsigned apicid_core_width(unsigned nr_cores, unsigned nr_threads)
|
||||
static inline unsigned apicid_core_width(unsigned nr_dies,
|
||||
unsigned nr_cores,
|
||||
unsigned nr_threads)
|
||||
{
|
||||
return apicid_bitwidth_for_count(nr_cores);
|
||||
}
|
||||
|
||||
/* Bit width of the Die_ID field */
|
||||
static inline unsigned apicid_die_width(unsigned nr_dies,
|
||||
unsigned nr_cores,
|
||||
unsigned nr_threads)
|
||||
{
|
||||
return apicid_bitwidth_for_count(nr_dies);
|
||||
}
|
||||
|
||||
/* Bit offset of the Core_ID field
|
||||
*/
|
||||
static inline unsigned apicid_core_offset(unsigned nr_cores,
|
||||
static inline unsigned apicid_core_offset(unsigned nr_dies,
|
||||
unsigned nr_cores,
|
||||
unsigned nr_threads)
|
||||
{
|
||||
return apicid_smt_width(nr_cores, nr_threads);
|
||||
return apicid_smt_width(nr_dies, nr_cores, nr_threads);
|
||||
}
|
||||
|
||||
/* Bit offset of the Die_ID field */
|
||||
static inline unsigned apicid_die_offset(unsigned nr_dies,
|
||||
unsigned nr_cores,
|
||||
unsigned nr_threads)
|
||||
{
|
||||
return apicid_core_offset(nr_dies, nr_cores, nr_threads) +
|
||||
apicid_core_width(nr_dies, nr_cores, nr_threads);
|
||||
}
|
||||
|
||||
/* Bit offset of the Pkg_ID (socket ID) field
|
||||
*/
|
||||
static inline unsigned apicid_pkg_offset(unsigned nr_cores, unsigned nr_threads)
|
||||
static inline unsigned apicid_pkg_offset(unsigned nr_dies,
|
||||
unsigned nr_cores,
|
||||
unsigned nr_threads)
|
||||
{
|
||||
return apicid_core_offset(nr_cores, nr_threads) +
|
||||
apicid_core_width(nr_cores, nr_threads);
|
||||
return apicid_die_offset(nr_dies, nr_cores, nr_threads) +
|
||||
apicid_die_width(nr_dies, nr_cores, nr_threads);
|
||||
}
|
||||
|
||||
/* Make APIC ID for the CPU based on Pkg_ID, Core_ID, SMT_ID
|
||||
*
|
||||
* The caller must make sure core_id < nr_cores and smt_id < nr_threads.
|
||||
*/
|
||||
static inline apic_id_t apicid_from_topo_ids(unsigned nr_cores,
|
||||
static inline apic_id_t apicid_from_topo_ids(unsigned nr_dies,
|
||||
unsigned nr_cores,
|
||||
unsigned nr_threads,
|
||||
const X86CPUTopoInfo *topo)
|
||||
{
|
||||
return (topo->pkg_id << apicid_pkg_offset(nr_cores, nr_threads)) |
|
||||
(topo->core_id << apicid_core_offset(nr_cores, nr_threads)) |
|
||||
return (topo->pkg_id << apicid_pkg_offset(nr_dies, nr_cores, nr_threads)) |
|
||||
(topo->die_id << apicid_die_offset(nr_dies, nr_cores, nr_threads)) |
|
||||
(topo->core_id << apicid_core_offset(nr_dies, nr_cores, nr_threads)) |
|
||||
topo->smt_id;
|
||||
}
|
||||
|
||||
/* Calculate thread/core/package IDs for a specific topology,
|
||||
* based on (contiguous) CPU index
|
||||
*/
|
||||
static inline void x86_topo_ids_from_idx(unsigned nr_cores,
|
||||
static inline void x86_topo_ids_from_idx(unsigned nr_dies,
|
||||
unsigned nr_cores,
|
||||
unsigned nr_threads,
|
||||
unsigned cpu_index,
|
||||
X86CPUTopoInfo *topo)
|
||||
{
|
||||
unsigned core_index = cpu_index / nr_threads;
|
||||
topo->pkg_id = cpu_index / (nr_dies * nr_cores * nr_threads);
|
||||
topo->die_id = cpu_index / (nr_cores * nr_threads) % nr_dies;
|
||||
topo->core_id = cpu_index / nr_threads % nr_cores;
|
||||
topo->smt_id = cpu_index % nr_threads;
|
||||
topo->core_id = core_index % nr_cores;
|
||||
topo->pkg_id = core_index / nr_cores;
|
||||
}
|
||||
|
||||
/* Calculate thread/core/package IDs for a specific topology,
|
||||
* based on APIC ID
|
||||
*/
|
||||
static inline void x86_topo_ids_from_apicid(apic_id_t apicid,
|
||||
unsigned nr_dies,
|
||||
unsigned nr_cores,
|
||||
unsigned nr_threads,
|
||||
X86CPUTopoInfo *topo)
|
||||
{
|
||||
topo->smt_id = apicid &
|
||||
~(0xFFFFFFFFUL << apicid_smt_width(nr_cores, nr_threads));
|
||||
topo->core_id = (apicid >> apicid_core_offset(nr_cores, nr_threads)) &
|
||||
~(0xFFFFFFFFUL << apicid_core_width(nr_cores, nr_threads));
|
||||
topo->pkg_id = apicid >> apicid_pkg_offset(nr_cores, nr_threads);
|
||||
~(0xFFFFFFFFUL << apicid_smt_width(nr_dies, nr_cores, nr_threads));
|
||||
topo->core_id =
|
||||
(apicid >> apicid_core_offset(nr_dies, nr_cores, nr_threads)) &
|
||||
~(0xFFFFFFFFUL << apicid_core_width(nr_dies, nr_cores, nr_threads));
|
||||
topo->die_id =
|
||||
(apicid >> apicid_die_offset(nr_dies, nr_cores, nr_threads)) &
|
||||
~(0xFFFFFFFFUL << apicid_die_width(nr_dies, nr_cores, nr_threads));
|
||||
topo->pkg_id = apicid >> apicid_pkg_offset(nr_dies, nr_cores, nr_threads);
|
||||
}
|
||||
|
||||
/* Make APIC ID for the CPU 'cpu_index'
|
||||
*
|
||||
* 'cpu_index' is a sequential, contiguous ID for the CPU.
|
||||
*/
|
||||
static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_cores,
|
||||
static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_dies,
|
||||
unsigned nr_cores,
|
||||
unsigned nr_threads,
|
||||
unsigned cpu_index)
|
||||
{
|
||||
X86CPUTopoInfo topo;
|
||||
x86_topo_ids_from_idx(nr_cores, nr_threads, cpu_index, &topo);
|
||||
return apicid_from_topo_ids(nr_cores, nr_threads, &topo);
|
||||
x86_topo_ids_from_idx(nr_dies, nr_cores, nr_threads, cpu_index, &topo);
|
||||
return apicid_from_topo_ids(nr_dies, nr_cores, nr_threads, &topo);
|
||||
}
|
||||
|
||||
#endif /* HW_I386_TOPOLOGY_H */
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "sysemu/balloon.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "trace.h"
|
||||
#include "hw/boards.h"
|
||||
|
||||
/* Arbitrary limit on size of each discard command,
|
||||
* keeps them around ~200 bytes
|
||||
@ -128,6 +129,8 @@ static void migration_exit_cb(Notifier *n, void *data)
|
||||
|
||||
static struct PostcopyBlocktimeContext *blocktime_context_new(void)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
unsigned int smp_cpus = ms->smp.cpus;
|
||||
PostcopyBlocktimeContext *ctx = g_new0(PostcopyBlocktimeContext, 1);
|
||||
ctx->page_fault_vcpu_time = g_new0(uint32_t, smp_cpus);
|
||||
ctx->vcpu_addr = g_new0(uintptr_t, smp_cpus);
|
||||
@ -141,10 +144,11 @@ static struct PostcopyBlocktimeContext *blocktime_context_new(void)
|
||||
|
||||
static uint32List *get_vcpu_blocktime_list(PostcopyBlocktimeContext *ctx)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
uint32List *list = NULL, *entry = NULL;
|
||||
int i;
|
||||
|
||||
for (i = smp_cpus - 1; i >= 0; i--) {
|
||||
for (i = ms->smp.cpus - 1; i >= 0; i--) {
|
||||
entry = g_new0(uint32List, 1);
|
||||
entry->value = ctx->vcpu_blocktime[i];
|
||||
entry->next = list;
|
||||
@ -807,6 +811,8 @@ static void mark_postcopy_blocktime_end(uintptr_t addr)
|
||||
{
|
||||
MigrationIncomingState *mis = migration_incoming_get_current();
|
||||
PostcopyBlocktimeContext *dc = mis->blocktime_ctx;
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
unsigned int smp_cpus = ms->smp.cpus;
|
||||
int i, affected_cpu = 0;
|
||||
bool vcpu_total_blocktime = false;
|
||||
uint32_t read_vcpu_time, low_time_offset;
|
||||
|
@ -279,6 +279,12 @@
|
||||
# to introspect properties configurable using -cpu or -global.
|
||||
# (since 2.9)
|
||||
#
|
||||
# @alias-of: Name of CPU model this model is an alias for. The target of the
|
||||
# CPU model alias may change depending on the machine type.
|
||||
# Management software is supposed to translate CPU model aliases
|
||||
# in the VM configuration, because aliases may stop being
|
||||
# migration-safe in the future (since 4.1)
|
||||
#
|
||||
# @unavailable-features is a list of QOM property names that
|
||||
# represent CPU model attributes that prevent the CPU from running.
|
||||
# If the QOM property is read-only, that means there's no known
|
||||
@ -302,7 +308,8 @@
|
||||
'*migration-safe': 'bool',
|
||||
'static': 'bool',
|
||||
'*unavailable-features': [ 'str' ],
|
||||
'typename': 'str' },
|
||||
'typename': 'str',
|
||||
'*alias-of' : 'str' },
|
||||
'if': 'defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_I386) || defined(TARGET_S390X) || defined(TARGET_MIPS)' }
|
||||
|
||||
##
|
||||
|
@ -318,12 +318,20 @@
|
||||
#
|
||||
# @hotpluggable-cpus: cpu hotplug via -device is supported (since 2.7.0)
|
||||
#
|
||||
# @numa-mem-supported: true if '-numa node,mem' option is supported by
|
||||
# the machine type and false otherwise (since 4.1)
|
||||
#
|
||||
# @deprecated: if true, the machine type is deprecated and may be removed
|
||||
# in future versions of QEMU according to the QEMU deprecation
|
||||
# policy (since 4.1.0)
|
||||
#
|
||||
# Since: 1.2.0
|
||||
##
|
||||
{ 'struct': 'MachineInfo',
|
||||
'data': { 'name': 'str', '*alias': 'str',
|
||||
'*is-default': 'bool', 'cpu-max': 'int',
|
||||
'hotpluggable-cpus': 'bool'} }
|
||||
'hotpluggable-cpus': 'bool', 'numa-mem-supported': 'bool',
|
||||
'deprecated': 'bool' } }
|
||||
|
||||
##
|
||||
# @query-machines:
|
||||
@ -588,10 +596,10 @@
|
||||
#
|
||||
# @node-id: NUMA node ID the CPU belongs to
|
||||
# @socket-id: socket number within node/board the CPU belongs to
|
||||
# @core-id: core number within socket the CPU belongs to
|
||||
# @thread-id: thread number within core the CPU belongs to
|
||||
# @die-id: die number within node/board 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
|
||||
#
|
||||
# Note: currently there are 4 properties that could be present
|
||||
# Note: currently there are 5 properties that could be present
|
||||
# but management should be prepared to pass through other
|
||||
# properties with device_add command to allow for future
|
||||
# interface extension. This also requires the filed names to be kept in
|
||||
@ -602,6 +610,7 @@
|
||||
{ 'struct': 'CpuInstanceProperties',
|
||||
'data': { '*node-id': 'int',
|
||||
'*socket-id': 'int',
|
||||
'*die-id': 'int',
|
||||
'*core-id': 'int',
|
||||
'*thread-id': 'int'
|
||||
}
|
||||
|
@ -88,6 +88,39 @@ The @code{-realtime mlock=on|off} argument has been replaced by the
|
||||
The ``-virtfs_synth'' argument is now deprecated. Please use ``-fsdev synth''
|
||||
and ``-device virtio-9p-...'' instead.
|
||||
|
||||
@subsection -numa node,mem=@var{size} (since 4.1)
|
||||
|
||||
The parameter @option{mem} of @option{-numa node} is used to assign a part of
|
||||
guest RAM to a NUMA node. But when using it, it's impossible to manage specified
|
||||
RAM chunk on the host side (like bind it to a host node, setting bind policy, ...),
|
||||
so guest end-ups with the fake NUMA configuration with suboptiomal performance.
|
||||
However since 2014 there is an alternative way to assign RAM to a NUMA node
|
||||
using parameter @option{memdev}, which does the same as @option{mem} and adds
|
||||
means to actualy manage node RAM on the host side. Use parameter @option{memdev}
|
||||
with @var{memory-backend-ram} backend as an replacement for parameter @option{mem}
|
||||
to achieve the same fake NUMA effect or a properly configured
|
||||
@var{memory-backend-file} backend to actually benefit from NUMA configuration.
|
||||
In future new machine versions will not accept the option but it will still
|
||||
work with old machine types. User can check QAPI schema to see if the legacy
|
||||
option is supported by looking at MachineInfo::numa-mem-supported property.
|
||||
|
||||
@subsection -numa node (without memory specified) (since 4.1)
|
||||
|
||||
Splitting RAM by default between NUMA nodes has the same issues as @option{mem}
|
||||
parameter described above with the difference that the role of the user plays
|
||||
QEMU using implicit generic or board specific splitting rule.
|
||||
Use @option{memdev} with @var{memory-backend-ram} backend or @option{mem} (if
|
||||
it's supported by used machine type) to define mapping explictly instead.
|
||||
|
||||
@subsection -mem-path fallback to RAM (since 4.1)
|
||||
Currently if guest RAM allocation from file pointed by @option{mem-path}
|
||||
fails, QEMU falls back to allocating from RAM, which might result
|
||||
in unpredictable behavior since the backing file specified by the user
|
||||
is ignored. In the future, users will be responsible for making sure
|
||||
the backing storage specified with @option{-mem-path} can actually provide
|
||||
the guest RAM configured with @option{-m} and QEMU will fail to start up if
|
||||
RAM allocation is unsuccessful.
|
||||
|
||||
@section QEMU Machine Protocol (QMP) commands
|
||||
|
||||
@subsection block-dirty-bitmap-add "autoload" parameter (since 2.12.0)
|
||||
@ -259,3 +292,22 @@ subset of the image.
|
||||
In the future, QEMU will require Python 3 to be available at
|
||||
build time. Support for Python 2 in scripts shipped with QEMU
|
||||
is deprecated.
|
||||
|
||||
@section Backwards compatibility
|
||||
|
||||
@subsection Runnability guarantee of CPU models (since 4.1.0)
|
||||
|
||||
Previous versions of QEMU never changed existing CPU models in
|
||||
ways that introduced additional host software or hardware
|
||||
requirements to the VM. This allowed management software to
|
||||
safely change the machine type of an existing VM without
|
||||
introducing new requirements ("runnability guarantee"). This
|
||||
prevented CPU models from being updated to include CPU
|
||||
vulnerability mitigations, leaving guests vulnerable in the
|
||||
default configuration.
|
||||
|
||||
The CPU model runnability guarantee won't apply anymore to
|
||||
existing CPU models. Management software that needs runnability
|
||||
guarantees must resolve the CPU model aliases using te
|
||||
``alias-of'' field returned by the ``query-cpu-definitions'' QMP
|
||||
command.
|
||||
|
@ -138,25 +138,26 @@ no incompatible TCG features have been enabled (e.g. icount/replay).
|
||||
ETEXI
|
||||
|
||||
DEF("smp", HAS_ARG, QEMU_OPTION_smp,
|
||||
"-smp [cpus=]n[,maxcpus=cpus][,cores=cores][,threads=threads][,sockets=sockets]\n"
|
||||
"-smp [cpus=]n[,maxcpus=cpus][,cores=cores][,threads=threads][,dies=dies][,sockets=sockets]\n"
|
||||
" set the number of CPUs to 'n' [default=1]\n"
|
||||
" maxcpus= maximum number of total cpus, including\n"
|
||||
" offline CPUs for hotplug, etc\n"
|
||||
" cores= number of CPU cores on one socket\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"
|
||||
" dies= number of CPU dies on one socket (for PC only)\n"
|
||||
" sockets= number of discrete sockets in the system\n",
|
||||
QEMU_ARCH_ALL)
|
||||
STEXI
|
||||
@item -smp [cpus=]@var{n}[,cores=@var{cores}][,threads=@var{threads}][,sockets=@var{sockets}][,maxcpus=@var{maxcpus}]
|
||||
@item -smp [cpus=]@var{n}[,cores=@var{cores}][,threads=@var{threads}][,dies=dies][,sockets=@var{sockets}][,maxcpus=@var{maxcpus}]
|
||||
@findex -smp
|
||||
Simulate an SMP system with @var{n} CPUs. On the PC target, up to 255
|
||||
CPUs are supported. On Sparc32 target, Linux limits the number of usable CPUs
|
||||
to 4.
|
||||
For the PC target, the number of @var{cores} per socket, the number
|
||||
of @var{threads} per cores and the total number of @var{sockets} can be
|
||||
specified. Missing values will be computed. If any on the three values is
|
||||
given, the total number of CPUs @var{n} can be omitted. @var{maxcpus}
|
||||
specifies the maximum number of hotpluggable CPUs.
|
||||
For the PC target, the number of @var{cores} per die, the number of @var{threads}
|
||||
per cores, the number of @var{dies} per packages and the total number of
|
||||
@var{sockets} can be specified. Missing values will be computed.
|
||||
If any on the three values is given, the total number of CPUs @var{n} can be omitted.
|
||||
@var{maxcpus} specifies the maximum number of hotpluggable CPUs.
|
||||
ETEXI
|
||||
|
||||
DEF("numa", HAS_ARG, QEMU_OPTION_numa,
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "hw/qdev-properties.h"
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
#include "hw/loader.h"
|
||||
#include "hw/boards.h"
|
||||
#endif
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/tcg.h"
|
||||
@ -1587,6 +1588,9 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
init_cpreg_list(cpu);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
unsigned int smp_cpus = ms->smp.cpus;
|
||||
|
||||
if (cpu->has_el3 || arm_feature(env, ARM_FEATURE_M_SECURITY)) {
|
||||
cs->num_ases = 2;
|
||||
|
||||
@ -2127,10 +2131,12 @@ static void cortex_a9_initfn(Object *obj)
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static uint64_t a15_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
|
||||
/* Linux wants the number of processors from here.
|
||||
* Might as well set the interrupt-controller bit too.
|
||||
*/
|
||||
return ((smp_cpus - 1) << 24) | (1 << 23);
|
||||
return ((ms->smp.cpus - 1) << 24) | (1 << 23);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -111,23 +111,6 @@ static void hppa_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void hppa_cpu_list_entry(gpointer data, gpointer user_data)
|
||||
{
|
||||
ObjectClass *oc = data;
|
||||
|
||||
qemu_printf(" %s\n", object_class_get_name(oc));
|
||||
}
|
||||
|
||||
void hppa_cpu_list(void)
|
||||
{
|
||||
GSList *list;
|
||||
|
||||
list = object_class_get_list_sorted(TYPE_HPPA_CPU, false);
|
||||
qemu_printf("Available CPUs:\n");
|
||||
g_slist_foreach(list, hppa_cpu_list_entry, NULL);
|
||||
g_slist_free(list);
|
||||
}
|
||||
|
||||
static void hppa_cpu_initfn(Object *obj)
|
||||
{
|
||||
CPUState *cs = CPU(obj);
|
||||
|
@ -241,8 +241,6 @@ void hppa_translate_init(void);
|
||||
|
||||
#define CPU_RESOLVING_TYPE TYPE_HPPA_CPU
|
||||
|
||||
void hppa_cpu_list(void);
|
||||
|
||||
static inline target_ulong hppa_form_gva_psw(target_ureg psw, uint64_t spc,
|
||||
target_ureg off)
|
||||
{
|
||||
|
@ -36,13 +36,7 @@
|
||||
#define X86_CPU_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(X86CPUClass, (obj), TYPE_X86_CPU)
|
||||
|
||||
/**
|
||||
* X86CPUDefinition:
|
||||
*
|
||||
* CPU model definition data that was not converted to QOM per-subclass
|
||||
* property defaults yet.
|
||||
*/
|
||||
typedef struct X86CPUDefinition X86CPUDefinition;
|
||||
typedef struct X86CPUModel X86CPUModel;
|
||||
|
||||
/**
|
||||
* X86CPUClass:
|
||||
@ -64,7 +58,7 @@ typedef struct X86CPUClass {
|
||||
/* CPU definition, automatically loaded by instance_init if not NULL.
|
||||
* Should be eventually replaced by subclass-specific property defaults.
|
||||
*/
|
||||
X86CPUDefinition *cpu_def;
|
||||
X86CPUModel *model;
|
||||
|
||||
bool host_cpuid_required;
|
||||
int ordering;
|
||||
|
1143
target/i386/cpu.c
1143
target/i386/cpu.c
File diff suppressed because it is too large
Load Diff
@ -736,6 +736,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
|
||||
#define CPUID_TOPOLOGY_LEVEL_INVALID (0U << 8)
|
||||
#define CPUID_TOPOLOGY_LEVEL_SMT (1U << 8)
|
||||
#define CPUID_TOPOLOGY_LEVEL_CORE (2U << 8)
|
||||
#define CPUID_TOPOLOGY_LEVEL_DIE (5U << 8)
|
||||
|
||||
/* MSR Feature Bits */
|
||||
#define MSR_ARCH_CAP_RDCL_NO (1U << 0)
|
||||
@ -1385,6 +1386,8 @@ typedef struct CPUX86State {
|
||||
uint64_t xss;
|
||||
|
||||
TPRAccess tpr_access_type;
|
||||
|
||||
unsigned nr_dies;
|
||||
} CPUX86State;
|
||||
|
||||
struct kvm_msrs;
|
||||
@ -1406,7 +1409,7 @@ struct X86CPU {
|
||||
CPUNegativeOffsetState neg;
|
||||
CPUX86State env;
|
||||
|
||||
int hyperv_spinlock_attempts;
|
||||
uint32_t hyperv_spinlock_attempts;
|
||||
char *hyperv_vendor_id;
|
||||
bool hyperv_synic_kvm_only;
|
||||
uint64_t hyperv_features;
|
||||
@ -1414,6 +1417,12 @@ struct X86CPU {
|
||||
|
||||
bool check_cpuid;
|
||||
bool enforce_cpuid;
|
||||
/*
|
||||
* Force features to be enabled even if the host doesn't support them.
|
||||
* This is dangerous and should be done only for testing CPUID
|
||||
* compatibility.
|
||||
*/
|
||||
bool force_features;
|
||||
bool expose_kvm;
|
||||
bool expose_tcg;
|
||||
bool migratable;
|
||||
@ -1438,7 +1447,7 @@ struct X86CPU {
|
||||
} mwait;
|
||||
|
||||
/* Features that were filtered out because of missing host capabilities */
|
||||
uint32_t filtered_features[FEATURE_WORDS];
|
||||
FeatureWordArray filtered_features;
|
||||
|
||||
/* Enable PMU CPUID bits. This can't be enabled by default yet because
|
||||
* it doesn't have ABI stability guarantees, as it passes all PMU CPUID
|
||||
@ -1498,6 +1507,7 @@ struct X86CPU {
|
||||
|
||||
int32_t node_id; /* NUMA node this CPU belongs to */
|
||||
int32_t socket_id;
|
||||
int32_t die_id;
|
||||
int32_t core_id;
|
||||
int32_t thread_id;
|
||||
|
||||
@ -1919,6 +1929,28 @@ void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip,
|
||||
*/
|
||||
void x86_cpu_change_kvm_default(const char *prop, const char *value);
|
||||
|
||||
/* Special values for X86CPUVersion: */
|
||||
|
||||
/* Resolve to latest CPU version */
|
||||
#define CPU_VERSION_LATEST -1
|
||||
|
||||
/*
|
||||
* Resolve to version defined by current machine type.
|
||||
* See x86_cpu_set_default_version()
|
||||
*/
|
||||
#define CPU_VERSION_AUTO -2
|
||||
|
||||
/* Don't resolve to any versioned CPU models, like old QEMU versions */
|
||||
#define CPU_VERSION_LEGACY 0
|
||||
|
||||
typedef int X86CPUVersion;
|
||||
|
||||
/*
|
||||
* Set default CPU model version for CPU models having
|
||||
* version == CPU_VERSION_AUTO.
|
||||
*/
|
||||
void x86_cpu_set_default_version(X86CPUVersion version);
|
||||
|
||||
/* Return name of 32-bit register, from a R_* constant */
|
||||
const char *get_register_name_32(unsigned int reg);
|
||||
|
||||
|
@ -1451,6 +1451,10 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x1f:
|
||||
if (env->nr_dies < 2) {
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
case 0xb:
|
||||
case 0xd:
|
||||
@ -1458,6 +1462,11 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||
if (i == 0xd && j == 64) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 0x1f && j == 64) {
|
||||
break;
|
||||
}
|
||||
|
||||
c->function = i;
|
||||
c->flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
|
||||
c->index = j;
|
||||
@ -1469,6 +1478,9 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||
if (i == 0xb && !(c->ecx & 0xff00)) {
|
||||
break;
|
||||
}
|
||||
if (i == 0x1f && !(c->ecx & 0xff00)) {
|
||||
break;
|
||||
}
|
||||
if (i == 0xd && c->eax == 0) {
|
||||
continue;
|
||||
}
|
||||
|
@ -24,6 +24,9 @@
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exception.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "hw/boards.h"
|
||||
#endif
|
||||
|
||||
#define TO_SPR(group, number) (((group) << 11) + (number))
|
||||
|
||||
@ -194,6 +197,7 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd,
|
||||
target_ulong spr)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
OpenRISCCPU *cpu = env_archcpu(env);
|
||||
CPUState *cs = env_cpu(env);
|
||||
int idx;
|
||||
@ -241,7 +245,7 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd,
|
||||
return cpu->parent_obj.cpu_index;
|
||||
|
||||
case TO_SPR(0, 129): /* NUMCORES */
|
||||
return max_cpus;
|
||||
return ms->smp.max_cpus;
|
||||
|
||||
case TO_SPR(0, 1024) ... TO_SPR(0, 1024 + (16 * 32)): /* Shadow GPRs */
|
||||
idx = (spr - 1024);
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "hw/qdev-properties.h"
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "hw/hw.h"
|
||||
#include "hw/boards.h"
|
||||
#include "sysemu/arch_init.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/tcg.h"
|
||||
@ -197,6 +198,8 @@ static void s390_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
unsigned int max_cpus = ms->smp.max_cpus;
|
||||
if (cpu->env.core_id >= max_cpus) {
|
||||
error_setg(&err, "Unable to add CPU with core-id: %" PRIu32
|
||||
", maximum core-id: %d", cpu->env.core_id,
|
||||
|
@ -31,6 +31,7 @@
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/s390x/s390_flic.h"
|
||||
#include "hw/boards.h"
|
||||
#endif
|
||||
|
||||
void QEMU_NORETURN tcg_s390_program_interrupt(CPUS390XState *env, uint32_t code,
|
||||
@ -315,6 +316,10 @@ static void do_ext_interrupt(CPUS390XState *env)
|
||||
g_assert(cpu_addr < S390_MAX_CPUS);
|
||||
lowcore->cpu_addr = cpu_to_be16(cpu_addr);
|
||||
clear_bit(cpu_addr, env->emergency_signals);
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
unsigned int max_cpus = ms->smp.max_cpus;
|
||||
#endif
|
||||
if (bitmap_empty(env->emergency_signals, max_cpus)) {
|
||||
env->pending_int &= ~INTERRUPT_EMERGENCY_SIGNAL;
|
||||
}
|
||||
|
@ -119,8 +119,8 @@
|
||||
* Needs to be big enough to contain max_cpus emergency signals
|
||||
* and in addition NR_LOCAL_IRQS interrupts
|
||||
*/
|
||||
#define VCPU_IRQ_BUF_SIZE (sizeof(struct kvm_s390_irq) * \
|
||||
(max_cpus + NR_LOCAL_IRQS))
|
||||
#define VCPU_IRQ_BUF_SIZE(max_cpus) (sizeof(struct kvm_s390_irq) * \
|
||||
(max_cpus + NR_LOCAL_IRQS))
|
||||
|
||||
static CPUWatchpoint hw_watchpoint;
|
||||
/*
|
||||
@ -362,9 +362,10 @@ unsigned long kvm_arch_vcpu_id(CPUState *cpu)
|
||||
|
||||
int kvm_arch_init_vcpu(CPUState *cs)
|
||||
{
|
||||
unsigned int max_cpus = MACHINE(qdev_get_machine())->smp.max_cpus;
|
||||
S390CPU *cpu = S390_CPU(cs);
|
||||
kvm_s390_set_cpu_state(cpu, cpu->env.cpu_state);
|
||||
cpu->irqstate = g_malloc0(VCPU_IRQ_BUF_SIZE);
|
||||
cpu->irqstate = g_malloc0(VCPU_IRQ_BUF_SIZE(max_cpus));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1950,9 +1951,10 @@ int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state)
|
||||
|
||||
void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu)
|
||||
{
|
||||
unsigned int max_cpus = MACHINE(qdev_get_machine())->smp.max_cpus;
|
||||
struct kvm_s390_irq_state irq_state = {
|
||||
.buf = (uint64_t) cpu->irqstate,
|
||||
.len = VCPU_IRQ_BUF_SIZE,
|
||||
.len = VCPU_IRQ_BUF_SIZE(max_cpus),
|
||||
};
|
||||
CPUState *cs = CPU(cpu);
|
||||
int32_t bytes;
|
||||
|
13
tcg/tcg.c
13
tcg/tcg.c
@ -45,6 +45,10 @@
|
||||
#include "exec/cpu-common.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
#include "hw/boards.h"
|
||||
#endif
|
||||
|
||||
#include "tcg-op.h"
|
||||
|
||||
#if UINTPTR_MAX == UINT32_MAX
|
||||
@ -620,6 +624,10 @@ static size_t tcg_n_regions(void)
|
||||
size_t i;
|
||||
|
||||
/* Use a single region if all we have is one vCPU thread */
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
unsigned int max_cpus = ms->smp.max_cpus;
|
||||
#endif
|
||||
if (max_cpus == 1 || !qemu_tcg_mttcg_enabled()) {
|
||||
return 1;
|
||||
}
|
||||
@ -752,6 +760,7 @@ void tcg_register_thread(void)
|
||||
#else
|
||||
void tcg_register_thread(void)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
TCGContext *s = g_malloc(sizeof(*s));
|
||||
unsigned int i, n;
|
||||
bool err;
|
||||
@ -769,7 +778,7 @@ void tcg_register_thread(void)
|
||||
|
||||
/* Claim an entry in tcg_ctxs */
|
||||
n = atomic_fetch_inc(&n_tcg_ctxs);
|
||||
g_assert(n < max_cpus);
|
||||
g_assert(n < ms->smp.max_cpus);
|
||||
atomic_set(&tcg_ctxs[n], s);
|
||||
|
||||
tcg_ctx = s;
|
||||
@ -979,6 +988,8 @@ void tcg_context_init(TCGContext *s)
|
||||
tcg_ctxs = &tcg_ctx;
|
||||
n_tcg_ctxs = 1;
|
||||
#else
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
unsigned int max_cpus = ms->smp.max_cpus;
|
||||
tcg_ctxs = g_new(TCGContext *, max_cpus);
|
||||
#endif
|
||||
|
||||
|
304
tests/acceptance/x86_cpu_model_versions.py
Normal file
304
tests/acceptance/x86_cpu_model_versions.py
Normal file
@ -0,0 +1,304 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Basic validation of x86 versioned CPU models and CPU model aliases
|
||||
#
|
||||
# Copyright (c) 2019 Red Hat Inc
|
||||
#
|
||||
# Author:
|
||||
# Eduardo Habkost <ehabkost@redhat.com>
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library 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
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
|
||||
import avocado_qemu
|
||||
import re
|
||||
|
||||
def get_cpu_prop(vm, prop):
|
||||
cpu_path = vm.command('query-cpus')[0].get('qom_path')
|
||||
return vm.command('qom-get', path=cpu_path, property=prop)
|
||||
|
||||
class X86CPUModelAliases(avocado_qemu.Test):
|
||||
"""
|
||||
Validation of PC CPU model versions and CPU model aliases
|
||||
|
||||
:avocado: tags=arch:x86_64
|
||||
"""
|
||||
def validate_aliases(self, cpus):
|
||||
for c in cpus.values():
|
||||
if 'alias-of' in c:
|
||||
# all aliases must point to a valid CPU model name:
|
||||
self.assertIn(c['alias-of'], cpus,
|
||||
'%s.alias-of (%s) is not a valid CPU model name' % (c['name'], c['alias-of']))
|
||||
# aliases must not point to aliases
|
||||
self.assertNotIn('alias-of', cpus[c['alias-of']],
|
||||
'%s.alias-of (%s) points to another alias' % (c['name'], c['alias-of']))
|
||||
|
||||
# aliases must not be static
|
||||
self.assertFalse(c['static'])
|
||||
|
||||
def validate_variant_aliases(self, cpus):
|
||||
# -noTSX, -IBRS and -IBPB variants of CPU models are special:
|
||||
# they shouldn't have their own versions:
|
||||
self.assertNotIn("Haswell-noTSX-v1", cpus,
|
||||
"Haswell-noTSX shouldn't be versioned")
|
||||
self.assertNotIn("Broadwell-noTSX-v1", cpus,
|
||||
"Broadwell-noTSX shouldn't be versioned")
|
||||
self.assertNotIn("Nehalem-IBRS-v1", cpus,
|
||||
"Nehalem-IBRS shouldn't be versioned")
|
||||
self.assertNotIn("Westmere-IBRS-v1", cpus,
|
||||
"Westmere-IBRS shouldn't be versioned")
|
||||
self.assertNotIn("SandyBridge-IBRS-v1", cpus,
|
||||
"SandyBridge-IBRS shouldn't be versioned")
|
||||
self.assertNotIn("IvyBridge-IBRS-v1", cpus,
|
||||
"IvyBridge-IBRS shouldn't be versioned")
|
||||
self.assertNotIn("Haswell-noTSX-IBRS-v1", cpus,
|
||||
"Haswell-noTSX-IBRS shouldn't be versioned")
|
||||
self.assertNotIn("Haswell-IBRS-v1", cpus,
|
||||
"Haswell-IBRS shouldn't be versioned")
|
||||
self.assertNotIn("Broadwell-noTSX-IBRS-v1", cpus,
|
||||
"Broadwell-noTSX-IBRS shouldn't be versioned")
|
||||
self.assertNotIn("Broadwell-IBRS-v1", cpus,
|
||||
"Broadwell-IBRS shouldn't be versioned")
|
||||
self.assertNotIn("Skylake-Client-IBRS-v1", cpus,
|
||||
"Skylake-Client-IBRS shouldn't be versioned")
|
||||
self.assertNotIn("Skylake-Server-IBRS-v1", cpus,
|
||||
"Skylake-Server-IBRS shouldn't be versioned")
|
||||
self.assertNotIn("EPYC-IBPB-v1", cpus,
|
||||
"EPYC-IBPB shouldn't be versioned")
|
||||
|
||||
def test_4_0_alias_compatibility(self):
|
||||
"""Check if pc-*-4.0 unversioned CPU model won't be reported as aliases"""
|
||||
# pc-*-4.0 won't expose non-versioned CPU models as aliases
|
||||
# We do this to help management software to keep compatibility
|
||||
# with older QEMU versions that didn't have the versioned CPU model
|
||||
self.vm.add_args('-S')
|
||||
self.vm.set_machine('pc-i440fx-4.0')
|
||||
self.vm.launch()
|
||||
cpus = dict((m['name'], m) for m in self.vm.command('query-cpu-definitions'))
|
||||
|
||||
self.assertFalse(cpus['Cascadelake-Server']['static'],
|
||||
'unversioned Cascadelake-Server CPU model must not be static')
|
||||
self.assertNotIn('alias-of', cpus['Cascadelake-Server'],
|
||||
'Cascadelake-Server must not be an alias')
|
||||
self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'],
|
||||
'Cascadelake-Server-v1 must not be an alias')
|
||||
|
||||
self.assertFalse(cpus['qemu64']['static'],
|
||||
'unversioned qemu64 CPU model must not be static')
|
||||
self.assertNotIn('alias-of', cpus['qemu64'],
|
||||
'qemu64 must not be an alias')
|
||||
self.assertNotIn('alias-of', cpus['qemu64-v1'],
|
||||
'qemu64-v1 must not be an alias')
|
||||
|
||||
self.validate_variant_aliases(cpus)
|
||||
|
||||
# On pc-*-4.0, no CPU model should be reported as an alias:
|
||||
for name,c in cpus.items():
|
||||
self.assertNotIn('alias-of', c, "%s shouldn't be an alias" % (name))
|
||||
|
||||
def test_4_1_alias(self):
|
||||
"""Check if unversioned CPU model is an alias pointing to right version"""
|
||||
self.vm.add_args('-S')
|
||||
self.vm.set_machine('pc-i440fx-4.1')
|
||||
self.vm.launch()
|
||||
|
||||
cpus = dict((m['name'], m) for m in self.vm.command('query-cpu-definitions'))
|
||||
|
||||
self.assertFalse(cpus['Cascadelake-Server']['static'],
|
||||
'unversioned Cascadelake-Server CPU model must not be static')
|
||||
self.assertEquals(cpus['Cascadelake-Server'].get('alias-of'), 'Cascadelake-Server-v1',
|
||||
'Cascadelake-Server must be an alias of Cascadelake-Server-v1')
|
||||
self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'],
|
||||
'Cascadelake-Server-v1 must not be an alias')
|
||||
|
||||
self.assertFalse(cpus['qemu64']['static'],
|
||||
'unversioned qemu64 CPU model must not be static')
|
||||
self.assertEquals(cpus['qemu64'].get('alias-of'), 'qemu64-v1',
|
||||
'qemu64 must be an alias of qemu64-v1')
|
||||
self.assertNotIn('alias-of', cpus['qemu64-v1'],
|
||||
'qemu64-v1 must not be an alias')
|
||||
|
||||
self.validate_variant_aliases(cpus)
|
||||
|
||||
# On pc-*-4.1, -noTSX and -IBRS models should be aliases:
|
||||
self.assertEquals(cpus["Haswell"].get('alias-of'),
|
||||
"Haswell-v1",
|
||||
"Haswell must be an alias")
|
||||
self.assertEquals(cpus["Haswell-noTSX"].get('alias-of'),
|
||||
"Haswell-v2",
|
||||
"Haswell-noTSX must be an alias")
|
||||
self.assertEquals(cpus["Haswell-IBRS"].get('alias-of'),
|
||||
"Haswell-v3",
|
||||
"Haswell-IBRS must be an alias")
|
||||
self.assertEquals(cpus["Haswell-noTSX-IBRS"].get('alias-of'),
|
||||
"Haswell-v4",
|
||||
"Haswell-noTSX-IBRS must be an alias")
|
||||
|
||||
self.assertEquals(cpus["Broadwell"].get('alias-of'),
|
||||
"Broadwell-v1",
|
||||
"Broadwell must be an alias")
|
||||
self.assertEquals(cpus["Broadwell-noTSX"].get('alias-of'),
|
||||
"Broadwell-v2",
|
||||
"Broadwell-noTSX must be an alias")
|
||||
self.assertEquals(cpus["Broadwell-IBRS"].get('alias-of'),
|
||||
"Broadwell-v3",
|
||||
"Broadwell-IBRS must be an alias")
|
||||
self.assertEquals(cpus["Broadwell-noTSX-IBRS"].get('alias-of'),
|
||||
"Broadwell-v4",
|
||||
"Broadwell-noTSX-IBRS must be an alias")
|
||||
|
||||
self.assertEquals(cpus["Nehalem"].get('alias-of'),
|
||||
"Nehalem-v1",
|
||||
"Nehalem must be an alias")
|
||||
self.assertEquals(cpus["Nehalem-IBRS"].get('alias-of'),
|
||||
"Nehalem-v2",
|
||||
"Nehalem-IBRS must be an alias")
|
||||
|
||||
self.assertEquals(cpus["Westmere"].get('alias-of'),
|
||||
"Westmere-v1",
|
||||
"Westmere must be an alias")
|
||||
self.assertEquals(cpus["Westmere-IBRS"].get('alias-of'),
|
||||
"Westmere-v2",
|
||||
"Westmere-IBRS must be an alias")
|
||||
|
||||
self.assertEquals(cpus["SandyBridge"].get('alias-of'),
|
||||
"SandyBridge-v1",
|
||||
"SandyBridge must be an alias")
|
||||
self.assertEquals(cpus["SandyBridge-IBRS"].get('alias-of'),
|
||||
"SandyBridge-v2",
|
||||
"SandyBridge-IBRS must be an alias")
|
||||
|
||||
self.assertEquals(cpus["IvyBridge"].get('alias-of'),
|
||||
"IvyBridge-v1",
|
||||
"IvyBridge must be an alias")
|
||||
self.assertEquals(cpus["IvyBridge-IBRS"].get('alias-of'),
|
||||
"IvyBridge-v2",
|
||||
"IvyBridge-IBRS must be an alias")
|
||||
|
||||
self.assertEquals(cpus["Skylake-Client"].get('alias-of'),
|
||||
"Skylake-Client-v1",
|
||||
"Skylake-Client must be an alias")
|
||||
self.assertEquals(cpus["Skylake-Client-IBRS"].get('alias-of'),
|
||||
"Skylake-Client-v2",
|
||||
"Skylake-Client-IBRS must be an alias")
|
||||
|
||||
self.assertEquals(cpus["Skylake-Server"].get('alias-of'),
|
||||
"Skylake-Server-v1",
|
||||
"Skylake-Server must be an alias")
|
||||
self.assertEquals(cpus["Skylake-Server-IBRS"].get('alias-of'),
|
||||
"Skylake-Server-v2",
|
||||
"Skylake-Server-IBRS must be an alias")
|
||||
|
||||
self.assertEquals(cpus["EPYC"].get('alias-of'),
|
||||
"EPYC-v1",
|
||||
"EPYC must be an alias")
|
||||
self.assertEquals(cpus["EPYC-IBPB"].get('alias-of'),
|
||||
"EPYC-v2",
|
||||
"EPYC-IBPB must be an alias")
|
||||
|
||||
self.validate_aliases(cpus)
|
||||
|
||||
def test_none_alias(self):
|
||||
"""Check if unversioned CPU model is an alias pointing to some version"""
|
||||
self.vm.add_args('-S')
|
||||
self.vm.set_machine('none')
|
||||
self.vm.launch()
|
||||
|
||||
cpus = dict((m['name'], m) for m in self.vm.command('query-cpu-definitions'))
|
||||
|
||||
self.assertFalse(cpus['Cascadelake-Server']['static'],
|
||||
'unversioned Cascadelake-Server CPU model must not be static')
|
||||
self.assertTrue(re.match('Cascadelake-Server-v[0-9]+', cpus['Cascadelake-Server']['alias-of']),
|
||||
'Cascadelake-Server must be an alias of versioned CPU model')
|
||||
self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'],
|
||||
'Cascadelake-Server-v1 must not be an alias')
|
||||
|
||||
self.assertFalse(cpus['qemu64']['static'],
|
||||
'unversioned qemu64 CPU model must not be static')
|
||||
self.assertTrue(re.match('qemu64-v[0-9]+', cpus['qemu64']['alias-of']),
|
||||
'qemu64 must be an alias of versioned CPU model')
|
||||
self.assertNotIn('alias-of', cpus['qemu64-v1'],
|
||||
'qemu64-v1 must not be an alias')
|
||||
|
||||
self.validate_aliases(cpus)
|
||||
|
||||
def test_Cascadelake_arch_capabilities_result(self):
|
||||
# machine-type only:
|
||||
vm = self.get_vm()
|
||||
vm.add_args('-S')
|
||||
vm.set_machine('pc-i440fx-4.1')
|
||||
vm.add_args('-cpu', 'Cascadelake-Server,x-force-features=on,check=off,enforce=off')
|
||||
vm.launch()
|
||||
self.assertFalse(get_cpu_prop(vm, 'arch-capabilities'),
|
||||
'pc-i440fx-4.1 + Cascadelake-Server should not have arch-capabilities')
|
||||
|
||||
vm = self.get_vm()
|
||||
vm.add_args('-S')
|
||||
vm.set_machine('pc-i440fx-4.0')
|
||||
vm.add_args('-cpu', 'Cascadelake-Server,x-force-features=on,check=off,enforce=off')
|
||||
vm.launch()
|
||||
self.assertFalse(get_cpu_prop(vm, 'arch-capabilities'),
|
||||
'pc-i440fx-4.0 + Cascadelake-Server should not have arch-capabilities')
|
||||
|
||||
# command line must override machine-type if CPU model is not versioned:
|
||||
vm = self.get_vm()
|
||||
vm.add_args('-S')
|
||||
vm.set_machine('pc-i440fx-4.0')
|
||||
vm.add_args('-cpu', 'Cascadelake-Server,x-force-features=on,check=off,enforce=off,+arch-capabilities')
|
||||
vm.launch()
|
||||
self.assertTrue(get_cpu_prop(vm, 'arch-capabilities'),
|
||||
'pc-i440fx-4.0 + Cascadelake-Server,+arch-capabilities should have arch-capabilities')
|
||||
|
||||
vm = self.get_vm()
|
||||
vm.add_args('-S')
|
||||
vm.set_machine('pc-i440fx-4.1')
|
||||
vm.add_args('-cpu', 'Cascadelake-Server,x-force-features=on,check=off,enforce=off,-arch-capabilities')
|
||||
vm.launch()
|
||||
self.assertFalse(get_cpu_prop(vm, 'arch-capabilities'),
|
||||
'pc-i440fx-4.1 + Cascadelake-Server,-arch-capabilities should not have arch-capabilities')
|
||||
|
||||
# versioned CPU model overrides machine-type:
|
||||
vm = self.get_vm()
|
||||
vm.add_args('-S')
|
||||
vm.set_machine('pc-i440fx-4.0')
|
||||
vm.add_args('-cpu', 'Cascadelake-Server-v1,x-force-features=on,check=off,enforce=off')
|
||||
vm.launch()
|
||||
self.assertFalse(get_cpu_prop(vm, 'arch-capabilities'),
|
||||
'pc-i440fx-4.1 + Cascadelake-Server-v1 should not have arch-capabilities')
|
||||
|
||||
vm = self.get_vm()
|
||||
vm.add_args('-S')
|
||||
vm.set_machine('pc-i440fx-4.0')
|
||||
vm.add_args('-cpu', 'Cascadelake-Server-v2,x-force-features=on,check=off,enforce=off')
|
||||
vm.launch()
|
||||
self.assertTrue(get_cpu_prop(vm, 'arch-capabilities'),
|
||||
'pc-i440fx-4.1 + Cascadelake-Server-v1 should have arch-capabilities')
|
||||
|
||||
# command line must override machine-type and versioned CPU model:
|
||||
vm = self.get_vm()
|
||||
vm.add_args('-S')
|
||||
vm.set_machine('pc-i440fx-4.0')
|
||||
vm.add_args('-cpu', 'Cascadelake-Server,x-force-features=on,check=off,enforce=off,+arch-capabilities')
|
||||
vm.launch()
|
||||
self.assertTrue(get_cpu_prop(vm, 'arch-capabilities'),
|
||||
'pc-i440fx-4.0 + Cascadelake-Server-v1,+arch-capabilities should have arch-capabilities')
|
||||
|
||||
vm = self.get_vm()
|
||||
vm.add_args('-S')
|
||||
vm.set_machine('pc-i440fx-4.1')
|
||||
vm.add_args('-cpu', 'Cascadelake-Server-v2,x-force-features=on,check=off,enforce=off,-arch-capabilities')
|
||||
vm.launch()
|
||||
self.assertFalse(get_cpu_prop(vm, 'arch-capabilities'),
|
||||
'pc-i440fx-4.1 + Cascadelake-Server-v2,-arch-capabilities should not have arch-capabilities')
|
@ -688,6 +688,8 @@ static void test_acpi_q35_tcg_mmio64(void)
|
||||
};
|
||||
|
||||
test_acpi_one("-m 128M,slots=1,maxmem=2G "
|
||||
"-object memory-backend-ram,id=ram0,size=128M "
|
||||
"-numa node,memdev=ram0 "
|
||||
"-device pci-testdev,membar=2G",
|
||||
&data);
|
||||
free_test_data(&data);
|
||||
@ -701,7 +703,9 @@ static void test_acpi_piix4_tcg_cphp(void)
|
||||
data.machine = MACHINE_PC;
|
||||
data.variant = ".cphp";
|
||||
test_acpi_one("-smp 2,cores=3,sockets=2,maxcpus=6"
|
||||
" -numa node -numa node"
|
||||
" -object memory-backend-ram,id=ram0,size=64M"
|
||||
" -object memory-backend-ram,id=ram1,size=64M"
|
||||
" -numa node,memdev=ram0 -numa node,memdev=ram1"
|
||||
" -numa dist,src=0,dst=1,val=21",
|
||||
&data);
|
||||
free_test_data(&data);
|
||||
@ -715,7 +719,9 @@ static void test_acpi_q35_tcg_cphp(void)
|
||||
data.machine = MACHINE_Q35;
|
||||
data.variant = ".cphp";
|
||||
test_acpi_one(" -smp 2,cores=3,sockets=2,maxcpus=6"
|
||||
" -numa node -numa node"
|
||||
" -object memory-backend-ram,id=ram0,size=64M"
|
||||
" -object memory-backend-ram,id=ram1,size=64M"
|
||||
" -numa node,memdev=ram0 -numa node,memdev=ram1"
|
||||
" -numa dist,src=0,dst=1,val=21",
|
||||
&data);
|
||||
free_test_data(&data);
|
||||
@ -766,7 +772,9 @@ static void test_acpi_q35_tcg_memhp(void)
|
||||
data.machine = MACHINE_Q35;
|
||||
data.variant = ".memhp";
|
||||
test_acpi_one(" -m 128,slots=3,maxmem=1G"
|
||||
" -numa node -numa node"
|
||||
" -object memory-backend-ram,id=ram0,size=64M"
|
||||
" -object memory-backend-ram,id=ram1,size=64M"
|
||||
" -numa node,memdev=ram0 -numa node,memdev=ram1"
|
||||
" -numa dist,src=0,dst=1,val=21",
|
||||
&data);
|
||||
free_test_data(&data);
|
||||
@ -780,7 +788,9 @@ static void test_acpi_piix4_tcg_memhp(void)
|
||||
data.machine = MACHINE_PC;
|
||||
data.variant = ".memhp";
|
||||
test_acpi_one(" -m 128,slots=3,maxmem=1G"
|
||||
" -numa node -numa node"
|
||||
" -object memory-backend-ram,id=ram0,size=64M"
|
||||
" -object memory-backend-ram,id=ram1,size=64M"
|
||||
" -numa node,memdev=ram0 -numa node,memdev=ram1"
|
||||
" -numa dist,src=0,dst=1,val=21",
|
||||
&data);
|
||||
free_test_data(&data);
|
||||
@ -793,7 +803,8 @@ static void test_acpi_q35_tcg_numamem(void)
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.machine = MACHINE_Q35;
|
||||
data.variant = ".numamem";
|
||||
test_acpi_one(" -numa node -numa node,mem=128", &data);
|
||||
test_acpi_one(" -object memory-backend-ram,id=ram0,size=128M"
|
||||
" -numa node -numa node,memdev=ram0", &data);
|
||||
free_test_data(&data);
|
||||
}
|
||||
|
||||
@ -804,7 +815,8 @@ static void test_acpi_piix4_tcg_numamem(void)
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.machine = MACHINE_PC;
|
||||
data.variant = ".numamem";
|
||||
test_acpi_one(" -numa node -numa node,mem=128", &data);
|
||||
test_acpi_one(" -object memory-backend-ram,id=ram0,size=128M"
|
||||
" -numa node -numa node,memdev=ram0", &data);
|
||||
free_test_data(&data);
|
||||
}
|
||||
|
||||
@ -818,17 +830,21 @@ static void test_acpi_tcg_dimm_pxm(const char *machine)
|
||||
test_acpi_one(" -machine nvdimm=on,nvdimm-persistence=cpu"
|
||||
" -smp 4,sockets=4"
|
||||
" -m 128M,slots=3,maxmem=1G"
|
||||
" -numa node,mem=32M,nodeid=0"
|
||||
" -numa node,mem=32M,nodeid=1"
|
||||
" -numa node,mem=32M,nodeid=2"
|
||||
" -numa node,mem=32M,nodeid=3"
|
||||
" -object memory-backend-ram,id=ram0,size=32M"
|
||||
" -object memory-backend-ram,id=ram1,size=32M"
|
||||
" -object memory-backend-ram,id=ram2,size=32M"
|
||||
" -object memory-backend-ram,id=ram3,size=32M"
|
||||
" -numa node,memdev=ram0,nodeid=0"
|
||||
" -numa node,memdev=ram1,nodeid=1"
|
||||
" -numa node,memdev=ram2,nodeid=2"
|
||||
" -numa node,memdev=ram3,nodeid=3"
|
||||
" -numa cpu,node-id=0,socket-id=0"
|
||||
" -numa cpu,node-id=1,socket-id=1"
|
||||
" -numa cpu,node-id=2,socket-id=2"
|
||||
" -numa cpu,node-id=3,socket-id=3"
|
||||
" -object memory-backend-ram,id=ram0,size=128M"
|
||||
" -object memory-backend-ram,id=ram4,size=128M"
|
||||
" -object memory-backend-ram,id=nvm0,size=128M"
|
||||
" -device pc-dimm,id=dimm0,memdev=ram0,node=1"
|
||||
" -device pc-dimm,id=dimm0,memdev=ram4,node=1"
|
||||
" -device nvdimm,id=dimm1,memdev=nvm0,node=2",
|
||||
&data);
|
||||
free_test_data(&data);
|
||||
|
@ -28,74 +28,80 @@
|
||||
|
||||
static void test_topo_bits(void)
|
||||
{
|
||||
/* simple tests for 1 thread per core, 1 core per socket */
|
||||
g_assert_cmpuint(apicid_smt_width(1, 1), ==, 0);
|
||||
g_assert_cmpuint(apicid_core_width(1, 1), ==, 0);
|
||||
/* simple tests for 1 thread per core, 1 core per die, 1 die per package */
|
||||
g_assert_cmpuint(apicid_smt_width(1, 1, 1), ==, 0);
|
||||
g_assert_cmpuint(apicid_core_width(1, 1, 1), ==, 0);
|
||||
g_assert_cmpuint(apicid_die_width(1, 1, 1), ==, 0);
|
||||
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 1, 0), ==, 0);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 1, 1), ==, 1);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 1, 2), ==, 2);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 1, 3), ==, 3);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 1, 1, 0), ==, 0);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 1, 1, 1), ==, 1);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 1, 1, 2), ==, 2);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 1, 1, 3), ==, 3);
|
||||
|
||||
|
||||
/* Test field width calculation for multiple values
|
||||
*/
|
||||
g_assert_cmpuint(apicid_smt_width(1, 2), ==, 1);
|
||||
g_assert_cmpuint(apicid_smt_width(1, 3), ==, 2);
|
||||
g_assert_cmpuint(apicid_smt_width(1, 4), ==, 2);
|
||||
g_assert_cmpuint(apicid_smt_width(1, 1, 2), ==, 1);
|
||||
g_assert_cmpuint(apicid_smt_width(1, 1, 3), ==, 2);
|
||||
g_assert_cmpuint(apicid_smt_width(1, 1, 4), ==, 2);
|
||||
|
||||
g_assert_cmpuint(apicid_smt_width(1, 14), ==, 4);
|
||||
g_assert_cmpuint(apicid_smt_width(1, 15), ==, 4);
|
||||
g_assert_cmpuint(apicid_smt_width(1, 16), ==, 4);
|
||||
g_assert_cmpuint(apicid_smt_width(1, 17), ==, 5);
|
||||
g_assert_cmpuint(apicid_smt_width(1, 1, 14), ==, 4);
|
||||
g_assert_cmpuint(apicid_smt_width(1, 1, 15), ==, 4);
|
||||
g_assert_cmpuint(apicid_smt_width(1, 1, 16), ==, 4);
|
||||
g_assert_cmpuint(apicid_smt_width(1, 1, 17), ==, 5);
|
||||
|
||||
|
||||
g_assert_cmpuint(apicid_core_width(30, 2), ==, 5);
|
||||
g_assert_cmpuint(apicid_core_width(31, 2), ==, 5);
|
||||
g_assert_cmpuint(apicid_core_width(32, 2), ==, 5);
|
||||
g_assert_cmpuint(apicid_core_width(33, 2), ==, 6);
|
||||
g_assert_cmpuint(apicid_core_width(1, 30, 2), ==, 5);
|
||||
g_assert_cmpuint(apicid_core_width(1, 31, 2), ==, 5);
|
||||
g_assert_cmpuint(apicid_core_width(1, 32, 2), ==, 5);
|
||||
g_assert_cmpuint(apicid_core_width(1, 33, 2), ==, 6);
|
||||
|
||||
g_assert_cmpuint(apicid_die_width(1, 30, 2), ==, 0);
|
||||
g_assert_cmpuint(apicid_die_width(2, 30, 2), ==, 1);
|
||||
g_assert_cmpuint(apicid_die_width(3, 30, 2), ==, 2);
|
||||
g_assert_cmpuint(apicid_die_width(4, 30, 2), ==, 2);
|
||||
|
||||
/* build a weird topology and see if IDs are calculated correctly
|
||||
*/
|
||||
|
||||
/* This will use 2 bits for thread ID and 3 bits for core ID
|
||||
*/
|
||||
g_assert_cmpuint(apicid_smt_width(6, 3), ==, 2);
|
||||
g_assert_cmpuint(apicid_core_width(6, 3), ==, 3);
|
||||
g_assert_cmpuint(apicid_pkg_offset(6, 3), ==, 5);
|
||||
g_assert_cmpuint(apicid_smt_width(1, 6, 3), ==, 2);
|
||||
g_assert_cmpuint(apicid_core_offset(1, 6, 3), ==, 2);
|
||||
g_assert_cmpuint(apicid_die_offset(1, 6, 3), ==, 5);
|
||||
g_assert_cmpuint(apicid_pkg_offset(1, 6, 3), ==, 5);
|
||||
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 0), ==, 0);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 1), ==, 1);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 2), ==, 2);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 0), ==, 0);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 1), ==, 1);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 2), ==, 2);
|
||||
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 1 * 3 + 0), ==,
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 1 * 3 + 0), ==,
|
||||
(1 << 2) | 0);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 1 * 3 + 1), ==,
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 1 * 3 + 1), ==,
|
||||
(1 << 2) | 1);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 1 * 3 + 2), ==,
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 1 * 3 + 2), ==,
|
||||
(1 << 2) | 2);
|
||||
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 2 * 3 + 0), ==,
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 2 * 3 + 0), ==,
|
||||
(2 << 2) | 0);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 2 * 3 + 1), ==,
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 2 * 3 + 1), ==,
|
||||
(2 << 2) | 1);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 2 * 3 + 2), ==,
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 2 * 3 + 2), ==,
|
||||
(2 << 2) | 2);
|
||||
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 5 * 3 + 0), ==,
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 5 * 3 + 0), ==,
|
||||
(5 << 2) | 0);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 5 * 3 + 1), ==,
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 5 * 3 + 1), ==,
|
||||
(5 << 2) | 1);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 5 * 3 + 2), ==,
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3, 5 * 3 + 2), ==,
|
||||
(5 << 2) | 2);
|
||||
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 1 * 6 * 3 + 0 * 3 + 0), ==,
|
||||
(1 << 5));
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 1 * 6 * 3 + 1 * 3 + 1), ==,
|
||||
(1 << 5) | (1 << 2) | 1);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(6, 3, 3 * 6 * 3 + 5 * 3 + 2), ==,
|
||||
(3 << 5) | (5 << 2) | 2);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3,
|
||||
1 * 6 * 3 + 0 * 3 + 0), ==, (1 << 5));
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3,
|
||||
1 * 6 * 3 + 1 * 3 + 1), ==, (1 << 5) | (1 << 2) | 1);
|
||||
g_assert_cmpuint(x86_apicid_from_cpu_idx(1, 6, 3,
|
||||
3 * 6 * 3 + 5 * 3 + 2), ==, (3 << 5) | (5 << 2) | 2);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
96
vl.c
96
vl.c
@ -163,10 +163,6 @@ static Chardev **serial_hds;
|
||||
Chardev *parallel_hds[MAX_PARALLEL_PORTS];
|
||||
int win2k_install_hack = 0;
|
||||
int singlestep = 0;
|
||||
int smp_cpus;
|
||||
unsigned int max_cpus;
|
||||
int smp_cores = 1;
|
||||
int smp_threads = 1;
|
||||
int acpi_enabled = 1;
|
||||
int no_hpet = 0;
|
||||
int fd_bootchk = 1;
|
||||
@ -1235,6 +1231,9 @@ static QemuOptsList qemu_smp_opts = {
|
||||
}, {
|
||||
.name = "sockets",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
}, {
|
||||
.name = "dies",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
}, {
|
||||
.name = "cores",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
@ -1249,74 +1248,6 @@ static QemuOptsList qemu_smp_opts = {
|
||||
},
|
||||
};
|
||||
|
||||
static void smp_parse(QemuOpts *opts)
|
||||
{
|
||||
if (opts) {
|
||||
unsigned cpus = qemu_opt_get_number(opts, "cpus", 0);
|
||||
unsigned sockets = qemu_opt_get_number(opts, "sockets", 0);
|
||||
unsigned cores = qemu_opt_get_number(opts, "cores", 0);
|
||||
unsigned threads = qemu_opt_get_number(opts, "threads", 0);
|
||||
|
||||
/* compute missing values, prefer sockets over cores over threads */
|
||||
if (cpus == 0 || sockets == 0) {
|
||||
cores = cores > 0 ? cores : 1;
|
||||
threads = threads > 0 ? threads : 1;
|
||||
if (cpus == 0) {
|
||||
sockets = sockets > 0 ? sockets : 1;
|
||||
cpus = cores * threads * sockets;
|
||||
} else {
|
||||
max_cpus = qemu_opt_get_number(opts, "maxcpus", cpus);
|
||||
sockets = max_cpus / (cores * threads);
|
||||
}
|
||||
} else if (cores == 0) {
|
||||
threads = threads > 0 ? threads : 1;
|
||||
cores = cpus / (sockets * threads);
|
||||
cores = cores > 0 ? cores : 1;
|
||||
} else if (threads == 0) {
|
||||
threads = cpus / (cores * sockets);
|
||||
threads = threads > 0 ? threads : 1;
|
||||
} else if (sockets * cores * threads < cpus) {
|
||||
error_report("cpu topology: "
|
||||
"sockets (%u) * cores (%u) * threads (%u) < "
|
||||
"smp_cpus (%u)",
|
||||
sockets, cores, threads, cpus);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
max_cpus = qemu_opt_get_number(opts, "maxcpus", cpus);
|
||||
|
||||
if (max_cpus < cpus) {
|
||||
error_report("maxcpus must be equal to or greater than smp");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (sockets * cores * threads > max_cpus) {
|
||||
error_report("cpu topology: "
|
||||
"sockets (%u) * cores (%u) * threads (%u) > "
|
||||
"maxcpus (%u)",
|
||||
sockets, cores, threads, max_cpus);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (sockets * cores * threads != max_cpus) {
|
||||
warn_report("Invalid CPU topology deprecated: "
|
||||
"sockets (%u) * cores (%u) * threads (%u) "
|
||||
"!= maxcpus (%u)",
|
||||
sockets, cores, threads, max_cpus);
|
||||
}
|
||||
|
||||
smp_cpus = cpus;
|
||||
smp_cores = cores;
|
||||
smp_threads = threads;
|
||||
}
|
||||
|
||||
if (smp_cpus > 1) {
|
||||
Error *blocker = NULL;
|
||||
error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, "smp");
|
||||
replay_add_blocker(blocker);
|
||||
}
|
||||
}
|
||||
|
||||
static void realtime_init(void)
|
||||
{
|
||||
if (enable_mlock) {
|
||||
@ -1580,7 +1511,7 @@ void qemu_system_reset(ShutdownCause reason)
|
||||
cpu_synchronize_all_states();
|
||||
|
||||
if (mc && mc->reset) {
|
||||
mc->reset();
|
||||
mc->reset(current_machine);
|
||||
} else {
|
||||
qemu_devices_reset();
|
||||
}
|
||||
@ -4009,21 +3940,26 @@ int main(int argc, char **argv, char **envp)
|
||||
machine_class->default_cpus = machine_class->default_cpus ?: 1;
|
||||
|
||||
/* default to machine_class->default_cpus */
|
||||
smp_cpus = machine_class->default_cpus;
|
||||
max_cpus = machine_class->default_cpus;
|
||||
current_machine->smp.cpus = machine_class->default_cpus;
|
||||
current_machine->smp.max_cpus = machine_class->default_cpus;
|
||||
current_machine->smp.cores = 1;
|
||||
current_machine->smp.threads = 1;
|
||||
|
||||
smp_parse(qemu_opts_find(qemu_find_opts("smp-opts"), NULL));
|
||||
machine_class->smp_parse(current_machine,
|
||||
qemu_opts_find(qemu_find_opts("smp-opts"), NULL));
|
||||
|
||||
/* sanity-check smp_cpus and max_cpus against machine_class */
|
||||
if (smp_cpus < machine_class->min_cpus) {
|
||||
if (current_machine->smp.cpus < machine_class->min_cpus) {
|
||||
error_report("Invalid SMP CPUs %d. The min CPUs "
|
||||
"supported by machine '%s' is %d", smp_cpus,
|
||||
"supported by machine '%s' is %d",
|
||||
current_machine->smp.cpus,
|
||||
machine_class->name, machine_class->min_cpus);
|
||||
exit(1);
|
||||
}
|
||||
if (max_cpus > machine_class->max_cpus) {
|
||||
if (current_machine->smp.max_cpus > machine_class->max_cpus) {
|
||||
error_report("Invalid SMP CPUs %d. The max CPUs "
|
||||
"supported by machine '%s' is %d", max_cpus,
|
||||
"supported by machine '%s' is %d",
|
||||
current_machine->smp.max_cpus,
|
||||
machine_class->name, machine_class->max_cpus);
|
||||
exit(1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user