1 #ifndef HW_PC_H 2 #define HW_PC_H 3 4 #include "qemu-common.h" 5 #include "exec/memory.h" 6 #include "hw/boards.h" 7 #include "hw/isa/isa.h" 8 #include "hw/block/fdc.h" 9 #include "net/net.h" 10 #include "hw/i386/ioapic.h" 11 12 #include "qemu/range.h" 13 #include "qemu/bitmap.h" 14 #include "sysemu/sysemu.h" 15 #include "hw/pci/pci.h" 16 #include "hw/boards.h" 17 #include "hw/compat.h" 18 #include "hw/mem/pc-dimm.h" 19 20 #define HPET_INTCAP "hpet-intcap" 21 22 /** 23 * PCMachineState: 24 * @acpi_dev: link to ACPI PM device that performs ACPI hotplug handling 25 * @enforce_aligned_dimm: check that DIMM's address/size is aligned by 26 * backend's alignment value if provided 27 */ 28 struct PCMachineState { 29 /*< private >*/ 30 MachineState parent_obj; 31 32 /* <public> */ 33 MemoryHotplugState hotplug_memory; 34 35 HotplugHandler *acpi_dev; 36 ISADevice *rtc; 37 38 uint64_t max_ram_below_4g; 39 OnOffAuto vmport; 40 bool enforce_aligned_dimm; 41 }; 42 43 #define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device" 44 #define PC_MACHINE_MEMHP_REGION_SIZE "hotplug-memory-region-size" 45 #define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g" 46 #define PC_MACHINE_VMPORT "vmport" 47 #define PC_MACHINE_ENFORCE_ALIGNED_DIMM "enforce-aligned-dimm" 48 49 /** 50 * PCMachineClass: 51 * @get_hotplug_handler: pointer to parent class callback @get_hotplug_handler 52 */ 53 struct PCMachineClass { 54 /*< private >*/ 55 MachineClass parent_class; 56 57 /*< public >*/ 58 HotplugHandler *(*get_hotplug_handler)(MachineState *machine, 59 DeviceState *dev); 60 }; 61 62 typedef struct PCMachineState PCMachineState; 63 typedef struct PCMachineClass PCMachineClass; 64 65 #define TYPE_PC_MACHINE "generic-pc-machine" 66 #define PC_MACHINE(obj) \ 67 OBJECT_CHECK(PCMachineState, (obj), TYPE_PC_MACHINE) 68 #define PC_MACHINE_GET_CLASS(obj) \ 69 OBJECT_GET_CLASS(PCMachineClass, (obj), TYPE_PC_MACHINE) 70 #define PC_MACHINE_CLASS(klass) \ 71 OBJECT_CLASS_CHECK(PCMachineClass, (klass), TYPE_PC_MACHINE) 72 73 /* PC-style peripherals (also used by other machines). */ 74 75 typedef struct PcPciInfo { 76 Range w32; 77 Range w64; 78 } PcPciInfo; 79 80 #define ACPI_PM_PROP_S3_DISABLED "disable_s3" 81 #define ACPI_PM_PROP_S4_DISABLED "disable_s4" 82 #define ACPI_PM_PROP_S4_VAL "s4_val" 83 #define ACPI_PM_PROP_SCI_INT "sci_int" 84 #define ACPI_PM_PROP_ACPI_ENABLE_CMD "acpi_enable_cmd" 85 #define ACPI_PM_PROP_ACPI_DISABLE_CMD "acpi_disable_cmd" 86 #define ACPI_PM_PROP_PM_IO_BASE "pm_io_base" 87 #define ACPI_PM_PROP_GPE0_BLK "gpe0_blk" 88 #define ACPI_PM_PROP_GPE0_BLK_LEN "gpe0_blk_len" 89 90 struct PcGuestInfo { 91 bool isapc_ram_fw; 92 hwaddr ram_size, ram_size_below_4g; 93 unsigned apic_id_limit; 94 bool apic_xrupt_override; 95 uint64_t numa_nodes; 96 uint64_t *node_mem; 97 uint64_t *node_cpu; 98 FWCfgState *fw_cfg; 99 int legacy_acpi_table_size; 100 bool has_acpi_build; 101 bool has_reserved_memory; 102 bool rsdp_in_ram; 103 }; 104 105 /* parallel.c */ 106 107 void parallel_hds_isa_init(ISABus *bus, int n); 108 109 bool parallel_mm_init(MemoryRegion *address_space, 110 hwaddr base, int it_shift, qemu_irq irq, 111 CharDriverState *chr); 112 113 /* i8259.c */ 114 115 extern DeviceState *isa_pic; 116 qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq); 117 qemu_irq *kvm_i8259_init(ISABus *bus); 118 int pic_read_irq(DeviceState *d); 119 int pic_get_output(DeviceState *d); 120 void hmp_info_pic(Monitor *mon, const QDict *qdict); 121 void hmp_info_irq(Monitor *mon, const QDict *qdict); 122 123 /* Global System Interrupts */ 124 125 #define GSI_NUM_PINS IOAPIC_NUM_PINS 126 127 typedef struct GSIState { 128 qemu_irq i8259_irq[ISA_NUM_IRQS]; 129 qemu_irq ioapic_irq[IOAPIC_NUM_PINS]; 130 } GSIState; 131 132 void gsi_handler(void *opaque, int n, int level); 133 134 /* vmport.c */ 135 typedef uint32_t (VMPortReadFunc)(void *opaque, uint32_t address); 136 137 static inline void vmport_init(ISABus *bus) 138 { 139 isa_create_simple(bus, "vmport"); 140 } 141 142 void vmport_register(unsigned char command, VMPortReadFunc *func, void *opaque); 143 void vmmouse_get_data(uint32_t *data); 144 void vmmouse_set_data(const uint32_t *data); 145 146 /* pckbd.c */ 147 148 void i8042_init(qemu_irq kbd_irq, qemu_irq mouse_irq, uint32_t io_base); 149 void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, 150 MemoryRegion *region, ram_addr_t size, 151 hwaddr mask); 152 void i8042_isa_mouse_fake_event(void *opaque); 153 void i8042_setup_a20_line(ISADevice *dev, qemu_irq *a20_out); 154 155 /* pc.c */ 156 extern int fd_bootchk; 157 158 void pc_register_ferr_irq(qemu_irq irq); 159 void pc_acpi_smi_interrupt(void *opaque, int irq, int level); 160 161 void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge); 162 void pc_hot_add_cpu(const int64_t id, Error **errp); 163 void pc_acpi_init(const char *default_dsdt); 164 165 PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size, 166 ram_addr_t above_4g_mem_size); 167 168 void pc_set_legacy_acpi_data_size(void); 169 170 #define PCI_HOST_PROP_PCI_HOLE_START "pci-hole-start" 171 #define PCI_HOST_PROP_PCI_HOLE_END "pci-hole-end" 172 #define PCI_HOST_PROP_PCI_HOLE64_START "pci-hole64-start" 173 #define PCI_HOST_PROP_PCI_HOLE64_END "pci-hole64-end" 174 #define PCI_HOST_PROP_PCI_HOLE64_SIZE "pci-hole64-size" 175 #define DEFAULT_PCI_HOLE64_SIZE (~0x0ULL) 176 177 178 void pc_pci_as_mapping_init(Object *owner, MemoryRegion *system_memory, 179 MemoryRegion *pci_address_space); 180 181 FWCfgState *xen_load_linux(const char *kernel_filename, 182 const char *kernel_cmdline, 183 const char *initrd_filename, 184 ram_addr_t below_4g_mem_size, 185 PcGuestInfo *guest_info); 186 FWCfgState *pc_memory_init(MachineState *machine, 187 MemoryRegion *system_memory, 188 ram_addr_t below_4g_mem_size, 189 ram_addr_t above_4g_mem_size, 190 MemoryRegion *rom_memory, 191 MemoryRegion **ram_memory, 192 PcGuestInfo *guest_info); 193 qemu_irq pc_allocate_cpu_irq(void); 194 DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus); 195 void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, 196 ISADevice **rtc_state, 197 bool create_fdctrl, 198 ISADevice **floppy, 199 bool no_vmport, 200 uint32 hpet_irqs); 201 void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd); 202 void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, 203 const char *boot_device, MachineState *machine, 204 ISADevice *floppy, BusState *ide0, BusState *ide1, 205 ISADevice *s); 206 void pc_nic_init(ISABus *isa_bus, PCIBus *pci_bus); 207 void pc_pci_device_init(PCIBus *pci_bus); 208 209 typedef void (*cpu_set_smm_t)(int smm, void *arg); 210 211 void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name); 212 213 /* acpi_piix.c */ 214 215 I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, 216 qemu_irq sci_irq, qemu_irq smi_irq, 217 int kvm_enabled, DeviceState **piix4_pm); 218 void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr); 219 220 /* hpet.c */ 221 extern int no_hpet; 222 223 /* piix_pci.c */ 224 struct PCII440FXState; 225 typedef struct PCII440FXState PCII440FXState; 226 227 PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn, 228 ISABus **isa_bus, qemu_irq *pic, 229 MemoryRegion *address_space_mem, 230 MemoryRegion *address_space_io, 231 ram_addr_t ram_size, 232 ram_addr_t below_4g_mem_size, 233 ram_addr_t above_4g_mem_size, 234 MemoryRegion *pci_memory, 235 MemoryRegion *ram_memory); 236 237 PCIBus *find_i440fx(void); 238 /* piix4.c */ 239 extern PCIDevice *piix4_dev; 240 int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn); 241 242 /* vga.c */ 243 enum vga_retrace_method { 244 VGA_RETRACE_DUMB, 245 VGA_RETRACE_PRECISE 246 }; 247 248 extern enum vga_retrace_method vga_retrace_method; 249 250 int isa_vga_mm_init(hwaddr vram_base, 251 hwaddr ctrl_base, int it_shift, 252 MemoryRegion *address_space); 253 254 /* ne2000.c */ 255 static inline bool isa_ne2000_init(ISABus *bus, int base, int irq, NICInfo *nd) 256 { 257 DeviceState *dev; 258 ISADevice *isadev; 259 260 qemu_check_nic_model(nd, "ne2k_isa"); 261 262 isadev = isa_try_create(bus, "ne2k_isa"); 263 if (!isadev) { 264 return false; 265 } 266 dev = DEVICE(isadev); 267 qdev_prop_set_uint32(dev, "iobase", base); 268 qdev_prop_set_uint32(dev, "irq", irq); 269 qdev_set_nic_properties(dev, nd); 270 qdev_init_nofail(dev); 271 return true; 272 } 273 274 /* pc_sysfw.c */ 275 void pc_system_firmware_init(MemoryRegion *rom_memory, 276 bool isapc_ram_fw); 277 278 /* pvpanic.c */ 279 uint16_t pvpanic_port(void); 280 281 /* e820 types */ 282 #define E820_RAM 1 283 #define E820_RESERVED 2 284 #define E820_ACPI 3 285 #define E820_NVS 4 286 #define E820_UNUSABLE 5 287 288 int e820_add_entry(uint64_t, uint64_t, uint32_t); 289 int e820_get_num_entries(void); 290 bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); 291 292 #define PC_COMPAT_2_3 \ 293 HW_COMPAT_2_3 294 295 #define PC_COMPAT_2_2 \ 296 PC_COMPAT_2_3 \ 297 HW_COMPAT_2_2 298 299 #define PC_COMPAT_2_1 \ 300 PC_COMPAT_2_2 \ 301 HW_COMPAT_2_1 302 303 #define PC_COMPAT_2_0 \ 304 PC_COMPAT_2_1 \ 305 {\ 306 .driver = "virtio-scsi-pci",\ 307 .property = "any_layout",\ 308 .value = "off",\ 309 },{\ 310 .driver = "PIIX4_PM",\ 311 .property = "memory-hotplug-support",\ 312 .value = "off",\ 313 },\ 314 {\ 315 .driver = "apic",\ 316 .property = "version",\ 317 .value = stringify(0x11),\ 318 },\ 319 {\ 320 .driver = "nec-usb-xhci",\ 321 .property = "superspeed-ports-first",\ 322 .value = "off",\ 323 },\ 324 {\ 325 .driver = "nec-usb-xhci",\ 326 .property = "force-pcie-endcap",\ 327 .value = "on",\ 328 },\ 329 {\ 330 .driver = "pci-serial",\ 331 .property = "prog_if",\ 332 .value = stringify(0),\ 333 },\ 334 {\ 335 .driver = "pci-serial-2x",\ 336 .property = "prog_if",\ 337 .value = stringify(0),\ 338 },\ 339 {\ 340 .driver = "pci-serial-4x",\ 341 .property = "prog_if",\ 342 .value = stringify(0),\ 343 },\ 344 {\ 345 .driver = "virtio-net-pci",\ 346 .property = "guest_announce",\ 347 .value = "off",\ 348 },\ 349 {\ 350 .driver = "ICH9-LPC",\ 351 .property = "memory-hotplug-support",\ 352 .value = "off",\ 353 },{\ 354 .driver = "xio3130-downstream",\ 355 .property = COMPAT_PROP_PCP,\ 356 .value = "off",\ 357 },{\ 358 .driver = "ioh3420",\ 359 .property = COMPAT_PROP_PCP,\ 360 .value = "off",\ 361 }, 362 363 #define PC_COMPAT_1_7 \ 364 PC_COMPAT_2_0 \ 365 {\ 366 .driver = TYPE_USB_DEVICE,\ 367 .property = "msos-desc",\ 368 .value = "no",\ 369 },\ 370 {\ 371 .driver = "PIIX4_PM",\ 372 .property = "acpi-pci-hotplug-with-bridge-support",\ 373 .value = "off",\ 374 },\ 375 {\ 376 .driver = "hpet",\ 377 .property = HPET_INTCAP,\ 378 .value = stringify(4),\ 379 }, 380 381 #define PC_COMPAT_1_6 \ 382 PC_COMPAT_1_7 \ 383 {\ 384 .driver = "e1000",\ 385 .property = "mitigation",\ 386 .value = "off",\ 387 },{\ 388 .driver = "qemu64-" TYPE_X86_CPU,\ 389 .property = "model",\ 390 .value = stringify(2),\ 391 },{\ 392 .driver = "qemu32-" TYPE_X86_CPU,\ 393 .property = "model",\ 394 .value = stringify(3),\ 395 },{\ 396 .driver = "i440FX-pcihost",\ 397 .property = "short_root_bus",\ 398 .value = stringify(1),\ 399 },{\ 400 .driver = "q35-pcihost",\ 401 .property = "short_root_bus",\ 402 .value = stringify(1),\ 403 }, 404 405 #define PC_COMPAT_1_5 \ 406 PC_COMPAT_1_6 \ 407 {\ 408 .driver = "Conroe-" TYPE_X86_CPU,\ 409 .property = "model",\ 410 .value = stringify(2),\ 411 },{\ 412 .driver = "Conroe-" TYPE_X86_CPU,\ 413 .property = "level",\ 414 .value = stringify(2),\ 415 },{\ 416 .driver = "Penryn-" TYPE_X86_CPU,\ 417 .property = "model",\ 418 .value = stringify(2),\ 419 },{\ 420 .driver = "Penryn-" TYPE_X86_CPU,\ 421 .property = "level",\ 422 .value = stringify(2),\ 423 },{\ 424 .driver = "Nehalem-" TYPE_X86_CPU,\ 425 .property = "model",\ 426 .value = stringify(2),\ 427 },{\ 428 .driver = "Nehalem-" TYPE_X86_CPU,\ 429 .property = "level",\ 430 .value = stringify(2),\ 431 },{\ 432 .driver = "virtio-net-pci",\ 433 .property = "any_layout",\ 434 .value = "off",\ 435 },{\ 436 .driver = TYPE_X86_CPU,\ 437 .property = "pmu",\ 438 .value = "on",\ 439 },{\ 440 .driver = "i440FX-pcihost",\ 441 .property = "short_root_bus",\ 442 .value = stringify(0),\ 443 },{\ 444 .driver = "q35-pcihost",\ 445 .property = "short_root_bus",\ 446 .value = stringify(0),\ 447 }, 448 449 #define PC_COMPAT_1_4 \ 450 PC_COMPAT_1_5 \ 451 {\ 452 .driver = "scsi-hd",\ 453 .property = "discard_granularity",\ 454 .value = stringify(0),\ 455 },{\ 456 .driver = "scsi-cd",\ 457 .property = "discard_granularity",\ 458 .value = stringify(0),\ 459 },{\ 460 .driver = "scsi-disk",\ 461 .property = "discard_granularity",\ 462 .value = stringify(0),\ 463 },{\ 464 .driver = "ide-hd",\ 465 .property = "discard_granularity",\ 466 .value = stringify(0),\ 467 },{\ 468 .driver = "ide-cd",\ 469 .property = "discard_granularity",\ 470 .value = stringify(0),\ 471 },{\ 472 .driver = "ide-drive",\ 473 .property = "discard_granularity",\ 474 .value = stringify(0),\ 475 },{\ 476 .driver = "virtio-blk-pci",\ 477 .property = "discard_granularity",\ 478 .value = stringify(0),\ 479 },{\ 480 .driver = "virtio-serial-pci",\ 481 .property = "vectors",\ 482 /* DEV_NVECTORS_UNSPECIFIED as a uint32_t string */\ 483 .value = stringify(0xFFFFFFFF),\ 484 },{ \ 485 .driver = "virtio-net-pci", \ 486 .property = "ctrl_guest_offloads", \ 487 .value = "off", \ 488 },{\ 489 .driver = "e1000",\ 490 .property = "romfile",\ 491 .value = "pxe-e1000.rom",\ 492 },{\ 493 .driver = "ne2k_pci",\ 494 .property = "romfile",\ 495 .value = "pxe-ne2k_pci.rom",\ 496 },{\ 497 .driver = "pcnet",\ 498 .property = "romfile",\ 499 .value = "pxe-pcnet.rom",\ 500 },{\ 501 .driver = "rtl8139",\ 502 .property = "romfile",\ 503 .value = "pxe-rtl8139.rom",\ 504 },{\ 505 .driver = "virtio-net-pci",\ 506 .property = "romfile",\ 507 .value = "pxe-virtio.rom",\ 508 },{\ 509 .driver = "486-" TYPE_X86_CPU,\ 510 .property = "model",\ 511 .value = stringify(0),\ 512 }, 513 514 static inline void pc_common_machine_options(MachineClass *m) 515 { 516 m->default_boot_order = "cad"; 517 } 518 519 static inline void pc_default_machine_options(MachineClass *m) 520 { 521 pc_common_machine_options(m); 522 m->hot_add_cpu = pc_hot_add_cpu; 523 m->max_cpus = 255; 524 } 525 526 #define DEFINE_PC_MACHINE(suffix, namestr, initfn, optsfn) \ 527 static void pc_machine_##suffix##_class_init(ObjectClass *oc, void *data) \ 528 { \ 529 MachineClass *mc = MACHINE_CLASS(oc); \ 530 optsfn(mc); \ 531 mc->name = namestr; \ 532 mc->init = initfn; \ 533 } \ 534 static const TypeInfo pc_machine_type_##suffix = { \ 535 .name = namestr TYPE_MACHINE_SUFFIX, \ 536 .parent = TYPE_PC_MACHINE, \ 537 .class_init = pc_machine_##suffix##_class_init, \ 538 }; \ 539 static void pc_machine_init_##suffix(void) \ 540 { \ 541 type_register(&pc_machine_type_##suffix); \ 542 } \ 543 machine_init(pc_machine_init_##suffix) 544 545 #define SET_MACHINE_COMPAT(m, COMPAT) do { \ 546 static GlobalProperty props[] = { \ 547 COMPAT \ 548 { /* end of list */ } \ 549 }; \ 550 (m)->compat_props = props; \ 551 } while (0) 552 553 #endif 554