Skip to content

Commit

Permalink
Merge branch 's390-for-upstream' of git://repo.or.cz/qemu/agraf
Browse files Browse the repository at this point in the history
* 's390-for-upstream' of git://repo.or.cz/qemu/agraf:
  s390: Add a hypercall registration interface.
  target-s390x: Unregister reset callback on finalization
  s390x: fix indentation
  s390: Add CPU reset handler
  s390x: Remove inline function ebcdic_put and related data from cpu.h
  S390: Enable -cpu help and QMP query-cpu-definitions
  s390: Move IPL code into a separate device
  s390: new contributions GPLv2 or later
  • Loading branch information
blueswirl committed Jan 19, 2013
2 parents 48b8599 + 28e942f commit 67c4f2d
Show file tree
Hide file tree
Showing 9 changed files with 470 additions and 220 deletions.
194 changes: 63 additions & 131 deletions hw/s390-virtio.c
Expand Up @@ -2,6 +2,7 @@
* QEMU S390 virtio target
*
* Copyright (c) 2009 Alexander Graf <agraf@suse.de>
* Copyright IBM Corp 2012
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Expand All @@ -13,7 +14,10 @@
* 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
* Contributions after 2012-10-29 are licensed under the terms of the
* GNU GPL, version 2 or (at your option) any later version.
*
* 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/>.
*/

Expand All @@ -25,14 +29,14 @@
#include "boards.h"
#include "monitor/monitor.h"
#include "loader.h"
#include "elf.h"
#include "hw/virtio.h"
#include "hw/sysbus.h"
#include "sysemu/kvm.h"
#include "exec/address-spaces.h"

#include "hw/s390-virtio-bus.h"
#include "hw/s390x/sclp.h"
#include "hw/s390-virtio.h"

//#define DEBUG_S390

Expand All @@ -44,21 +48,6 @@
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 ZIPL_START 0x009000UL
#define ZIPL_LOAD_ADDR 0x009000UL
#define ZIPL_FILENAME "s390-zipl.rom"

#define MAX_BLK_DEVS 10

static VirtIOS390Bus *s390_bus;
Expand All @@ -73,56 +62,63 @@ S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
return ipi_states[cpu_addr];
}

int s390_virtio_hypercall(CPUS390XState *env, uint64_t mem, uint64_t hypercall)
static int s390_virtio_hcall_notify(const uint64_t *args)
{
uint64_t mem = args[0];
int r = 0, i;

dprintf("KVM hypercall: %ld\n", hypercall);
switch (hypercall) {
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:
{
VirtIOS390Device *dev;

dev = s390_virtio_bus_find_mem(s390_bus, mem);
virtio_reset(dev->vdev);
stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0);
s390_virtio_device_sync(dev);
s390_virtio_reset_idx(dev);
break;
}
case KVM_S390_VIRTIO_SET_STATUS:
{
VirtIOS390Device *dev;

dev = s390_virtio_bus_find_mem(s390_bus, mem);
if (mem > ram_size) {
VirtIOS390Device *dev = s390_virtio_bus_find_vring(s390_bus, mem, &i);
if (dev) {
s390_virtio_device_update_status(dev);
virtio_queue_notify(dev->vdev, i);
} else {
r = -EINVAL;
}
break;
} else {
/* Early printk */
}
default:
return r;
}

static int s390_virtio_hcall_reset(const uint64_t *args)
{
uint64_t mem = args[0];
VirtIOS390Device *dev;

dev = s390_virtio_bus_find_mem(s390_bus, mem);
virtio_reset(dev->vdev);
stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0);
s390_virtio_device_sync(dev);
s390_virtio_reset_idx(dev);

return 0;
}

static int s390_virtio_hcall_set_status(const uint64_t *args)
{
uint64_t mem = args[0];
int r = 0;
VirtIOS390Device *dev;

dev = s390_virtio_bus_find_mem(s390_bus, mem);
if (dev) {
s390_virtio_device_update_status(dev);
} else {
r = -EINVAL;
break;
}

return r;
}

static void s390_virtio_register_hcalls(void)
{
s390_register_virtio_hypercall(KVM_S390_VIRTIO_NOTIFY,
s390_virtio_hcall_notify);
s390_register_virtio_hypercall(KVM_S390_VIRTIO_RESET,
s390_virtio_hcall_reset);
s390_register_virtio_hypercall(KVM_S390_VIRTIO_SET_STATUS,
s390_virtio_hcall_set_status);
}

