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:
Peter Maydell 2019-07-08 09:46:19 +01:00
commit 3a1acf5d47
79 changed files with 1687 additions and 936 deletions

View File

@ -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;

View File

@ -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
View File

@ -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
View File

@ -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;

View File

@ -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);

View File

@ -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));

View File

@ -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) {
/*

View File

@ -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)",

View File

@ -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)",

View File

@ -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)",

View File

@ -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];

View File

@ -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),

View File

@ -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);

View File

@ -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",

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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];

View File

@ -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)

View File

@ -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;

View File

@ -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);
}

View File

@ -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");
}

View File

@ -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, ", ");

View File

@ -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.
*/

View File

@ -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)

View File

@ -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();

View File

@ -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);

View File

@ -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);

View File

@ -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,

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View File

@ -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) {

View File

@ -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) {

View File

@ -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));

View File

@ -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};

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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++) {

View File

@ -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. "

View File

@ -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 */

View File

@ -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);

View File

@ -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());

View File

@ -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;
}

View File

@ -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++) {

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;
};

View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

@ -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)' }
##

View File

@ -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'
}

View File

@ -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.

View File

@ -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,

View File

@ -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

View File

@ -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);

View File

@ -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)
{

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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,

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View 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')

View File

@ -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);

View File

@ -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
View File

@ -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);
}