xref: /openbmc/qemu/hw/ppc/mac_oldworld.c (revision baec19105bb9824593bf6f37556302da2f67e583)
1*baec1910SAndreas Färber 
2*baec1910SAndreas Färber /*
3*baec1910SAndreas Färber  * QEMU OldWorld PowerMac (currently ~G3 Beige) hardware System Emulator
4*baec1910SAndreas Färber  *
5*baec1910SAndreas Färber  * Copyright (c) 2004-2007 Fabrice Bellard
6*baec1910SAndreas Färber  * Copyright (c) 2007 Jocelyn Mayer
7*baec1910SAndreas Färber  *
8*baec1910SAndreas Färber  * Permission is hereby granted, free of charge, to any person obtaining a copy
9*baec1910SAndreas Färber  * of this software and associated documentation files (the "Software"), to deal
10*baec1910SAndreas Färber  * in the Software without restriction, including without limitation the rights
11*baec1910SAndreas Färber  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12*baec1910SAndreas Färber  * copies of the Software, and to permit persons to whom the Software is
13*baec1910SAndreas Färber  * furnished to do so, subject to the following conditions:
14*baec1910SAndreas Färber  *
15*baec1910SAndreas Färber  * The above copyright notice and this permission notice shall be included in
16*baec1910SAndreas Färber  * all copies or substantial portions of the Software.
17*baec1910SAndreas Färber  *
18*baec1910SAndreas Färber  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19*baec1910SAndreas Färber  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20*baec1910SAndreas Färber  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21*baec1910SAndreas Färber  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22*baec1910SAndreas Färber  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23*baec1910SAndreas Färber  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24*baec1910SAndreas Färber  * THE SOFTWARE.
25*baec1910SAndreas Färber  */
26*baec1910SAndreas Färber #include "hw/hw.h"
27*baec1910SAndreas Färber #include "hw/ppc.h"
28*baec1910SAndreas Färber #include "mac.h"
29*baec1910SAndreas Färber #include "hw/adb.h"
30*baec1910SAndreas Färber #include "hw/mac_dbdma.h"
31*baec1910SAndreas Färber #include "hw/nvram.h"
32*baec1910SAndreas Färber #include "sysemu/sysemu.h"
33*baec1910SAndreas Färber #include "net/net.h"
34*baec1910SAndreas Färber #include "hw/isa.h"
35*baec1910SAndreas Färber #include "hw/pci/pci.h"
36*baec1910SAndreas Färber #include "hw/boards.h"
37*baec1910SAndreas Färber #include "hw/fw_cfg.h"
38*baec1910SAndreas Färber #include "hw/escc.h"
39*baec1910SAndreas Färber #include "hw/ide.h"
40*baec1910SAndreas Färber #include "hw/loader.h"
41*baec1910SAndreas Färber #include "elf.h"
42*baec1910SAndreas Färber #include "sysemu/kvm.h"
43*baec1910SAndreas Färber #include "kvm_ppc.h"
44*baec1910SAndreas Färber #include "sysemu/blockdev.h"
45*baec1910SAndreas Färber #include "exec/address-spaces.h"
46*baec1910SAndreas Färber 
47*baec1910SAndreas Färber #define MAX_IDE_BUS 2
48*baec1910SAndreas Färber #define CFG_ADDR 0xf0000510
49*baec1910SAndreas Färber 
50*baec1910SAndreas Färber static int fw_cfg_boot_set(void *opaque, const char *boot_device)
51*baec1910SAndreas Färber {
52*baec1910SAndreas Färber     fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
53*baec1910SAndreas Färber     return 0;
54*baec1910SAndreas Färber }
55*baec1910SAndreas Färber 
56*baec1910SAndreas Färber 
57*baec1910SAndreas Färber static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
58*baec1910SAndreas Färber {
59*baec1910SAndreas Färber     return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
60*baec1910SAndreas Färber }
61*baec1910SAndreas Färber 
62*baec1910SAndreas Färber static hwaddr round_page(hwaddr addr)
63*baec1910SAndreas Färber {
64*baec1910SAndreas Färber     return (addr + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
65*baec1910SAndreas Färber }
66*baec1910SAndreas Färber 
67*baec1910SAndreas Färber static void ppc_heathrow_reset(void *opaque)
68*baec1910SAndreas Färber {
69*baec1910SAndreas Färber     PowerPCCPU *cpu = opaque;
70*baec1910SAndreas Färber 
71*baec1910SAndreas Färber     cpu_reset(CPU(cpu));
72*baec1910SAndreas Färber }
73*baec1910SAndreas Färber 
74*baec1910SAndreas Färber static void ppc_heathrow_init(QEMUMachineInitArgs *args)
75*baec1910SAndreas Färber {
76*baec1910SAndreas Färber     ram_addr_t ram_size = args->ram_size;
77*baec1910SAndreas Färber     const char *cpu_model = args->cpu_model;
78*baec1910SAndreas Färber     const char *kernel_filename = args->kernel_filename;
79*baec1910SAndreas Färber     const char *kernel_cmdline = args->kernel_cmdline;
80*baec1910SAndreas Färber     const char *initrd_filename = args->initrd_filename;
81*baec1910SAndreas Färber     const char *boot_device = args->boot_device;
82*baec1910SAndreas Färber     MemoryRegion *sysmem = get_system_memory();
83*baec1910SAndreas Färber     PowerPCCPU *cpu = NULL;
84*baec1910SAndreas Färber     CPUPPCState *env = NULL;
85*baec1910SAndreas Färber     char *filename;
86*baec1910SAndreas Färber     qemu_irq *pic, **heathrow_irqs;
87*baec1910SAndreas Färber     int linux_boot, i;
88*baec1910SAndreas Färber     MemoryRegion *ram = g_new(MemoryRegion, 1);
89*baec1910SAndreas Färber     MemoryRegion *bios = g_new(MemoryRegion, 1);
90*baec1910SAndreas Färber     uint32_t kernel_base, initrd_base, cmdline_base = 0;
91*baec1910SAndreas Färber     int32_t kernel_size, initrd_size;
92*baec1910SAndreas Färber     PCIBus *pci_bus;
93*baec1910SAndreas Färber     MacIONVRAMState *nvr;
94*baec1910SAndreas Färber     int bios_size;
95*baec1910SAndreas Färber     MemoryRegion *pic_mem, *dbdma_mem, *cuda_mem;
96*baec1910SAndreas Färber     MemoryRegion *escc_mem, *escc_bar = g_new(MemoryRegion, 1), *ide_mem[2];
97*baec1910SAndreas Färber     uint16_t ppc_boot_device;
98*baec1910SAndreas Färber     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
99*baec1910SAndreas Färber     void *fw_cfg;
100*baec1910SAndreas Färber     void *dbdma;
101*baec1910SAndreas Färber 
102*baec1910SAndreas Färber     linux_boot = (kernel_filename != NULL);
103*baec1910SAndreas Färber 
104*baec1910SAndreas Färber     /* init CPUs */
105*baec1910SAndreas Färber     if (cpu_model == NULL)
106*baec1910SAndreas Färber         cpu_model = "G3";
107*baec1910SAndreas Färber     for (i = 0; i < smp_cpus; i++) {
108*baec1910SAndreas Färber         cpu = cpu_ppc_init(cpu_model);
109*baec1910SAndreas Färber         if (cpu == NULL) {
110*baec1910SAndreas Färber             fprintf(stderr, "Unable to find PowerPC CPU definition\n");
111*baec1910SAndreas Färber             exit(1);
112*baec1910SAndreas Färber         }
113*baec1910SAndreas Färber         env = &cpu->env;
114*baec1910SAndreas Färber 
115*baec1910SAndreas Färber         /* Set time-base frequency to 16.6 Mhz */
116*baec1910SAndreas Färber         cpu_ppc_tb_init(env,  16600000UL);
117*baec1910SAndreas Färber         qemu_register_reset(ppc_heathrow_reset, cpu);
118*baec1910SAndreas Färber     }
119*baec1910SAndreas Färber 
120*baec1910SAndreas Färber     /* allocate RAM */
121*baec1910SAndreas Färber     if (ram_size > (2047 << 20)) {
122*baec1910SAndreas Färber         fprintf(stderr,
123*baec1910SAndreas Färber                 "qemu: Too much memory for this machine: %d MB, maximum 2047 MB\n",
124*baec1910SAndreas Färber                 ((unsigned int)ram_size / (1 << 20)));
125*baec1910SAndreas Färber         exit(1);
126*baec1910SAndreas Färber     }
127*baec1910SAndreas Färber 
128*baec1910SAndreas Färber     memory_region_init_ram(ram, "ppc_heathrow.ram", ram_size);
129*baec1910SAndreas Färber     vmstate_register_ram_global(ram);
130*baec1910SAndreas Färber     memory_region_add_subregion(sysmem, 0, ram);
131*baec1910SAndreas Färber 
132*baec1910SAndreas Färber     /* allocate and load BIOS */
133*baec1910SAndreas Färber     memory_region_init_ram(bios, "ppc_heathrow.bios", BIOS_SIZE);
134*baec1910SAndreas Färber     vmstate_register_ram_global(bios);
135*baec1910SAndreas Färber     if (bios_name == NULL)
136*baec1910SAndreas Färber         bios_name = PROM_FILENAME;
137*baec1910SAndreas Färber     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
138*baec1910SAndreas Färber     memory_region_set_readonly(bios, true);
139*baec1910SAndreas Färber     memory_region_add_subregion(sysmem, PROM_ADDR, bios);
140*baec1910SAndreas Färber 
141*baec1910SAndreas Färber     /* Load OpenBIOS (ELF) */
142*baec1910SAndreas Färber     if (filename) {
143*baec1910SAndreas Färber         bios_size = load_elf(filename, 0, NULL, NULL, NULL, NULL,
144*baec1910SAndreas Färber                              1, ELF_MACHINE, 0);
145*baec1910SAndreas Färber         g_free(filename);
146*baec1910SAndreas Färber     } else {
147*baec1910SAndreas Färber         bios_size = -1;
148*baec1910SAndreas Färber     }
149*baec1910SAndreas Färber     if (bios_size < 0 || bios_size > BIOS_SIZE) {
150*baec1910SAndreas Färber         hw_error("qemu: could not load PowerPC bios '%s'\n", bios_name);
151*baec1910SAndreas Färber         exit(1);
152*baec1910SAndreas Färber     }
153*baec1910SAndreas Färber 
154*baec1910SAndreas Färber     if (linux_boot) {
155*baec1910SAndreas Färber         uint64_t lowaddr = 0;
156*baec1910SAndreas Färber         int bswap_needed;
157*baec1910SAndreas Färber 
158*baec1910SAndreas Färber #ifdef BSWAP_NEEDED
159*baec1910SAndreas Färber         bswap_needed = 1;
160*baec1910SAndreas Färber #else
161*baec1910SAndreas Färber         bswap_needed = 0;
162*baec1910SAndreas Färber #endif
163*baec1910SAndreas Färber         kernel_base = KERNEL_LOAD_ADDR;
164*baec1910SAndreas Färber         kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
165*baec1910SAndreas Färber                                NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);
166*baec1910SAndreas Färber         if (kernel_size < 0)
167*baec1910SAndreas Färber             kernel_size = load_aout(kernel_filename, kernel_base,
168*baec1910SAndreas Färber                                     ram_size - kernel_base, bswap_needed,
169*baec1910SAndreas Färber                                     TARGET_PAGE_SIZE);
170*baec1910SAndreas Färber         if (kernel_size < 0)
171*baec1910SAndreas Färber             kernel_size = load_image_targphys(kernel_filename,
172*baec1910SAndreas Färber                                               kernel_base,
173*baec1910SAndreas Färber                                               ram_size - kernel_base);
174*baec1910SAndreas Färber         if (kernel_size < 0) {
175*baec1910SAndreas Färber             hw_error("qemu: could not load kernel '%s'\n",
176*baec1910SAndreas Färber                       kernel_filename);
177*baec1910SAndreas Färber             exit(1);
178*baec1910SAndreas Färber         }
179*baec1910SAndreas Färber         /* load initrd */
180*baec1910SAndreas Färber         if (initrd_filename) {
181*baec1910SAndreas Färber             initrd_base = round_page(kernel_base + kernel_size + KERNEL_GAP);
182*baec1910SAndreas Färber             initrd_size = load_image_targphys(initrd_filename, initrd_base,
183*baec1910SAndreas Färber                                               ram_size - initrd_base);
184*baec1910SAndreas Färber             if (initrd_size < 0) {
185*baec1910SAndreas Färber                 hw_error("qemu: could not load initial ram disk '%s'\n",
186*baec1910SAndreas Färber                          initrd_filename);
187*baec1910SAndreas Färber                 exit(1);
188*baec1910SAndreas Färber             }
189*baec1910SAndreas Färber             cmdline_base = round_page(initrd_base + initrd_size);
190*baec1910SAndreas Färber         } else {
191*baec1910SAndreas Färber             initrd_base = 0;
192*baec1910SAndreas Färber             initrd_size = 0;
193*baec1910SAndreas Färber             cmdline_base = round_page(kernel_base + kernel_size + KERNEL_GAP);
194*baec1910SAndreas Färber         }
195*baec1910SAndreas Färber         ppc_boot_device = 'm';
196*baec1910SAndreas Färber     } else {
197*baec1910SAndreas Färber         kernel_base = 0;
198*baec1910SAndreas Färber         kernel_size = 0;
199*baec1910SAndreas Färber         initrd_base = 0;
200*baec1910SAndreas Färber         initrd_size = 0;
201*baec1910SAndreas Färber         ppc_boot_device = '\0';
202*baec1910SAndreas Färber         for (i = 0; boot_device[i] != '\0'; i++) {
203*baec1910SAndreas Färber             /* TOFIX: for now, the second IDE channel is not properly
204*baec1910SAndreas Färber              *        used by OHW. The Mac floppy disk are not emulated.
205*baec1910SAndreas Färber              *        For now, OHW cannot boot from the network.
206*baec1910SAndreas Färber              */
207*baec1910SAndreas Färber #if 0
208*baec1910SAndreas Färber             if (boot_device[i] >= 'a' && boot_device[i] <= 'f') {
209*baec1910SAndreas Färber                 ppc_boot_device = boot_device[i];
210*baec1910SAndreas Färber                 break;
211*baec1910SAndreas Färber             }
212*baec1910SAndreas Färber #else
213*baec1910SAndreas Färber             if (boot_device[i] >= 'c' && boot_device[i] <= 'd') {
214*baec1910SAndreas Färber                 ppc_boot_device = boot_device[i];
215*baec1910SAndreas Färber                 break;
216*baec1910SAndreas Färber             }
217*baec1910SAndreas Färber #endif
218*baec1910SAndreas Färber         }
219*baec1910SAndreas Färber         if (ppc_boot_device == '\0') {
220*baec1910SAndreas Färber             fprintf(stderr, "No valid boot device for G3 Beige machine\n");
221*baec1910SAndreas Färber             exit(1);
222*baec1910SAndreas Färber         }
223*baec1910SAndreas Färber     }
224*baec1910SAndreas Färber 
225*baec1910SAndreas Färber     /* Register 2 MB of ISA IO space */
226*baec1910SAndreas Färber     isa_mmio_init(0xfe000000, 0x00200000);
227*baec1910SAndreas Färber 
228*baec1910SAndreas Färber     /* XXX: we register only 1 output pin for heathrow PIC */
229*baec1910SAndreas Färber     heathrow_irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
230*baec1910SAndreas Färber     heathrow_irqs[0] =
231*baec1910SAndreas Färber         g_malloc0(smp_cpus * sizeof(qemu_irq) * 1);
232*baec1910SAndreas Färber     /* Connect the heathrow PIC outputs to the 6xx bus */
233*baec1910SAndreas Färber     for (i = 0; i < smp_cpus; i++) {
234*baec1910SAndreas Färber         switch (PPC_INPUT(env)) {
235*baec1910SAndreas Färber         case PPC_FLAGS_INPUT_6xx:
236*baec1910SAndreas Färber             heathrow_irqs[i] = heathrow_irqs[0] + (i * 1);
237*baec1910SAndreas Färber             heathrow_irqs[i][0] =
238*baec1910SAndreas Färber                 ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
239*baec1910SAndreas Färber             break;
240*baec1910SAndreas Färber         default:
241*baec1910SAndreas Färber             hw_error("Bus model not supported on OldWorld Mac machine\n");
242*baec1910SAndreas Färber         }
243*baec1910SAndreas Färber     }
244*baec1910SAndreas Färber 
245*baec1910SAndreas Färber     /* init basic PC hardware */
246*baec1910SAndreas Färber     if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
247*baec1910SAndreas Färber         hw_error("Only 6xx bus is supported on heathrow machine\n");
248*baec1910SAndreas Färber     }
249*baec1910SAndreas Färber     pic = heathrow_pic_init(&pic_mem, 1, heathrow_irqs);
250*baec1910SAndreas Färber     pci_bus = pci_grackle_init(0xfec00000, pic,
251*baec1910SAndreas Färber                                get_system_memory(),
252*baec1910SAndreas Färber                                get_system_io());
253*baec1910SAndreas Färber     pci_vga_init(pci_bus);
254*baec1910SAndreas Färber 
255*baec1910SAndreas Färber     escc_mem = escc_init(0, pic[0x0f], pic[0x10], serial_hds[0],
256*baec1910SAndreas Färber                                serial_hds[1], ESCC_CLOCK, 4);
257*baec1910SAndreas Färber     memory_region_init_alias(escc_bar, "escc-bar",
258*baec1910SAndreas Färber                              escc_mem, 0, memory_region_size(escc_mem));
259*baec1910SAndreas Färber 
260*baec1910SAndreas Färber     for(i = 0; i < nb_nics; i++)
261*baec1910SAndreas Färber         pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
262*baec1910SAndreas Färber 
263*baec1910SAndreas Färber 
264*baec1910SAndreas Färber     ide_drive_get(hd, MAX_IDE_BUS);
265*baec1910SAndreas Färber 
266*baec1910SAndreas Färber     /* First IDE channel is a MAC IDE on the MacIO bus */
267*baec1910SAndreas Färber     dbdma = DBDMA_init(&dbdma_mem);
268*baec1910SAndreas Färber     ide_mem[0] = NULL;
269*baec1910SAndreas Färber     ide_mem[1] = pmac_ide_init(hd, pic[0x0D], dbdma, 0x16, pic[0x02]);
270*baec1910SAndreas Färber 
271*baec1910SAndreas Färber     /* Second IDE channel is a CMD646 on the PCI bus */
272*baec1910SAndreas Färber     hd[0] = hd[MAX_IDE_DEVS];
273*baec1910SAndreas Färber     hd[1] = hd[MAX_IDE_DEVS + 1];
274*baec1910SAndreas Färber     hd[3] = hd[2] = NULL;
275*baec1910SAndreas Färber     pci_cmd646_ide_init(pci_bus, hd, 0);
276*baec1910SAndreas Färber 
277*baec1910SAndreas Färber     /* cuda also initialize ADB */
278*baec1910SAndreas Färber     cuda_init(&cuda_mem, pic[0x12]);
279*baec1910SAndreas Färber 
280*baec1910SAndreas Färber     adb_kbd_init(&adb_bus);
281*baec1910SAndreas Färber     adb_mouse_init(&adb_bus);
282*baec1910SAndreas Färber 
283*baec1910SAndreas Färber     nvr = macio_nvram_init(0x2000, 4);
284*baec1910SAndreas Färber     pmac_format_nvram_partition(nvr, 0x2000);
285*baec1910SAndreas Färber 
286*baec1910SAndreas Färber     macio_init(pci_bus, PCI_DEVICE_ID_APPLE_343S1201, 1, pic_mem,
287*baec1910SAndreas Färber                dbdma_mem, cuda_mem, nvr, 2, ide_mem, escc_bar);
288*baec1910SAndreas Färber 
289*baec1910SAndreas Färber     if (usb_enabled(false)) {
290*baec1910SAndreas Färber         pci_create_simple(pci_bus, -1, "pci-ohci");
291*baec1910SAndreas Färber     }
292*baec1910SAndreas Färber 
293*baec1910SAndreas Färber     if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
294*baec1910SAndreas Färber         graphic_depth = 15;
295*baec1910SAndreas Färber 
296*baec1910SAndreas Färber     /* No PCI init: the BIOS will do it */
297*baec1910SAndreas Färber 
298*baec1910SAndreas Färber     fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
299*baec1910SAndreas Färber     fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
300*baec1910SAndreas Färber     fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
301*baec1910SAndreas Färber     fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, ARCH_HEATHROW);
302*baec1910SAndreas Färber     fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base);
303*baec1910SAndreas Färber     fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
304*baec1910SAndreas Färber     if (kernel_cmdline) {
305*baec1910SAndreas Färber         fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, cmdline_base);
306*baec1910SAndreas Färber         pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, kernel_cmdline);
307*baec1910SAndreas Färber     } else {
308*baec1910SAndreas Färber         fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
309*baec1910SAndreas Färber     }
310*baec1910SAndreas Färber     fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_base);
311*baec1910SAndreas Färber     fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
312*baec1910SAndreas Färber     fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ppc_boot_device);
313*baec1910SAndreas Färber 
314*baec1910SAndreas Färber     fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_WIDTH, graphic_width);
315*baec1910SAndreas Färber     fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height);
316*baec1910SAndreas Färber     fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth);
317*baec1910SAndreas Färber 
318*baec1910SAndreas Färber     fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_IS_KVM, kvm_enabled());
319*baec1910SAndreas Färber     if (kvm_enabled()) {
320*baec1910SAndreas Färber #ifdef CONFIG_KVM
321*baec1910SAndreas Färber         uint8_t *hypercall;
322*baec1910SAndreas Färber 
323*baec1910SAndreas Färber         fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq());
324*baec1910SAndreas Färber         hypercall = g_malloc(16);
325*baec1910SAndreas Färber         kvmppc_get_hypercall(env, hypercall, 16);
326*baec1910SAndreas Färber         fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16);
327*baec1910SAndreas Färber         fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid());
328*baec1910SAndreas Färber #endif
329*baec1910SAndreas Färber     } else {
330*baec1910SAndreas Färber         fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, get_ticks_per_sec());
331*baec1910SAndreas Färber     }
332*baec1910SAndreas Färber 
333*baec1910SAndreas Färber     qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
334*baec1910SAndreas Färber }
335*baec1910SAndreas Färber 
336*baec1910SAndreas Färber static QEMUMachine heathrow_machine = {
337*baec1910SAndreas Färber     .name = "g3beige",
338*baec1910SAndreas Färber     .desc = "Heathrow based PowerMAC",
339*baec1910SAndreas Färber     .init = ppc_heathrow_init,
340*baec1910SAndreas Färber     .max_cpus = MAX_CPUS,
341*baec1910SAndreas Färber #ifndef TARGET_PPC64
342*baec1910SAndreas Färber     .is_default = 1,
343*baec1910SAndreas Färber #endif
344*baec1910SAndreas Färber     DEFAULT_MACHINE_OPTIONS,
345*baec1910SAndreas Färber };
346*baec1910SAndreas Färber 
347*baec1910SAndreas Färber static void heathrow_machine_init(void)
348*baec1910SAndreas Färber {
349*baec1910SAndreas Färber     qemu_register_machine(&heathrow_machine);
350*baec1910SAndreas Färber }
351*baec1910SAndreas Färber 
352*baec1910SAndreas Färber machine_init(heathrow_machine_init);
353