mirror of https://github.com/xemu-project/xemu.git
x86 and CPU queue, 2016-10-24
x2APIC support to APIC code, cpu_exec_init() refactor on all architectures, and other x86 changes. -----BEGIN PGP SIGNATURE----- iQIcBAABCAAGBQJYDmYyAAoJECgHk2+YTcWmoSUP/2ga+b9YmPuyL7XC+12pff0I Z8gdjUzbMUNcCI0JMZCTGUJbs3BapLcnsA7ypmt88s9kG02WeDMhNx1BfYiAFgLU kPLQlXAM7awEdGagd3sTCiFojSUZ7GxYHjd5fuhPoOAXvXM8im6zJl18ZcsnStjO /J8JGoGDHq1XJlz+RIjnGamojJWCiO/+iiD+rFmVSic8zjHPDYq14sIk/QJX+DaF azLiOI6DAlX3kyrN5ZshhIRQ3COzzUMUSDF/ZaYHjudUco5MBnwj/oLQniTq+ZUd hCu7dr5TpLxI7q1yltyd0UIl/+aZGbE8tEvoXAtc735iK4m2CTckT7ql6x3xI+Ir PmpPgIswHqfCiCXm8imLj6ZI47kRA1x4x4AudLaNVKP7jO82485sS9HWpOadYsaU jvek2SqfqvH+vce4FzwlLEcXGDb73MT/XkIUvd7SfPIbs9umgdZc03U4SHfAWr0i lAIRs4Ym0AAS2WSE4E09wvdUUr9oxaQBMhw3JAiNmg7hLfyINTP+D/IhtlAVXXEA F9D7fky5lDwfKvIwPxPJbDD5bCBV9AmxhiahIhv3epu4Kg4orf1inkrx0IZWSbB0 7+JZ7j8asuizfibkeZAN9rxVwmz32makJNsnjzZHlnaPxTvIDzvRkNceBnhC5vKq 3yfxgl4agXmMjveraAtt =T2kg -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/ehabkost/tags/x86-pull-request' into staging x86 and CPU queue, 2016-10-24 x2APIC support to APIC code, cpu_exec_init() refactor on all architectures, and other x86 changes. # gpg: Signature made Mon 24 Oct 2016 20:51:14 BST # gpg: using RSA key 0x2807936F984DC5A6 # gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>" # Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF D1AA 2807 936F 984D C5A6 * remotes/ehabkost/tags/x86-pull-request: exec: call cpu_exec_exit() from a CPU unrealize common function exec: move cpu_exec_init() calls to realize functions exec: split cpu_exec_init() pc: q35: Bump max_cpus to 288 pc: Require IRQ remapping and EIM if there could be x2APIC CPUs pc: Add 'etc/boot-cpus' fw_cfg file for machine with more than 255 CPUs Increase MAX_CPUMASK_BITS from 255 to 288 pc: Clarify FW_CFG_MAX_CPUS usage comment pc: kvm_apic: Pass APIC ID depending on xAPIC/x2APIC mode pc: apic_common: Reset APIC ID to initial ID when switching into x2APIC mode pc: apic_common: Restore APIC ID to initial ID on reset pc: apic_common: Extend APIC ID property to 32bit pc: Leave max apic_id_limit only in legacy cpu hotplug code acpi: cphp: Force switch to modern cpu hotplug if APIC ID > 254 pc: acpi: x2APIC support for SRAT table pc: acpi: x2APIC support for MADT table and _MAT method Conflicts: target-arm/cpu.c Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
c43e853afe
12
exec.c
12
exec.c
|
@ -630,7 +630,7 @@ AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void cpu_exec_exit(CPUState *cpu)
|
void cpu_exec_unrealizefn(CPUState *cpu)
|
||||||
{
|
{
|
||||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||||
|
|
||||||
|
@ -644,11 +644,8 @@ void cpu_exec_exit(CPUState *cpu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpu_exec_init(CPUState *cpu, Error **errp)
|
void cpu_exec_initfn(CPUState *cpu)
|
||||||
{
|
{
|
||||||
CPUClass *cc ATTRIBUTE_UNUSED = CPU_GET_CLASS(cpu);
|
|
||||||
Error *local_err ATTRIBUTE_UNUSED = NULL;
|
|
||||||
|
|
||||||
cpu->as = NULL;
|
cpu->as = NULL;
|
||||||
cpu->num_ases = 0;
|
cpu->num_ases = 0;
|
||||||
|
|
||||||
|
@ -669,6 +666,11 @@ void cpu_exec_init(CPUState *cpu, Error **errp)
|
||||||
cpu->memory = system_memory;
|
cpu->memory = system_memory;
|
||||||
object_ref(OBJECT(cpu->memory));
|
object_ref(OBJECT(cpu->memory));
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpu_exec_realizefn(CPUState *cpu, Error **errp)
|
||||||
|
{
|
||||||
|
CPUClass *cc ATTRIBUTE_UNUSED = CPU_GET_CLASS(cpu);
|
||||||
|
|
||||||
cpu_list_add(cpu);
|
cpu_list_add(cpu);
|
||||||
|
|
||||||
|
|
|
@ -531,6 +531,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
||||||
apic->flags = cpu_to_le32(1);
|
apic->flags = cpu_to_le32(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ACPI_APIC_LOCAL_X2APIC: {
|
||||||
|
AcpiMadtProcessorX2Apic *apic = (void *)madt_buf->data;
|
||||||
|
apic->flags = cpu_to_le32(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qom/cpu.h"
|
#include "qom/cpu.h"
|
||||||
#include "hw/i386/pc.h"
|
#include "hw/i386/pc.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
|
|
||||||
#define CPU_EJECT_METHOD "CPEJ"
|
#define CPU_EJECT_METHOD "CPEJ"
|
||||||
#define CPU_MAT_METHOD "CPMA"
|
#define CPU_MAT_METHOD "CPMA"
|
||||||
|
@ -63,7 +64,8 @@ static void acpi_set_cpu_present_bit(AcpiCpuHotplug *g, CPUState *cpu,
|
||||||
|
|
||||||
cpu_id = k->get_arch_id(cpu);
|
cpu_id = k->get_arch_id(cpu);
|
||||||
if ((cpu_id / 8) >= ACPI_GPE_PROC_LEN) {
|
if ((cpu_id / 8) >= ACPI_GPE_PROC_LEN) {
|
||||||
error_setg(errp, "acpi: invalid cpu id: %" PRIi64, cpu_id);
|
object_property_set_bool(g->device, false, "cpu-hotplug-legacy",
|
||||||
|
&error_abort);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,13 +87,14 @@ void legacy_acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
|
||||||
{
|
{
|
||||||
CPUState *cpu;
|
CPUState *cpu;
|
||||||
|
|
||||||
CPU_FOREACH(cpu) {
|
|
||||||
acpi_set_cpu_present_bit(gpe_cpu, cpu, &error_abort);
|
|
||||||
}
|
|
||||||
memory_region_init_io(&gpe_cpu->io, owner, &AcpiCpuHotplug_ops,
|
memory_region_init_io(&gpe_cpu->io, owner, &AcpiCpuHotplug_ops,
|
||||||
gpe_cpu, "acpi-cpu-hotplug", ACPI_GPE_PROC_LEN);
|
gpe_cpu, "acpi-cpu-hotplug", ACPI_GPE_PROC_LEN);
|
||||||
memory_region_add_subregion(parent, base, &gpe_cpu->io);
|
memory_region_add_subregion(parent, base, &gpe_cpu->io);
|
||||||
gpe_cpu->device = owner;
|
gpe_cpu->device = owner;
|
||||||
|
|
||||||
|
CPU_FOREACH(cpu) {
|
||||||
|
acpi_set_cpu_present_bit(gpe_cpu, cpu, &error_abort);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void acpi_switch_to_modern_cphp(AcpiCpuHotplug *gpe_cpu,
|
void acpi_switch_to_modern_cphp(AcpiCpuHotplug *gpe_cpu,
|
||||||
|
@ -234,7 +237,11 @@ void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine,
|
||||||
/* The current AML generator can cover the APIC ID range [0..255],
|
/* The current AML generator can cover the APIC ID range [0..255],
|
||||||
* inclusive, for VCPU hotplug. */
|
* inclusive, for VCPU hotplug. */
|
||||||
QEMU_BUILD_BUG_ON(ACPI_CPU_HOTPLUG_ID_LIMIT > 256);
|
QEMU_BUILD_BUG_ON(ACPI_CPU_HOTPLUG_ID_LIMIT > 256);
|
||||||
g_assert(pcms->apic_id_limit <= ACPI_CPU_HOTPLUG_ID_LIMIT);
|
if (pcms->apic_id_limit > ACPI_CPU_HOTPLUG_ID_LIMIT) {
|
||||||
|
error_report("max_cpus is too large. APIC ID of last CPU is %u",
|
||||||
|
pcms->apic_id_limit - 1);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
/* create PCI0.PRES device and its _CRS to reserve CPU hotplug MMIO */
|
/* create PCI0.PRES device and its _CRS to reserve CPU hotplug MMIO */
|
||||||
dev = aml_device("PCI0." stringify(CPU_HOTPLUG_RESOURCE_DEVICE));
|
dev = aml_device("PCI0." stringify(CPU_HOTPLUG_RESOURCE_DEVICE));
|
||||||
|
|
|
@ -1494,7 +1494,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
|
||||||
* it later in machvirt_init, where we have more information about the
|
* it later in machvirt_init, where we have more information about the
|
||||||
* configuration of the particular instance.
|
* configuration of the particular instance.
|
||||||
*/
|
*/
|
||||||
mc->max_cpus = MAX_CPUMASK_BITS;
|
mc->max_cpus = 255;
|
||||||
mc->has_dynamic_sysbus = true;
|
mc->has_dynamic_sysbus = true;
|
||||||
mc->block_default_type = IF_VIRTIO;
|
mc->block_default_type = IF_VIRTIO;
|
||||||
mc->no_cdrom = 1;
|
mc->no_cdrom = 1;
|
||||||
|
|
|
@ -340,10 +340,17 @@ build_fadt(GArray *table_data, BIOSLinker *linker, AcpiPmInfo *pm,
|
||||||
void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
|
void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
|
||||||
CPUArchIdList *apic_ids, GArray *entry)
|
CPUArchIdList *apic_ids, GArray *entry)
|
||||||
{
|
{
|
||||||
int apic_id;
|
uint32_t apic_id = apic_ids->cpus[uid].arch_id;
|
||||||
|
|
||||||
|
/* ACPI spec says that LAPIC entry for non present
|
||||||
|
* CPU may be omitted from MADT or it must be marked
|
||||||
|
* as disabled. However omitting non present CPU from
|
||||||
|
* MADT breaks hotplug on linux. So possible CPUs
|
||||||
|
* should be put in MADT but kept disabled.
|
||||||
|
*/
|
||||||
|
if (apic_id < 255) {
|
||||||
AcpiMadtProcessorApic *apic = acpi_data_push(entry, sizeof *apic);
|
AcpiMadtProcessorApic *apic = acpi_data_push(entry, sizeof *apic);
|
||||||
|
|
||||||
apic_id = apic_ids->cpus[uid].arch_id;
|
|
||||||
apic->type = ACPI_APIC_PROCESSOR;
|
apic->type = ACPI_APIC_PROCESSOR;
|
||||||
apic->length = sizeof(*apic);
|
apic->length = sizeof(*apic);
|
||||||
apic->processor_id = uid;
|
apic->processor_id = uid;
|
||||||
|
@ -351,14 +358,21 @@ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
|
||||||
if (apic_ids->cpus[uid].cpu != NULL) {
|
if (apic_ids->cpus[uid].cpu != NULL) {
|
||||||
apic->flags = cpu_to_le32(1);
|
apic->flags = cpu_to_le32(1);
|
||||||
} else {
|
} else {
|
||||||
/* ACPI spec says that LAPIC entry for non present
|
|
||||||
* CPU may be omitted from MADT or it must be marked
|
|
||||||
* as disabled. However omitting non present CPU from
|
|
||||||
* MADT breaks hotplug on linux. So possible CPUs
|
|
||||||
* should be put in MADT but kept disabled.
|
|
||||||
*/
|
|
||||||
apic->flags = cpu_to_le32(0);
|
apic->flags = cpu_to_le32(0);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
AcpiMadtProcessorX2Apic *apic = acpi_data_push(entry, sizeof *apic);
|
||||||
|
|
||||||
|
apic->type = ACPI_APIC_LOCAL_X2APIC;
|
||||||
|
apic->length = sizeof(*apic);
|
||||||
|
apic->uid = cpu_to_le32(uid);
|
||||||
|
apic->x2apic_id = cpu_to_le32(apic_id);
|
||||||
|
if (apic_ids->cpus[uid].cpu != NULL) {
|
||||||
|
apic->flags = cpu_to_le32(1);
|
||||||
|
} else {
|
||||||
|
apic->flags = cpu_to_le32(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -369,11 +383,11 @@ build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
|
||||||
int madt_start = table_data->len;
|
int madt_start = table_data->len;
|
||||||
AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(pcms->acpi_dev);
|
AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(pcms->acpi_dev);
|
||||||
AcpiDeviceIf *adev = ACPI_DEVICE_IF(pcms->acpi_dev);
|
AcpiDeviceIf *adev = ACPI_DEVICE_IF(pcms->acpi_dev);
|
||||||
|
bool x2apic_mode = false;
|
||||||
|
|
||||||
AcpiMultipleApicTable *madt;
|
AcpiMultipleApicTable *madt;
|
||||||
AcpiMadtIoApic *io_apic;
|
AcpiMadtIoApic *io_apic;
|
||||||
AcpiMadtIntsrcovr *intsrcovr;
|
AcpiMadtIntsrcovr *intsrcovr;
|
||||||
AcpiMadtLocalNmi *local_nmi;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
madt = acpi_data_push(table_data, sizeof *madt);
|
madt = acpi_data_push(table_data, sizeof *madt);
|
||||||
|
@ -382,6 +396,9 @@ build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
|
||||||
|
|
||||||
for (i = 0; i < apic_ids->len; i++) {
|
for (i = 0; i < apic_ids->len; i++) {
|
||||||
adevc->madt_cpu(adev, i, apic_ids, table_data);
|
adevc->madt_cpu(adev, i, apic_ids, table_data);
|
||||||
|
if (apic_ids->cpus[i].arch_id > 254) {
|
||||||
|
x2apic_mode = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
g_free(apic_ids);
|
g_free(apic_ids);
|
||||||
|
|
||||||
|
@ -414,12 +431,25 @@ build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
|
||||||
intsrcovr->flags = cpu_to_le16(0xd); /* active high, level triggered */
|
intsrcovr->flags = cpu_to_le16(0xd); /* active high, level triggered */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (x2apic_mode) {
|
||||||
|
AcpiMadtLocalX2ApicNmi *local_nmi;
|
||||||
|
|
||||||
|
local_nmi = acpi_data_push(table_data, sizeof *local_nmi);
|
||||||
|
local_nmi->type = ACPI_APIC_LOCAL_X2APIC_NMI;
|
||||||
|
local_nmi->length = sizeof(*local_nmi);
|
||||||
|
local_nmi->uid = 0xFFFFFFFF; /* all processors */
|
||||||
|
local_nmi->flags = cpu_to_le16(0);
|
||||||
|
local_nmi->lint = 1; /* ACPI_LINT1 */
|
||||||
|
} else {
|
||||||
|
AcpiMadtLocalNmi *local_nmi;
|
||||||
|
|
||||||
local_nmi = acpi_data_push(table_data, sizeof *local_nmi);
|
local_nmi = acpi_data_push(table_data, sizeof *local_nmi);
|
||||||
local_nmi->type = ACPI_APIC_LOCAL_NMI;
|
local_nmi->type = ACPI_APIC_LOCAL_NMI;
|
||||||
local_nmi->length = sizeof(*local_nmi);
|
local_nmi->length = sizeof(*local_nmi);
|
||||||
local_nmi->processor_id = 0xff; /* all processors */
|
local_nmi->processor_id = 0xff; /* all processors */
|
||||||
local_nmi->flags = cpu_to_le16(0);
|
local_nmi->flags = cpu_to_le16(0);
|
||||||
local_nmi->lint = 1; /* ACPI_LINT1 */
|
local_nmi->lint = 1; /* ACPI_LINT1 */
|
||||||
|
}
|
||||||
|
|
||||||
build_header(linker, table_data,
|
build_header(linker, table_data,
|
||||||
(void *)(table_data->data + madt_start), "APIC",
|
(void *)(table_data->data + madt_start), "APIC",
|
||||||
|
@ -2391,7 +2421,6 @@ static void
|
||||||
build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||||
{
|
{
|
||||||
AcpiSystemResourceAffinityTable *srat;
|
AcpiSystemResourceAffinityTable *srat;
|
||||||
AcpiSratProcessorAffinity *core;
|
|
||||||
AcpiSratMemoryAffinity *numamem;
|
AcpiSratMemoryAffinity *numamem;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
@ -2411,7 +2440,10 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||||
|
|
||||||
for (i = 0; i < apic_ids->len; i++) {
|
for (i = 0; i < apic_ids->len; i++) {
|
||||||
int j = numa_get_node_for_cpu(i);
|
int j = numa_get_node_for_cpu(i);
|
||||||
int apic_id = apic_ids->cpus[i].arch_id;
|
uint32_t apic_id = apic_ids->cpus[i].arch_id;
|
||||||
|
|
||||||
|
if (apic_id < 255) {
|
||||||
|
AcpiSratProcessorAffinity *core;
|
||||||
|
|
||||||
core = acpi_data_push(table_data, sizeof *core);
|
core = acpi_data_push(table_data, sizeof *core);
|
||||||
core->type = ACPI_SRAT_PROCESSOR_APIC;
|
core->type = ACPI_SRAT_PROCESSOR_APIC;
|
||||||
|
@ -2423,6 +2455,18 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||||
memset(core->proximity_hi, 0, 3);
|
memset(core->proximity_hi, 0, 3);
|
||||||
core->local_sapic_eid = 0;
|
core->local_sapic_eid = 0;
|
||||||
core->flags = cpu_to_le32(1);
|
core->flags = cpu_to_le32(1);
|
||||||
|
} else {
|
||||||
|
AcpiSratProcessorX2ApicAffinity *core;
|
||||||
|
|
||||||
|
core = acpi_data_push(table_data, sizeof *core);
|
||||||
|
core->type = ACPI_SRAT_PROCESSOR_x2APIC;
|
||||||
|
core->length = sizeof(*core);
|
||||||
|
core->x2apic_id = cpu_to_le32(apic_id);
|
||||||
|
if (j < nb_numa_nodes) {
|
||||||
|
core->proximity_domain = cpu_to_le32(j);
|
||||||
|
}
|
||||||
|
core->flags = cpu_to_le32(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,11 @@ static void kvm_put_apic_state(APICCommonState *s, struct kvm_lapic_state *kapic
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
memset(kapic, 0, sizeof(*kapic));
|
memset(kapic, 0, sizeof(*kapic));
|
||||||
|
if (kvm_has_x2apic_api() && s->apicbase & MSR_IA32_APICBASE_EXTD) {
|
||||||
|
kvm_apic_set_reg(kapic, 0x2, s->initial_apic_id);
|
||||||
|
} else {
|
||||||
kvm_apic_set_reg(kapic, 0x2, s->id << 24);
|
kvm_apic_set_reg(kapic, 0x2, s->id << 24);
|
||||||
|
}
|
||||||
kvm_apic_set_reg(kapic, 0x8, s->tpr);
|
kvm_apic_set_reg(kapic, 0x8, s->tpr);
|
||||||
kvm_apic_set_reg(kapic, 0xd, s->log_dest << 24);
|
kvm_apic_set_reg(kapic, 0xd, s->log_dest << 24);
|
||||||
kvm_apic_set_reg(kapic, 0xe, s->dest_mode << 28 | 0x0fffffff);
|
kvm_apic_set_reg(kapic, 0xe, s->dest_mode << 28 | 0x0fffffff);
|
||||||
|
@ -59,7 +63,11 @@ void kvm_get_apic_state(DeviceState *dev, struct kvm_lapic_state *kapic)
|
||||||
APICCommonState *s = APIC_COMMON(dev);
|
APICCommonState *s = APIC_COMMON(dev);
|
||||||
int i, v;
|
int i, v;
|
||||||
|
|
||||||
|
if (kvm_has_x2apic_api() && s->apicbase & MSR_IA32_APICBASE_EXTD) {
|
||||||
|
assert(kvm_apic_get_reg(kapic, 0x2) == s->initial_apic_id);
|
||||||
|
} else {
|
||||||
s->id = kvm_apic_get_reg(kapic, 0x2) >> 24;
|
s->id = kvm_apic_get_reg(kapic, 0x2) >> 24;
|
||||||
|
}
|
||||||
s->tpr = kvm_apic_get_reg(kapic, 0x8);
|
s->tpr = kvm_apic_get_reg(kapic, 0x8);
|
||||||
s->arb_id = kvm_apic_get_reg(kapic, 0x9);
|
s->arb_id = kvm_apic_get_reg(kapic, 0x9);
|
||||||
s->log_dest = kvm_apic_get_reg(kapic, 0xd) >> 24;
|
s->log_dest = kvm_apic_get_reg(kapic, 0xd) >> 24;
|
||||||
|
|
82
hw/i386/pc.c
82
hw/i386/pc.c
|
@ -68,6 +68,7 @@
|
||||||
#include "qapi-visit.h"
|
#include "qapi-visit.h"
|
||||||
#include "qom/cpu.h"
|
#include "qom/cpu.h"
|
||||||
#include "hw/nmi.h"
|
#include "hw/nmi.h"
|
||||||
|
#include "hw/i386/intel_iommu.h"
|
||||||
|
|
||||||
/* debug PC/ISA interrupts */
|
/* debug PC/ISA interrupts */
|
||||||
//#define DEBUG_IRQ
|
//#define DEBUG_IRQ
|
||||||
|
@ -746,17 +747,15 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms)
|
||||||
|
|
||||||
/* FW_CFG_MAX_CPUS is a bit confusing/problematic on x86:
|
/* FW_CFG_MAX_CPUS is a bit confusing/problematic on x86:
|
||||||
*
|
*
|
||||||
* SeaBIOS needs FW_CFG_MAX_CPUS for CPU hotplug, but the CPU hotplug
|
* For machine types prior to 1.8, SeaBIOS needs FW_CFG_MAX_CPUS for
|
||||||
* QEMU<->SeaBIOS interface is not based on the "CPU index", but on the APIC
|
* building MPTable, ACPI MADT, ACPI CPU hotplug and ACPI SRAT table,
|
||||||
* ID of hotplugged CPUs[1]. This means that FW_CFG_MAX_CPUS is not the
|
* that tables are based on xAPIC ID and QEMU<->SeaBIOS interface
|
||||||
* "maximum number of CPUs", but the "limit to the APIC ID values SeaBIOS
|
* for CPU hotplug also uses APIC ID and not "CPU index".
|
||||||
* may see".
|
* This means that FW_CFG_MAX_CPUS is not the "maximum number of CPUs",
|
||||||
|
* but the "limit to the APIC ID values SeaBIOS may see".
|
||||||
*
|
*
|
||||||
* So, this means we must not use max_cpus, here, but the maximum possible
|
* So for compatibility reasons with old BIOSes we are stuck with
|
||||||
* APIC ID value, plus one.
|
* "etc/max-cpus" actually being apic_id_limit
|
||||||
*
|
|
||||||
* [1] The only kind of "CPU identifier" used between SeaBIOS and QEMU is
|
|
||||||
* the APIC ID, not the "CPU index"
|
|
||||||
*/
|
*/
|
||||||
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)pcms->apic_id_limit);
|
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)pcms->apic_id_limit);
|
||||||
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
|
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
|
||||||
|
@ -1087,17 +1086,6 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pc_present_cpus_count(PCMachineState *pcms)
|
|
||||||
{
|
|
||||||
int i, boot_cpus = 0;
|
|
||||||
for (i = 0; i < pcms->possible_cpus->len; i++) {
|
|
||||||
if (pcms->possible_cpus->cpus[i].cpu) {
|
|
||||||
boot_cpus++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return boot_cpus;
|
|
||||||
}
|
|
||||||
|
|
||||||
static X86CPU *pc_new_cpu(const char *typename, int64_t apic_id,
|
static X86CPU *pc_new_cpu(const char *typename, int64_t apic_id,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
@ -1190,12 +1178,6 @@ void pc_cpus_init(PCMachineState *pcms)
|
||||||
* This is used for FW_CFG_MAX_CPUS. See comments on bochs_bios_init().
|
* This is used for FW_CFG_MAX_CPUS. See comments on bochs_bios_init().
|
||||||
*/
|
*/
|
||||||
pcms->apic_id_limit = x86_cpu_apic_id_from_index(max_cpus - 1) + 1;
|
pcms->apic_id_limit = x86_cpu_apic_id_from_index(max_cpus - 1) + 1;
|
||||||
if (pcms->apic_id_limit > ACPI_CPU_HOTPLUG_ID_LIMIT) {
|
|
||||||
error_report("max_cpus is too large. APIC ID of last CPU is %u",
|
|
||||||
pcms->apic_id_limit - 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
pcms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
|
pcms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
|
||||||
sizeof(CPUArchId) * max_cpus);
|
sizeof(CPUArchId) * max_cpus);
|
||||||
for (i = 0; i < max_cpus; i++) {
|
for (i = 0; i < max_cpus; i++) {
|
||||||
|
@ -1240,6 +1222,19 @@ static void pc_build_feature_control_file(PCMachineState *pcms)
|
||||||
fw_cfg_add_file(pcms->fw_cfg, "etc/msr_feature_control", val, sizeof(*val));
|
fw_cfg_add_file(pcms->fw_cfg, "etc/msr_feature_control", val, sizeof(*val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count)
|
||||||
|
{
|
||||||
|
if (cpus_count > 0xff) {
|
||||||
|
/* If the number of CPUs can't be represented in 8 bits, the
|
||||||
|
* BIOS must use "etc/boot-cpus". Set RTC field to 0 just
|
||||||
|
* to make old BIOSes fail more predictably.
|
||||||
|
*/
|
||||||
|
rtc_set_memory(rtc, 0x5f, 0);
|
||||||
|
} else {
|
||||||
|
rtc_set_memory(rtc, 0x5f, cpus_count - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void pc_machine_done(Notifier *notifier, void *data)
|
void pc_machine_done(Notifier *notifier, void *data)
|
||||||
{
|
{
|
||||||
|
@ -1248,7 +1243,7 @@ void pc_machine_done(Notifier *notifier, void *data)
|
||||||
PCIBus *bus = pcms->bus;
|
PCIBus *bus = pcms->bus;
|
||||||
|
|
||||||
/* set the number of CPUs */
|
/* set the number of CPUs */
|
||||||
rtc_set_memory(pcms->rtc, 0x5f, pc_present_cpus_count(pcms) - 1);
|
rtc_set_cpus_count(pcms->rtc, le16_to_cpu(pcms->boot_cpus_le));
|
||||||
|
|
||||||
if (bus) {
|
if (bus) {
|
||||||
int extra_hosts = 0;
|
int extra_hosts = 0;
|
||||||
|
@ -1269,8 +1264,28 @@ void pc_machine_done(Notifier *notifier, void *data)
|
||||||
|
|
||||||
acpi_setup();
|
acpi_setup();
|
||||||
if (pcms->fw_cfg) {
|
if (pcms->fw_cfg) {
|
||||||
|
MachineClass *mc = MACHINE_GET_CLASS(pcms);
|
||||||
|
|
||||||
pc_build_smbios(pcms->fw_cfg);
|
pc_build_smbios(pcms->fw_cfg);
|
||||||
pc_build_feature_control_file(pcms);
|
pc_build_feature_control_file(pcms);
|
||||||
|
|
||||||
|
if (mc->max_cpus > 255) {
|
||||||
|
fw_cfg_add_file(pcms->fw_cfg, "etc/boot-cpus", &pcms->boot_cpus_le,
|
||||||
|
sizeof(pcms->boot_cpus_le));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pcms->apic_id_limit > 255) {
|
||||||
|
IntelIOMMUState *iommu = INTEL_IOMMU_DEVICE(x86_iommu_get_default());
|
||||||
|
|
||||||
|
if (!iommu || !iommu->x86_iommu.intr_supported ||
|
||||||
|
iommu->intr_eim != ON_OFF_AUTO_ON) {
|
||||||
|
error_report("current -smp configuration requires "
|
||||||
|
"Extended Interrupt Mode enabled. "
|
||||||
|
"You can add an IOMMU using: "
|
||||||
|
"-device intel-iommu,intremap=on,eim=on");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1794,9 +1809,11 @@ static void pc_cpu_plug(HotplugHandler *hotplug_dev,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->hotplugged) {
|
|
||||||
/* increment the number of CPUs */
|
/* increment the number of CPUs */
|
||||||
rtc_set_memory(pcms->rtc, 0x5f, rtc_get_memory(pcms->rtc, 0x5f) + 1);
|
pcms->boot_cpus_le = cpu_to_le16(le16_to_cpu(pcms->boot_cpus_le) + 1);
|
||||||
|
if (dev->hotplugged) {
|
||||||
|
/* Update the number of CPUs in CMOS */
|
||||||
|
rtc_set_cpus_count(pcms->rtc, le16_to_cpu(pcms->boot_cpus_le));
|
||||||
}
|
}
|
||||||
|
|
||||||
found_cpu = pc_find_cpu_slot(pcms, CPU(dev), NULL);
|
found_cpu = pc_find_cpu_slot(pcms, CPU(dev), NULL);
|
||||||
|
@ -1850,7 +1867,10 @@ static void pc_cpu_unplug_cb(HotplugHandler *hotplug_dev,
|
||||||
found_cpu->cpu = NULL;
|
found_cpu->cpu = NULL;
|
||||||
object_unparent(OBJECT(dev));
|
object_unparent(OBJECT(dev));
|
||||||
|
|
||||||
rtc_set_memory(pcms->rtc, 0x5f, rtc_get_memory(pcms->rtc, 0x5f) - 1);
|
/* decrement the number of CPUs */
|
||||||
|
pcms->boot_cpus_le = cpu_to_le16(le16_to_cpu(pcms->boot_cpus_le) - 1);
|
||||||
|
/* Update the number of CPUs in CMOS */
|
||||||
|
rtc_set_cpus_count(pcms->rtc, le16_to_cpu(pcms->boot_cpus_le));
|
||||||
out:
|
out:
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
}
|
}
|
||||||
|
|
|
@ -291,6 +291,7 @@ static void pc_q35_machine_options(MachineClass *m)
|
||||||
m->default_display = "std";
|
m->default_display = "std";
|
||||||
m->no_floppy = 1;
|
m->no_floppy = 1;
|
||||||
m->has_dynamic_sysbus = true;
|
m->has_dynamic_sysbus = true;
|
||||||
|
m->max_cpus = 288;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_q35_2_8_machine_options(MachineClass *m)
|
static void pc_q35_2_8_machine_options(MachineClass *m)
|
||||||
|
@ -306,6 +307,7 @@ static void pc_q35_2_7_machine_options(MachineClass *m)
|
||||||
{
|
{
|
||||||
pc_q35_2_8_machine_options(m);
|
pc_q35_2_8_machine_options(m);
|
||||||
m->alias = NULL;
|
m->alias = NULL;
|
||||||
|
m->max_cpus = 255;
|
||||||
SET_MACHINE_COMPAT(m, PC_COMPAT_2_7);
|
SET_MACHINE_COMPAT(m, PC_COMPAT_2_7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "qapi/visitor.h"
|
||||||
#include "hw/i386/apic.h"
|
#include "hw/i386/apic.h"
|
||||||
#include "hw/i386/apic_internal.h"
|
#include "hw/i386/apic_internal.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
@ -39,6 +40,11 @@ void cpu_set_apic_base(DeviceState *dev, uint64_t val)
|
||||||
if (dev) {
|
if (dev) {
|
||||||
APICCommonState *s = APIC_COMMON(dev);
|
APICCommonState *s = APIC_COMMON(dev);
|
||||||
APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
|
APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
|
||||||
|
/* switching to x2APIC, reset possibly modified xAPIC ID */
|
||||||
|
if (!(s->apicbase & MSR_IA32_APICBASE_EXTD) &&
|
||||||
|
(val & MSR_IA32_APICBASE_EXTD)) {
|
||||||
|
s->id = s->initial_apic_id;
|
||||||
|
}
|
||||||
info->set_base(s, val);
|
info->set_base(s, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,6 +248,7 @@ static void apic_reset_common(DeviceState *dev)
|
||||||
|
|
||||||
bsp = s->apicbase & MSR_IA32_APICBASE_BSP;
|
bsp = s->apicbase & MSR_IA32_APICBASE_BSP;
|
||||||
s->apicbase = APIC_DEFAULT_ADDRESS | bsp | MSR_IA32_APICBASE_ENABLE;
|
s->apicbase = APIC_DEFAULT_ADDRESS | bsp | MSR_IA32_APICBASE_ENABLE;
|
||||||
|
s->id = s->initial_apic_id;
|
||||||
|
|
||||||
s->vapic_paddr = 0;
|
s->vapic_paddr = 0;
|
||||||
info->vapic_base_update(s);
|
info->vapic_base_update(s);
|
||||||
|
@ -428,7 +435,6 @@ static const VMStateDescription vmstate_apic_common = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static Property apic_properties_common[] = {
|
static Property apic_properties_common[] = {
|
||||||
DEFINE_PROP_UINT8("id", APICCommonState, id, -1),
|
|
||||||
DEFINE_PROP_UINT8("version", APICCommonState, version, 0x14),
|
DEFINE_PROP_UINT8("version", APICCommonState, version, 0x14),
|
||||||
DEFINE_PROP_BIT("vapic", APICCommonState, vapic_control, VAPIC_ENABLE_BIT,
|
DEFINE_PROP_BIT("vapic", APICCommonState, vapic_control, VAPIC_ENABLE_BIT,
|
||||||
true),
|
true),
|
||||||
|
@ -437,6 +443,49 @@ static Property apic_properties_common[] = {
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void apic_common_get_id(Object *obj, Visitor *v, const char *name,
|
||||||
|
void *opaque, Error **errp)
|
||||||
|
{
|
||||||
|
APICCommonState *s = APIC_COMMON(obj);
|
||||||
|
int64_t value;
|
||||||
|
|
||||||
|
value = s->apicbase & MSR_IA32_APICBASE_EXTD ? s->initial_apic_id : s->id;
|
||||||
|
visit_type_int(v, name, &value, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void apic_common_set_id(Object *obj, Visitor *v, const char *name,
|
||||||
|
void *opaque, Error **errp)
|
||||||
|
{
|
||||||
|
APICCommonState *s = APIC_COMMON(obj);
|
||||||
|
DeviceState *dev = DEVICE(obj);
|
||||||
|
Error *local_err = NULL;
|
||||||
|
int64_t value;
|
||||||
|
|
||||||
|
if (dev->realized) {
|
||||||
|
qdev_prop_set_after_realize(dev, name, errp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_type_int(v, name, &value, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->initial_apic_id = value;
|
||||||
|
s->id = (uint8_t)value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void apic_common_initfn(Object *obj)
|
||||||
|
{
|
||||||
|
APICCommonState *s = APIC_COMMON(obj);
|
||||||
|
|
||||||
|
s->id = s->initial_apic_id = -1;
|
||||||
|
object_property_add(obj, "id", "int",
|
||||||
|
apic_common_get_id,
|
||||||
|
apic_common_set_id, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void apic_common_class_init(ObjectClass *klass, void *data)
|
static void apic_common_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
@ -456,6 +505,7 @@ static const TypeInfo apic_common_type = {
|
||||||
.name = TYPE_APIC_COMMON,
|
.name = TYPE_APIC_COMMON,
|
||||||
.parent = TYPE_DEVICE,
|
.parent = TYPE_DEVICE,
|
||||||
.instance_size = sizeof(APICCommonState),
|
.instance_size = sizeof(APICCommonState),
|
||||||
|
.instance_init = apic_common_initfn,
|
||||||
.class_size = sizeof(APICCommonClass),
|
.class_size = sizeof(APICCommonClass),
|
||||||
.class_init = apic_common_class_init,
|
.class_init = apic_common_class_init,
|
||||||
.abstract = true,
|
.abstract = true,
|
||||||
|
|
|
@ -2438,7 +2438,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
|
||||||
mc->init = ppc_spapr_init;
|
mc->init = ppc_spapr_init;
|
||||||
mc->reset = ppc_spapr_reset;
|
mc->reset = ppc_spapr_reset;
|
||||||
mc->block_default_type = IF_SCSI;
|
mc->block_default_type = IF_SCSI;
|
||||||
mc->max_cpus = MAX_CPUMASK_BITS;
|
mc->max_cpus = 255;
|
||||||
mc->no_parallel = 1;
|
mc->no_parallel = 1;
|
||||||
mc->default_boot_order = "";
|
mc->default_boot_order = "";
|
||||||
mc->default_ram_size = 512 * M_BYTE;
|
mc->default_ram_size = 512 * M_BYTE;
|
||||||
|
|
|
@ -57,7 +57,6 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||||
uint32_t flags,
|
uint32_t flags,
|
||||||
int cflags);
|
int cflags);
|
||||||
|
|
||||||
void cpu_exec_init(CPUState *cpu, Error **errp);
|
|
||||||
void QEMU_NORETURN cpu_loop_exit(CPUState *cpu);
|
void QEMU_NORETURN cpu_loop_exit(CPUState *cpu);
|
||||||
void QEMU_NORETURN cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc);
|
void QEMU_NORETURN cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc);
|
||||||
|
|
||||||
|
|
|
@ -343,6 +343,24 @@ struct AcpiMadtLocalNmi {
|
||||||
} QEMU_PACKED;
|
} QEMU_PACKED;
|
||||||
typedef struct AcpiMadtLocalNmi AcpiMadtLocalNmi;
|
typedef struct AcpiMadtLocalNmi AcpiMadtLocalNmi;
|
||||||
|
|
||||||
|
struct AcpiMadtProcessorX2Apic {
|
||||||
|
ACPI_SUB_HEADER_DEF
|
||||||
|
uint16_t reserved;
|
||||||
|
uint32_t x2apic_id; /* Processor's local x2APIC ID */
|
||||||
|
uint32_t flags;
|
||||||
|
uint32_t uid; /* Processor object _UID */
|
||||||
|
} QEMU_PACKED;
|
||||||
|
typedef struct AcpiMadtProcessorX2Apic AcpiMadtProcessorX2Apic;
|
||||||
|
|
||||||
|
struct AcpiMadtLocalX2ApicNmi {
|
||||||
|
ACPI_SUB_HEADER_DEF
|
||||||
|
uint16_t flags; /* MPS INTI flags */
|
||||||
|
uint32_t uid; /* Processor object _UID */
|
||||||
|
uint8_t lint; /* Local APIC LINT# */
|
||||||
|
uint8_t reserved[3]; /* Local APIC LINT# */
|
||||||
|
} QEMU_PACKED;
|
||||||
|
typedef struct AcpiMadtLocalX2ApicNmi AcpiMadtLocalX2ApicNmi;
|
||||||
|
|
||||||
struct AcpiMadtGenericInterrupt {
|
struct AcpiMadtGenericInterrupt {
|
||||||
ACPI_SUB_HEADER_DEF
|
ACPI_SUB_HEADER_DEF
|
||||||
uint16_t reserved;
|
uint16_t reserved;
|
||||||
|
@ -485,6 +503,17 @@ struct AcpiSratProcessorAffinity
|
||||||
} QEMU_PACKED;
|
} QEMU_PACKED;
|
||||||
typedef struct AcpiSratProcessorAffinity AcpiSratProcessorAffinity;
|
typedef struct AcpiSratProcessorAffinity AcpiSratProcessorAffinity;
|
||||||
|
|
||||||
|
struct AcpiSratProcessorX2ApicAffinity {
|
||||||
|
ACPI_SUB_HEADER_DEF
|
||||||
|
uint16_t reserved;
|
||||||
|
uint32_t proximity_domain;
|
||||||
|
uint32_t x2apic_id;
|
||||||
|
uint32_t flags;
|
||||||
|
uint32_t clk_domain;
|
||||||
|
uint32_t reserved2;
|
||||||
|
} QEMU_PACKED;
|
||||||
|
typedef struct AcpiSratProcessorX2ApicAffinity AcpiSratProcessorX2ApicAffinity;
|
||||||
|
|
||||||
struct AcpiSratMemoryAffinity
|
struct AcpiSratMemoryAffinity
|
||||||
{
|
{
|
||||||
ACPI_SUB_HEADER_DEF
|
ACPI_SUB_HEADER_DEF
|
||||||
|
|
|
@ -160,7 +160,8 @@ struct APICCommonState {
|
||||||
MemoryRegion io_memory;
|
MemoryRegion io_memory;
|
||||||
X86CPU *cpu;
|
X86CPU *cpu;
|
||||||
uint32_t apicbase;
|
uint32_t apicbase;
|
||||||
uint8_t id;
|
uint8_t id; /* legacy APIC ID */
|
||||||
|
uint32_t initial_apic_id;
|
||||||
uint8_t version;
|
uint8_t version;
|
||||||
uint8_t arb_id;
|
uint8_t arb_id;
|
||||||
uint8_t tpr;
|
uint8_t tpr;
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
/**
|
/**
|
||||||
* PCMachineState:
|
* PCMachineState:
|
||||||
* @acpi_dev: link to ACPI PM device that performs ACPI hotplug handling
|
* @acpi_dev: link to ACPI PM device that performs ACPI hotplug handling
|
||||||
|
* @boot_cpus_le: number of present VCPUs, referenced by 'etc/boot-cpus' fw_cfg
|
||||||
*/
|
*/
|
||||||
struct PCMachineState {
|
struct PCMachineState {
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
|
@ -69,6 +70,7 @@ struct PCMachineState {
|
||||||
bool apic_xrupt_override;
|
bool apic_xrupt_override;
|
||||||
unsigned apic_id_limit;
|
unsigned apic_id_limit;
|
||||||
CPUArchIdList *possible_cpus;
|
CPUArchIdList *possible_cpus;
|
||||||
|
uint16_t boot_cpus_le;
|
||||||
|
|
||||||
/* NUMA information: */
|
/* NUMA information: */
|
||||||
uint64_t numa_nodes;
|
uint64_t numa_nodes;
|
||||||
|
|
|
@ -946,7 +946,9 @@ AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx);
|
||||||
|
|
||||||
void QEMU_NORETURN cpu_abort(CPUState *cpu, const char *fmt, ...)
|
void QEMU_NORETURN cpu_abort(CPUState *cpu, const char *fmt, ...)
|
||||||
GCC_FMT_ATTR(2, 3);
|
GCC_FMT_ATTR(2, 3);
|
||||||
void cpu_exec_exit(CPUState *cpu);
|
void cpu_exec_initfn(CPUState *cpu);
|
||||||
|
void cpu_exec_realizefn(CPUState *cpu, Error **errp);
|
||||||
|
void cpu_exec_unrealizefn(CPUState *cpu);
|
||||||
|
|
||||||
#ifdef CONFIG_SOFTMMU
|
#ifdef CONFIG_SOFTMMU
|
||||||
extern const struct VMStateDescription vmstate_cpu_common;
|
extern const struct VMStateDescription vmstate_cpu_common;
|
||||||
|
|
|
@ -173,7 +173,7 @@ extern int mem_prealloc;
|
||||||
*
|
*
|
||||||
* Note that cpu->get_arch_id() may be larger than MAX_CPUMASK_BITS.
|
* Note that cpu->get_arch_id() may be larger than MAX_CPUMASK_BITS.
|
||||||
*/
|
*/
|
||||||
#define MAX_CPUMASK_BITS 255
|
#define MAX_CPUMASK_BITS 288
|
||||||
|
|
||||||
#define MAX_OPTION_ROMS 16
|
#define MAX_OPTION_ROMS 16
|
||||||
typedef struct QEMUOptionRom {
|
typedef struct QEMUOptionRom {
|
||||||
|
|
10
qom/cpu.c
10
qom/cpu.c
|
@ -345,6 +345,12 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp)
|
||||||
trace_init_vcpu(cpu);
|
trace_init_vcpu(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cpu_common_unrealizefn(DeviceState *dev, Error **errp)
|
||||||
|
{
|
||||||
|
CPUState *cpu = CPU(dev);
|
||||||
|
cpu_exec_unrealizefn(cpu);
|
||||||
|
}
|
||||||
|
|
||||||
static void cpu_common_initfn(Object *obj)
|
static void cpu_common_initfn(Object *obj)
|
||||||
{
|
{
|
||||||
CPUState *cpu = CPU(obj);
|
CPUState *cpu = CPU(obj);
|
||||||
|
@ -362,12 +368,13 @@ static void cpu_common_initfn(Object *obj)
|
||||||
QTAILQ_INIT(&cpu->watchpoints);
|
QTAILQ_INIT(&cpu->watchpoints);
|
||||||
|
|
||||||
cpu->trace_dstate = bitmap_new(trace_get_vcpu_event_count());
|
cpu->trace_dstate = bitmap_new(trace_get_vcpu_event_count());
|
||||||
|
|
||||||
|
cpu_exec_initfn(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cpu_common_finalize(Object *obj)
|
static void cpu_common_finalize(Object *obj)
|
||||||
{
|
{
|
||||||
CPUState *cpu = CPU(obj);
|
CPUState *cpu = CPU(obj);
|
||||||
cpu_exec_exit(cpu);
|
|
||||||
g_free(cpu->trace_dstate);
|
g_free(cpu->trace_dstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,6 +408,7 @@ static void cpu_class_init(ObjectClass *klass, void *data)
|
||||||
k->cpu_exec_exit = cpu_common_noop;
|
k->cpu_exec_exit = cpu_common_noop;
|
||||||
k->cpu_exec_interrupt = cpu_common_exec_interrupt;
|
k->cpu_exec_interrupt = cpu_common_exec_interrupt;
|
||||||
dc->realize = cpu_common_realizefn;
|
dc->realize = cpu_common_realizefn;
|
||||||
|
dc->unrealize = cpu_common_unrealizefn;
|
||||||
/*
|
/*
|
||||||
* Reason: CPUs still need special care by board code: wiring up
|
* Reason: CPUs still need special care by board code: wiring up
|
||||||
* IRQs, adding reset handlers, halting non-first CPUs, ...
|
* IRQs, adding reset handlers, halting non-first CPUs, ...
|
||||||
|
|
|
@ -59,6 +59,13 @@ static void alpha_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
CPUState *cs = CPU(dev);
|
CPUState *cs = CPU(dev);
|
||||||
AlphaCPUClass *acc = ALPHA_CPU_GET_CLASS(dev);
|
AlphaCPUClass *acc = ALPHA_CPU_GET_CLASS(dev);
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
cpu_exec_realizefn(cs, &local_err);
|
||||||
|
if (local_err != NULL) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
qemu_init_vcpu(cs);
|
qemu_init_vcpu(cs);
|
||||||
|
|
||||||
|
@ -266,7 +273,6 @@ static void alpha_cpu_initfn(Object *obj)
|
||||||
CPUAlphaState *env = &cpu->env;
|
CPUAlphaState *env = &cpu->env;
|
||||||
|
|
||||||
cs->env_ptr = env;
|
cs->env_ptr = env;
|
||||||
cpu_exec_init(cs, &error_abort);
|
|
||||||
tlb_flush(cs, 1);
|
tlb_flush(cs, 1);
|
||||||
|
|
||||||
alpha_translate_init();
|
alpha_translate_init();
|
||||||
|
@ -309,13 +315,6 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data)
|
||||||
cc->disas_set_info = alpha_cpu_disas_set_info;
|
cc->disas_set_info = alpha_cpu_disas_set_info;
|
||||||
|
|
||||||
cc->gdb_num_core_regs = 67;
|
cc->gdb_num_core_regs = 67;
|
||||||
|
|
||||||
/*
|
|
||||||
* Reason: alpha_cpu_initfn() calls cpu_exec_init(), which saves
|
|
||||||
* the object in cpus -> dangling pointer after final
|
|
||||||
* object_unref().
|
|
||||||
*/
|
|
||||||
dc->cannot_destroy_with_object_finalize_yet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo alpha_cpu_type_info = {
|
static const TypeInfo alpha_cpu_type_info = {
|
||||||
|
|
|
@ -80,9 +80,11 @@ void arm_gt_stimer_cb(void *opaque);
|
||||||
#define ARM_AFF2_MASK (0xFFULL << ARM_AFF2_SHIFT)
|
#define ARM_AFF2_MASK (0xFFULL << ARM_AFF2_SHIFT)
|
||||||
#define ARM_AFF3_SHIFT 32
|
#define ARM_AFF3_SHIFT 32
|
||||||
#define ARM_AFF3_MASK (0xFFULL << ARM_AFF3_SHIFT)
|
#define ARM_AFF3_MASK (0xFFULL << ARM_AFF3_SHIFT)
|
||||||
|
#define ARM_DEFAULT_CPUS_PER_CLUSTER 8
|
||||||
|
|
||||||
#define ARM32_AFFINITY_MASK (ARM_AFF0_MASK|ARM_AFF1_MASK|ARM_AFF2_MASK)
|
#define ARM32_AFFINITY_MASK (ARM_AFF0_MASK|ARM_AFF1_MASK|ARM_AFF2_MASK)
|
||||||
#define ARM64_AFFINITY_MASK \
|
#define ARM64_AFFINITY_MASK \
|
||||||
(ARM_AFF0_MASK|ARM_AFF1_MASK|ARM_AFF2_MASK|ARM_AFF3_MASK)
|
(ARM_AFF0_MASK|ARM_AFF1_MASK|ARM_AFF2_MASK|ARM_AFF3_MASK)
|
||||||
|
#define ARM64_AFFINITY_INVALID (~ARM64_AFFINITY_MASK)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -434,29 +434,16 @@ static void arm_disas_set_info(CPUState *cpu, disassemble_info *info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ARM_CPUS_PER_CLUSTER 8
|
|
||||||
|
|
||||||
static void arm_cpu_initfn(Object *obj)
|
static void arm_cpu_initfn(Object *obj)
|
||||||
{
|
{
|
||||||
CPUState *cs = CPU(obj);
|
CPUState *cs = CPU(obj);
|
||||||
ARMCPU *cpu = ARM_CPU(obj);
|
ARMCPU *cpu = ARM_CPU(obj);
|
||||||
static bool inited;
|
static bool inited;
|
||||||
uint32_t Aff1, Aff0;
|
|
||||||
|
|
||||||
cs->env_ptr = &cpu->env;
|
cs->env_ptr = &cpu->env;
|
||||||
cpu_exec_init(cs, &error_abort);
|
|
||||||
cpu->cp_regs = g_hash_table_new_full(g_int_hash, g_int_equal,
|
cpu->cp_regs = g_hash_table_new_full(g_int_hash, g_int_equal,
|
||||||
g_free, g_free);
|
g_free, g_free);
|
||||||
|
|
||||||
/* This cpu-id-to-MPIDR affinity is used only for TCG; KVM will override it.
|
|
||||||
* We don't support setting cluster ID ([16..23]) (known as Aff2
|
|
||||||
* in later ARM ARM versions), or any of the higher affinity level fields,
|
|
||||||
* so these bits always RAZ.
|
|
||||||
*/
|
|
||||||
Aff1 = cs->cpu_index / ARM_CPUS_PER_CLUSTER;
|
|
||||||
Aff0 = cs->cpu_index % ARM_CPUS_PER_CLUSTER;
|
|
||||||
cpu->mp_affinity = (Aff1 << ARM_AFF1_SHIFT) | Aff0;
|
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
/* Our inbound IRQ and FIQ lines */
|
/* Our inbound IRQ and FIQ lines */
|
||||||
if (kvm_enabled()) {
|
if (kvm_enabled()) {
|
||||||
|
@ -577,6 +564,13 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
ARMCPUClass *acc = ARM_CPU_GET_CLASS(dev);
|
ARMCPUClass *acc = ARM_CPU_GET_CLASS(dev);
|
||||||
CPUARMState *env = &cpu->env;
|
CPUARMState *env = &cpu->env;
|
||||||
int pagebits;
|
int pagebits;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
cpu_exec_realizefn(cs, &local_err);
|
||||||
|
if (local_err != NULL) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Some features automatically imply others: */
|
/* Some features automatically imply others: */
|
||||||
if (arm_feature(env, ARM_FEATURE_V8)) {
|
if (arm_feature(env, ARM_FEATURE_V8)) {
|
||||||
|
@ -655,6 +649,17 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This cpu-id-to-MPIDR affinity is used only for TCG; KVM will override it.
|
||||||
|
* We don't support setting cluster ID ([16..23]) (known as Aff2
|
||||||
|
* in later ARM ARM versions), or any of the higher affinity level fields,
|
||||||
|
* so these bits always RAZ.
|
||||||
|
*/
|
||||||
|
if (cpu->mp_affinity == ARM64_AFFINITY_INVALID) {
|
||||||
|
uint32_t Aff1 = cs->cpu_index / ARM_DEFAULT_CPUS_PER_CLUSTER;
|
||||||
|
uint32_t Aff0 = cs->cpu_index % ARM_DEFAULT_CPUS_PER_CLUSTER;
|
||||||
|
cpu->mp_affinity = (Aff1 << ARM_AFF1_SHIFT) | Aff0;
|
||||||
|
}
|
||||||
|
|
||||||
if (cpu->reset_hivecs) {
|
if (cpu->reset_hivecs) {
|
||||||
cpu->reset_sctlr |= (1 << 13);
|
cpu->reset_sctlr |= (1 << 13);
|
||||||
}
|
}
|
||||||
|
@ -1485,7 +1490,8 @@ static Property arm_cpu_properties[] = {
|
||||||
DEFINE_PROP_BOOL("start-powered-off", ARMCPU, start_powered_off, false),
|
DEFINE_PROP_BOOL("start-powered-off", ARMCPU, start_powered_off, false),
|
||||||
DEFINE_PROP_UINT32("psci-conduit", ARMCPU, psci_conduit, 0),
|
DEFINE_PROP_UINT32("psci-conduit", ARMCPU, psci_conduit, 0),
|
||||||
DEFINE_PROP_UINT32("midr", ARMCPU, midr, 0),
|
DEFINE_PROP_UINT32("midr", ARMCPU, midr, 0),
|
||||||
DEFINE_PROP_UINT64("mp-affinity", ARMCPU, mp_affinity, 0),
|
DEFINE_PROP_UINT64("mp-affinity", ARMCPU,
|
||||||
|
mp_affinity, ARM64_AFFINITY_INVALID),
|
||||||
DEFINE_PROP_END_OF_LIST()
|
DEFINE_PROP_END_OF_LIST()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1557,17 +1563,6 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
|
||||||
cc->debug_check_watchpoint = arm_debug_check_watchpoint;
|
cc->debug_check_watchpoint = arm_debug_check_watchpoint;
|
||||||
|
|
||||||
cc->disas_set_info = arm_disas_set_info;
|
cc->disas_set_info = arm_disas_set_info;
|
||||||
|
|
||||||
/*
|
|
||||||
* Reason: arm_cpu_initfn() calls cpu_exec_init(), which saves
|
|
||||||
* the object in cpus -> dangling pointer after final
|
|
||||||
* object_unref().
|
|
||||||
*
|
|
||||||
* Once this is fixed, the devices that create ARM CPUs should be
|
|
||||||
* updated not to set cannot_destroy_with_object_finalize_yet,
|
|
||||||
* unless they still screw up something else.
|
|
||||||
*/
|
|
||||||
dc->cannot_destroy_with_object_finalize_yet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cpu_register(const ARMCPUInfo *info)
|
static void cpu_register(const ARMCPUInfo *info)
|
||||||
|
|
|
@ -142,6 +142,13 @@ static void cris_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
CPUState *cs = CPU(dev);
|
CPUState *cs = CPU(dev);
|
||||||
CRISCPUClass *ccc = CRIS_CPU_GET_CLASS(dev);
|
CRISCPUClass *ccc = CRIS_CPU_GET_CLASS(dev);
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
cpu_exec_realizefn(cs, &local_err);
|
||||||
|
if (local_err != NULL) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cpu_reset(cs);
|
cpu_reset(cs);
|
||||||
qemu_init_vcpu(cs);
|
qemu_init_vcpu(cs);
|
||||||
|
@ -187,7 +194,6 @@ static void cris_cpu_initfn(Object *obj)
|
||||||
static bool tcg_initialized;
|
static bool tcg_initialized;
|
||||||
|
|
||||||
cs->env_ptr = env;
|
cs->env_ptr = env;
|
||||||
cpu_exec_init(cs, &error_abort);
|
|
||||||
|
|
||||||
env->pregs[PR_VR] = ccc->vr;
|
env->pregs[PR_VR] = ccc->vr;
|
||||||
|
|
||||||
|
@ -326,13 +332,6 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data)
|
||||||
cc->gdb_stop_before_watchpoint = true;
|
cc->gdb_stop_before_watchpoint = true;
|
||||||
|
|
||||||
cc->disas_set_info = cris_disas_set_info;
|
cc->disas_set_info = cris_disas_set_info;
|
||||||
|
|
||||||
/*
|
|
||||||
* Reason: cris_cpu_initfn() calls cpu_exec_init(), which saves
|
|
||||||
* the object in cpus -> dangling pointer after final
|
|
||||||
* object_unref().
|
|
||||||
*/
|
|
||||||
dc->cannot_destroy_with_object_finalize_yet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo cris_cpu_type_info = {
|
static const TypeInfo cris_cpu_type_info = {
|
||||||
|
|
|
@ -68,6 +68,7 @@ typedef struct X86CPUClass {
|
||||||
const char *model_description;
|
const char *model_description;
|
||||||
|
|
||||||
DeviceRealize parent_realize;
|
DeviceRealize parent_realize;
|
||||||
|
DeviceUnrealize parent_unrealize;
|
||||||
void (*parent_reset)(CPUState *cpu);
|
void (*parent_reset)(CPUState *cpu);
|
||||||
} X86CPUClass;
|
} X86CPUClass;
|
||||||
|
|
||||||
|
|
|
@ -2945,7 +2945,7 @@ static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
|
||||||
OBJECT(cpu->apic_state), &error_abort);
|
OBJECT(cpu->apic_state), &error_abort);
|
||||||
object_unref(OBJECT(cpu->apic_state));
|
object_unref(OBJECT(cpu->apic_state));
|
||||||
|
|
||||||
qdev_prop_set_uint8(cpu->apic_state, "id", cpu->apic_id);
|
qdev_prop_set_uint32(cpu->apic_state, "id", cpu->apic_id);
|
||||||
/* TODO: convert to link<> */
|
/* TODO: convert to link<> */
|
||||||
apic = APIC_COMMON(cpu->apic_state);
|
apic = APIC_COMMON(cpu->apic_state);
|
||||||
apic->cpu = cpu;
|
apic->cpu = cpu;
|
||||||
|
@ -3271,7 +3271,11 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
cpu->phys_bits = 32;
|
cpu->phys_bits = 32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cpu_exec_init(cs, &error_abort);
|
cpu_exec_realizefn(cs, &local_err);
|
||||||
|
if (local_err != NULL) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (tcg_enabled()) {
|
if (tcg_enabled()) {
|
||||||
tcg_x86_init();
|
tcg_x86_init();
|
||||||
|
@ -3352,6 +3356,8 @@ out:
|
||||||
static void x86_cpu_unrealizefn(DeviceState *dev, Error **errp)
|
static void x86_cpu_unrealizefn(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
X86CPU *cpu = X86_CPU(dev);
|
X86CPU *cpu = X86_CPU(dev);
|
||||||
|
X86CPUClass *xcc = X86_CPU_GET_CLASS(dev);
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
cpu_remove_sync(CPU(dev));
|
cpu_remove_sync(CPU(dev));
|
||||||
|
@ -3362,6 +3368,12 @@ static void x86_cpu_unrealizefn(DeviceState *dev, Error **errp)
|
||||||
object_unparent(OBJECT(cpu->apic_state));
|
object_unparent(OBJECT(cpu->apic_state));
|
||||||
cpu->apic_state = NULL;
|
cpu->apic_state = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xcc->parent_unrealize(dev, &local_err);
|
||||||
|
if (local_err != NULL) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct BitProperty {
|
typedef struct BitProperty {
|
||||||
|
@ -3636,6 +3648,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
|
||||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||||
|
|
||||||
xcc->parent_realize = dc->realize;
|
xcc->parent_realize = dc->realize;
|
||||||
|
xcc->parent_unrealize = dc->unrealize;
|
||||||
dc->realize = x86_cpu_realizefn;
|
dc->realize = x86_cpu_realizefn;
|
||||||
dc->unrealize = x86_cpu_unrealizefn;
|
dc->unrealize = x86_cpu_unrealizefn;
|
||||||
dc->props = x86_cpu_properties;
|
dc->props = x86_cpu_properties;
|
||||||
|
|
|
@ -325,6 +325,7 @@
|
||||||
#define MSR_IA32_APICBASE 0x1b
|
#define MSR_IA32_APICBASE 0x1b
|
||||||
#define MSR_IA32_APICBASE_BSP (1<<8)
|
#define MSR_IA32_APICBASE_BSP (1<<8)
|
||||||
#define MSR_IA32_APICBASE_ENABLE (1<<11)
|
#define MSR_IA32_APICBASE_ENABLE (1<<11)
|
||||||
|
#define MSR_IA32_APICBASE_EXTD (1 << 10)
|
||||||
#define MSR_IA32_APICBASE_BASE (0xfffffU<<12)
|
#define MSR_IA32_APICBASE_BASE (0xfffffU<<12)
|
||||||
#define MSR_IA32_FEATURE_CONTROL 0x0000003a
|
#define MSR_IA32_FEATURE_CONTROL 0x0000003a
|
||||||
#define MSR_TSC_ADJUST 0x0000003b
|
#define MSR_TSC_ADJUST 0x0000003b
|
||||||
|
|
|
@ -129,9 +129,8 @@ static bool kvm_x2apic_api_set_flags(uint64_t flags)
|
||||||
return !kvm_vm_enable_cap(s, KVM_CAP_X2APIC_API, 0, flags);
|
return !kvm_vm_enable_cap(s, KVM_CAP_X2APIC_API, 0, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MEMORIZE(fn) \
|
#define MEMORIZE(fn, _result) \
|
||||||
({ \
|
({ \
|
||||||
static typeof(fn) _result; \
|
|
||||||
static bool _memorized; \
|
static bool _memorized; \
|
||||||
\
|
\
|
||||||
if (_memorized) { \
|
if (_memorized) { \
|
||||||
|
@ -141,11 +140,19 @@ static bool kvm_x2apic_api_set_flags(uint64_t flags)
|
||||||
_result = fn; \
|
_result = fn; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
static bool has_x2apic_api;
|
||||||
|
|
||||||
|
bool kvm_has_x2apic_api(void)
|
||||||
|
{
|
||||||
|
return has_x2apic_api;
|
||||||
|
}
|
||||||
|
|
||||||
bool kvm_enable_x2apic(void)
|
bool kvm_enable_x2apic(void)
|
||||||
{
|
{
|
||||||
return MEMORIZE(
|
return MEMORIZE(
|
||||||
kvm_x2apic_api_set_flags(KVM_X2APIC_API_USE_32BIT_IDS |
|
kvm_x2apic_api_set_flags(KVM_X2APIC_API_USE_32BIT_IDS |
|
||||||
KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK));
|
KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK),
|
||||||
|
has_x2apic_api);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kvm_get_tsc(CPUState *cs)
|
static int kvm_get_tsc(CPUState *cs)
|
||||||
|
|
|
@ -44,4 +44,5 @@ int kvm_device_msix_deassign(KVMState *s, uint32_t dev_id);
|
||||||
void kvm_put_apicbase(X86CPU *cpu, uint64_t value);
|
void kvm_put_apicbase(X86CPU *cpu, uint64_t value);
|
||||||
|
|
||||||
bool kvm_enable_x2apic(void);
|
bool kvm_enable_x2apic(void);
|
||||||
|
bool kvm_has_x2apic_api(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -144,6 +144,13 @@ static void lm32_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
CPUState *cs = CPU(dev);
|
CPUState *cs = CPU(dev);
|
||||||
LM32CPUClass *lcc = LM32_CPU_GET_CLASS(dev);
|
LM32CPUClass *lcc = LM32_CPU_GET_CLASS(dev);
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
cpu_exec_realizefn(cs, &local_err);
|
||||||
|
if (local_err != NULL) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cpu_reset(cs);
|
cpu_reset(cs);
|
||||||
|
|
||||||
|
@ -160,7 +167,6 @@ static void lm32_cpu_initfn(Object *obj)
|
||||||
static bool tcg_initialized;
|
static bool tcg_initialized;
|
||||||
|
|
||||||
cs->env_ptr = env;
|
cs->env_ptr = env;
|
||||||
cpu_exec_init(cs, &error_abort);
|
|
||||||
|
|
||||||
env->flags = 0;
|
env->flags = 0;
|
||||||
|
|
||||||
|
@ -285,13 +291,6 @@ static void lm32_cpu_class_init(ObjectClass *oc, void *data)
|
||||||
cc->gdb_stop_before_watchpoint = true;
|
cc->gdb_stop_before_watchpoint = true;
|
||||||
cc->debug_excp_handler = lm32_debug_excp_handler;
|
cc->debug_excp_handler = lm32_debug_excp_handler;
|
||||||
cc->disas_set_info = lm32_cpu_disas_set_info;
|
cc->disas_set_info = lm32_cpu_disas_set_info;
|
||||||
|
|
||||||
/*
|
|
||||||
* Reason: lm32_cpu_initfn() calls cpu_exec_init(), which saves
|
|
||||||
* the object in cpus -> dangling pointer after final
|
|
||||||
* object_unref().
|
|
||||||
*/
|
|
||||||
dc->cannot_destroy_with_object_finalize_yet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lm32_register_cpu_type(const LM32CPUInfo *info)
|
static void lm32_register_cpu_type(const LM32CPUInfo *info)
|
||||||
|
|
|
@ -159,6 +159,13 @@ static void m68k_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
CPUState *cs = CPU(dev);
|
CPUState *cs = CPU(dev);
|
||||||
M68kCPU *cpu = M68K_CPU(dev);
|
M68kCPU *cpu = M68K_CPU(dev);
|
||||||
M68kCPUClass *mcc = M68K_CPU_GET_CLASS(dev);
|
M68kCPUClass *mcc = M68K_CPU_GET_CLASS(dev);
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
cpu_exec_realizefn(cs, &local_err);
|
||||||
|
if (local_err != NULL) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m68k_cpu_init_gdb(cpu);
|
m68k_cpu_init_gdb(cpu);
|
||||||
|
|
||||||
|
@ -176,7 +183,6 @@ static void m68k_cpu_initfn(Object *obj)
|
||||||
static bool inited;
|
static bool inited;
|
||||||
|
|
||||||
cs->env_ptr = env;
|
cs->env_ptr = env;
|
||||||
cpu_exec_init(cs, &error_abort);
|
|
||||||
|
|
||||||
if (tcg_enabled() && !inited) {
|
if (tcg_enabled() && !inited) {
|
||||||
inited = true;
|
inited = true;
|
||||||
|
@ -222,13 +228,6 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
|
||||||
cc->gdb_core_xml_file = "cf-core.xml";
|
cc->gdb_core_xml_file = "cf-core.xml";
|
||||||
|
|
||||||
dc->vmsd = &vmstate_m68k_cpu;
|
dc->vmsd = &vmstate_m68k_cpu;
|
||||||
|
|
||||||
/*
|
|
||||||
* Reason: m68k_cpu_initfn() calls cpu_exec_init(), which saves
|
|
||||||
* the object in cpus -> dangling pointer after final
|
|
||||||
* object_unref().
|
|
||||||
*/
|
|
||||||
dc->cannot_destroy_with_object_finalize_yet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void register_cpu_type(const M68kCPUInfo *info)
|
static void register_cpu_type(const M68kCPUInfo *info)
|
||||||
|
|
|
@ -138,6 +138,13 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
CPUMBState *env = &cpu->env;
|
CPUMBState *env = &cpu->env;
|
||||||
uint8_t version_code = 0;
|
uint8_t version_code = 0;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
cpu_exec_realizefn(cs, &local_err);
|
||||||
|
if (local_err != NULL) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
qemu_init_vcpu(cs);
|
qemu_init_vcpu(cs);
|
||||||
|
|
||||||
|
@ -199,7 +206,6 @@ static void mb_cpu_initfn(Object *obj)
|
||||||
static bool tcg_initialized;
|
static bool tcg_initialized;
|
||||||
|
|
||||||
cs->env_ptr = env;
|
cs->env_ptr = env;
|
||||||
cpu_exec_init(cs, &error_abort);
|
|
||||||
|
|
||||||
set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
|
set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
|
||||||
|
|
||||||
|
@ -267,12 +273,6 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data)
|
||||||
cc->gdb_num_core_regs = 32 + 5;
|
cc->gdb_num_core_regs = 32 + 5;
|
||||||
|
|
||||||
cc->disas_set_info = mb_disas_set_info;
|
cc->disas_set_info = mb_disas_set_info;
|
||||||
|
|
||||||
/*
|
|
||||||
* Reason: mb_cpu_initfn() calls cpu_exec_init(), which saves the
|
|
||||||
* object in cpus -> dangling pointer after final object_unref().
|
|
||||||
*/
|
|
||||||
dc->cannot_destroy_with_object_finalize_yet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo mb_cpu_type_info = {
|
static const TypeInfo mb_cpu_type_info = {
|
||||||
|
|
|
@ -124,6 +124,13 @@ static void mips_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
CPUState *cs = CPU(dev);
|
CPUState *cs = CPU(dev);
|
||||||
MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(dev);
|
MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(dev);
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
cpu_exec_realizefn(cs, &local_err);
|
||||||
|
if (local_err != NULL) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cpu_reset(cs);
|
cpu_reset(cs);
|
||||||
qemu_init_vcpu(cs);
|
qemu_init_vcpu(cs);
|
||||||
|
@ -138,7 +145,6 @@ static void mips_cpu_initfn(Object *obj)
|
||||||
CPUMIPSState *env = &cpu->env;
|
CPUMIPSState *env = &cpu->env;
|
||||||
|
|
||||||
cs->env_ptr = env;
|
cs->env_ptr = env;
|
||||||
cpu_exec_init(cs, &error_abort);
|
|
||||||
|
|
||||||
if (tcg_enabled()) {
|
if (tcg_enabled()) {
|
||||||
mips_tcg_init();
|
mips_tcg_init();
|
||||||
|
@ -177,13 +183,6 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
|
||||||
|
|
||||||
cc->gdb_num_core_regs = 73;
|
cc->gdb_num_core_regs = 73;
|
||||||
cc->gdb_stop_before_watchpoint = true;
|
cc->gdb_stop_before_watchpoint = true;
|
||||||
|
|
||||||
/*
|
|
||||||
* Reason: mips_cpu_initfn() calls cpu_exec_init(), which saves
|
|
||||||
* the object in cpus -> dangling pointer after final
|
|
||||||
* object_unref().
|
|
||||||
*/
|
|
||||||
dc->cannot_destroy_with_object_finalize_yet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo mips_cpu_type_info = {
|
static const TypeInfo mips_cpu_type_info = {
|
||||||
|
|
|
@ -61,6 +61,13 @@ static void moxie_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
CPUState *cs = CPU(dev);
|
CPUState *cs = CPU(dev);
|
||||||
MoxieCPUClass *mcc = MOXIE_CPU_GET_CLASS(dev);
|
MoxieCPUClass *mcc = MOXIE_CPU_GET_CLASS(dev);
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
cpu_exec_realizefn(cs, &local_err);
|
||||||
|
if (local_err != NULL) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
qemu_init_vcpu(cs);
|
qemu_init_vcpu(cs);
|
||||||
cpu_reset(cs);
|
cpu_reset(cs);
|
||||||
|
@ -75,7 +82,6 @@ static void moxie_cpu_initfn(Object *obj)
|
||||||
static int inited;
|
static int inited;
|
||||||
|
|
||||||
cs->env_ptr = &cpu->env;
|
cs->env_ptr = &cpu->env;
|
||||||
cpu_exec_init(cs, &error_abort);
|
|
||||||
|
|
||||||
if (tcg_enabled() && !inited) {
|
if (tcg_enabled() && !inited) {
|
||||||
inited = 1;
|
inited = 1;
|
||||||
|
@ -124,13 +130,6 @@ static void moxie_cpu_class_init(ObjectClass *oc, void *data)
|
||||||
cc->vmsd = &vmstate_moxie_cpu;
|
cc->vmsd = &vmstate_moxie_cpu;
|
||||||
#endif
|
#endif
|
||||||
cc->disas_set_info = moxie_cpu_disas_set_info;
|
cc->disas_set_info = moxie_cpu_disas_set_info;
|
||||||
|
|
||||||
/*
|
|
||||||
* Reason: moxie_cpu_initfn() calls cpu_exec_init(), which saves
|
|
||||||
* the object in cpus -> dangling pointer after final
|
|
||||||
* object_unref().
|
|
||||||
*/
|
|
||||||
dc->cannot_destroy_with_object_finalize_yet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void moxielite_initfn(Object *obj)
|
static void moxielite_initfn(Object *obj)
|
||||||
|
|
|
@ -81,6 +81,13 @@ static void openrisc_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
CPUState *cs = CPU(dev);
|
CPUState *cs = CPU(dev);
|
||||||
OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(dev);
|
OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(dev);
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
cpu_exec_realizefn(cs, &local_err);
|
||||||
|
if (local_err != NULL) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
qemu_init_vcpu(cs);
|
qemu_init_vcpu(cs);
|
||||||
cpu_reset(cs);
|
cpu_reset(cs);
|
||||||
|
@ -95,7 +102,6 @@ static void openrisc_cpu_initfn(Object *obj)
|
||||||
static int inited;
|
static int inited;
|
||||||
|
|
||||||
cs->env_ptr = &cpu->env;
|
cs->env_ptr = &cpu->env;
|
||||||
cpu_exec_init(cs, &error_abort);
|
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
cpu_openrisc_mmu_init(cpu);
|
cpu_openrisc_mmu_init(cpu);
|
||||||
|
@ -180,13 +186,6 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
|
||||||
dc->vmsd = &vmstate_openrisc_cpu;
|
dc->vmsd = &vmstate_openrisc_cpu;
|
||||||
#endif
|
#endif
|
||||||
cc->gdb_num_core_regs = 32 + 3;
|
cc->gdb_num_core_regs = 32 + 3;
|
||||||
|
|
||||||
/*
|
|
||||||
* Reason: openrisc_cpu_initfn() calls cpu_exec_init(), which saves
|
|
||||||
* the object in cpus -> dangling pointer after final
|
|
||||||
* object_unref().
|
|
||||||
*/
|
|
||||||
dc->cannot_destroy_with_object_finalize_yet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cpu_register(const OpenRISCCPUInfo *info)
|
static void cpu_register(const OpenRISCCPUInfo *info)
|
||||||
|
|
|
@ -174,6 +174,7 @@ typedef struct PowerPCCPUClass {
|
||||||
/*< public >*/
|
/*< public >*/
|
||||||
|
|
||||||
DeviceRealize parent_realize;
|
DeviceRealize parent_realize;
|
||||||
|
DeviceUnrealize parent_unrealize;
|
||||||
void (*parent_reset)(CPUState *cpu);
|
void (*parent_reset)(CPUState *cpu);
|
||||||
|
|
||||||
uint32_t pvr;
|
uint32_t pvr;
|
||||||
|
|
|
@ -9678,7 +9678,7 @@ static void ppc_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
cpu_exec_init(cs, &local_err);
|
cpu_exec_realizefn(cs, &local_err);
|
||||||
if (local_err != NULL) {
|
if (local_err != NULL) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
return;
|
return;
|
||||||
|
@ -9906,11 +9906,17 @@ static void ppc_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
static void ppc_cpu_unrealizefn(DeviceState *dev, Error **errp)
|
static void ppc_cpu_unrealizefn(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
PowerPCCPU *cpu = POWERPC_CPU(dev);
|
PowerPCCPU *cpu = POWERPC_CPU(dev);
|
||||||
|
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
|
||||||
CPUPPCState *env = &cpu->env;
|
CPUPPCState *env = &cpu->env;
|
||||||
|
Error *local_err = NULL;
|
||||||
opc_handler_t **table, **table_2;
|
opc_handler_t **table, **table_2;
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
|
|
||||||
cpu_exec_exit(CPU(dev));
|
pcc->parent_unrealize(dev, &local_err);
|
||||||
|
if (local_err != NULL) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < PPC_CPU_OPCODES_LEN; i++) {
|
for (i = 0; i < PPC_CPU_OPCODES_LEN; i++) {
|
||||||
if (env->opcodes[i] == &invalid_handler) {
|
if (env->opcodes[i] == &invalid_handler) {
|
||||||
|
@ -10521,6 +10527,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
|
||||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||||
|
|
||||||
pcc->parent_realize = dc->realize;
|
pcc->parent_realize = dc->realize;
|
||||||
|
pcc->parent_unrealize = dc->unrealize;
|
||||||
pcc->pvr_match = ppc_pvr_match_default;
|
pcc->pvr_match = ppc_pvr_match_default;
|
||||||
pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_always;
|
pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_always;
|
||||||
dc->realize = ppc_cpu_realizefn;
|
dc->realize = ppc_cpu_realizefn;
|
||||||
|
|
|
@ -207,7 +207,7 @@ static void s390_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu_exec_init(cs, &err);
|
cpu_exec_realizefn(cs, &err);
|
||||||
if (err != NULL) {
|
if (err != NULL) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -440,12 +440,6 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
|
||||||
cc->gdb_core_xml_file = "s390x-core64.xml";
|
cc->gdb_core_xml_file = "s390x-core64.xml";
|
||||||
cc->gdb_arch_name = s390_gdb_arch_name;
|
cc->gdb_arch_name = s390_gdb_arch_name;
|
||||||
|
|
||||||
/*
|
|
||||||
* Reason: s390_cpu_realizefn() calls cpu_exec_init(), which saves
|
|
||||||
* the object in cpus -> dangling pointer after final
|
|
||||||
* object_unref().
|
|
||||||
*/
|
|
||||||
dc->cannot_destroy_with_object_finalize_yet = true;
|
|
||||||
s390_cpu_model_class_register_props(oc);
|
s390_cpu_model_class_register_props(oc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -244,6 +244,13 @@ static void superh_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
CPUState *cs = CPU(dev);
|
CPUState *cs = CPU(dev);
|
||||||
SuperHCPUClass *scc = SUPERH_CPU_GET_CLASS(dev);
|
SuperHCPUClass *scc = SUPERH_CPU_GET_CLASS(dev);
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
cpu_exec_realizefn(cs, &local_err);
|
||||||
|
if (local_err != NULL) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cpu_reset(cs);
|
cpu_reset(cs);
|
||||||
qemu_init_vcpu(cs);
|
qemu_init_vcpu(cs);
|
||||||
|
@ -258,7 +265,6 @@ static void superh_cpu_initfn(Object *obj)
|
||||||
CPUSH4State *env = &cpu->env;
|
CPUSH4State *env = &cpu->env;
|
||||||
|
|
||||||
cs->env_ptr = env;
|
cs->env_ptr = env;
|
||||||
cpu_exec_init(cs, &error_abort);
|
|
||||||
|
|
||||||
env->movcal_backup_tail = &(env->movcal_backup);
|
env->movcal_backup_tail = &(env->movcal_backup);
|
||||||
|
|
||||||
|
@ -303,13 +309,6 @@ static void superh_cpu_class_init(ObjectClass *oc, void *data)
|
||||||
cc->gdb_num_core_regs = 59;
|
cc->gdb_num_core_regs = 59;
|
||||||
|
|
||||||
dc->vmsd = &vmstate_sh_cpu;
|
dc->vmsd = &vmstate_sh_cpu;
|
||||||
|
|
||||||
/*
|
|
||||||
* Reason: superh_cpu_initfn() calls cpu_exec_init(), which saves
|
|
||||||
* the object in cpus -> dangling pointer after final
|
|
||||||
* object_unref().
|
|
||||||
*/
|
|
||||||
dc->cannot_destroy_with_object_finalize_yet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo superh_cpu_type_info = {
|
static const TypeInfo superh_cpu_type_info = {
|
||||||
|
|
|
@ -792,7 +792,9 @@ static bool sparc_cpu_has_work(CPUState *cs)
|
||||||
|
|
||||||
static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
|
static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
|
CPUState *cs = CPU(dev);
|
||||||
SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
|
SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
|
||||||
|
Error *local_err = NULL;
|
||||||
#if defined(CONFIG_USER_ONLY)
|
#if defined(CONFIG_USER_ONLY)
|
||||||
SPARCCPU *cpu = SPARC_CPU(dev);
|
SPARCCPU *cpu = SPARC_CPU(dev);
|
||||||
CPUSPARCState *env = &cpu->env;
|
CPUSPARCState *env = &cpu->env;
|
||||||
|
@ -802,7 +804,13 @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
qemu_init_vcpu(CPU(dev));
|
cpu_exec_realizefn(cs, &local_err);
|
||||||
|
if (local_err != NULL) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qemu_init_vcpu(cs);
|
||||||
|
|
||||||
scc->parent_realize(dev, errp);
|
scc->parent_realize(dev, errp);
|
||||||
}
|
}
|
||||||
|
@ -814,7 +822,6 @@ static void sparc_cpu_initfn(Object *obj)
|
||||||
CPUSPARCState *env = &cpu->env;
|
CPUSPARCState *env = &cpu->env;
|
||||||
|
|
||||||
cs->env_ptr = env;
|
cs->env_ptr = env;
|
||||||
cpu_exec_init(cs, &error_abort);
|
|
||||||
|
|
||||||
if (tcg_enabled()) {
|
if (tcg_enabled()) {
|
||||||
gen_intermediate_code_init(env);
|
gen_intermediate_code_init(env);
|
||||||
|
@ -867,13 +874,6 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data)
|
||||||
#else
|
#else
|
||||||
cc->gdb_num_core_regs = 72;
|
cc->gdb_num_core_regs = 72;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Reason: sparc_cpu_initfn() calls cpu_exec_init(), which saves
|
|
||||||
* the object in cpus -> dangling pointer after final
|
|
||||||
* object_unref().
|
|
||||||
*/
|
|
||||||
dc->cannot_destroy_with_object_finalize_yet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo sparc_cpu_type_info = {
|
static const TypeInfo sparc_cpu_type_info = {
|
||||||
|
|
|
@ -92,6 +92,13 @@ static void tilegx_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
CPUState *cs = CPU(dev);
|
CPUState *cs = CPU(dev);
|
||||||
TileGXCPUClass *tcc = TILEGX_CPU_GET_CLASS(dev);
|
TileGXCPUClass *tcc = TILEGX_CPU_GET_CLASS(dev);
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
cpu_exec_realizefn(cs, &local_err);
|
||||||
|
if (local_err != NULL) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cpu_reset(cs);
|
cpu_reset(cs);
|
||||||
qemu_init_vcpu(cs);
|
qemu_init_vcpu(cs);
|
||||||
|
@ -107,7 +114,6 @@ static void tilegx_cpu_initfn(Object *obj)
|
||||||
static bool tcg_initialized;
|
static bool tcg_initialized;
|
||||||
|
|
||||||
cs->env_ptr = env;
|
cs->env_ptr = env;
|
||||||
cpu_exec_init(cs, &error_abort);
|
|
||||||
|
|
||||||
if (tcg_enabled() && !tcg_initialized) {
|
if (tcg_enabled() && !tcg_initialized) {
|
||||||
tcg_initialized = true;
|
tcg_initialized = true;
|
||||||
|
@ -162,13 +168,6 @@ static void tilegx_cpu_class_init(ObjectClass *oc, void *data)
|
||||||
cc->set_pc = tilegx_cpu_set_pc;
|
cc->set_pc = tilegx_cpu_set_pc;
|
||||||
cc->handle_mmu_fault = tilegx_cpu_handle_mmu_fault;
|
cc->handle_mmu_fault = tilegx_cpu_handle_mmu_fault;
|
||||||
cc->gdb_num_core_regs = 0;
|
cc->gdb_num_core_regs = 0;
|
||||||
|
|
||||||
/*
|
|
||||||
* Reason: tilegx_cpu_initfn() calls cpu_exec_init(), which saves
|
|
||||||
* the object in cpus -> dangling pointer after final
|
|
||||||
* object_unref().
|
|
||||||
*/
|
|
||||||
dc->cannot_destroy_with_object_finalize_yet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo tilegx_cpu_type_info = {
|
static const TypeInfo tilegx_cpu_type_info = {
|
||||||
|
|
|
@ -69,6 +69,13 @@ static void tricore_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
TriCoreCPU *cpu = TRICORE_CPU(dev);
|
TriCoreCPU *cpu = TRICORE_CPU(dev);
|
||||||
TriCoreCPUClass *tcc = TRICORE_CPU_GET_CLASS(dev);
|
TriCoreCPUClass *tcc = TRICORE_CPU_GET_CLASS(dev);
|
||||||
CPUTriCoreState *env = &cpu->env;
|
CPUTriCoreState *env = &cpu->env;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
cpu_exec_realizefn(cs, &local_err);
|
||||||
|
if (local_err != NULL) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Some features automatically imply others */
|
/* Some features automatically imply others */
|
||||||
if (tricore_feature(env, TRICORE_FEATURE_161)) {
|
if (tricore_feature(env, TRICORE_FEATURE_161)) {
|
||||||
|
@ -95,7 +102,6 @@ static void tricore_cpu_initfn(Object *obj)
|
||||||
CPUTriCoreState *env = &cpu->env;
|
CPUTriCoreState *env = &cpu->env;
|
||||||
|
|
||||||
cs->env_ptr = env;
|
cs->env_ptr = env;
|
||||||
cpu_exec_init(cs, &error_abort);
|
|
||||||
|
|
||||||
if (tcg_enabled()) {
|
if (tcg_enabled()) {
|
||||||
tricore_tcg_init();
|
tricore_tcg_init();
|
||||||
|
@ -172,13 +178,6 @@ static void tricore_cpu_class_init(ObjectClass *c, void *data)
|
||||||
cc->dump_state = tricore_cpu_dump_state;
|
cc->dump_state = tricore_cpu_dump_state;
|
||||||
cc->set_pc = tricore_cpu_set_pc;
|
cc->set_pc = tricore_cpu_set_pc;
|
||||||
cc->synchronize_from_tb = tricore_cpu_synchronize_from_tb;
|
cc->synchronize_from_tb = tricore_cpu_synchronize_from_tb;
|
||||||
|
|
||||||
/*
|
|
||||||
* Reason: tricore_cpu_initfn() calls cpu_exec_init(), which saves
|
|
||||||
* the object in cpus -> dangling pointer after final
|
|
||||||
* object_unref().
|
|
||||||
*/
|
|
||||||
dc->cannot_destroy_with_object_finalize_yet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cpu_register(const TriCoreCPUInfo *info)
|
static void cpu_register(const TriCoreCPUInfo *info)
|
||||||
|
|
|
@ -101,9 +101,17 @@ static const UniCore32CPUInfo uc32_cpus[] = {
|
||||||
|
|
||||||
static void uc32_cpu_realizefn(DeviceState *dev, Error **errp)
|
static void uc32_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
|
CPUState *cs = CPU(dev);
|
||||||
UniCore32CPUClass *ucc = UNICORE32_CPU_GET_CLASS(dev);
|
UniCore32CPUClass *ucc = UNICORE32_CPU_GET_CLASS(dev);
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
qemu_init_vcpu(CPU(dev));
|
cpu_exec_realizefn(cs, &local_err);
|
||||||
|
if (local_err != NULL) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qemu_init_vcpu(cs);
|
||||||
|
|
||||||
ucc->parent_realize(dev, errp);
|
ucc->parent_realize(dev, errp);
|
||||||
}
|
}
|
||||||
|
@ -116,7 +124,6 @@ static void uc32_cpu_initfn(Object *obj)
|
||||||
static bool inited;
|
static bool inited;
|
||||||
|
|
||||||
cs->env_ptr = env;
|
cs->env_ptr = env;
|
||||||
cpu_exec_init(cs, &error_abort);
|
|
||||||
|
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
env->uncached_asr = ASR_MODE_USER;
|
env->uncached_asr = ASR_MODE_USER;
|
||||||
|
@ -160,13 +167,6 @@ static void uc32_cpu_class_init(ObjectClass *oc, void *data)
|
||||||
cc->get_phys_page_debug = uc32_cpu_get_phys_page_debug;
|
cc->get_phys_page_debug = uc32_cpu_get_phys_page_debug;
|
||||||
#endif
|
#endif
|
||||||
dc->vmsd = &vmstate_uc32_cpu;
|
dc->vmsd = &vmstate_uc32_cpu;
|
||||||
|
|
||||||
/*
|
|
||||||
* Reason: uc32_cpu_initfn() calls cpu_exec_init(), which saves
|
|
||||||
* the object in cpus -> dangling pointer after final
|
|
||||||
* object_unref().
|
|
||||||
*/
|
|
||||||
dc->cannot_destroy_with_object_finalize_yet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void uc32_register_cpu_type(const UniCore32CPUInfo *info)
|
static void uc32_register_cpu_type(const UniCore32CPUInfo *info)
|
||||||
|
|
|
@ -99,6 +99,13 @@ static void xtensa_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
CPUState *cs = CPU(dev);
|
CPUState *cs = CPU(dev);
|
||||||
XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(dev);
|
XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(dev);
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
cpu_exec_realizefn(cs, &local_err);
|
||||||
|
if (local_err != NULL) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cs->gdb_num_regs = xcc->config->gdb_regmap.num_regs;
|
cs->gdb_num_regs = xcc->config->gdb_regmap.num_regs;
|
||||||
|
|
||||||
|
@ -117,7 +124,6 @@ static void xtensa_cpu_initfn(Object *obj)
|
||||||
|
|
||||||
cs->env_ptr = env;
|
cs->env_ptr = env;
|
||||||
env->config = xcc->config;
|
env->config = xcc->config;
|
||||||
cpu_exec_init(cs, &error_abort);
|
|
||||||
|
|
||||||
if (tcg_enabled() && !tcg_inited) {
|
if (tcg_enabled() && !tcg_inited) {
|
||||||
tcg_inited = true;
|
tcg_inited = true;
|
||||||
|
@ -158,13 +164,6 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
|
||||||
#endif
|
#endif
|
||||||
cc->debug_excp_handler = xtensa_breakpoint_handler;
|
cc->debug_excp_handler = xtensa_breakpoint_handler;
|
||||||
dc->vmsd = &vmstate_xtensa_cpu;
|
dc->vmsd = &vmstate_xtensa_cpu;
|
||||||
|
|
||||||
/*
|
|
||||||
* Reason: xtensa_cpu_initfn() calls cpu_exec_init(), which saves
|
|
||||||
* the object in cpus -> dangling pointer after final
|
|
||||||
* object_unref().
|
|
||||||
*/
|
|
||||||
dc->cannot_destroy_with_object_finalize_yet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo xtensa_cpu_type_info = {
|
static const TypeInfo xtensa_cpu_type_info = {
|
||||||
|
|
Loading…
Reference in New Issue