diff options
author | Avi Kivity <avi@redhat.com> | 2009-12-07 11:22:32 +0200 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-12-07 11:22:32 +0200 |
commit | d95f05082bb2b6a695784f006f21d14547177786 (patch) | |
tree | ac8653f87582c7328a65e3edef6a8e05e6bfef43 | |
parent | Merge commit 'f3304eea9338b7e694843fa1a6db5540e8783d1d' into upstream-merge (diff) | |
parent | Add S390 maintainer information (diff) | |
download | qemu-kvm-d95f05082bb2b6a695784f006f21d14547177786.tar.gz qemu-kvm-d95f05082bb2b6a695784f006f21d14547177786.tar.bz2 qemu-kvm-d95f05082bb2b6a695784f006f21d14547177786.zip |
Merge commit '749717a0ea2f60d33d01c1e37fa24dfa7250dfc0' into upstream-merge
* commit '749717a0ea2f60d33d01c1e37fa24dfa7250dfc0':
Add S390 maintainer information
Set default console to virtio on S390x
S390 GDB stub
Add S390x virtio machine description
Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r-- | MAINTAINERS | 3 | ||||
-rw-r--r-- | Makefile.target | 2 | ||||
-rw-r--r-- | gdbstub.c | 52 | ||||
-rw-r--r-- | hw/s390-virtio.c | 255 | ||||
-rw-r--r-- | vl.c | 26 |
5 files changed, 337 insertions, 1 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index d35649591..56f107e8e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20,6 +20,7 @@ SH4 ? CRIS Edgar E. Iglesias Alpha ? MicroBlaze Edgar E. Iglesias +S390 ? Machines (sorted by CPU): ------------------------- @@ -63,6 +64,8 @@ CRIS Alpha MicroBlaze petalogix_s3adsp1800.c Edgar E. Iglesias +S390 + s390-*.c Alexander Graf Generic Subsystems: ------------------- diff --git a/Makefile.target b/Makefile.target index a69089e59..b3a54ca18 100644 --- a/Makefile.target +++ b/Makefile.target @@ -321,7 +321,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 ifeq ($(TARGET_ARCH), ia64) firmware.o: firmware.c @@ -1349,6 +1349,55 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n) return 8; } +#elif defined (TARGET_S390X) + +#define NUM_CORE_REGS S390_NUM_TOTAL_REGS + +static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n) +{ + switch (n) { + case S390_PSWM_REGNUM: GET_REGL(env->psw.mask); break; + case S390_PSWA_REGNUM: GET_REGL(env->psw.addr); break; + case S390_R0_REGNUM ... S390_R15_REGNUM: + GET_REGL(env->regs[n-S390_R0_REGNUM]); break; + case S390_A0_REGNUM ... S390_A15_REGNUM: + GET_REG32(env->aregs[n-S390_A0_REGNUM]); break; + case S390_FPC_REGNUM: GET_REG32(env->fpc); break; + case S390_F0_REGNUM ... S390_F15_REGNUM: + /* XXX */ + break; + case S390_PC_REGNUM: GET_REGL(env->psw.addr); break; + case S390_CC_REGNUM: GET_REG32(env->cc); break; + } + + return 0; +} + +static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n) +{ + target_ulong tmpl; + uint32_t tmp32; + int r = 8; + tmpl = ldtul_p(mem_buf); + tmp32 = ldl_p(mem_buf); + + switch (n) { + case S390_PSWM_REGNUM: env->psw.mask = tmpl; break; + case S390_PSWA_REGNUM: env->psw.addr = tmpl; break; + case S390_R0_REGNUM ... S390_R15_REGNUM: + env->regs[n-S390_R0_REGNUM] = tmpl; break; + case S390_A0_REGNUM ... S390_A15_REGNUM: + env->aregs[n-S390_A0_REGNUM] = tmp32; r=4; break; + case S390_FPC_REGNUM: env->fpc = tmp32; r=4; break; + case S390_F0_REGNUM ... S390_F15_REGNUM: + /* XXX */ + break; + case S390_PC_REGNUM: env->psw.addr = tmpl; break; + case S390_CC_REGNUM: env->cc = tmp32; r=4; break; + } + + return r; +} #else #define NUM_CORE_REGS 0 @@ -1617,6 +1666,9 @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc) s->c_cpu->pc = pc; #elif defined (TARGET_ALPHA) s->c_cpu->pc = pc; +#elif defined (TARGET_S390X) + cpu_synchronize_state(s->c_cpu); + s->c_cpu->psw.addr = pc; #endif } diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c new file mode 100644 index 000000000..cc21ee6da --- /dev/null +++ b/hw/s390-virtio.c @@ -0,0 +1,255 @@ +/* + * QEMU S390 virtio target + * + * Copyright (c) 2009 Alexander Graf <agraf@suse.de> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#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_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); @@ -4769,6 +4769,20 @@ int main(int argc, char **argv, char **envp) cyls = heads = secs = 0; translation = BIOS_ATA_TRANSLATION_AUTO; +#ifdef TARGET_S390X + for(i = 0; i < MAX_SERIAL_PORTS; i++) + serial_devices[i] = NULL; + serial_device_index = 0; + + for(i = 0; i < MAX_PARALLEL_PORTS; i++) + parallel_devices[i] = NULL; + parallel_device_index = 0; + + virtio_consoles[0] = "mon:stdio"; + for(i = 1; i < MAX_VIRTIO_CONSOLES; i++) + virtio_consoles[i] = NULL; + virtio_console_index = 0; +#else serial_devices[0] = "vc:80Cx24C"; for(i = 1; i < MAX_SERIAL_PORTS; i++) serial_devices[i] = NULL; @@ -4782,6 +4796,7 @@ int main(int argc, char **argv, char **envp) for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) virtio_consoles[i] = NULL; virtio_console_index = 0; +#endif monitor_devices[0] = "vc:80Cx24C"; monitor_flags[0] = MONITOR_IS_DEFAULT | MONITOR_USE_READLINE; @@ -5753,6 +5768,17 @@ int main(int argc, char **argv, char **envp) break; } } + for (i = 0; i < MAX_VIRTIO_CONSOLES; i++) { + const char *devname = virtio_consoles[i]; + if (devname && !strcmp(devname,"mon:stdio")) { + monitor_devices[0] = NULL; + break; + } else if (devname && !strcmp(devname,"stdio")) { + monitor_devices[0] = NULL; + virtio_consoles[i] = "mon:stdio"; + break; + } + } } if (nb_numa_nodes > 0) { |