From patchwork Thu Dec 29 22:12:16 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Herv=C3=A9_Poussineau?= X-Patchwork-Id: 9491505 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 560C162AB8 for ; Thu, 29 Dec 2016 22:15:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 44AA41FFD6 for ; Thu, 29 Dec 2016 22:15:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 395952094D; Thu, 29 Dec 2016 22:15:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 757FE1FFD6 for ; Thu, 29 Dec 2016 22:15:09 +0000 (UTC) Received: from localhost ([::1]:37503 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cMiya-00056L-GQ for patchwork-qemu-devel@patchwork.kernel.org; Thu, 29 Dec 2016 17:15:08 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52980) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cMixw-00053d-EU for qemu-devel@nongnu.org; Thu, 29 Dec 2016 17:14:30 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cMixu-0001dt-RI for qemu-devel@nongnu.org; Thu, 29 Dec 2016 17:14:28 -0500 Received: from smtp5-g21.free.fr ([2a01:e0c:1:1599::14]:62724) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cMixu-0001cY-C0; Thu, 29 Dec 2016 17:14:26 -0500 Received: from localhost.localdomain (unknown [78.230.185.200]) by smtp5-g21.free.fr (Postfix) with ESMTP id C6B645FFAA; Thu, 29 Dec 2016 23:14:21 +0100 (CET) From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= To: qemu-devel@nongnu.org Date: Thu, 29 Dec 2016 23:12:16 +0100 Message-Id: <1483049536-21548-7-git-send-email-hpoussin@reactos.org> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1483049536-21548-1-git-send-email-hpoussin@reactos.org> References: <1483049536-21548-1-git-send-email-hpoussin@reactos.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Windows NT kernel [generic] [fuzzy] X-Received-From: 2a01:e0c:1:1599::14 Subject: [Qemu-devel] [PATCH 6/6] prep: add IBM RS/6000 7020 (40p) machine emulation X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Giancarlo Teodori , Thomas Huth , Alexander Graf , =?UTF-8?q?Herv=C3=A9=20Poussineau?= , qemu-ppc@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- default-configs/ppc-softmmu.mak | 1 + hw/ppc/prep.c | 231 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 232 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..c0373d1 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) 2016 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,6 +44,7 @@ #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" @@ -54,6 +56,8 @@ #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 +320,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_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]); +} + static void ppc_prep_reset(void *opaque) { PowerPCCPU *cpu = opaque; @@ -677,4 +687,225 @@ 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; + + rtc = 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 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; + const char *vga_type; + 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 == NULL) { + fprintf(stderr, "Unable to find PowerPC CPU definition\n"); + exit(1); + } + env = &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) != PPC_FLAGS_INPUT_6xx) { + hw_error("Only 6xx bus is supported on PREP machine\n"); + } + + /* 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 == NULL) { + fprintf(stderr, "Couldn't create PCI host controller.\n"); + 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"); + + vga_type = pci_vga_type(); + if (vga_type) { + pci_create_simple(pci_bus, PCI_DEVFN(2, 0), pci_vga_type()); + } + + 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_display = "std"; /* FIXME: should be S3 Trio */ + mc->default_boot_order = "c"; +} + +DEFINE_MACHINE("40p", ibm_40p_machine_init) DEFINE_MACHINE("prep", prep_machine_init)