/*
* The number of running CPUs. On s390 a shutdown is the state of all CPUs
* being either stopped or disabled (for interrupts) waiting. We have to
Expand Down Expand Up @@ -156,15 +152,10 @@ static void s390_init(QEMUMachineInitArgs *args)
{
ram_addr_t my_ram_size = args->ram_size;
const char *cpu_model = args->cpu_model;
const char *kernel_filename = args->kernel_filename;
const char *kernel_cmdline = args->kernel_cmdline;
const char *initrd_filename = args->initrd_filename;
CPUS390XState *env = NULL;
DeviceState *dev;
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
ram_addr_t kernel_size = 0;
ram_addr_t initrd_offset;
ram_addr_t initrd_size = 0;
int shift = 0;
uint8_t *storage_keys;
void *virtio_region;
Expand All @@ -185,6 +176,18 @@ static void s390_init(QEMUMachineInitArgs *args)
/* get a BUS */
s390_bus = s390_virtio_bus_init(&my_ram_size);
s390_sclp_init();
dev = qdev_create(NULL, "s390-ipl");
if (args->kernel_filename) {
qdev_prop_set_string(dev, "kernel", args->kernel_filename);
}
if (args->initrd_filename) {
qdev_prop_set_string(dev, "initrd", args->initrd_filename);
}
qdev_prop_set_string(dev, "cmdline", args->kernel_cmdline);
qdev_init_nofail(dev);

/* register hypercalls */
s390_virtio_register_hcalls();

/* allocate RAM */
memory_region_init_ram(ram, "s390.ram", my_ram_size);
Expand Down Expand Up @@ -225,76 +228,6 @@ static void s390_init(QEMUMachineInitArgs *args)
tmp_env->storage_keys = storage_keys;
}

/* One CPU has to run */
s390_add_running_cpu(env);

if (kernel_filename) {

kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, NULL,
NULL, 1, ELF_MACHINE, 0);
if (kernel_size == -1UL) {
kernel_size = load_image_targphys(kernel_filename, 0, ram_size);
}
if (kernel_size == -1UL) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
exit(1);
}
/*
* we can not rely on the ELF entry point, since up to 3.2 this
* value was 0x800 (the SALIPL loader) and it wont work. For
* all (Linux) cases 0x10000 (KERN_IMAGE_START) should be fine.
*/
env->psw.addr = KERN_IMAGE_START;
env->psw.mask = 0x0000000180000000ULL;
} else {
ram_addr_t bios_size = 0;
char *bios_filename;

/* Load zipl bootloader */
if (bios_name == NULL) {
bios_name = ZIPL_FILENAME;
}

bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
bios_size = load_image_targphys(bios_filename, ZIPL_LOAD_ADDR, 4096);
g_free(bios_filename);

if ((long)bios_size < 0) {
hw_error("could not load bootloader '%s'\n", bios_name);
}

if (bios_size > 4096) {
hw_error("stage1 bootloader is > 4k\n");
}

env->psw.addr = ZIPL_START;
env->psw.mask = 0x0000000180000000ULL;
}

if (initrd_filename) {
initrd_offset = INITRD_START;
while (kernel_size + 0x100000 > initrd_offset) {
initrd_offset += 0x100000;
}
initrd_size = load_image_targphys(initrd_filename, initrd_offset,
ram_size - initrd_offset);
if (initrd_size == -1UL) {
fprintf(stderr, "qemu: could not load initrd '%s'\n",
initrd_filename);
exit(1);
}

/* we have to overwrite values in the kernel image, which are "rom" */
stq_p(rom_ptr(INITRD_PARM_START), initrd_offset);
stq_p(rom_ptr(INITRD_PARM_SIZE), initrd_size);
}

if (rom_ptr(KERN_PARM_AREA)) {
/* we have to overwrite values in the kernel image, which are "rom" */
memcpy(rom_ptr(KERN_PARM_AREA), kernel_cmdline,
strlen(kernel_cmdline) + 1);
}

/* Create VirtIO network adapters */
for(i = 0; i < nb_nics; i++) {
Expand Down Expand Up @@ -339,4 +272,3 @@ static void s390_machine_init(void)
}

machine_init(s390_machine_init);

22 changes: 22 additions & 0 deletions hw/s390-virtio.h
@@ -0,0 +1,22 @@
/*
* Virtio interfaces for s390
*
* Copyright 2012 IBM Corp.
* Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or (at
* your option) any later version. See the COPYING file in the top-level
* directory.
*/

#ifndef HW_S390_VIRTIO_H
#define HW_S390_VIRTIO_H 1

#define KVM_S390_VIRTIO_NOTIFY 0
#define KVM_S390_VIRTIO_RESET 1
#define KVM_S390_VIRTIO_SET_STATUS 2

typedef int (*s390_virtio_fn)(const uint64_t *args);
void s390_register_virtio_hypercall(uint64_t code, s390_virtio_fn fn);

#endif
2 changes: 2 additions & 0 deletions hw/s390x/Makefile.objs
@@ -1,6 +1,8 @@
obj-y = s390-virtio-bus.o s390-virtio.o

obj-y := $(addprefix ../,$(obj-y))
obj-y += s390-virtio-hcall.o
obj-y += sclp.o
obj-y += event-facility.o
obj-y += sclpquiesce.o sclpconsole.o
obj-y += ipl.o

0 comments on commit 67c4f2d

Please sign in to comment.