diff options
Diffstat (limited to 'hw/i386/pc_q35.c')
-rw-r--r-- | hw/i386/pc_q35.c | 165 |
1 files changed, 125 insertions, 40 deletions
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 10e770e36..c844dc2a9 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -28,6 +28,7 @@ * THE SOFTWARE. */ #include "hw/hw.h" +#include "hw/loader.h" #include "sysemu/arch_init.h" #include "hw/i2c/smbus.h" #include "hw/boards.h" @@ -38,6 +39,7 @@ #include "hw/pci-host/q35.h" #include "exec/address-spaces.h" #include "hw/i386/ich9.h" +#include "hw/i386/smbios.h" #include "hw/ide/pci.h" #include "hw/ide/ahci.h" #include "hw/usb.h" @@ -46,18 +48,18 @@ /* ICH9 AHCI has 6 ports */ #define MAX_SATA_PORTS 6 -static bool has_pvpanic; -static bool has_pci_info = true; +static bool has_pci_info; +static bool has_acpi_build = true; +static bool smbios_type1_defaults = true; +/* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to + * host addresses aligned at 1Gbyte boundaries. This way we can use 1GByte + * pages in the host. + */ +static bool gigabyte_align = true; /* PC hardware initialisation */ static void pc_q35_init(QEMUMachineInitArgs *args) { - ram_addr_t ram_size = args->ram_size; - const char *cpu_model = args->cpu_model; - const char *kernel_filename = args->kernel_filename; - const char *kernel_cmdline = args->kernel_cmdline; - const char *initrd_filename = args->initrd_filename; - const char *boot_device = args->boot_device; ram_addr_t below_4g_mem_size, above_4g_mem_size; Q35PCIHost *q35_host; PCIHostState *phb; @@ -81,27 +83,42 @@ static void pc_q35_init(QEMUMachineInitArgs *args) DeviceState *icc_bridge; PcGuestInfo *guest_info; + if (xen_enabled() && xen_hvm_init(&ram_memory) != 0) { + fprintf(stderr, "xen hardware virtual machine initialisation failed\n"); + 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(cpu_model, icc_bridge); + pc_cpus_init(args->cpu_model, icc_bridge); pc_acpi_init("q35-acpi-dsdt.aml"); kvmclock_create(); - if (ram_size >= 0xb0000000) { - above_4g_mem_size = ram_size - 0xb0000000; - below_4g_mem_size = 0xb0000000; + /* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory + * and 256 Mbytes for PCI Express Enhanced Configuration Access Mapping + * also known as MMCFG). + * 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. + */ + if (args->ram_size >= 0xb0000000) { + ram_addr_t lowmem = gigabyte_align ? 0x80000000 : 0xb0000000; + above_4g_mem_size = args->ram_size - lowmem; + below_4g_mem_size = lowmem; } else { above_4g_mem_size = 0; - below_4g_mem_size = ram_size; + below_4g_mem_size = args->ram_size; } /* pci enabled */ if (pci_enabled) { pci_memory = g_new(MemoryRegion, 1); - memory_region_init(pci_memory, NULL, "pci", INT64_MAX); + memory_region_init(pci_memory, NULL, "pci", UINT64_MAX); rom_memory = pci_memory; } else { pci_memory = NULL; @@ -111,11 +128,20 @@ static void pc_q35_init(QEMUMachineInitArgs *args) guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size); guest_info->has_pci_info = has_pci_info; guest_info->isapc_ram_fw = false; + guest_info->has_acpi_build = has_acpi_build; + + if (smbios_type1_defaults) { + /* These values are guest ABI, do not change */ + smbios_set_type1_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)", + args->machine->name); + } /* allocate ram and load rom/bios */ if (!xen_enabled()) { - pc_memory_init(get_system_memory(), kernel_filename, kernel_cmdline, - initrd_filename, below_4g_mem_size, above_4g_mem_size, + pc_memory_init(get_system_memory(), + args->kernel_filename, args->kernel_cmdline, + args->initrd_filename, + below_4g_mem_size, above_4g_mem_size, rom_memory, &ram_memory, guest_info); } @@ -179,7 +205,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args) pc_register_ferr_irq(gsi[13]); /* init basic PC hardware */ - pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, false); + pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, false, 0xff0104); /* connect pm stuff to lpc */ ich9_lpc_pm_init(lpc); @@ -203,7 +229,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args) 0xb100), 8, NULL, 0); - pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, + pc_cmos_init(below_4g_mem_size, above_4g_mem_size, args->boot_order, floppy, idebus[0], idebus[1], rtc_state); /* the rest devices to which pci devfn is automatically assigned */ @@ -212,69 +238,128 @@ static void pc_q35_init(QEMUMachineInitArgs *args) if (pci_enabled) { pc_pci_device_init(host_bus); } +} - if (has_pvpanic) { - pvpanic_init(isa_bus); - } +static void pc_compat_1_7(QEMUMachineInitArgs *args) +{ + smbios_type1_defaults = false; + gigabyte_align = false; + option_rom_has_mr = true; + x86_cpu_compat_disable_kvm_features(FEAT_1_ECX, CPUID_EXT_X2APIC); } -static void pc_q35_init_1_6(QEMUMachineInitArgs *args) +static void pc_compat_1_6(QEMUMachineInitArgs *args) { + pc_compat_1_7(args); has_pci_info = false; + rom_file_has_mr = false; + has_acpi_build = false; +} + +static void pc_compat_1_5(QEMUMachineInitArgs *args) +{ + pc_compat_1_6(args); +} + +static void pc_compat_1_4(QEMUMachineInitArgs *args) +{ + pc_compat_1_5(args); + x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE); + x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ); +} + +static void pc_q35_init_1_7(QEMUMachineInitArgs *args) +{ + pc_compat_1_7(args); + pc_q35_init(args); +} + +static void pc_q35_init_1_6(QEMUMachineInitArgs *args) +{ + pc_compat_1_6(args); pc_q35_init(args); } static void pc_q35_init_1_5(QEMUMachineInitArgs *args) { - has_pvpanic = true; - pc_q35_init_1_6(args); + pc_compat_1_5(args); + pc_q35_init(args); } static void pc_q35_init_1_4(QEMUMachineInitArgs *args) { - x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE); - x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ); - has_pci_info = false; + pc_compat_1_4(args); pc_q35_init(args); } +#define PC_Q35_MACHINE_OPTIONS \ + PC_DEFAULT_MACHINE_OPTIONS, \ + .desc = "Standard PC (Q35 + ICH9, 2009)", \ + .hot_add_cpu = pc_hot_add_cpu + +#define PC_Q35_2_0_MACHINE_OPTIONS \ + PC_Q35_MACHINE_OPTIONS, \ + .default_machine_opts = "firmware=bios-256k.bin" + +static QEMUMachine pc_q35_machine_v2_0 = { + PC_Q35_2_0_MACHINE_OPTIONS, + .name = "pc-q35-2.0", + .alias = "q35", + .init = pc_q35_init, +}; + +#define PC_Q35_1_7_MACHINE_OPTIONS PC_Q35_MACHINE_OPTIONS + +static QEMUMachine pc_q35_machine_v1_7 = { + PC_Q35_1_7_MACHINE_OPTIONS, + .name = "pc-q35-1.7", + .init = pc_q35_init_1_7, + .compat_props = (GlobalProperty[]) { + PC_Q35_COMPAT_1_7, + { /* end of list */ } + }, +}; + +#define PC_Q35_1_6_MACHINE_OPTIONS PC_Q35_MACHINE_OPTIONS + static QEMUMachine pc_q35_machine_v1_6 = { + PC_Q35_1_6_MACHINE_OPTIONS, .name = "pc-q35-1.6", - .alias = "q35", - .desc = "Standard PC (Q35 + ICH9, 2009)", .init = pc_q35_init_1_6, - .hot_add_cpu = pc_hot_add_cpu, - .max_cpus = 255, - DEFAULT_MACHINE_OPTIONS, + .compat_props = (GlobalProperty[]) { + PC_Q35_COMPAT_1_6, + { /* end of list */ } + }, }; static QEMUMachine pc_q35_machine_v1_5 = { + PC_Q35_1_6_MACHINE_OPTIONS, .name = "pc-q35-1.5", - .desc = "Standard PC (Q35 + ICH9, 2009)", .init = pc_q35_init_1_5, - .hot_add_cpu = pc_hot_add_cpu, - .max_cpus = 255, .compat_props = (GlobalProperty[]) { - PC_COMPAT_1_5, + PC_Q35_COMPAT_1_5, { /* end of list */ } }, - DEFAULT_MACHINE_OPTIONS, }; +#define PC_Q35_1_4_MACHINE_OPTIONS \ + PC_Q35_1_6_MACHINE_OPTIONS, \ + .hot_add_cpu = NULL + static QEMUMachine pc_q35_machine_v1_4 = { + PC_Q35_1_4_MACHINE_OPTIONS, .name = "pc-q35-1.4", - .desc = "Standard PC (Q35 + ICH9, 2009)", .init = pc_q35_init_1_4, - .max_cpus = 255, .compat_props = (GlobalProperty[]) { PC_COMPAT_1_4, { /* end of list */ } }, - DEFAULT_MACHINE_OPTIONS, }; static void pc_q35_machine_init(void) { + qemu_register_machine(&pc_q35_machine_v2_0); + qemu_register_machine(&pc_q35_machine_v1_7); qemu_register_machine(&pc_q35_machine_v1_6); qemu_register_machine(&pc_q35_machine_v1_5); qemu_register_machine(&pc_q35_machine_v1_4); |