From 4044d7dffef8ab5cfe1338e595897367ae995b8a Mon Sep 17 00:00:00 2001
From: Bruce Rogers <brogers@suse.com>
Date: Mon, 22 Jan 2018 14:57:11 -0700
Subject: [PATCH] kvm-qemu-macmodel

---
 hw/pc.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++---------------
 vl.c    |  4 ++++
 2 files changed, 69 insertions(+), 19 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 632f439cd7..7d68845e0a 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -92,6 +92,12 @@ static void isa_irq_handler(void *opaque, int n, int level)
         qemu_set_irq(isa->ioapic[n], level);
 };
 
+enum pc_model {
+    MODEL_ISA = 0,
+    MODEL_PCI = 1,
+    MODEL_MAC = 2
+};
+
 static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
 {
 }
@@ -991,7 +997,7 @@ static void pc_init1(ram_addr_t ram_size,
                      const char *kernel_cmdline,
                      const char *initrd_filename,
                      const char *cpu_model,
-                     int pci_enabled)
+                     int model)
 {
     char *filename;
     int ret, linux_boot, i;
@@ -1021,11 +1027,15 @@ static void pc_init1(ram_addr_t ram_size,
 
     /* init CPUs */
     if (cpu_model == NULL) {
+        if(model == MODEL_MAC) {
+            cpu_model = "coreduo,vendor=GenuineIntel";
+        } else {
 #ifdef TARGET_X86_64
-        cpu_model = "qemu64";
+            cpu_model = "qemu64";
 #else
-        cpu_model = "qemu32";
+            cpu_model = "qemu32";
 #endif
+        }
     }
 
     if (kvm_enabled()) {
@@ -1058,8 +1068,16 @@ static void pc_init1(ram_addr_t ram_size,
 
 
     /* BIOS load */
-    if (bios_name == NULL)
-        bios_name = BIOS_FILENAME;
+    if (bios_name == NULL) {
+        switch(model) {
+            case MODEL_MAC:
+                bios_name = "bios-mac.bin";
+                break;
+            default:
+                bios_name = BIOS_FILENAME;
+                break;
+        }
+    }
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
     if (filename) {
         bios_size = get_image_size(filename);
@@ -1129,7 +1147,7 @@ static void pc_init1(ram_addr_t ram_size,
         isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
     }
 
-    if (pci_enabled) {
+    if (model > MODEL_ISA) {
         pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq);
     } else {
         pci_bus = NULL;
@@ -1145,18 +1163,18 @@ static void pc_init1(ram_addr_t ram_size,
     register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
 
     if (cirrus_vga_enabled) {
-        if (pci_enabled) {
+        if (model >= MODEL_PCI) {
             pci_cirrus_vga_init(pci_bus);
         } else {
             isa_cirrus_vga_init();
         }
     } else if (vmsvga_enabled) {
-        if (pci_enabled)
+        if (model >= MODEL_PCI)
             pci_vmsvga_init(pci_bus);
         else
             fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
     } else if (std_vga_enabled) {
-        if (pci_enabled) {
+        if (model >= MODEL_PCI) {
             pci_vga_init(pci_bus, 0, 0);
         } else {
             isa_vga_init();
@@ -1170,7 +1188,12 @@ static void pc_init1(ram_addr_t ram_size,
     register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
     register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
 
-    if (pci_enabled) {
+    if (model == MODEL_MAC) {
+        applesmc_init();
+        lpc_init(pci_bus, piix3_devfn, i8259);
+    }
+
+    if (model > MODEL_ISA) {
         isa_irq_state->ioapic = ioapic_init();
         ioapic_irq_hack = isa_irq;
     }
@@ -1200,7 +1223,7 @@ static void pc_init1(ram_addr_t ram_size,
     for(i = 0; i < nb_nics; i++) {
         NICInfo *nd = &nd_table[i];
 
-        if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
+        if (!(model > MODEL_ISA) || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
             pc_init_ne2k_isa(nd);
         else
             pci_nic_init_nofail(nd, "rtl8139", NULL);
@@ -1215,7 +1238,9 @@ static void pc_init1(ram_addr_t ram_size,
         hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
     }
 
-    if (pci_enabled) {
+    if (model == MODEL_MAC) {
+        pci_ich6_ide_init(pci_bus, hd, piix3_devfn + 1);
+    else if (model > MODEL_ISA) {
         pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
     } else {
         for(i = 0; i < MAX_IDE_BUS; i++) {
@@ -1227,7 +1252,7 @@ static void pc_init1(ram_addr_t ram_size,
     isa_dev = isa_create_simple("i8042");
     DMA_init(0);
 #ifdef HAS_AUDIO
-    audio_init(pci_enabled ? pci_bus : NULL, isa_irq);
+    audio_init((model > MODEL_ISA) ? pci_bus : NULL, isa_irq);
 #endif
 
     for(i = 0; i < MAX_FD; i++) {
@@ -1237,11 +1262,11 @@ static void pc_init1(ram_addr_t ram_size,
 
     cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd);
 
-    if (pci_enabled && usb_enabled) {
+    if ((model > MODEL_ISA) && usb_enabled) {
         usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
     }
 
-    if (pci_enabled && acpi_enabled) {
+    if ((model > MODEL_ISA) && acpi_enabled) {
         uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
         i2c_bus *smbus;
 
@@ -1262,7 +1287,7 @@ static void pc_init1(ram_addr_t ram_size,
         i440fx_init_memory_mappings(i440fx_state);
     }
 
-    if (pci_enabled) {
+    if (model > MODEL_ISA) {
 	int max_bus;
         int bus;
 
@@ -1285,7 +1310,7 @@ static void pc_init1(ram_addr_t ram_size,
     }
 
     /* Add virtio console devices */
-    if (pci_enabled) {
+    if (model > MODEL_ISA) {
         for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
             if (virtcon_hds[i]) {
                 pci_create_simple(pci_bus, -1, "virtio-console-pci");
@@ -1300,6 +1325,19 @@ static void pc_init1(ram_addr_t ram_size,
 #endif /* CONFIG_KVM_DEVICE_ASSIGNMENT */
 }
 
+static void pc_init_mac(ram_addr_t ram_size,
+                        const char *boot_device,
+                        const char *kernel_filename,
+                        const char *kernel_cmdline,
+                        const char *initrd_filename,
+                        const char *cpu_model)
+{
+    pc_init1(ram_size, boot_device,
+             kernel_filename, kernel_cmdline,
+             initrd_filename, cpu_model,
+             MODEL_MAC);
+}
+
 static void pc_init_pci(ram_addr_t ram_size,
                         const char *boot_device,
                         const char *kernel_filename,
@@ -1309,7 +1347,7 @@ static void pc_init_pci(ram_addr_t ram_size,
 {
     pc_init1(ram_size, boot_device,
              kernel_filename, kernel_cmdline,
-             initrd_filename, cpu_model, 1);
+             initrd_filename, cpu_model, MODEL_PCI);
 }
 
 static void pc_init_isa(ram_addr_t ram_size,
@@ -1323,7 +1361,7 @@ static void pc_init_isa(ram_addr_t ram_size,
         cpu_model = "486";
     pc_init1(ram_size, boot_device,
              kernel_filename, kernel_cmdline,
-             initrd_filename, cpu_model, 0);
+             initrd_filename, cpu_model, MODEL_ISA);
 }
 
 /* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
@@ -1370,6 +1408,13 @@ static QEMUMachine pc_machine_v0_11 = {
     }
 };
 
+static QEMUMachine mac_machine = {
+    .name = "mac",
+    .desc = "Intel-Mac",
+    .init = pc_init_mac,
+    .max_cpus = 255,
+};
+
 static QEMUMachine pc_machine_v0_10 = {
     .name = "pc-0.10",
     .desc = "Standard PC, qemu 0.10",
@@ -1422,6 +1467,7 @@ static void pc_machine_init(void)
     qemu_register_machine(&pc_machine_v0_11);
     qemu_register_machine(&pc_machine_v0_10);
     qemu_register_machine(&isapc_machine);
+    qemu_register_machine(&mac_machine);
 }
 
 machine_init(pc_machine_init);
diff --git a/vl.c b/vl.c
index e942610c3f..a1f6823542 100644
--- a/vl.c
+++ b/vl.c
@@ -5910,6 +5910,10 @@ int main(int argc, char **argv, char **envp)
     if (kvm_enabled()) {
         int ret;
 
+        if (machine == find_machine("mac")) {
+            kvm_pit = 0;
+        }
+
         ret = kvm_init(smp_cpus);
         if (ret < 0) {
 #if defined(KVM_UPSTREAM) || defined(CONFIG_NO_CPU_EMULATION)
