From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:36859) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UXzo3-0003L1-6A for qemu-devel@nongnu.org; Thu, 02 May 2013 16:08:44 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UXzo1-0000yY-GZ for qemu-devel@nongnu.org; Thu, 02 May 2013 16:08:43 -0400 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Thu, 2 May 2013 22:09:03 +0200 Message-Id: <1367525344-7755-7-git-send-email-hpoussin@reactos.org> In-Reply-To: <1367525344-7755-1-git-send-email-hpoussin@reactos.org> References: <1367525344-7755-1-git-send-email-hpoussin@reactos.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [PATCH 6/7] prep: add IBM RS/6000 7248 (43p) machine emulation List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Herv=C3=A9=20Poussineau?= , qemu-ppc@nongnu.org, =?UTF-8?q?Andreas=20F=C3=A4rber?= Machine is very simple (only one PCI host bridge and an ISA bridge). Provide a ibm_43p.cfg file to add more devices to this machine. Syntax is: qemu-system-ppc -M 43p -readconfig ibm_43p.cfg Signed-off-by: Herv=C3=A9 Poussineau --- docs/ibm_43p.cfg | 38 ++++++++++ hw/ppc/prep.c | 213 ++++++++++++++++++++++++++++++++++++++++++++++++= ++++++ 2 files changed, 251 insertions(+) create mode 100644 docs/ibm_43p.cfg diff --git a/docs/ibm_43p.cfg b/docs/ibm_43p.cfg new file mode 100644 index 0000000..70bbfdb --- /dev/null +++ b/docs/ibm_43p.cfg @@ -0,0 +1,38 @@ +########################################################################= #### +# +# qemu-system-ppc -M 43p creates a bare machine with just the very essen= tial +# chipset devices being present: +# +# 00.0 - Host bridge +# 0b.0 - ISA bridge +# +# This config file documents the other devices and how they are +# created. You can simply use "-readconfig $thisfile" to create +# them all. + +[device] + driver =3D "i8042" + +[device] + driver =3D "pc87312" + config =3D "12" + +[device] + driver =3D "pcnet" + addr =3D "12.0" + +[device] + driver =3D "isa-m48t59" + iobase =3D "0x74" + +[device] + driver =3D "isa-ide" + iobase =3D "0x1f0" + iobase2 =3D "0x3f6" + irq =3D "14" + +[device] + driver =3D "isa-ide" + iobase =3D "0x170" + iobase2 =3D "0x376" + irq =3D "15" diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index 59c7da3..f307d41 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -30,6 +30,7 @@ #include "sysemu/sysemu.h" #include "hw/isa/isa.h" #include "hw/pci/pci.h" +#include "hw/pci/pci_bus.h" #include "hw/pci/pci_host.h" #include "hw/ppc/ppc.h" #include "hw/boards.h" @@ -41,6 +42,9 @@ #include "sysemu/blockdev.h" #include "sysemu/arch_init.h" #include "exec/address-spaces.h" +#include "elf.h" +#include "hw/nvram/fw_cfg.h" +#include "hw/sparc/firmware_abi.h" =20 //#define HARD_DEBUG_PPC_IO //#define DEBUG_PPC_IO @@ -50,6 +54,8 @@ =20 #define MAX_IDE_BUS 2 =20 +#define CFG_ADDR 0xf0000510 + #define BIOS_SIZE (1024 * 1024) #define BIOS_FILENAME "ppc_rom.bin" #define KERNEL_LOAD_ADDR 0x01000000 @@ -413,6 +419,61 @@ static const MemoryRegionOps PPC_prep_io_ops =3D { =20 #define NVRAM_SIZE 0x2000 =20 +static int fw_cfg_boot_set(void *opaque, const char *boot_device) +{ + fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]); + return 0; +} + +#define DEF_SYSTEM_SIZE 0xc10 + +static void nvram_init(NvramClass *k, Nvram *nvram) +{ + uint8_t image[NVRAM_SIZE]; + struct OpenBIOS_nvpart_v1 *part_header; + uint32_t start, end; + unsigned int i; + + memset(image, '\0', sizeof(image)); + + start =3D 0; + + /* OpenBIOS nvram variables */ + /* Variable partition */ + part_header =3D (struct OpenBIOS_nvpart_v1 *)&image[start]; + part_header->signature =3D OPENBIOS_PART_SYSTEM; + pstrcpy(part_header->name, sizeof(part_header->name), "system"); + + end =3D start + sizeof(struct OpenBIOS_nvpart_v1); + for (i =3D 0; i < nb_prom_envs; i++) { + end =3D OpenBIOS_set_var(image, end, prom_envs[i]); + } + + /* End marker */ + image[end++] =3D '\0'; + + end =3D start + ((end - start + 15) & ~15); + /* XXX: OpenBIOS is not able to grow up a partition. Leave some spac= e for + new variables. */ + if (end < DEF_SYSTEM_SIZE) { + end =3D DEF_SYSTEM_SIZE; + } + OpenBIOS_finish_partition(part_header, end - start); + + /* free partition */ + start =3D end; + part_header =3D (struct OpenBIOS_nvpart_v1 *)&image[start]; + part_header->signature =3D OPENBIOS_PART_FREE; + pstrcpy(part_header->name, sizeof(part_header->name), "free"); + + end =3D NVRAM_SIZE; + OpenBIOS_finish_partition(part_header, end - start); + + for (i =3D 0; i < sizeof(image); i++) { + k->write(nvram, i, image[i]); + } +} + static void cpu_request_exit(void *opaque, int irq, int level) { CPUPPCState *env =3D cpu_single_env; @@ -660,6 +721,150 @@ static void ppc_prep_init(QEMUMachineInitArgs *args= ) register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL); } =20 +static int prep_set_cmos_checksum(DeviceState *dev, void *opaque) +{ + uint16_t checksum =3D *(uint16_t *)opaque; + ISADevice *rtc; + + rtc =3D ISA_DEVICE(object_dynamic_cast(OBJECT(dev), "mc146818rtc")); + if (rtc) { + 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 int prep_init_m48t59(DeviceState *dev, void *opaque) +{ + if (object_dynamic_cast(OBJECT(dev), TYPE_NVRAM)) { + /* if nvram is initialized, we expect first word to be not null = */ + Nvram *nvram =3D NVRAM(dev); + NvramClass *k =3D NVRAM_GET_CLASS(dev); + if (k->read(nvram, 0) =3D=3D 0 && k->read(nvram, 1) =3D=3D 0) { + nvram_init(k, nvram); + } + } + return 0; +} + +static void ppc_prep_init_m48t59(void *opaque) +{ + BusState *bus =3D opaque; + qbus_walk_children(bus, prep_init_m48t59, NULL, NULL); +} + +static void ibm_43p_init(QEMUMachineInitArgs *args) +{ + CPUPPCState *env =3D NULL; + uint16_t cmos_checksum; + PowerPCCPU *cpu; + DeviceState *dev; + SysBusDevice *pcihost; + PCIBus *pci_bus; + ISABus *isa_bus; + qemu_irq *cpu_exit_irq; + void *fw_cfg; + + /* init CPU */ + if (!args->cpu_model) { + args->cpu_model =3D "604"; + } + cpu =3D cpu_ppc_init(args->cpu_model); + if (cpu =3D=3D NULL) { + fprintf(stderr, "Unable to find PowerPC CPU definition\n"); + exit(1); + } + env =3D &cpu->env; + + if (env->flags & POWERPC_FLAG_RTC_CLK) { + /* POWER / PowerPC 601 RTC clock frequency is 7.8125 MHz */ + cpu_ppc_tb_init(env, 7812500UL); + } else { + /* Set time-base frequency to 100 Mhz */ + cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL); + } + qemu_register_reset(ppc_prep_reset, cpu); + if (PPC_INPUT(env) !=3D PPC_FLAGS_INPUT_6xx) { + hw_error("Only 6xx bus is supported on PREP machine\n"); + } + + /* PCI host */ + pcihost =3D SYS_BUS_DEVICE(qdev_create(NULL, "mpc105-pcihost")); + qdev_prop_set_uint32(DEVICE(pcihost), "ram-size", (uint32_t)args->ra= m_size); + qdev_prop_set_uint32(DEVICE(pcihost), "elf-machine", ELF_MACHINE); + qdev_prop_set_bit(DEVICE(pcihost), "x-auto-conf", 1); + if (bios_name =3D=3D NULL) { + bios_name =3D "openbios-ppc.elf"; + } + qdev_prop_set_string(DEVICE(pcihost), "bios-name", bios_name); + object_property_add_child(qdev_get_machine(), "eagle", OBJECT(pcihos= t), + NULL); + qdev_init_nofail(DEVICE(pcihost)); + pci_bus =3D PCI_BUS(qdev_get_child_bus(DEVICE(pcihost), "pci.0")); + if (pci_bus =3D=3D NULL) { + fprintf(stderr, "Couldn't create PCI host controller.\n"); + exit(1); + } + + /* PCI -> ISA bridge */ + dev =3D DEVICE(pci_create_simple(pci_bus, PCI_DEVFN(11, 0), "i82378"= )); + cpu_exit_irq =3D qemu_allocate_irqs(cpu_request_exit, NULL, 1); + qdev_connect_gpio_out(dev, 0, + first_cpu->irq_inputs[PPC6xx_INPUT_INT]); + qdev_connect_gpio_out(dev, 1, *cpu_exit_irq); + sysbus_connect_irq(pcihost, 0, qdev_get_gpio_in(dev, 9)); + sysbus_connect_irq(pcihost, 1, qdev_get_gpio_in(dev, 11)); + sysbus_connect_irq(pcihost, 2, qdev_get_gpio_in(dev, 9)); + sysbus_connect_irq(pcihost, 3, qdev_get_gpio_in(dev, 11)); + isa_bus =3D ISA_BUS(qdev_get_child_bus(dev, "isa.0")); + + /* initialize CMOS checksums */ + cmos_checksum =3D 0x6aa9; + qbus_walk_children(BUS(isa_bus), prep_set_cmos_checksum, NULL, + &cmos_checksum); + + /* initialize audio subsystem */ + audio_init(); + + /* Initialize NVRAM (if empty) at next reboot */ + qemu_register_reset(ppc_prep_init_m48t59, BUS(isa_bus)); + + /* Prepare firmware configuration for OpenBIOS */ + fw_cfg =3D fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2); + fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus); + fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); + fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)args->ram_size); + fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, ARCH_PREP); + fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, 0); + fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, 0); + fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0); + fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, 0); + fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0); + fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, '\0'); + + 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 =3D 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, get_ticks_per_sec()); + } + qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); +} + static QEMUMachine prep_machine =3D { .name =3D "prep", .desc =3D "PowerPC PREP platform", @@ -668,9 +873,17 @@ static QEMUMachine prep_machine =3D { DEFAULT_MACHINE_OPTIONS, }; =20 +static QEMUMachine ibm_43p_machine =3D { + .name =3D "43p", + .desc =3D "IBM RS/6000 7248 (43p)", + .init =3D ibm_43p_init, + .max_cpus =3D 1, +}; + static void prep_machine_init(void) { qemu_register_machine(&prep_machine); + qemu_register_machine(&ibm_43p_machine); } =20 machine_init(prep_machine_init); --=20 1.7.10.4