On Thu, Feb 2, 2017 at 6:13 AM, David Gibson <da...@gibson.dropbear.id.au> wrote: > From: Hervé Poussineau <hpous...@reactos.org> > > Machine supports both Open Hack'Ware and OpenBIOS. > Open Hack'Ware is the default because OpenBIOS is currently unable to boot > PReP boot partitions or PReP kernels. > > Signed-off-by: Hervé Poussineau <hpous...@reactos.org> > [dwg: Correct compile failure with KVM located by Thomas Huth] > Signed-off-by: David Gibson <da...@gibson.dropbear.id.au> > --- > default-configs/ppc-softmmu.mak | 1 + > hw/ppc/prep.c | 230 > ++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 231 insertions(+) > > diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak > index e567658..7dd004e 100644 > --- a/default-configs/ppc-softmmu.mak > +++ b/default-configs/ppc-softmmu.mak > @@ -18,6 +18,7 @@ CONFIG_I82378=y > CONFIG_PC87312=y > CONFIG_MACIO=y > CONFIG_PCSPK=y > +CONFIG_CS4231A=y > CONFIG_CUDA=y > CONFIG_ADB=y > CONFIG_MAC_NVRAM=y > diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c > index 9fb89d3..ca7959c 100644 > --- a/hw/ppc/prep.c > +++ b/hw/ppc/prep.c > @@ -2,6 +2,7 @@ > * QEMU PPC PREP hardware System Emulator > * > * Copyright (c) 2003-2007 Jocelyn Mayer > + * Copyright (c) 2017 Hervé Poussineau > * > * Permission is hereby granted, free of charge, to any person obtaining a > copy > * of this software and associated documentation files (the "Software"), to > deal > @@ -43,17 +44,21 @@ > #include "hw/isa/pc87312.h" > #include "sysemu/block-backend.h" > #include "sysemu/arch_init.h" > +#include "sysemu/kvm.h" > #include "sysemu/qtest.h" > #include "exec/address-spaces.h" > #include "trace.h" > #include "elf.h" > #include "qemu/cutils.h" > +#include "kvm_ppc.h" > > /* SMP is not enabled, for now */ > #define MAX_CPUS 1 > > #define MAX_IDE_BUS 2 > > +#define CFG_ADDR 0xf0000510 > + > #define BIOS_SIZE (1024 * 1024) > #define BIOS_FILENAME "ppc_rom.bin" > #define KERNEL_LOAD_ADDR 0x01000000 > @@ -316,6 +321,12 @@ static uint32_t PREP_io_800_readb (void *opaque, > uint32_t addr) > > #define NVRAM_SIZE 0x2000 > > +static void fw_cfg_boot_set(void *opaque, const char *boot_device, > + Error **errp) > +{ > + fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]); > +} > + > static void ppc_prep_reset(void *opaque) > { > PowerPCCPU *cpu = opaque; > @@ -677,4 +688,223 @@ static void prep_machine_init(MachineClass *mc) > mc->default_boot_order = "cad"; > } > > +static int prep_set_cmos_checksum(DeviceState *dev, void *opaque) > +{ > + uint16_t checksum = *(uint16_t *)opaque; > + ISADevice *rtc; > + > + if (object_dynamic_cast(OBJECT(dev), "mc146818rtc")) { > + rtc = ISA_DEVICE(dev); > + rtc_set_memory(rtc, 0x2e, checksum & 0xff); > + rtc_set_memory(rtc, 0x3e, checksum & 0xff); > + rtc_set_memory(rtc, 0x2f, checksum >> 8); > + rtc_set_memory(rtc, 0x3f, checksum >> 8); > + } > + return 0; > +} > + > +static void ibm_40p_init(MachineState *machine) > +{ > + CPUPPCState *env = NULL; > + uint16_t cmos_checksum; > + PowerPCCPU *cpu; > + DeviceState *dev; > + SysBusDevice *pcihost; > + Nvram *m48t59 = NULL; > + PCIBus *pci_bus; > + ISABus *isa_bus; > + void *fw_cfg; > + int i; > + uint32_t kernel_base = 0, initrd_base = 0; > + long kernel_size = 0, initrd_size = 0; > + char boot_device; > + > + /* init CPU */ > + if (!machine->cpu_model) { > + machine->cpu_model = "604"; > + } > + cpu = cpu_ppc_init(machine->cpu_model); > + if (!cpu) { > + error_report("could not initialize CPU '%s'", > + machine->cpu_model); > + exit(1); > + } > + env = &cpu->env; > + if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) { > + error_report("only 6xx bus is supported on this machine"); > + exit(1); > + } > + > + if (env->flags & POWERPC_FLAG_RTC_CLK) { > + /* POWER / PowerPC 601 RTC clock frequency is 7.8125 MHz */ > + cpu_ppc_tb_init(env, 7812500UL);
Is this necessary? Looks like it sets both decrementer and cpu frequency to 7.8125 MHz, so the machine with -cpu 601 is working very slow. > + } else { > + /* Set time-base frequency to 100 Mhz */ > + cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL); > + } > + qemu_register_reset(ppc_prep_reset, cpu); > + > + /* PCI host */ > + dev = qdev_create(NULL, "raven-pcihost"); > + if (!bios_name) { > + bios_name = BIOS_FILENAME; > + } > + qdev_prop_set_string(dev, "bios-name", bios_name); > + qdev_prop_set_uint32(dev, "elf-machine", PPC_ELF_MACHINE); > + pcihost = SYS_BUS_DEVICE(dev); > + object_property_add_child(qdev_get_machine(), "raven", OBJECT(dev), > NULL); > + qdev_init_nofail(dev); > + pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci.0")); > + if (!pci_bus) { > + error_report("could not create PCI host controller"); > + exit(1); > + } > + > + /* PCI -> ISA bridge */ > + dev = DEVICE(pci_create_simple(pci_bus, PCI_DEVFN(11, 0), "i82378")); > + qdev_connect_gpio_out(dev, 0, > + cpu->env.irq_inputs[PPC6xx_INPUT_INT]); > + sysbus_connect_irq(pcihost, 0, qdev_get_gpio_in(dev, 15)); > + sysbus_connect_irq(pcihost, 1, qdev_get_gpio_in(dev, 13)); > + sysbus_connect_irq(pcihost, 2, qdev_get_gpio_in(dev, 15)); > + sysbus_connect_irq(pcihost, 3, qdev_get_gpio_in(dev, 13)); > + isa_bus = ISA_BUS(qdev_get_child_bus(dev, "isa.0")); > + > + /* Memory controller */ > + dev = DEVICE(isa_create(isa_bus, "rs6000-mc")); > + qdev_prop_set_uint32(dev, "ram-size", machine->ram_size); > + qdev_init_nofail(dev); > + > + /* initialize CMOS checksums */ > + cmos_checksum = 0x6aa9; > + qbus_walk_children(BUS(isa_bus), prep_set_cmos_checksum, NULL, NULL, > NULL, > + &cmos_checksum); > + > + /* initialize audio subsystem */ > + audio_init(); > + > + /* add some more devices */ > + if (defaults_enabled()) { > + isa_create_simple(isa_bus, "i8042"); > + m48t59 = NVRAM(isa_create_simple(isa_bus, "isa-m48t59")); > + > + dev = DEVICE(isa_create(isa_bus, "cs4231a")); > + qdev_prop_set_uint32(dev, "iobase", 0x830); > + qdev_prop_set_uint32(dev, "irq", 10); > + qdev_init_nofail(dev); > + > + dev = DEVICE(isa_create(isa_bus, "pc87312")); > + qdev_prop_set_uint32(dev, "config", 12); > + qdev_init_nofail(dev); > + > + dev = DEVICE(isa_create(isa_bus, "prep-systemio")); > + qdev_prop_set_uint32(dev, "ibm-planar-id", 0xfc); > + qdev_prop_set_uint32(dev, "equipment", 0xc0); > + qdev_init_nofail(dev); > + > + pci_create_simple(pci_bus, PCI_DEVFN(1, 0), "lsi53c810"); > + > + /* XXX: s3-trio at PCI_DEVFN(2, 0) */ > + pci_vga_init(pci_bus); > + > + for (i = 0; i < nb_nics; i++) { > + pci_nic_init_nofail(&nd_table[i], pci_bus, "pcnet", > + i == 0 ? "3" : NULL); > + } > + } > + > + /* Prepare firmware configuration for OpenBIOS */ > + fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2); > + > + if (machine->kernel_filename) { > + /* load kernel */ > + kernel_base = KERNEL_LOAD_ADDR; > + kernel_size = load_image_targphys(machine->kernel_filename, > + kernel_base, > + machine->ram_size - kernel_base); > + if (kernel_size < 0) { > + error_report("could not load kernel '%s'", > + machine->kernel_filename); > + exit(1); > + } > + fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base); > + fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); > + /* load initrd */ > + if (machine->initrd_filename) { > + initrd_base = INITRD_LOAD_ADDR; > + initrd_size = load_image_targphys(machine->initrd_filename, > + initrd_base, > + machine->ram_size - > initrd_base); > + if (initrd_size < 0) { > + error_report("could not load initial ram disk '%s'", > + machine->initrd_filename); > + exit(1); > + } > + fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_base); > + fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size); > + } > + if (machine->kernel_cmdline && *machine->kernel_cmdline) { > + fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR); > + pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, > + machine->kernel_cmdline); > + fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, > + machine->kernel_cmdline); > + fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, > + strlen(machine->kernel_cmdline) + 1); > + } > + boot_device = 'm'; > + } else { > + boot_device = machine->boot_order[0]; > + } > + > + fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus); > + fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)machine->ram_size); > + fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, ARCH_PREP); > + > + fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_WIDTH, graphic_width); > + fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height); > + fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth); > + > + fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_IS_KVM, kvm_enabled()); > + if (kvm_enabled()) { > +#ifdef CONFIG_KVM > + uint8_t *hypercall; > + > + fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq()); > + hypercall = g_malloc(16); > + kvmppc_get_hypercall(env, hypercall, 16); > + fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16); > + fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid()); > +#endif > + } else { > + fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, NANOSECONDS_PER_SECOND); > + } > + fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_device); > + qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); > + > + /* Prepare firmware configuration for Open Hack'Ware */ > + if (m48t59) { > + PPC_NVRAM_set_params(m48t59, NVRAM_SIZE, "PREP", ram_size, > + boot_device, > + kernel_base, kernel_size, > + machine->kernel_cmdline, > + initrd_base, initrd_size, > + /* XXX: need an option to load a NVRAM image */ > + 0, > + graphic_width, graphic_height, graphic_depth); > + } > +} > + > +static void ibm_40p_machine_init(MachineClass *mc) > +{ > + mc->desc = "IBM RS/6000 7020 (40p)", > + mc->init = ibm_40p_init; > + mc->max_cpus = 1; > + mc->pci_allow_0_address = true; > + mc->default_ram_size = 128 * M_BYTE; > + mc->block_default_type = IF_SCSI; > + mc->default_boot_order = "c"; > +} > + > +DEFINE_MACHINE("40p", ibm_40p_machine_init) > DEFINE_MACHINE("prep", prep_machine_init) > -- > 2.9.3 > > -- Regards, Artyom Tarasenko SPARC and PPC PReP under qemu blog: http://tyom.blogspot.com/search/label/qemu