X86 queue, 2015-10-05
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJWEp+WAAoJECgHk2+YTcWmTWQQAL3PXCXh5tY6LKlr3OfeSxns cFyuMeeq3K7NGVM0BNJjfaHTl/NRKyGseDaVUaa6kosdunN2QyMaIQP7RyvpMrNk V7RI2ivax22NHWo52cdBvsRhHOSx1AR/Qqc6YV+lVD8Awz5OsV0oLApG7c862b6q 5FVDeopQ8Mm7zkun/PUuQqaJax+mdtrSb90wr1Ehsm8D3hJiWs8dA6UFTxLB8ve6 fGrtDgs7MIs+fbZ1yS1ulDGuNdBtBHL2T0h4elU3o4CN3z9ChxEp/sYzGkEC+cyB o+JPk4sr5CnUKqVgDfIHxE88Ycaulz2AmObT/IUhf+QLkwcJ72uohV6n/NPr0zJ4 B4hIah9nkPQ4TTUhInt93Ftq2FkmmAm1or/+SkCKIkIYfvakW0S6KnbMZvfMS8Hu acJb4W+4c78CBI9EbCtHs7lezTTH2dYSUBKA09gIi+pM93G22lh2Sl8J4ZvfSF2a qlL7J4KiogBbLhuaakPuyOIS77afkCSkA9NFTkn294THr3tqFaXaHzAY0+AwW4W1 dH8Y4w5LH+pXyLp5jVzvEmopX4DDOaYPlvwGB6y0vhMCi28hkroXMrU76wT5w9+y yo6RFJseHi7SbJCGgie9kehBFv8q3Si1XomiPxGlPWCUnOVe8nf3DPUvWYwn3VJw VRkkcp+RzEOlPsWK3Aj7 =pr5r -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/ehabkost/tags/x86-pull-request' into staging X86 queue, 2015-10-05 # gpg: Signature made Mon 05 Oct 2015 17:04:38 BST using RSA key ID 984DC5A6 # gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>" * remotes/ehabkost/tags/x86-pull-request: icc_bus: drop the unused files cpu/apic: drop icc bus/bridge x86: use new method to correct reset sequence apic: move APIC's MMIO region mapping into APIC Correctly re-init EFER state during INIT IPI target-i386: add ABM to Haswell* and Broadwell* CPU models target-i386: get/put MSR_TSC_AUX across reset and migration target-i386: Make check_hw_breakpoints static target-i386: Move breakpoint related functions to new file target-i386: Convert kvm_default_*features to property/value pairs vl: Add another sanity check to smp_parse() function cpu: Introduce X86CPUTopoInfo structure for argument simplification Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
5fdb4671b0
@ -44,7 +44,6 @@ CONFIG_LPC_ICH9=y
|
||||
CONFIG_PCI_Q35=y
|
||||
CONFIG_APIC=y
|
||||
CONFIG_IOAPIC=y
|
||||
CONFIG_ICC_BUS=y
|
||||
CONFIG_PVPANIC=y
|
||||
CONFIG_MEM_HOTPLUG=y
|
||||
CONFIG_XIO3130=y
|
||||
|
@ -44,7 +44,6 @@ CONFIG_LPC_ICH9=y
|
||||
CONFIG_PCI_Q35=y
|
||||
CONFIG_APIC=y
|
||||
CONFIG_IOAPIC=y
|
||||
CONFIG_ICC_BUS=y
|
||||
CONFIG_PVPANIC=y
|
||||
CONFIG_MEM_HOTPLUG=y
|
||||
CONFIG_XIO3130=y
|
||||
|
@ -2,5 +2,4 @@ obj-$(CONFIG_ARM11MPCORE) += arm11mpcore.o
|
||||
obj-$(CONFIG_REALVIEW) += realview_mpcore.o
|
||||
obj-$(CONFIG_A9MPCORE) += a9mpcore.o
|
||||
obj-$(CONFIG_A15MPCORE) += a15mpcore.o
|
||||
obj-$(CONFIG_ICC_BUS) += icc_bus.o
|
||||
|
||||
|
118
hw/cpu/icc_bus.c
118
hw/cpu/icc_bus.c
@ -1,118 +0,0 @@
|
||||
/* icc_bus.c
|
||||
* emulate x86 ICC (Interrupt Controller Communications) bus
|
||||
*
|
||||
* Copyright (c) 2013 Red Hat, Inc
|
||||
*
|
||||
* Authors:
|
||||
* Igor Mammedov <imammedo@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/>
|
||||
*/
|
||||
#include "hw/cpu/icc_bus.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
/* icc-bridge implementation */
|
||||
|
||||
static const TypeInfo icc_bus_info = {
|
||||
.name = TYPE_ICC_BUS,
|
||||
.parent = TYPE_BUS,
|
||||
.instance_size = sizeof(ICCBus),
|
||||
};
|
||||
|
||||
|
||||
/* icc-device implementation */
|
||||
|
||||
static void icc_device_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
ICCDeviceClass *idc = ICC_DEVICE_GET_CLASS(dev);
|
||||
|
||||
/* convert to QOM */
|
||||
if (idc->realize) {
|
||||
idc->realize(dev, errp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void icc_device_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
dc->realize = icc_device_realize;
|
||||
dc->bus_type = TYPE_ICC_BUS;
|
||||
}
|
||||
|
||||
static const TypeInfo icc_device_info = {
|
||||
.name = TYPE_ICC_DEVICE,
|
||||
.parent = TYPE_DEVICE,
|
||||
.abstract = true,
|
||||
.instance_size = sizeof(ICCDevice),
|
||||
.class_size = sizeof(ICCDeviceClass),
|
||||
.class_init = icc_device_class_init,
|
||||
};
|
||||
|
||||
|
||||
/* icc-bridge implementation */
|
||||
|
||||
typedef struct ICCBridgeState {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
ICCBus icc_bus;
|
||||
MemoryRegion apic_container;
|
||||
} ICCBridgeState;
|
||||
|
||||
#define ICC_BRIDGE(obj) OBJECT_CHECK(ICCBridgeState, (obj), TYPE_ICC_BRIDGE)
|
||||
|
||||
static void icc_bridge_init(Object *obj)
|
||||
{
|
||||
ICCBridgeState *s = ICC_BRIDGE(obj);
|
||||
SysBusDevice *sb = SYS_BUS_DEVICE(obj);
|
||||
|
||||
qbus_create_inplace(&s->icc_bus, sizeof(s->icc_bus), TYPE_ICC_BUS,
|
||||
DEVICE(s), "icc");
|
||||
|
||||
/* Do not change order of registering regions,
|
||||
* APIC must be first registered region, board maps it by 0 index
|
||||
*/
|
||||
memory_region_init(&s->apic_container, obj, "icc-apic-container",
|
||||
APIC_SPACE_SIZE);
|
||||
sysbus_init_mmio(sb, &s->apic_container);
|
||||
s->icc_bus.apic_address_space = &s->apic_container;
|
||||
}
|
||||
|
||||
static void icc_bridge_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo icc_bridge_info = {
|
||||
.name = TYPE_ICC_BRIDGE,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_init = icc_bridge_init,
|
||||
.instance_size = sizeof(ICCBridgeState),
|
||||
.class_init = icc_bridge_class_init,
|
||||
};
|
||||
|
||||
|
||||
static void icc_bus_register_types(void)
|
||||
{
|
||||
type_register_static(&icc_bus_info);
|
||||
type_register_static(&icc_device_info);
|
||||
type_register_static(&icc_bridge_info);
|
||||
}
|
||||
|
||||
type_init(icc_bus_register_types)
|
52
hw/i386/pc.c
52
hw/i386/pc.c
@ -59,7 +59,6 @@
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/acpi/acpi.h"
|
||||
#include "hw/acpi/cpu_hotplug.h"
|
||||
#include "hw/cpu/icc_bus.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/pci/pci_host.h"
|
||||
#include "acpi-build.h"
|
||||
@ -1052,23 +1051,16 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
|
||||
}
|
||||
|
||||
static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id,
|
||||
DeviceState *icc_bridge, Error **errp)
|
||||
Error **errp)
|
||||
{
|
||||
X86CPU *cpu = NULL;
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (icc_bridge == NULL) {
|
||||
error_setg(&local_err, "Invalid icc-bridge value");
|
||||
goto out;
|
||||
}
|
||||
|
||||
cpu = cpu_x86_create(cpu_model, &local_err);
|
||||
if (local_err != NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
qdev_set_parent_bus(DEVICE(cpu), qdev_get_child_bus(icc_bridge, "icc"));
|
||||
|
||||
object_property_set_int(OBJECT(cpu), apic_id, "apic-id", &local_err);
|
||||
object_property_set_bool(OBJECT(cpu), true, "realized", &local_err);
|
||||
|
||||
@ -1085,7 +1077,6 @@ static const char *current_cpu_model;
|
||||
|
||||
void pc_hot_add_cpu(const int64_t id, Error **errp)
|
||||
{
|
||||
DeviceState *icc_bridge;
|
||||
X86CPU *cpu;
|
||||
int64_t apic_id = x86_cpu_apic_id_from_index(id);
|
||||
Error *local_err = NULL;
|
||||
@ -1114,9 +1105,7 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
icc_bridge = DEVICE(object_resolve_path_type("icc-bridge",
|
||||
TYPE_ICC_BRIDGE, NULL));
|
||||
cpu = pc_new_cpu(current_cpu_model, apic_id, icc_bridge, &local_err);
|
||||
cpu = pc_new_cpu(current_cpu_model, apic_id, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
@ -1124,7 +1113,7 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
|
||||
object_unref(OBJECT(cpu));
|
||||
}
|
||||
|
||||
void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
|
||||
void pc_cpus_init(const char *cpu_model)
|
||||
{
|
||||
int i;
|
||||
X86CPU *cpu = NULL;
|
||||
@ -1150,7 +1139,7 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
|
||||
|
||||
for (i = 0; i < smp_cpus; i++) {
|
||||
cpu = pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i),
|
||||
icc_bridge, &error);
|
||||
&error);
|
||||
if (error) {
|
||||
error_report_err(error);
|
||||
exit(1);
|
||||
@ -1158,13 +1147,6 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
|
||||
object_unref(OBJECT(cpu));
|
||||
}
|
||||
|
||||
/* map APIC MMIO area if CPU has APIC */
|
||||
if (cpu && cpu->apic_state) {
|
||||
/* XXX: what if the base changes? */
|
||||
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(icc_bridge), 0,
|
||||
APIC_DEFAULT_ADDRESS, 0x1000);
|
||||
}
|
||||
|
||||
/* tell smbios about cpuid version and features */
|
||||
smbios_set_cpuid(cpu->env.cpuid_version, cpu->env.features[FEAT_1_EDX]);
|
||||
}
|
||||
@ -1933,12 +1915,31 @@ static void pc_machine_initfn(Object *obj)
|
||||
NULL, &error_abort);
|
||||
}
|
||||
|
||||
static void pc_machine_reset(void)
|
||||
{
|
||||
CPUState *cs;
|
||||
X86CPU *cpu;
|
||||
|
||||
qemu_devices_reset();
|
||||
|
||||
/* Reset APIC after devices have been reset to cancel
|
||||
* any changes that qemu_devices_reset() might have done.
|
||||
*/
|
||||
CPU_FOREACH(cs) {
|
||||
cpu = X86_CPU(cs);
|
||||
|
||||
if (cpu->apic_state) {
|
||||
device_reset(cpu->apic_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned pc_cpu_index_to_socket_id(unsigned cpu_index)
|
||||
{
|
||||
unsigned pkg_id, core_id, smt_id;
|
||||
X86CPUTopoInfo topo;
|
||||
x86_topo_ids_from_idx(smp_cores, smp_threads, cpu_index,
|
||||
&pkg_id, &core_id, &smt_id);
|
||||
return pkg_id;
|
||||
&topo);
|
||||
return topo.pkg_id;
|
||||
}
|
||||
|
||||
static void pc_machine_class_init(ObjectClass *oc, void *data)
|
||||
@ -1954,6 +1955,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
|
||||
mc->default_boot_order = "cad";
|
||||
mc->hot_add_cpu = pc_hot_add_cpu;
|
||||
mc->max_cpus = 255;
|
||||
mc->reset = pc_machine_reset;
|
||||
hc->plug = pc_machine_device_plug_cb;
|
||||
hc->unplug_request = pc_machine_device_unplug_request_cb;
|
||||
hc->unplug = pc_machine_device_unplug_cb;
|
||||
|
@ -39,7 +39,6 @@
|
||||
#include "hw/kvm/clock.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/cpu/icc_bus.h"
|
||||
#include "sysemu/arch_init.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "hw/i2c/smbus.h"
|
||||
@ -98,7 +97,6 @@ static void pc_init1(MachineState *machine,
|
||||
MemoryRegion *ram_memory;
|
||||
MemoryRegion *pci_memory;
|
||||
MemoryRegion *rom_memory;
|
||||
DeviceState *icc_bridge;
|
||||
PcGuestInfo *guest_info;
|
||||
ram_addr_t lowmem;
|
||||
|
||||
@ -141,11 +139,7 @@ static void pc_init1(MachineState *machine,
|
||||
exit(1);
|
||||
}
|
||||
|
||||
icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
|
||||
object_property_add_child(qdev_get_machine(), "icc-bridge",
|
||||
OBJECT(icc_bridge), NULL);
|
||||
|
||||
pc_cpus_init(machine->cpu_model, icc_bridge);
|
||||
pc_cpus_init(machine->cpu_model);
|
||||
|
||||
if (kvm_enabled() && kvmclock_enabled) {
|
||||
kvmclock_create();
|
||||
@ -226,7 +220,6 @@ static void pc_init1(MachineState *machine,
|
||||
if (pci_enabled) {
|
||||
ioapic_init_gsi(gsi_state, "i440fx");
|
||||
}
|
||||
qdev_init_nofail(icc_bridge);
|
||||
|
||||
pc_register_ferr_irq(gsi[13]);
|
||||
|
||||
@ -332,7 +325,7 @@ static void pc_compat_2_1(MachineState *machine)
|
||||
|
||||
pc_compat_2_2(machine);
|
||||
smbios_uuid_encoded = false;
|
||||
x86_cpu_compat_kvm_no_autodisable(FEAT_8000_0001_ECX, CPUID_EXT3_SVM);
|
||||
x86_cpu_change_kvm_default("svm", NULL);
|
||||
pcms->enforce_aligned_dimm = false;
|
||||
}
|
||||
|
||||
@ -368,7 +361,7 @@ static void pc_compat_1_7(MachineState *machine)
|
||||
gigabyte_align = false;
|
||||
option_rom_has_mr = true;
|
||||
legacy_acpi_table_size = 6414;
|
||||
x86_cpu_compat_kvm_no_autoenable(FEAT_1_ECX, CPUID_EXT_X2APIC);
|
||||
x86_cpu_change_kvm_default("x2apic", NULL);
|
||||
}
|
||||
|
||||
static void pc_compat_1_6(MachineState *machine)
|
||||
@ -398,7 +391,7 @@ static void pc_compat_1_3(MachineState *machine)
|
||||
static void pc_compat_1_2(MachineState *machine)
|
||||
{
|
||||
pc_compat_1_3(machine);
|
||||
x86_cpu_compat_kvm_no_autoenable(FEAT_KVM, 1 << KVM_FEATURE_PV_EOI);
|
||||
x86_cpu_change_kvm_default("kvm-pv-eoi", NULL);
|
||||
}
|
||||
|
||||
/* PC compat function for pc-0.10 to pc-0.13 */
|
||||
@ -421,7 +414,7 @@ static void pc_init_isa(MachineState *machine)
|
||||
if (!machine->cpu_model) {
|
||||
machine->cpu_model = "486";
|
||||
}
|
||||
x86_cpu_compat_kvm_no_autoenable(FEAT_KVM, 1 << KVM_FEATURE_PV_EOI);
|
||||
x86_cpu_change_kvm_default("kvm-pv-eoi", NULL);
|
||||
enable_compat_apic_id_mode();
|
||||
pc_init1(machine, TYPE_I440FX_PCI_HOST_BRIDGE, TYPE_I440FX_PCI_DEVICE);
|
||||
}
|
||||
|
@ -43,7 +43,6 @@
|
||||
#include "hw/ide/pci.h"
|
||||
#include "hw/ide/ahci.h"
|
||||
#include "hw/usb.h"
|
||||
#include "hw/cpu/icc_bus.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "migration/migration.h"
|
||||
|
||||
@ -83,7 +82,6 @@ static void pc_q35_init(MachineState *machine)
|
||||
int i;
|
||||
ICH9LPCState *ich9_lpc;
|
||||
PCIDevice *ahci;
|
||||
DeviceState *icc_bridge;
|
||||
PcGuestInfo *guest_info;
|
||||
ram_addr_t lowmem;
|
||||
DriveInfo *hd[MAX_SATA_PORTS];
|
||||
@ -130,11 +128,7 @@ static void pc_q35_init(MachineState *machine)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
|
||||
object_property_add_child(qdev_get_machine(), "icc-bridge",
|
||||
OBJECT(icc_bridge), NULL);
|
||||
|
||||
pc_cpus_init(machine->cpu_model, icc_bridge);
|
||||
pc_cpus_init(machine->cpu_model);
|
||||
pc_acpi_init("q35-acpi-dsdt.aml");
|
||||
|
||||
kvmclock_create();
|
||||
@ -236,7 +230,6 @@ static void pc_q35_init(MachineState *machine)
|
||||
if (pci_enabled) {
|
||||
ioapic_init_gsi(gsi_state, "q35");
|
||||
}
|
||||
qdev_init_nofail(icc_bridge);
|
||||
|
||||
pc_register_ferr_irq(gsi[13]);
|
||||
|
||||
@ -316,7 +309,7 @@ static void pc_compat_2_1(MachineState *machine)
|
||||
pc_compat_2_2(machine);
|
||||
pcms->enforce_aligned_dimm = false;
|
||||
smbios_uuid_encoded = false;
|
||||
x86_cpu_compat_kvm_no_autodisable(FEAT_8000_0001_ECX, CPUID_EXT3_SVM);
|
||||
x86_cpu_change_kvm_default("svm", NULL);
|
||||
}
|
||||
|
||||
static void pc_compat_2_0(MachineState *machine)
|
||||
@ -333,7 +326,7 @@ static void pc_compat_1_7(MachineState *machine)
|
||||
smbios_defaults = false;
|
||||
gigabyte_align = false;
|
||||
option_rom_has_mr = true;
|
||||
x86_cpu_compat_kvm_no_autoenable(FEAT_1_ECX, CPUID_EXT_X2APIC);
|
||||
x86_cpu_change_kvm_default("x2apic", NULL);
|
||||
}
|
||||
|
||||
static void pc_compat_1_6(MachineState *machine)
|
||||
|
@ -296,7 +296,6 @@ static void apic_common_realize(DeviceState *dev, Error **errp)
|
||||
APICCommonClass *info;
|
||||
static DeviceState *vapic;
|
||||
static int apic_no;
|
||||
static bool mmio_registered;
|
||||
|
||||
if (apic_no >= MAX_APICS) {
|
||||
error_setg(errp, "%s initialization failed.",
|
||||
@ -307,11 +306,6 @@ static void apic_common_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
info = APIC_COMMON_GET_CLASS(s);
|
||||
info->realize(dev, errp);
|
||||
if (!mmio_registered) {
|
||||
ICCBus *b = ICC_BUS(qdev_get_parent_bus(dev));
|
||||
memory_region_add_subregion(b->apic_address_space, 0, &s->io_memory);
|
||||
mmio_registered = true;
|
||||
}
|
||||
|
||||
/* Note: We need at least 1M to map the VAPIC option ROM */
|
||||
if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK &&
|
||||
@ -425,13 +419,12 @@ static Property apic_properties_common[] = {
|
||||
|
||||
static void apic_common_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
ICCDeviceClass *idc = ICC_DEVICE_CLASS(klass);
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->vmsd = &vmstate_apic_common;
|
||||
dc->reset = apic_reset_common;
|
||||
dc->props = apic_properties_common;
|
||||
idc->realize = apic_common_realize;
|
||||
dc->realize = apic_common_realize;
|
||||
/*
|
||||
* Reason: APIC and CPU need to be wired up by
|
||||
* x86_cpu_apic_create()
|
||||
@ -441,7 +434,7 @@ static void apic_common_class_init(ObjectClass *klass, void *data)
|
||||
|
||||
static const TypeInfo apic_common_type = {
|
||||
.name = TYPE_APIC_COMMON,
|
||||
.parent = TYPE_ICC_DEVICE,
|
||||
.parent = TYPE_DEVICE,
|
||||
.instance_size = sizeof(APICCommonState),
|
||||
.class_size = sizeof(APICCommonClass),
|
||||
.class_init = apic_common_class_init,
|
||||
|
@ -1,82 +0,0 @@
|
||||
/* icc_bus.h
|
||||
* emulate x86 ICC (Interrupt Controller Communications) bus
|
||||
*
|
||||
* Copyright (c) 2013 Red Hat, Inc
|
||||
*
|
||||
* Authors:
|
||||
* Igor Mammedov <imammedo@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/>
|
||||
*/
|
||||
#ifndef ICC_BUS_H
|
||||
#define ICC_BUS_H
|
||||
|
||||
#include "exec/memory.h"
|
||||
#include "hw/qdev-core.h"
|
||||
|
||||
#define TYPE_ICC_BUS "icc-bus"
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
/**
|
||||
* ICCBus:
|
||||
*
|
||||
* ICC bus
|
||||
*/
|
||||
typedef struct ICCBus {
|
||||
/*< private >*/
|
||||
BusState parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
MemoryRegion *apic_address_space;
|
||||
} ICCBus;
|
||||
|
||||
#define ICC_BUS(obj) OBJECT_CHECK(ICCBus, (obj), TYPE_ICC_BUS)
|
||||
|
||||
/**
|
||||
* ICCDevice:
|
||||
*
|
||||
* ICC device
|
||||
*/
|
||||
typedef struct ICCDevice {
|
||||
/*< private >*/
|
||||
DeviceState qdev;
|
||||
/*< public >*/
|
||||
} ICCDevice;
|
||||
|
||||
/**
|
||||
* ICCDeviceClass:
|
||||
* @init: Initialization callback for derived classes.
|
||||
*
|
||||
* ICC device class
|
||||
*/
|
||||
typedef struct ICCDeviceClass {
|
||||
/*< private >*/
|
||||
DeviceClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
DeviceRealize realize;
|
||||
} ICCDeviceClass;
|
||||
|
||||
#define TYPE_ICC_DEVICE "icc-device"
|
||||
#define ICC_DEVICE(obj) OBJECT_CHECK(ICCDevice, (obj), TYPE_ICC_DEVICE)
|
||||
#define ICC_DEVICE_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(ICCDeviceClass, (klass), TYPE_ICC_DEVICE)
|
||||
#define ICC_DEVICE_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(ICCDeviceClass, (obj), TYPE_ICC_DEVICE)
|
||||
|
||||
#define TYPE_ICC_BRIDGE "icc-bridge"
|
||||
|
||||
#endif /* CONFIG_USER_ONLY */
|
||||
#endif
|
@ -22,7 +22,6 @@
|
||||
|
||||
#include "cpu.h"
|
||||
#include "exec/memory.h"
|
||||
#include "hw/cpu/icc_bus.h"
|
||||
#include "qemu/timer.h"
|
||||
|
||||
/* APIC Local Vector Table */
|
||||
@ -135,7 +134,7 @@ typedef struct APICCommonState APICCommonState;
|
||||
|
||||
typedef struct APICCommonClass
|
||||
{
|
||||
ICCDeviceClass parent_class;
|
||||
DeviceClass parent_class;
|
||||
|
||||
DeviceRealize realize;
|
||||
void (*set_base)(APICCommonState *s, uint64_t val);
|
||||
@ -150,7 +149,9 @@ typedef struct APICCommonClass
|
||||
} APICCommonClass;
|
||||
|
||||
struct APICCommonState {
|
||||
ICCDevice busdev;
|
||||
/*< private >*/
|
||||
DeviceState parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
MemoryRegion io_memory;
|
||||
X86CPU *cpu;
|
||||
|
@ -168,7 +168,7 @@ bool pc_machine_is_smm_enabled(PCMachineState *pcms);
|
||||
void pc_register_ferr_irq(qemu_irq irq);
|
||||
void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
|
||||
|
||||
void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge);
|
||||
void pc_cpus_init(const char *cpu_model);
|
||||
void pc_hot_add_cpu(const int64_t id, Error **errp);
|
||||
void pc_acpi_init(const char *default_dsdt);
|
||||
|
||||
@ -298,7 +298,27 @@ int e820_get_num_entries(void);
|
||||
bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
||||
|
||||
#define PC_COMPAT_2_4 \
|
||||
HW_COMPAT_2_4
|
||||
HW_COMPAT_2_4 \
|
||||
{\
|
||||
.driver = "Haswell-" TYPE_X86_CPU,\
|
||||
.property = "abm",\
|
||||
.value = "off",\
|
||||
},\
|
||||
{\
|
||||
.driver = "Haswell-noTSX-" TYPE_X86_CPU,\
|
||||
.property = "abm",\
|
||||
.value = "off",\
|
||||
},\
|
||||
{\
|
||||
.driver = "Broadwell-" TYPE_X86_CPU,\
|
||||
.property = "abm",\
|
||||
.value = "off",\
|
||||
},\
|
||||
{\
|
||||
.driver = "Broadwell-noTSX-" TYPE_X86_CPU,\
|
||||
.property = "abm",\
|
||||
.value = "off",\
|
||||
},
|
||||
|
||||
#define PC_COMPAT_2_3 \
|
||||
PC_COMPAT_2_4 \
|
||||
|
@ -47,6 +47,12 @@
|
||||
*/
|
||||
typedef uint32_t apic_id_t;
|
||||
|
||||
typedef struct X86CPUTopoInfo {
|
||||
unsigned pkg_id;
|
||||
unsigned core_id;
|
||||
unsigned smt_id;
|
||||
} X86CPUTopoInfo;
|
||||
|
||||
/* Return the bit width needed for 'count' IDs
|
||||
*/
|
||||
static unsigned apicid_bitwidth_for_count(unsigned count)
|
||||
@ -92,13 +98,11 @@ static inline unsigned apicid_pkg_offset(unsigned nr_cores, unsigned nr_threads)
|
||||
*/
|
||||
static inline apic_id_t apicid_from_topo_ids(unsigned nr_cores,
|
||||
unsigned nr_threads,
|
||||
unsigned pkg_id,
|
||||
unsigned core_id,
|
||||
unsigned smt_id)
|
||||
const X86CPUTopoInfo *topo)
|
||||
{
|
||||
return (pkg_id << apicid_pkg_offset(nr_cores, nr_threads)) |
|
||||
(core_id << apicid_core_offset(nr_cores, nr_threads)) |
|
||||
smt_id;
|
||||
return (topo->pkg_id << apicid_pkg_offset(nr_cores, nr_threads)) |
|
||||
(topo->core_id << apicid_core_offset(nr_cores, nr_threads)) |
|
||||
topo->smt_id;
|
||||
}
|
||||
|
||||
/* Calculate thread/core/package IDs for a specific topology,
|
||||
@ -107,14 +111,12 @@ static inline apic_id_t apicid_from_topo_ids(unsigned nr_cores,
|
||||
static inline void x86_topo_ids_from_idx(unsigned nr_cores,
|
||||
unsigned nr_threads,
|
||||
unsigned cpu_index,
|
||||
unsigned *pkg_id,
|
||||
unsigned *core_id,
|
||||
unsigned *smt_id)
|
||||
X86CPUTopoInfo *topo)
|
||||
{
|
||||
unsigned core_index = cpu_index / nr_threads;
|
||||
*smt_id = cpu_index % nr_threads;
|
||||
*core_id = core_index % nr_cores;
|
||||
*pkg_id = core_index / nr_cores;
|
||||
topo->smt_id = cpu_index % nr_threads;
|
||||
topo->core_id = core_index % nr_cores;
|
||||
topo->pkg_id = core_index / nr_cores;
|
||||
}
|
||||
|
||||
/* Make APIC ID for the CPU 'cpu_index'
|
||||
@ -125,10 +127,9 @@ static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_cores,
|
||||
unsigned nr_threads,
|
||||
unsigned cpu_index)
|
||||
{
|
||||
unsigned pkg_id, core_id, smt_id;
|
||||
x86_topo_ids_from_idx(nr_cores, nr_threads, cpu_index,
|
||||
&pkg_id, &core_id, &smt_id);
|
||||
return apicid_from_topo_ids(nr_cores, nr_threads, pkg_id, core_id, smt_id);
|
||||
X86CPUTopoInfo topo;
|
||||
x86_topo_ids_from_idx(nr_cores, nr_threads, cpu_index, &topo);
|
||||
return apicid_from_topo_ids(nr_cores, nr_threads, &topo);
|
||||
}
|
||||
|
||||
#endif /* HW_I386_TOPOLOGY_H */
|
||||
|
@ -1,4 +1,4 @@
|
||||
obj-y += translate.o helper.o cpu.o
|
||||
obj-y += translate.o helper.o cpu.o bpt_helper.o
|
||||
obj-y += excp_helper.o fpu_helper.o cc_helper.o int_helper.o svm_helper.o
|
||||
obj-y += smm_helper.o misc_helper.o mem_helper.o seg_helper.o
|
||||
obj-y += gdbstub.o
|
||||
|
182
target-i386/bpt_helper.c
Normal file
182
target-i386/bpt_helper.c
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* i386 breakpoint helpers
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "cpu.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
||||
|
||||
void hw_breakpoint_insert(CPUX86State *env, int index)
|
||||
{
|
||||
CPUState *cs = CPU(x86_env_get_cpu(env));
|
||||
int type = 0, err = 0;
|
||||
|
||||
switch (hw_breakpoint_type(env->dr[7], index)) {
|
||||
case DR7_TYPE_BP_INST:
|
||||
if (hw_breakpoint_enabled(env->dr[7], index)) {
|
||||
err = cpu_breakpoint_insert(cs, env->dr[index], BP_CPU,
|
||||
&env->cpu_breakpoint[index]);
|
||||
}
|
||||
break;
|
||||
case DR7_TYPE_DATA_WR:
|
||||
type = BP_CPU | BP_MEM_WRITE;
|
||||
break;
|
||||
case DR7_TYPE_IO_RW:
|
||||
/* No support for I/O watchpoints yet */
|
||||
break;
|
||||
case DR7_TYPE_DATA_RW:
|
||||
type = BP_CPU | BP_MEM_ACCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
if (type != 0) {
|
||||
err = cpu_watchpoint_insert(cs, env->dr[index],
|
||||
hw_breakpoint_len(env->dr[7], index),
|
||||
type, &env->cpu_watchpoint[index]);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
env->cpu_breakpoint[index] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void hw_breakpoint_remove(CPUX86State *env, int index)
|
||||
{
|
||||
CPUState *cs;
|
||||
|
||||
if (!env->cpu_breakpoint[index]) {
|
||||
return;
|
||||
}
|
||||
cs = CPU(x86_env_get_cpu(env));
|
||||
switch (hw_breakpoint_type(env->dr[7], index)) {
|
||||
case DR7_TYPE_BP_INST:
|
||||
if (hw_breakpoint_enabled(env->dr[7], index)) {
|
||||
cpu_breakpoint_remove_by_ref(cs, env->cpu_breakpoint[index]);
|
||||
}
|
||||
break;
|
||||
case DR7_TYPE_DATA_WR:
|
||||
case DR7_TYPE_DATA_RW:
|
||||
cpu_watchpoint_remove_by_ref(cs, env->cpu_watchpoint[index]);
|
||||
break;
|
||||
case DR7_TYPE_IO_RW:
|
||||
/* No support for I/O watchpoints yet */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool check_hw_breakpoints(CPUX86State *env, bool force_dr6_update)
|
||||
{
|
||||
target_ulong dr6;
|
||||
int reg;
|
||||
bool hit_enabled = false;
|
||||
|
||||
dr6 = env->dr[6] & ~0xf;
|
||||
for (reg = 0; reg < DR7_MAX_BP; reg++) {
|
||||
bool bp_match = false;
|
||||
bool wp_match = false;
|
||||
|
||||
switch (hw_breakpoint_type(env->dr[7], reg)) {
|
||||
case DR7_TYPE_BP_INST:
|
||||
if (env->dr[reg] == env->eip) {
|
||||
bp_match = true;
|
||||
}
|
||||
break;
|
||||
case DR7_TYPE_DATA_WR:
|
||||
case DR7_TYPE_DATA_RW:
|
||||
if (env->cpu_watchpoint[reg] &&
|
||||
env->cpu_watchpoint[reg]->flags & BP_WATCHPOINT_HIT) {
|
||||
wp_match = true;
|
||||
}
|
||||
break;
|
||||
case DR7_TYPE_IO_RW:
|
||||
break;
|
||||
}
|
||||
if (bp_match || wp_match) {
|
||||
dr6 |= 1 << reg;
|
||||
if (hw_breakpoint_enabled(env->dr[7], reg)) {
|
||||
hit_enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hit_enabled || force_dr6_update) {
|
||||
env->dr[6] = dr6;
|
||||
}
|
||||
|
||||
return hit_enabled;
|
||||
}
|
||||
|
||||
void breakpoint_handler(CPUState *cs)
|
||||
{
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
CPUX86State *env = &cpu->env;
|
||||
CPUBreakpoint *bp;
|
||||
|
||||
if (cs->watchpoint_hit) {
|
||||
if (cs->watchpoint_hit->flags & BP_CPU) {
|
||||
cs->watchpoint_hit = NULL;
|
||||
if (check_hw_breakpoints(env, false)) {
|
||||
raise_exception(env, EXCP01_DB);
|
||||
} else {
|
||||
cpu_resume_from_signal(cs, NULL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
|
||||
if (bp->pc == env->eip) {
|
||||
if (bp->flags & BP_CPU) {
|
||||
check_hw_breakpoints(env, true);
|
||||
raise_exception(env, EXCP01_DB);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void helper_single_step(CPUX86State *env)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
check_hw_breakpoints(env, true);
|
||||
env->dr[6] |= DR6_BS;
|
||||
#endif
|
||||
raise_exception(env, EXCP01_DB);
|
||||
}
|
||||
|
||||
void helper_movl_drN_T0(CPUX86State *env, int reg, target_ulong t0)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
int i;
|
||||
|
||||
if (reg < 4) {
|
||||
hw_breakpoint_remove(env, reg);
|
||||
env->dr[reg] = t0;
|
||||
hw_breakpoint_insert(env, reg);
|
||||
} else if (reg == 7) {
|
||||
for (i = 0; i < DR7_MAX_BP; i++) {
|
||||
hw_breakpoint_remove(env, i);
|
||||
}
|
||||
env->dr[7] = t0;
|
||||
for (i = 0; i < DR7_MAX_BP; i++) {
|
||||
hw_breakpoint_insert(env, i);
|
||||
}
|
||||
} else {
|
||||
env->dr[reg] = t0;
|
||||
}
|
||||
#endif
|
||||
}
|
@ -43,7 +43,6 @@
|
||||
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/cpu/icc_bus.h"
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "exec/address-spaces.h"
|
||||
#include "hw/xen/xen.h"
|
||||
@ -478,38 +477,6 @@ const char *get_register_name_32(unsigned int reg)
|
||||
return x86_reg_info_32[reg].name;
|
||||
}
|
||||
|
||||
/* KVM-specific features that are automatically added to all CPU models
|
||||
* when KVM is enabled.
|
||||
*/
|
||||
static uint32_t kvm_default_features[FEATURE_WORDS] = {
|
||||
[FEAT_KVM] = (1 << KVM_FEATURE_CLOCKSOURCE) |
|
||||
(1 << KVM_FEATURE_NOP_IO_DELAY) |
|
||||
(1 << KVM_FEATURE_CLOCKSOURCE2) |
|
||||
(1 << KVM_FEATURE_ASYNC_PF) |
|
||||
(1 << KVM_FEATURE_STEAL_TIME) |
|
||||
(1 << KVM_FEATURE_PV_EOI) |
|
||||
(1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT),
|
||||
[FEAT_1_ECX] = CPUID_EXT_X2APIC,
|
||||
};
|
||||
|
||||
/* Features that are not added by default to any CPU model when KVM is enabled.
|
||||
*/
|
||||
static uint32_t kvm_default_unset_features[FEATURE_WORDS] = {
|
||||
[FEAT_1_EDX] = CPUID_ACPI,
|
||||
[FEAT_1_ECX] = CPUID_EXT_MONITOR,
|
||||
[FEAT_8000_0001_ECX] = CPUID_EXT3_SVM,
|
||||
};
|
||||
|
||||
void x86_cpu_compat_kvm_no_autoenable(FeatureWord w, uint32_t features)
|
||||
{
|
||||
kvm_default_features[w] &= ~features;
|
||||
}
|
||||
|
||||
void x86_cpu_compat_kvm_no_autodisable(FeatureWord w, uint32_t features)
|
||||
{
|
||||
kvm_default_unset_features[w] &= ~features;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the set of feature flags that are supported and migratable by
|
||||
* QEMU, for a given FeatureWord.
|
||||
@ -1113,7 +1080,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||
CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
|
||||
CPUID_EXT2_SYSCALL,
|
||||
.features[FEAT_8000_0001_ECX] =
|
||||
CPUID_EXT3_LAHF_LM,
|
||||
CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM,
|
||||
.features[FEAT_7_0_EBX] =
|
||||
CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
|
||||
CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
|
||||
@ -1148,7 +1115,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||
CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
|
||||
CPUID_EXT2_SYSCALL,
|
||||
.features[FEAT_8000_0001_ECX] =
|
||||
CPUID_EXT3_LAHF_LM,
|
||||
CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM,
|
||||
.features[FEAT_7_0_EBX] =
|
||||
CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
|
||||
CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
|
||||
@ -1185,7 +1152,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||
CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
|
||||
CPUID_EXT2_SYSCALL,
|
||||
.features[FEAT_8000_0001_ECX] =
|
||||
CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH,
|
||||
CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH,
|
||||
.features[FEAT_7_0_EBX] =
|
||||
CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
|
||||
CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
|
||||
@ -1223,7 +1190,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||
CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
|
||||
CPUID_EXT2_SYSCALL,
|
||||
.features[FEAT_8000_0001_ECX] =
|
||||
CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH,
|
||||
CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH,
|
||||
.features[FEAT_7_0_EBX] =
|
||||
CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
|
||||
CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
|
||||
@ -1392,6 +1359,43 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||
},
|
||||
};
|
||||
|
||||
typedef struct PropValue {
|
||||
const char *prop, *value;
|
||||
} PropValue;
|
||||
|
||||
/* KVM-specific features that are automatically added/removed
|
||||
* from all CPU models when KVM is enabled.
|
||||
*/
|
||||
static PropValue kvm_default_props[] = {
|
||||
{ "kvmclock", "on" },
|
||||
{ "kvm-nopiodelay", "on" },
|
||||
{ "kvm-asyncpf", "on" },
|
||||
{ "kvm-steal-time", "on" },
|
||||
{ "kvm-pv-eoi", "on" },
|
||||
{ "kvmclock-stable-bit", "on" },
|
||||
{ "x2apic", "on" },
|
||||
{ "acpi", "off" },
|
||||
{ "monitor", "off" },
|
||||
{ "svm", "off" },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
void x86_cpu_change_kvm_default(const char *prop, const char *value)
|
||||
{
|
||||
PropValue *pv;
|
||||
for (pv = kvm_default_props; pv->prop; pv++) {
|
||||
if (!strcmp(pv->prop, prop)) {
|
||||
pv->value = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* It is valid to call this function only for properties that
|
||||
* are already present in the kvm_default_props table.
|
||||
*/
|
||||
assert(pv->prop);
|
||||
}
|
||||
|
||||
static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w,
|
||||
bool migratable_only);
|
||||
|
||||
@ -2061,6 +2065,18 @@ static int x86_cpu_filter_features(X86CPU *cpu)
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void x86_cpu_apply_props(X86CPU *cpu, PropValue *props)
|
||||
{
|
||||
PropValue *pv;
|
||||
for (pv = props; pv->prop; pv++) {
|
||||
if (!pv->value) {
|
||||
continue;
|
||||
}
|
||||
object_property_parse(OBJECT(cpu), pv->value, pv->prop,
|
||||
&error_abort);
|
||||
}
|
||||
}
|
||||
|
||||
/* Load data from X86CPUDefinition
|
||||
*/
|
||||
static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp)
|
||||
@ -2084,11 +2100,7 @@ static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp)
|
||||
|
||||
/* Special cases not set in the X86CPUDefinition structs: */
|
||||
if (kvm_enabled()) {
|
||||
FeatureWord w;
|
||||
for (w = 0; w < FEATURE_WORDS; w++) {
|
||||
env->features[w] |= kvm_default_features[w];
|
||||
env->features[w] &= ~kvm_default_unset_features[w];
|
||||
}
|
||||
x86_cpu_apply_props(cpu, kvm_default_props);
|
||||
}
|
||||
|
||||
env->features[FEAT_1_ECX] |= CPUID_EXT_HYPERVISOR;
|
||||
@ -2723,7 +2735,6 @@ static void mce_init(X86CPU *cpu)
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(cpu);
|
||||
APICCommonState *apic;
|
||||
const char *apic_type = "apic";
|
||||
|
||||
@ -2733,11 +2744,7 @@ static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
|
||||
apic_type = "xen-apic";
|
||||
}
|
||||
|
||||
cpu->apic_state = qdev_try_create(qdev_get_parent_bus(dev), apic_type);
|
||||
if (cpu->apic_state == NULL) {
|
||||
error_setg(errp, "APIC device '%s' could not be created", apic_type);
|
||||
return;
|
||||
}
|
||||
cpu->apic_state = DEVICE(object_new(apic_type));
|
||||
|
||||
object_property_add_child(OBJECT(cpu), "apic",
|
||||
OBJECT(cpu->apic_state), NULL);
|
||||
@ -2745,15 +2752,30 @@ static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
|
||||
/* TODO: convert to link<> */
|
||||
apic = APIC_COMMON(cpu->apic_state);
|
||||
apic->cpu = cpu;
|
||||
apic->apicbase = APIC_DEFAULT_ADDRESS | MSR_IA32_APICBASE_ENABLE;
|
||||
}
|
||||
|
||||
static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
|
||||
{
|
||||
APICCommonState *apic;
|
||||
static bool apic_mmio_map_once;
|
||||
|
||||
if (cpu->apic_state == NULL) {
|
||||
return;
|
||||
}
|
||||
object_property_set_bool(OBJECT(cpu->apic_state), true, "realized",
|
||||
errp);
|
||||
|
||||
/* Map APIC MMIO area */
|
||||
apic = APIC_COMMON(cpu->apic_state);
|
||||
if (!apic_mmio_map_once) {
|
||||
memory_region_add_subregion_overlap(get_system_memory(),
|
||||
apic->apicbase &
|
||||
MSR_IA32_APICBASE_BASE,
|
||||
&apic->io_memory,
|
||||
0x1000);
|
||||
apic_mmio_map_once = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void x86_cpu_machine_done(Notifier *n, void *unused)
|
||||
@ -3133,7 +3155,6 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
|
||||
|
||||
xcc->parent_realize = dc->realize;
|
||||
dc->realize = x86_cpu_realizefn;
|
||||
dc->bus_type = TYPE_ICC_BUS;
|
||||
dc->props = x86_cpu_properties;
|
||||
|
||||
xcc->parent_reset = cc->reset;
|
||||
|
@ -833,6 +833,7 @@ typedef struct CPUX86State {
|
||||
BNDReg bnd_regs[4];
|
||||
BNDCSReg bndcs_regs;
|
||||
uint64_t msr_bndcfgs;
|
||||
uint64_t efer;
|
||||
|
||||
/* Beginning of state preserved by INIT (dummy marker). */
|
||||
struct {} start_init_save;
|
||||
@ -865,7 +866,6 @@ typedef struct CPUX86State {
|
||||
uint32_t sysenter_cs;
|
||||
target_ulong sysenter_esp;
|
||||
target_ulong sysenter_eip;
|
||||
uint64_t efer;
|
||||
uint64_t star;
|
||||
|
||||
uint64_t vm_hsave;
|
||||
@ -1154,7 +1154,6 @@ static inline int hw_breakpoint_len(unsigned long dr7, int index)
|
||||
|
||||
void hw_breakpoint_insert(CPUX86State *env, int index);
|
||||
void hw_breakpoint_remove(CPUX86State *env, int index);
|
||||
bool check_hw_breakpoints(CPUX86State *env, bool force_dr6_update);
|
||||
void breakpoint_handler(CPUState *cs);
|
||||
|
||||
/* will be suppressed */
|
||||
@ -1341,8 +1340,15 @@ void cpu_smm_update(X86CPU *cpu);
|
||||
|
||||
void cpu_report_tpr_access(CPUX86State *env, TPRAccess access);
|
||||
|
||||
void x86_cpu_compat_kvm_no_autoenable(FeatureWord w, uint32_t features);
|
||||
void x86_cpu_compat_kvm_no_autodisable(FeatureWord w, uint32_t features);
|
||||
/* Change the value of a KVM-specific default
|
||||
*
|
||||
* If value is NULL, no default will be set and the original
|
||||
* value from the CPU model table will be kept.
|
||||
*
|
||||
* It is valid to call this funciton only for properties that
|
||||
* are already present in the kvm_default_props table.
|
||||
*/
|
||||
void x86_cpu_change_kvm_default(const char *prop, const char *value);
|
||||
|
||||
|
||||
/* Return name of 32-bit register, from a R_* constant */
|
||||
|
@ -1096,134 +1096,6 @@ out:
|
||||
return pte | page_offset;
|
||||
}
|
||||
|
||||
void hw_breakpoint_insert(CPUX86State *env, int index)
|
||||
{
|
||||
CPUState *cs = CPU(x86_env_get_cpu(env));
|
||||
int type = 0, err = 0;
|
||||
|
||||
switch (hw_breakpoint_type(env->dr[7], index)) {
|
||||
case DR7_TYPE_BP_INST:
|
||||
if (hw_breakpoint_enabled(env->dr[7], index)) {
|
||||
err = cpu_breakpoint_insert(cs, env->dr[index], BP_CPU,
|
||||
&env->cpu_breakpoint[index]);
|
||||
}
|
||||
break;
|
||||
case DR7_TYPE_DATA_WR:
|
||||
type = BP_CPU | BP_MEM_WRITE;
|
||||
break;
|
||||
case DR7_TYPE_IO_RW:
|
||||
/* No support for I/O watchpoints yet */
|
||||
break;
|
||||
case DR7_TYPE_DATA_RW:
|
||||
type = BP_CPU | BP_MEM_ACCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
if (type != 0) {
|
||||
err = cpu_watchpoint_insert(cs, env->dr[index],
|
||||
hw_breakpoint_len(env->dr[7], index),
|
||||
type, &env->cpu_watchpoint[index]);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
env->cpu_breakpoint[index] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void hw_breakpoint_remove(CPUX86State *env, int index)
|
||||
{
|
||||
CPUState *cs;
|
||||
|
||||
if (!env->cpu_breakpoint[index]) {
|
||||
return;
|
||||
}
|
||||
cs = CPU(x86_env_get_cpu(env));
|
||||
switch (hw_breakpoint_type(env->dr[7], index)) {
|
||||
case DR7_TYPE_BP_INST:
|
||||
if (hw_breakpoint_enabled(env->dr[7], index)) {
|
||||
cpu_breakpoint_remove_by_ref(cs, env->cpu_breakpoint[index]);
|
||||
}
|
||||
break;
|
||||
case DR7_TYPE_DATA_WR:
|
||||
case DR7_TYPE_DATA_RW:
|
||||
cpu_watchpoint_remove_by_ref(cs, env->cpu_watchpoint[index]);
|
||||
break;
|
||||
case DR7_TYPE_IO_RW:
|
||||
/* No support for I/O watchpoints yet */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool check_hw_breakpoints(CPUX86State *env, bool force_dr6_update)
|
||||
{
|
||||
target_ulong dr6;
|
||||
int reg;
|
||||
bool hit_enabled = false;
|
||||
|
||||
dr6 = env->dr[6] & ~0xf;
|
||||
for (reg = 0; reg < DR7_MAX_BP; reg++) {
|
||||
bool bp_match = false;
|
||||
bool wp_match = false;
|
||||
|
||||
switch (hw_breakpoint_type(env->dr[7], reg)) {
|
||||
case DR7_TYPE_BP_INST:
|
||||
if (env->dr[reg] == env->eip) {
|
||||
bp_match = true;
|
||||
}
|
||||
break;
|
||||
case DR7_TYPE_DATA_WR:
|
||||
case DR7_TYPE_DATA_RW:
|
||||
if (env->cpu_watchpoint[reg] &&
|
||||
env->cpu_watchpoint[reg]->flags & BP_WATCHPOINT_HIT) {
|
||||
wp_match = true;
|
||||
}
|
||||
break;
|
||||
case DR7_TYPE_IO_RW:
|
||||
break;
|
||||
}
|
||||
if (bp_match || wp_match) {
|
||||
dr6 |= 1 << reg;
|
||||
if (hw_breakpoint_enabled(env->dr[7], reg)) {
|
||||
hit_enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hit_enabled || force_dr6_update) {
|
||||
env->dr[6] = dr6;
|
||||
}
|
||||
|
||||
return hit_enabled;
|
||||
}
|
||||
|
||||
void breakpoint_handler(CPUState *cs)
|
||||
{
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
CPUX86State *env = &cpu->env;
|
||||
CPUBreakpoint *bp;
|
||||
|
||||
if (cs->watchpoint_hit) {
|
||||
if (cs->watchpoint_hit->flags & BP_CPU) {
|
||||
cs->watchpoint_hit = NULL;
|
||||
if (check_hw_breakpoints(env, false)) {
|
||||
raise_exception(env, EXCP01_DB);
|
||||
} else {
|
||||
cpu_resume_from_signal(cs, NULL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
|
||||
if (bp->pc == env->eip) {
|
||||
if (bp->flags & BP_CPU) {
|
||||
check_hw_breakpoints(env, true);
|
||||
raise_exception(env, EXCP01_DB);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct MCEInjectionParams {
|
||||
Monitor *mon;
|
||||
X86CPU *cpu;
|
||||
|
@ -67,6 +67,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
|
||||
|
||||
static bool has_msr_star;
|
||||
static bool has_msr_hsave_pa;
|
||||
static bool has_msr_tsc_aux;
|
||||
static bool has_msr_tsc_adjust;
|
||||
static bool has_msr_tsc_deadline;
|
||||
static bool has_msr_feature_control;
|
||||
@ -825,6 +826,10 @@ static int kvm_get_supported_msrs(KVMState *s)
|
||||
has_msr_hsave_pa = true;
|
||||
continue;
|
||||
}
|
||||
if (kvm_msr_list->indices[i] == MSR_TSC_AUX) {
|
||||
has_msr_tsc_aux = true;
|
||||
continue;
|
||||
}
|
||||
if (kvm_msr_list->indices[i] == MSR_TSC_ADJUST) {
|
||||
has_msr_tsc_adjust = true;
|
||||
continue;
|
||||
@ -1299,6 +1304,9 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
|
||||
if (has_msr_hsave_pa) {
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_VM_HSAVE_PA, env->vm_hsave);
|
||||
}
|
||||
if (has_msr_tsc_aux) {
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_TSC_AUX, env->tsc_aux);
|
||||
}
|
||||
if (has_msr_tsc_adjust) {
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_TSC_ADJUST, env->tsc_adjust);
|
||||
}
|
||||
@ -1671,6 +1679,9 @@ static int kvm_get_msrs(X86CPU *cpu)
|
||||
if (has_msr_hsave_pa) {
|
||||
msrs[n++].index = MSR_VM_HSAVE_PA;
|
||||
}
|
||||
if (has_msr_tsc_aux) {
|
||||
msrs[n++].index = MSR_TSC_AUX;
|
||||
}
|
||||
if (has_msr_tsc_adjust) {
|
||||
msrs[n++].index = MSR_TSC_ADJUST;
|
||||
}
|
||||
@ -1820,6 +1831,9 @@ static int kvm_get_msrs(X86CPU *cpu)
|
||||
case MSR_IA32_TSC:
|
||||
env->tsc = msrs[i].data;
|
||||
break;
|
||||
case MSR_TSC_AUX:
|
||||
env->tsc_aux = msrs[i].data;
|
||||
break;
|
||||
case MSR_TSC_ADJUST:
|
||||
env->tsc_adjust = msrs[i].data;
|
||||
break;
|
||||
|
@ -95,15 +95,6 @@ void helper_into(CPUX86State *env, int next_eip_addend)
|
||||
}
|
||||
}
|
||||
|
||||
void helper_single_step(CPUX86State *env)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
check_hw_breakpoints(env, true);
|
||||
env->dr[6] |= DR6_BS;
|
||||
#endif
|
||||
raise_exception(env, EXCP01_DB);
|
||||
}
|
||||
|
||||
void helper_cpuid(CPUX86State *env)
|
||||
{
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
@ -127,10 +118,6 @@ target_ulong helper_read_crN(CPUX86State *env, int reg)
|
||||
void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
|
||||
{
|
||||
}
|
||||
|
||||
void helper_movl_drN_T0(CPUX86State *env, int reg, target_ulong t0)
|
||||
{
|
||||
}
|
||||
#else
|
||||
target_ulong helper_read_crN(CPUX86State *env, int reg)
|
||||
{
|
||||
@ -176,27 +163,6 @@ void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void helper_movl_drN_T0(CPUX86State *env, int reg, target_ulong t0)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (reg < 4) {
|
||||
hw_breakpoint_remove(env, reg);
|
||||
env->dr[reg] = t0;
|
||||
hw_breakpoint_insert(env, reg);
|
||||
} else if (reg == 7) {
|
||||
for (i = 0; i < DR7_MAX_BP; i++) {
|
||||
hw_breakpoint_remove(env, i);
|
||||
}
|
||||
env->dr[7] = t0;
|
||||
for (i = 0; i < DR7_MAX_BP; i++) {
|
||||
hw_breakpoint_insert(env, i);
|
||||
}
|
||||
} else {
|
||||
env->dr[reg] = t0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void helper_lmsw(CPUX86State *env, target_ulong t0)
|
||||
|
8
vl.c
8
vl.c
@ -1223,7 +1223,13 @@ static void smp_parse(QemuOpts *opts)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
max_cpus = qemu_opt_get_number(opts, "maxcpus", 0);
|
||||
max_cpus = qemu_opt_get_number(opts, "maxcpus", cpus);
|
||||
if (sockets * cores * threads > max_cpus) {
|
||||
fprintf(stderr, "cpu topology: error: "
|
||||
"sockets (%u) * cores (%u) * threads (%u) > maxcpus (%u)\n",
|
||||
sockets, cores, threads, max_cpus);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
smp_cpus = cpus;
|
||||
smp_cores = cores > 0 ? cores : 1;
|
||||
|
Loading…
Reference in New Issue
Block a user