#include "qemu/osdep.h"
#include "qemu/units.h"
-#include "hw/i386/x86.h"
#include "hw/i386/pc.h"
#include "hw/char/serial.h"
#include "hw/char/parallel.h"
-#include "hw/i386/topology.h"
+#include "hw/hyperv/hv-balloon.h"
#include "hw/i386/fw_cfg.h"
#include "hw/i386/vmport.h"
#include "sysemu/cpus.h"
-#include "hw/block/fdc.h"
#include "hw/ide/internal.h"
-#include "hw/ide/isa.h"
-#include "hw/pci/pci.h"
-#include "hw/pci/pci_bus.h"
-#include "hw/pci-bridge/pci_expander_bridge.h"
-#include "hw/nvram/fw_cfg.h"
#include "hw/timer/hpet.h"
-#include "hw/firmware/smbios.h"
#include "hw/loader.h"
-#include "elf.h"
-#include "migration/vmstate.h"
-#include "multiboot.h"
#include "hw/rtc/mc146818rtc.h"
#include "hw/intc/i8259.h"
-#include "hw/intc/ioapic.h"
#include "hw/timer/i8254.h"
#include "hw/input/i8042.h"
-#include "hw/irq.h"
#include "hw/audio/pcspk.h"
-#include "hw/pci/msi.h"
-#include "hw/sysbus.h"
#include "sysemu/sysemu.h"
-#include "sysemu/tcg.h"
-#include "sysemu/numa.h"
-#include "sysemu/kvm.h"
#include "sysemu/xen.h"
#include "sysemu/reset.h"
-#include "sysemu/runstate.h"
#include "kvm/kvm_i386.h"
#include "hw/xen/xen.h"
-#include "hw/xen/start_info.h"
-#include "ui/qemu-spice.h"
-#include "exec/memory.h"
-#include "qemu/bitmap.h"
-#include "qemu/config-file.h"
+#include "qapi/qmp/qlist.h"
#include "qemu/error-report.h"
-#include "qemu/option.h"
-#include "qemu/cutils.h"
-#include "hw/acpi/acpi.h"
#include "hw/acpi/cpu_hotplug.h"
#include "acpi-build.h"
-#include "hw/mem/pc-dimm.h"
#include "hw/mem/nvdimm.h"
-#include "hw/cxl/cxl.h"
#include "hw/cxl/cxl_host.h"
-#include "qapi/error.h"
-#include "qapi/qapi-visit-common.h"
-#include "qapi/qapi-visit-machine.h"
-#include "qapi/visitor.h"
-#include "hw/core/cpu.h"
#include "hw/usb.h"
#include "hw/i386/intel_iommu.h"
#include "hw/net/ne2000-isa.h"
-#include "standard-headers/asm-x86/bootparam.h"
#include "hw/virtio/virtio-iommu.h"
#include "hw/virtio/virtio-md-pci.h"
#include "hw/i386/kvm/xen_overlay.h"
#include "hw/i386/kvm/xen_evtchn.h"
#include "hw/i386/kvm/xen_gnttab.h"
#include "hw/i386/kvm/xen_xenstore.h"
-#include "sysemu/replay.h"
-#include "target/i386/cpu.h"
+#include "hw/mem/memory-device.h"
#include "e820_memory_layout.h"
-#include "fw_cfg.h"
#include "trace.h"
#include CONFIG_DEVICES
{ "qemu64-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },\
{ "athlon-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },
+GlobalProperty pc_compat_8_2[] = {};
+const size_t pc_compat_8_2_len = G_N_ELEMENTS(pc_compat_8_2);
+
+GlobalProperty pc_compat_8_1[] = {};
+const size_t pc_compat_8_1_len = G_N_ELEMENTS(pc_compat_8_1);
+
GlobalProperty pc_compat_8_0[] = {
{ "virtio-mem", "unplugged-inaccessible", "auto" },
};
};
const size_t pc_compat_2_0_len = G_N_ELEMENTS(pc_compat_2_0);
-GlobalProperty pc_compat_1_7[] = {
- PC_CPU_MODEL_IDS("1.7.0")
- { TYPE_USB_DEVICE, "msos-desc", "no" },
- { "PIIX4_PM", ACPI_PM_PROP_ACPI_PCIHP_BRIDGE, "off" },
- { "hpet", HPET_INTCAP, "4" },
-};
-const size_t pc_compat_1_7_len = G_N_ELEMENTS(pc_compat_1_7);
-
-GlobalProperty pc_compat_1_6[] = {
- PC_CPU_MODEL_IDS("1.6.0")
- { "e1000", "mitigation", "off" },
- { "qemu64-" TYPE_X86_CPU, "model", "2" },
- { "qemu32-" TYPE_X86_CPU, "model", "3" },
- { "i440FX-pcihost", "short_root_bus", "1" },
- { "q35-pcihost", "short_root_bus", "1" },
-};
-const size_t pc_compat_1_6_len = G_N_ELEMENTS(pc_compat_1_6);
-
-GlobalProperty pc_compat_1_5[] = {
- PC_CPU_MODEL_IDS("1.5.0")
- { "Conroe-" TYPE_X86_CPU, "model", "2" },
- { "Conroe-" TYPE_X86_CPU, "min-level", "2" },
- { "Penryn-" TYPE_X86_CPU, "model", "2" },
- { "Penryn-" TYPE_X86_CPU, "min-level", "2" },
- { "Nehalem-" TYPE_X86_CPU, "model", "2" },
- { "Nehalem-" TYPE_X86_CPU, "min-level", "2" },
- { "virtio-net-pci", "any_layout", "off" },
- { TYPE_X86_CPU, "pmu", "on" },
- { "i440FX-pcihost", "short_root_bus", "0" },
- { "q35-pcihost", "short_root_bus", "0" },
-};
-const size_t pc_compat_1_5_len = G_N_ELEMENTS(pc_compat_1_5);
-
-GlobalProperty pc_compat_1_4[] = {
- PC_CPU_MODEL_IDS("1.4.0")
- { "scsi-hd", "discard_granularity", "0" },
- { "scsi-cd", "discard_granularity", "0" },
- { "ide-hd", "discard_granularity", "0" },
- { "ide-cd", "discard_granularity", "0" },
- { "virtio-blk-pci", "discard_granularity", "0" },
- /* DEV_NVECTORS_UNSPECIFIED as a uint32_t string: */
- { "virtio-serial-pci", "vectors", "0xFFFFFFFF" },
- { "virtio-net-pci", "ctrl_guest_offloads", "off" },
- { "e1000", "romfile", "pxe-e1000.rom" },
- { "ne2k_pci", "romfile", "pxe-ne2k_pci.rom" },
- { "pcnet", "romfile", "pxe-pcnet.rom" },
- { "rtl8139", "romfile", "pxe-rtl8139.rom" },
- { "virtio-net-pci", "romfile", "pxe-virtio.rom" },
- { "486-" TYPE_X86_CPU, "model", "0" },
- { "n270" "-" TYPE_X86_CPU, "movbe", "off" },
- { "Westmere" "-" TYPE_X86_CPU, "pclmulqdq", "off" },
-};
-const size_t pc_compat_1_4_len = G_N_ELEMENTS(pc_compat_1_4);
-
GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled)
{
GSIState *s;
return 0xffffffffffffffffULL;
}
-/* MSDOS compatibility mode FPU exception support */
+/* MS-DOS compatibility mode FPU exception support */
static void ioportF0_write(void *opaque, hwaddr addr, uint64_t data,
unsigned size)
{
static uint64_t pc_get_cxl_range_start(PCMachineState *pcms)
{
PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+ MachineState *ms = MACHINE(pcms);
hwaddr cxl_base;
ram_addr_t size;
- if (pcmc->has_reserved_memory) {
+ if (pcmc->has_reserved_memory &&
+ (ms->ram_size < ms->maxram_size)) {
pc_get_device_memory_range(pcms, &cxl_base, &size);
cxl_base += size;
} else {
static hwaddr pc_max_used_gpa(PCMachineState *pcms, uint64_t pci_hole64_size)
{
X86CPU *cpu = X86_CPU(first_cpu);
+ PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+ MachineState *ms = MACHINE(pcms);
+
+ if (cpu->env.features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
+ /* 64-bit systems */
+ return pc_pci_hole64_start() + pci_hole64_size - 1;
+ }
- /* 32-bit systems don't have hole64 thus return max CPU address */
- if (cpu->phys_bits <= 32) {
+ /* 32-bit systems */
+ if (pcmc->broken_32bit_mem_addr_check) {
+ /* old value for compatibility reasons */
return ((hwaddr)1 << cpu->phys_bits) - 1;
}
- return pc_pci_hole64_start() + pci_hole64_size - 1;
+ /*
+ * 32-bit systems don't have hole64 but they might have a region for
+ * memory devices. Even if additional hotplugged memory devices might
+ * not be usable by most guest OSes, we need to still consider them for
+ * calculating the highest possible GPA so that we can properly report
+ * if someone configures them on a CPU that cannot possibly address them.
+ */
+ if (pcmc->has_reserved_memory &&
+ (ms->ram_size < ms->maxram_size)) {
+ hwaddr devmem_start;
+ ram_addr_t devmem_size;
+
+ pc_get_device_memory_range(pcms, &devmem_start, &devmem_size);
+ devmem_start += devmem_size;
+ return devmem_start - 1;
+ }
+
+ /* configuration without any memory hotplug */
+ return pc_above_4g_end(pcms) - 1;
}
/*
if (machine->device_memory) {
uint64_t *val = g_malloc(sizeof(*val));
- PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
uint64_t res_mem_end = machine->device_memory->base;
if (!pcmc->broken_reserved_end) {
DeviceState *hpet = NULL;
int pit_isa_irq = 0;
qemu_irq pit_alt_irq = NULL;
- qemu_irq rtc_irq = NULL;
ISADevice *pit = NULL;
MemoryRegion *ioport80_io = g_new(MemoryRegion, 1);
MemoryRegion *ioportF0_io = g_new(MemoryRegion, 1);
/*
* Check if an HPET shall be created.
- *
- * Without KVM_CAP_PIT_STATE2, we cannot switch off the in-kernel PIT
- * when the HPET wants to take over. Thus we have to disable the latter.
*/
- if (pcms->hpet_enabled && (!kvm_irqchip_in_kernel() ||
- kvm_has_pit_state2())) {
+ if (pcms->hpet_enabled) {
+ qemu_irq rtc_irq;
+
hpet = qdev_try_new(TYPE_HPET);
if (!hpet) {
error_report("couldn't create HPET device");
exit(1);
}
/*
- * For pc-piix-*, hpet's intcap is always IRQ2. For pc-q35-1.7 and
- * earlier, use IRQ2 for compat. Otherwise, use IRQ16~23, IRQ8 and
- * IRQ2.
+ * For pc-piix-*, hpet's intcap is always IRQ2. For pc-q35-*,
+ * use IRQ16~23, IRQ8 and IRQ2. If the user has already set
+ * the property, use whatever mask they specified.
*/
uint8_t compat = object_property_get_uint(OBJECT(hpet),
HPET_INTCAP, NULL);
pit_isa_irq = -1;
pit_alt_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_PIT_INT);
rtc_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_RTC_INT);
- }
- if (rtc_irq) {
+ /* overwrite connection created by south bridge */
qdev_connect_gpio_out(DEVICE(rtc_state), 0, rtc_irq);
- } else {
- uint32_t irq = object_property_get_uint(OBJECT(rtc_state),
- "irq",
- &error_fatal);
- isa_connect_gpio_out(rtc_state, 0, irq);
}
+
object_property_add_alias(OBJECT(pcms), "rtc-time", OBJECT(rtc_state),
"date");
if (pcms->bus) {
pci_create_simple(pcms->bus, -1, "xen-platform");
}
- xen_bus_init();
+ pcms->xenbus = xen_bus_init();
xen_be_init();
}
#endif
/* connect PIT to output control line of the HPET */
qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(DEVICE(pit), 0));
}
- pcspk_init(pcms->pcspk, isa_bus, pit);
+ object_property_set_link(OBJECT(pcms->pcspk), "pit",
+ OBJECT(pit), &error_fatal);
+ isa_realize_and_unref(pcms->pcspk, isa_bus, &error_fatal);
}
/* Super I/O */
pcms->vmport != ON_OFF_AUTO_ON);
}
-void pc_nic_init(PCMachineClass *pcmc, ISABus *isa_bus, PCIBus *pci_bus)
+void pc_nic_init(PCMachineClass *pcmc, ISABus *isa_bus, PCIBus *pci_bus,
+ BusState *xen_bus)
{
MachineClass *mc = MACHINE_CLASS(pcmc);
int i;
NICInfo *nd = &nd_table[i];
const char *model = nd->model ? nd->model : mc->default_nic;
- if (g_str_equal(model, "ne2k_isa")) {
+ if (xen_bus && (!nd->model || g_str_equal(model, "xen-net-device"))) {
+ DeviceState *dev = qdev_new("xen-net-device");
+ qdev_set_nic_properties(dev, nd);
+ qdev_realize_and_unref(dev, xen_bus, &error_fatal);
+ } else if (g_str_equal(model, "ne2k_isa")) {
pc_init_ne2k_isa(isa_bus, nd);
} else {
pci_nic_init_nofail(nd, pci_bus, model, NULL);
Error *local_err = NULL;
/*
- * When -no-acpi is used with Q35 machine type, no ACPI is built,
+ * When "acpi=off" is used with the Q35 machine type, no ACPI is built,
* but pcms->acpi_dev is still created. Check !acpi_enabled in
* addition to cover this case.
*/
X86MachineState *x86ms = X86_MACHINE(hotplug_dev);
/*
- * When -no-acpi is used with Q35 machine type, no ACPI is built,
+ * When "acpi=off" is used with the Q35 machine type, no ACPI is built,
* but pcms->acpi_dev is still created. Check !acpi_enabled in
* addition to cover this case.
*/
error_propagate(errp, local_err);
}
+static void pc_hv_balloon_pre_plug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ /* The vmbus handler has no hotplug handler; we should never end up here. */
+ g_assert(!dev->hotplugged);
+ memory_device_pre_plug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev), NULL,
+ errp);
+}
+
+static void pc_hv_balloon_plug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ memory_device_plug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev));
+}
+
static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
/* Declare the APIC range as the reserved MSI region */
char *resv_prop_str = g_strdup_printf("0xfee00000:0xfeefffff:%d",
VIRTIO_IOMMU_RESV_MEM_T_MSI);
+ QList *reserved_regions = qlist_new();
+
+ qlist_append_str(reserved_regions, resv_prop_str);
+ qdev_prop_set_array(dev, "reserved-regions", reserved_regions);
- object_property_set_uint(OBJECT(dev), "len-reserved-regions", 1, errp);
- object_property_set_str(OBJECT(dev), "reserved-regions[0]",
- resv_prop_str, errp);
g_free(resv_prop_str);
}
return;
}
pcms->iommu = dev;
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_HV_BALLOON)) {
+ pc_hv_balloon_pre_plug(hotplug_dev, dev, errp);
}
}
x86_cpu_plug(hotplug_dev, dev, errp);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) {
virtio_md_pci_plug(VIRTIO_MD_PCI(dev), MACHINE(hotplug_dev), errp);
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_HV_BALLOON)) {
+ pc_hv_balloon_plug(hotplug_dev, dev, errp);
}
}
object_dynamic_cast(OBJECT(dev), TYPE_CPU) ||
object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI) ||
object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI) ||
+ object_dynamic_cast(OBJECT(dev), TYPE_HV_BALLOON) ||
object_dynamic_cast(OBJECT(dev), TYPE_X86_IOMMU_DEVICE)) {
return HOTPLUG_HANDLER(machine);
}
}
/*
- * We don't have a theoretically justifiable exact lower bound on the base
- * address of any flash mapping. In practice, the IO-APIC MMIO range is
- * [0xFEE00000..0xFEE01000] -- see IO_APIC_DEFAULT_ADDRESS --, leaving free
- * only 18MB-4KB below 4G. For now, restrict the cumulative mapping to 8MB in
- * size.
- */
+ * We don't have a theoretically justifiable exact lower bound on the base
+ * address of any flash mapping. In practice, the IO-APIC MMIO range is
+ * [0xFEE00000..0xFEE01000] -- see IO_APIC_DEFAULT_ADDRESS --, leaving free
+ * only 18MiB-4KiB below 4GiB. For now, restrict the cumulative mapping to
+ * 16MiB in size.
+ */
if (value > 16 * MiB) {
error_setg(errp,
"User specified max allowed firmware size %" PRIu64 " is "
- "greater than 16MiB. If combined firwmare size exceeds "
+ "greater than 16MiB. If combined firmware size exceeds "
"16MiB the system may not boot, or experience intermittent"
"stability issues.",
value);
#endif /* CONFIG_VMPORT */
pcms->max_ram_below_4g = 0; /* use default */
pcms->smbios_entry_point_type = pcmc->default_smbios_ep_type;
+ pcms->south_bridge = pcmc->default_south_bridge;
/* acpi build is enabled by default if machine supports it */
pcms->acpi_build_enabled = pcmc->has_acpi_build;