*/
#include "qemu/osdep.h"
-#include <glib.h>
#include "hw/hw.h"
#include "hw/loader.h"
#include <xen/hvm/hvm_info_table.h>
#include "hw/xen/xen_pt.h"
#endif
-#include "migration/migration.h"
+#include "migration/global_state.h"
+#include "migration/misc.h"
#include "kvm_i386.h"
+#include "sysemu/numa.h"
#define MAX_IDE_BUS 2
ISABus *isa_bus;
PCII440FXState *i440fx_state;
int piix3_devfn = -1;
- qemu_irq *gsi;
qemu_irq *i8259;
qemu_irq smi_irq;
GSIState *gsi_state;
MemoryRegion *rom_memory;
ram_addr_t lowmem;
- /* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory).
- * If it doesn't, we need to split it in chunks below and above 4G.
- * In any case, try to make sure that guest addresses aligned at
- * 1G boundaries get mapped to host addresses aligned at 1G boundaries.
- * For old machine types, use whatever split we used historically to avoid
- * breaking migration.
+ /*
+ * Calculate ram split, for memory below and above 4G. It's a bit
+ * complicated for backward compatibility reasons ...
+ *
+ * - Traditional split is 3.5G (lowmem = 0xe0000000). This is the
+ * default value for max_ram_below_4g now.
+ *
+ * - Then, to gigabyte align the memory, we move the split to 3G
+ * (lowmem = 0xc0000000). But only in case we have to split in
+ * the first place, i.e. ram_size is larger than (traditional)
+ * lowmem. And for new machine types (gigabyte_align = true)
+ * only, for live migration compatibility reasons.
+ *
+ * - Next the max-ram-below-4g option was added, which allowed to
+ * reduce lowmem to a smaller value, to allow a larger PCI I/O
+ * window below 4G. qemu doesn't enforce gigabyte alignment here,
+ * but prints a warning.
+ *
+ * - Finally max-ram-below-4g got updated to also allow raising lowmem,
+ * so legacy non-PAE guests can get as much memory as possible in
+ * the 32bit address space below 4G.
+ *
+ * - Note that Xen has its own ram setp code in xen_ram_init(),
+ * called via xen_hvm_init().
+ *
+ * Examples:
+ * qemu -M pc-1.7 -m 4G (old default) -> 3584M low, 512M high
+ * qemu -M pc -m 4G (new default) -> 3072M low, 1024M high
+ * qemu -M pc,max-ram-below-4g=2G -m 4G -> 2048M low, 2048M high
+ * qemu -M pc,max-ram-below-4g=4G -m 3968M -> 3968M low (=4G-128M)
*/
- if (machine->ram_size >= 0xe0000000) {
- lowmem = pcmc->gigabyte_align ? 0xc0000000 : 0xe0000000;
+ if (xen_enabled()) {
+ xen_hvm_init(pcms, &ram_memory);
} else {
- lowmem = 0xe0000000;
- }
-
- /* Handle the machine opt max-ram-below-4g. It is basically doing
- * min(qemu limit, user limit).
- */
- if (lowmem > pcms->max_ram_below_4g) {
+ if (!pcms->max_ram_below_4g) {
+ pcms->max_ram_below_4g = 0xe0000000; /* default: 3.5G */
+ }
lowmem = pcms->max_ram_below_4g;
- if (machine->ram_size - lowmem > lowmem &&
- lowmem & ((1ULL << 30) - 1)) {
- error_report("Warning: Large machine and max_ram_below_4g(%"PRIu64
- ") not a multiple of 1G; possible bad performance.",
- pcms->max_ram_below_4g);
+ if (machine->ram_size >= pcms->max_ram_below_4g) {
+ if (pcmc->gigabyte_align) {
+ if (lowmem > 0xc0000000) {
+ lowmem = 0xc0000000;
+ }
+ if (lowmem & ((1ULL << 30) - 1)) {
+ warn_report("Large machine and max_ram_below_4g "
+ "(%" PRIu64 ") not a multiple of 1G; "
+ "possible bad performance.",
+ pcms->max_ram_below_4g);
+ }
+ }
}
- }
-
- if (machine->ram_size >= lowmem) {
- pcms->above_4g_mem_size = machine->ram_size - lowmem;
- pcms->below_4g_mem_size = lowmem;
- } else {
- pcms->above_4g_mem_size = 0;
- pcms->below_4g_mem_size = machine->ram_size;
- }
- if (xen_enabled()) {
- xen_hvm_init(pcms, &ram_memory);
+ if (machine->ram_size >= lowmem) {
+ pcms->above_4g_mem_size = machine->ram_size - lowmem;
+ pcms->below_4g_mem_size = lowmem;
+ } else {
+ pcms->above_4g_mem_size = 0;
+ pcms->below_4g_mem_size = machine->ram_size;
+ }
}
pc_cpus_init(pcms);
gsi_state = g_malloc0(sizeof(*gsi_state));
if (kvm_ioapic_in_kernel()) {
kvm_pc_setup_irq_routing(pcmc->pci_enabled);
- gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
- GSI_NUM_PINS);
+ pcms->gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
+ GSI_NUM_PINS);
} else {
- gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
+ pcms->gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
}
if (pcmc->pci_enabled) {
pci_bus = i440fx_init(host_type,
pci_type,
- &i440fx_state, &piix3_devfn, &isa_bus, gsi,
+ &i440fx_state, &piix3_devfn, &isa_bus, pcms->gsi,
system_memory, system_io, machine->ram_size,
pcms->below_4g_mem_size,
pcms->above_4g_mem_size,
&error_abort);
no_hpet = 1;
}
- isa_bus_irqs(isa_bus, gsi);
+ isa_bus_irqs(isa_bus, pcms->gsi);
if (kvm_pic_in_kernel()) {
i8259 = kvm_i8259_init(isa_bus);
ioapic_init_gsi(gsi_state, "i440fx");
}
- pc_register_ferr_irq(gsi[13]);
+ pc_register_ferr_irq(pcms->gsi[13]);
pc_vga_init(isa_bus, pcmc->pci_enabled ? pci_bus : NULL);
}
/* init basic PC hardware */
- pc_basic_device_init(isa_bus, gsi, &rtc_state, true,
- (pcms->vmport != ON_OFF_AUTO_ON), 0x4);
+ pc_basic_device_init(isa_bus, pcms->gsi, &rtc_state, true,
+ (pcms->vmport != ON_OFF_AUTO_ON), pcms->pit, 0x4);
pc_nic_init(isa_bus, pci_bus);
pc_cmos_init(pcms, idebus[0], idebus[1], rtc_state);
- if (pcmc->pci_enabled && usb_enabled()) {
+ if (pcmc->pci_enabled && machine_usb(machine)) {
pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci");
}
smi_irq = qemu_allocate_irq(pc_acpi_smi_interrupt, first_cpu, 0);
/* TODO: Populate SPD eeprom data. */
smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
- gsi[9], smi_irq,
+ pcms->gsi[9], smi_irq,
pc_machine_is_smm_enabled(pcms),
&piix4_pm);
smbus_eeprom_init(smbus, 8, NULL, 0);
static void pc_compat_2_3(MachineState *machine)
{
PCMachineState *pcms = PC_MACHINE(machine);
- savevm_skip_section_footers();
if (kvm_enabled()) {
pcms->smm = ON_OFF_AUTO_OFF;
}
- global_state_set_optional();
- savevm_skip_configuration();
}
static void pc_compat_2_2(MachineState *machine)
m->default_display = "std";
}
-static void pc_i440fx_2_6_machine_options(MachineClass *m)
+static void pc_i440fx_2_10_machine_options(MachineClass *m)
{
pc_i440fx_machine_options(m);
m->alias = "pc";
m->is_default = 1;
}
+DEFINE_I440FX_MACHINE(v2_10, "pc-i440fx-2.10", NULL,
+ pc_i440fx_2_10_machine_options);
+
+static void pc_i440fx_2_9_machine_options(MachineClass *m)
+{
+ pc_i440fx_2_10_machine_options(m);
+ m->is_default = 0;
+ m->alias = NULL;
+ SET_MACHINE_COMPAT(m, PC_COMPAT_2_9);
+ m->numa_auto_assign_ram = numa_legacy_auto_assign_ram;
+}
+
+DEFINE_I440FX_MACHINE(v2_9, "pc-i440fx-2.9", NULL,
+ pc_i440fx_2_9_machine_options);
+
+static void pc_i440fx_2_8_machine_options(MachineClass *m)
+{
+ pc_i440fx_2_9_machine_options(m);
+ SET_MACHINE_COMPAT(m, PC_COMPAT_2_8);
+}
+
+DEFINE_I440FX_MACHINE(v2_8, "pc-i440fx-2.8", NULL,
+ pc_i440fx_2_8_machine_options);
+
+
+static void pc_i440fx_2_7_machine_options(MachineClass *m)
+{
+ pc_i440fx_2_8_machine_options(m);
+ SET_MACHINE_COMPAT(m, PC_COMPAT_2_7);
+}
+
+DEFINE_I440FX_MACHINE(v2_7, "pc-i440fx-2.7", NULL,
+ pc_i440fx_2_7_machine_options);
+
+
+static void pc_i440fx_2_6_machine_options(MachineClass *m)
+{
+ PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
+ pc_i440fx_2_7_machine_options(m);
+ pcmc->legacy_cpu_hotplug = true;
+ pcmc->linuxboot_dma_enabled = false;
+ SET_MACHINE_COMPAT(m, PC_COMPAT_2_6);
+}
+
DEFINE_I440FX_MACHINE(v2_6, "pc-i440fx-2.6", NULL,
pc_i440fx_2_6_machine_options);
{
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
pc_i440fx_2_6_machine_options(m);
- m->alias = NULL;
- m->is_default = 0;
pcmc->save_tsc_khz = false;
m->legacy_fw_cfg_order = 1;
SET_MACHINE_COMPAT(m, PC_COMPAT_2_5);
#define PC_COMPAT_1_3 \
+ PC_CPU_MODEL_IDS("1.3.0") \
{\
.driver = "usb-tablet",\
.property = "usb_version",\
#define PC_COMPAT_1_2 \
+ PC_CPU_MODEL_IDS("1.2.0") \
{\
.driver = "nec-usb-xhci",\
.property = "msi",\
#define PC_COMPAT_1_1 \
+ PC_CPU_MODEL_IDS("1.1.0") \
{\
.driver = "virtio-scsi-pci",\
.property = "hotplug",\
#define PC_COMPAT_1_0 \
+ PC_CPU_MODEL_IDS("1.0") \
{\
.driver = TYPE_ISA_FDC,\
.property = "check_media_rate",\
pc_i440fx_1_0_machine_options);
+#define PC_COMPAT_0_15 \
+ PC_CPU_MODEL_IDS("0.15")
+
static void pc_i440fx_0_15_machine_options(MachineClass *m)
{
pc_i440fx_1_0_machine_options(m);
m->hw_version = "0.15";
+ SET_MACHINE_COMPAT(m, PC_COMPAT_0_15);
}
DEFINE_I440FX_MACHINE(v0_15, "pc-0.15", pc_compat_1_2,
#define PC_COMPAT_0_14 \
+ PC_CPU_MODEL_IDS("0.14") \
{\
.driver = "virtio-blk-pci",\
.property = "event_idx",\
#define PC_COMPAT_0_13 \
+ PC_CPU_MODEL_IDS("0.13") \
{\
.driver = TYPE_PCI_DEVICE,\
.property = "command_serr_enable",\
#define PC_COMPAT_0_12 \
+ PC_CPU_MODEL_IDS("0.12") \
{\
.driver = "virtio-serial-pci",\
.property = "max_ports",\
#define PC_COMPAT_0_11 \
+ PC_CPU_MODEL_IDS("0.11") \
{\
.driver = "virtio-blk-pci",\
.property = "vectors",\
#define PC_COMPAT_0_10 \
+ PC_CPU_MODEL_IDS("0.10") \
{\
.driver = "virtio-blk-pci",\
.property = "class",\