From patchwork Sat Dec 5 11:44:28 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 40395 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 3E0F2B7BEB for ; Sat, 5 Dec 2009 23:04:56 +1100 (EST) Received: from localhost ([127.0.0.1]:57480 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NGtNd-0008LJ-D4 for incoming@patchwork.ozlabs.org; Sat, 05 Dec 2009 07:04:53 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NGt49-0004BE-2U for qemu-devel@nongnu.org; Sat, 05 Dec 2009 06:44:45 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NGt42-000467-4m for qemu-devel@nongnu.org; Sat, 05 Dec 2009 06:44:42 -0500 Received: from [199.232.76.173] (port=49824 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NGt3z-00045D-JG for qemu-devel@nongnu.org; Sat, 05 Dec 2009 06:44:35 -0500 Received: from cantor2.suse.de ([195.135.220.15]:36021 helo=mx2.suse.de) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NGt3y-0008Gm-S2 for qemu-devel@nongnu.org; Sat, 05 Dec 2009 06:44:35 -0500 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.221.2]) by mx2.suse.de (Postfix) with ESMTP id 3B9B7890B6; Sat, 5 Dec 2009 12:44:32 +0100 (CET) From: Alexander Graf To: qemu-devel@nongnu.org Date: Sat, 5 Dec 2009 12:44:28 +0100 Message-Id: <1260013471-18691-9-git-send-email-agraf@suse.de> X-Mailer: git-send-email 1.6.0.2 In-Reply-To: <1260013471-18691-1-git-send-email-agraf@suse.de> References: <1260013471-18691-1-git-send-email-agraf@suse.de> X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.4-2.6 Cc: Carsten Otte , Aurelien Jarno Subject: [Qemu-devel] [PATCH 08/11] Add S390x virtio machine description X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org In order to use the new S390x virtio bus we just introduced, we also need a machine description that sets up the machine according to our PV specification. Let's add that machine description and be happy! Signed-off-by: Alexander Graf --- v4 -> v5 - disable early console v5 -> v6: - make SMP work (use CPU 0 as CPU 0) - fix typo "allicate" - fail on non-virtio nics - coding style --- Makefile.target | 2 +- hw/s390-virtio.c | 255 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 256 insertions(+), 1 deletions(-) create mode 100644 hw/s390-virtio.c diff --git a/Makefile.target b/Makefile.target index 725cbeb..7c1f30c 100644 --- a/Makefile.target +++ b/Makefile.target @@ -293,7 +293,7 @@ obj-sh4-y += ide/core.o ide/mmio.o obj-m68k-y = an5206.o mcf5206.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o obj-m68k-y += m68k-semi.o dummy_m68k.o -obj-s390x-y = s390-virtio-bus.o +obj-s390x-y = s390-virtio-bus.o s390-virtio.o main.o vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS) diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c new file mode 100644 index 0000000..345d198 --- /dev/null +++ b/hw/s390-virtio.c @@ -0,0 +1,255 @@ +/* + * QEMU S390 virtio target + * + * Copyright (c) 2009 Alexander Graf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "hw.h" +#include "block.h" +#include "sysemu.h" +#include "net.h" +#include "boards.h" +#include "monitor.h" +#include "loader.h" +#include "elf.h" +#include "hw/virtio.h" +#include "hw/virtio-console.h" +#include "hw/sysbus.h" +#include "kvm.h" + +#include "hw/s390-virtio-bus.h" + +//#define DEBUG_S390 + +#ifdef DEBUG_S390 +#define dprintf(fmt, ...) \ + do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) +#else +#define dprintf(fmt, ...) \ + do { } while (0) +#endif + +#define KVM_S390_VIRTIO_NOTIFY 0 +#define KVM_S390_VIRTIO_RESET 1 +#define KVM_S390_VIRTIO_SET_STATUS 2 + +#define KERN_IMAGE_START 0x010000UL +#define KERN_PARM_AREA 0x010480UL +#define INITRD_START 0x800000UL +#define INITRD_PARM_START 0x010408UL +#define INITRD_PARM_SIZE 0x010410UL +#define PARMFILE_START 0x001000UL + +#define MAX_BLK_DEVS 10 + +static VirtIOS390Bus *s390_bus; +static CPUState **ipi_states; + +void irq_info(Monitor *mon); +void pic_info(Monitor *mon); + +void irq_info(Monitor *mon) +{ +} + +void pic_info(Monitor *mon) +{ +} + +CPUState *s390_cpu_addr2state(uint16_t cpu_addr) +{ + if (cpu_addr >= smp_cpus) { + return NULL; + } + + return ipi_states[cpu_addr]; +} + +int s390_virtio_hypercall(CPUState *env) +{ + int r = 0, i; + target_ulong mem = env->regs[2]; + + dprintf("KVM hypercall: %ld\n", env->regs[1]); + switch (env->regs[1]) { + case KVM_S390_VIRTIO_NOTIFY: + if (mem > ram_size) { + VirtIOS390Device *dev = s390_virtio_bus_find_vring(s390_bus, + mem, &i); + if (dev) { + virtio_queue_notify(dev->vdev, i); + } else { + r = -EINVAL; + } + } else { + /* Early printk */ + } + break; + case KVM_S390_VIRTIO_RESET: + { + /* Virtio_reset resets the internal addresses, so we'd have to sync + them up again. We don't want to reallocate a vring though, so let's + just not reset. */ + /* virtio_reset(dev->vdev); */ + break; + } + case KVM_S390_VIRTIO_SET_STATUS: + { + VirtIOS390Device *dev; + + dev = s390_virtio_bus_find_mem(s390_bus, mem); + if (dev) { + s390_virtio_device_update_status(dev); + } else { + r = -EINVAL; + } + break; + } + default: + r = -EINVAL; + break; + } + + env->regs[2] = r; + return 0; +} + +/* PC hardware initialisation */ +static void s390_init(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) +{ + CPUState *env = NULL; + ram_addr_t ram_addr, ram_size = _ram_size; + ram_addr_t kernel_size = 0; + ram_addr_t initrd_offset; + ram_addr_t initrd_size = 0; + int i; + + /* get a BUS */ + s390_bus = s390_virtio_bus_init(&ram_size); + + /* allocate RAM */ + ram_addr = qemu_ram_alloc(ram_size); + cpu_register_physical_memory(0, ram_size, ram_addr); + + /* init CPUs */ + if (cpu_model == NULL) { + cpu_model = "host"; + } + + ipi_states = qemu_malloc(sizeof(CPUState *) * smp_cpus); + + for (i = 0; i < smp_cpus; i++) { + CPUState *tmp_env; + + tmp_env = cpu_init(cpu_model); + if (!env) { + env = tmp_env; + } + ipi_states[i] = tmp_env; + tmp_env->halted = 1; + tmp_env->exception_index = EXCP_HLT; + } + + env->halted = 0; + env->exception_index = 0; + + if (kernel_filename) { + kernel_size = load_image(kernel_filename, qemu_get_ram_ptr(0)); + + if (lduw_phys(KERN_IMAGE_START) != 0x0dd0) { + fprintf(stderr, "Specified image is not an s390 boot image\n"); + exit(1); + } + + cpu_synchronize_state(env); + env->psw.addr = KERN_IMAGE_START; + env->psw.mask = 0x0000000180000000UL; + } + + if (initrd_filename) { + initrd_offset = INITRD_START; + while (kernel_size + 0x100000 > initrd_offset) { + initrd_offset += 0x100000; + } + initrd_size = load_image(initrd_filename, qemu_get_ram_ptr(initrd_offset)); + + stq_phys(INITRD_PARM_START, initrd_offset); + stq_phys(INITRD_PARM_SIZE, initrd_size); + } + + if (kernel_cmdline) { + cpu_physical_memory_rw(KERN_PARM_AREA, (uint8_t *)kernel_cmdline, + strlen(kernel_cmdline), 1); + } + + /* Create VirtIO console */ + qdev_init_nofail(qdev_create((BusState *)s390_bus, "virtio-console-s390")); + + /* Create VirtIO network adapters */ + for(i = 0; i < nb_nics; i++) { + NICInfo *nd = &nd_table[i]; + DeviceState *dev; + + if (!nd->model) { + nd->model = (char*)"virtio"; + } + + if (strcmp(nd->model, "virtio")) { + fprintf(stderr, "S390 only supports VirtIO nics\n"); + exit(1); + } + + dev = qdev_create((BusState *)s390_bus, "virtio-net-s390"); + qdev_set_nic_properties(dev, nd); + qdev_init_nofail(dev); + } + + /* Create VirtIO disk drives */ + for(i = 0; i < MAX_BLK_DEVS; i++) { + DriveInfo *dinfo; + DeviceState *dev; + + dinfo = drive_get(IF_IDE, 0, i); + if (!dinfo) { + continue; + } + + dev = qdev_create((BusState *)s390_bus, "virtio-blk-s390"); + qdev_prop_set_drive(dev, "drive", dinfo); + qdev_init_nofail(dev); + } +} + +static QEMUMachine s390_machine = { + .name = "s390-virtio", + .alias = "s390", + .desc = "VirtIO based S390 machine", + .init = s390_init, + .max_cpus = 255, + .is_default = 1, +}; + +static void s390_machine_init(void) +{ + qemu_register_machine(&s390_machine); +} + +machine_init(s390_machine_init);