qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 8/8] s390: Add new channel I/O based virtio tran


From: Alexander Graf
Subject: Re: [Qemu-devel] [PATCH 8/8] s390: Add new channel I/O based virtio transport.
Date: Wed, 16 Jan 2013 14:53:06 +0100

On 16.01.2013, at 14:24, Alexander Graf wrote:

> 
> On 07.12.2012, at 13:50, Cornelia Huck wrote:
> 
>> Add a new virtio transport that uses channel commands to perform
>> virtio operations.
>> 
>> Add a new machine type s390-ccw that uses this virtio-ccw transport
>> and make it the default machine for s390.
>> 
>> Signed-off-by: Cornelia Huck <address@hidden>
>> ---
>> hw/s390-virtio.c       | 149 ++++++--
>> hw/s390x/Makefile.objs |   1 +
>> hw/s390x/virtio-ccw.c  | 909 
>> +++++++++++++++++++++++++++++++++++++++++++++++++
>> hw/s390x/virtio-ccw.h  |  81 +++++
>> trace-events           |   4 +
>> 5 files changed, 1124 insertions(+), 20 deletions(-)
>> create mode 100644 hw/s390x/virtio-ccw.c
>> create mode 100644 hw/s390x/virtio-ccw.h
>> 
>> diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
>> index 9e1afb2..f29ff74 100644
>> --- a/hw/s390-virtio.c
>> +++ b/hw/s390-virtio.c
>> @@ -33,6 +33,8 @@
>> 
>> #include "hw/s390-virtio-bus.h"
>> #include "hw/s390x/sclp.h"
>> +#include "hw/s390x/css.h"
>> +#include "hw/s390x/virtio-ccw.h"
>> 
>> //#define DEBUG_S390
>> 
>> @@ -47,6 +49,7 @@
>> #define KVM_S390_VIRTIO_NOTIFY          0
>> #define KVM_S390_VIRTIO_RESET           1
>> #define KVM_S390_VIRTIO_SET_STATUS      2
>> +#define KVM_S390_VIRTIO_CCW_NOTIFY      3
>> 
>> #define KERN_IMAGE_START                0x010000UL
>> #define KERN_PARM_AREA                  0x010480UL
>> @@ -63,6 +66,7 @@
>> 
>> static VirtIOS390Bus *s390_bus;
>> static S390CPU **ipi_states;
>> +VirtioCcwBus *ccw_bus;
>> 
>> S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
>> {
>> @@ -76,15 +80,21 @@ S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
>> int s390_virtio_hypercall(CPUS390XState *env, uint64_t mem, uint64_t 
>> hypercall)
>> {
>>    int r = 0, i;
>> +    int cssid, ssid, schid, m;
>> +    SubchDev *sch;
>> 
>>    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);
>> +            if (s390_bus) {
>> +                VirtIOS390Device *dev = s390_virtio_bus_find_vring(s390_bus,
>> +                                                                   mem, &i);
>> +                if (dev) {
>> +                    virtio_queue_notify(dev->vdev, i);
>> +                } else {
>> +                    r = -EINVAL;
>> +                }
>>            } else {
>>                r = -EINVAL;
>>            }
>> @@ -93,28 +103,49 @@ int s390_virtio_hypercall(CPUS390XState *env, uint64_t 
>> mem, uint64_t hypercall)
>>        }
>>        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);
>> +        if (s390_bus) {
>> +            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);
>> +        } else {
>> +            r = -EINVAL;
>> +        }
>>        break;
>> -    }
>>    case KVM_S390_VIRTIO_SET_STATUS:
>> -    {
>> -        VirtIOS390Device *dev;
>> +        if (s390_bus) {
>> +            VirtIOS390Device *dev;
>> 
>> -        dev = s390_virtio_bus_find_mem(s390_bus, mem);
>> -        if (dev) {
>> -            s390_virtio_device_update_status(dev);
>> +            dev = s390_virtio_bus_find_mem(s390_bus, mem);
>> +            if (dev) {
>> +                s390_virtio_device_update_status(dev);
>> +            } else {
>> +                r = -EINVAL;
>> +            }
>>        } else {
>>            r = -EINVAL;
>>        }
>>        break;
>> -    }
>> +    case KVM_S390_VIRTIO_CCW_NOTIFY:
>> +        if (ccw_bus) {
>> +            if (ioinst_disassemble_sch_ident(env->regs[2], &m, &cssid, 
>> &ssid,
>> +                                             &schid)) {
>> +                r = -EINVAL;
>> +            } else {
>> +                sch = css_find_subch(m, cssid, ssid, schid);
>> +                if (sch && css_subch_visible(sch)) {
>> +                    virtio_queue_notify(virtio_ccw_get_vdev(sch), 
>> env->regs[3]);
>> +                } else {
>> +                    r = -EINVAL;
>> +                }
>> +            }
>> +         } else {
>> +             r = -EINVAL;
>> +         }
>> +         break;
>>    default:
>>        r = -EINVAL;
>>        break;
>> @@ -370,7 +401,6 @@ static QEMUMachine s390_machine = {
>>    .no_sdcard = 1,
>>    .use_virtcon = 1,
>>    .max_cpus = 255,
>> -    .is_default = 1,
>> };
>> 
>> static void s390_machine_init(void)
>> @@ -379,3 +409,82 @@ static void s390_machine_init(void)
>> }
>> 
>> machine_init(s390_machine_init);
>> +
>> +static void ccw_init(QEMUMachineInitArgs *args)
>> +{
>> +    ram_addr_t my_ram_size = args->ram_size;
>> +    ram_addr_t 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;
>> +    MemoryRegion *sysmem = get_system_memory();
>> +    MemoryRegion *ram = g_new(MemoryRegion, 1);
>> +    int shift = 0;
>> +    uint8_t *storage_keys;
>> +    int ret;
>> +
>> +    /* s390x ram size detection needs a 16bit multiplier + an increment. So
>> +       guests > 64GB can be specified in 2MB steps etc. */
>> +    while ((my_ram_size >> (20 + shift)) > 65535) {
>> +        shift++;
>> +    }
>> +    my_ram_size = my_ram_size >> (20 + shift) << (20 + shift);
>> +
>> +    /* lets propagate the changed ram size into the global variable. */
>> +    ram_size = my_ram_size;
>> +
>> +    /* get a BUS */
>> +    ccw_bus = virtio_ccw_bus_init();
>> +    s390_sclp_init();
>> +
>> +    /* allocate RAM */
>> +    memory_region_init_ram(ram, "s390.ram", my_ram_size);
>> +    vmstate_register_ram_global(ram);
>> +    memory_region_add_subregion(sysmem, 0, ram);
>> +
>> +    /* allocate storage keys */
>> +    storage_keys = g_malloc0(my_ram_size / TARGET_PAGE_SIZE);
>> +
>> +    /* init CPUs */
>> +    env = s390_init_cpus(cpu_model, storage_keys);
>> +
>> +    kvm_s390_enable_css_support(env);
>> +
>> +    /*
>> +     * Create virtual css and set it as default so that non mcss-e
>> +     * enabled guests only see virtio devices.
>> +     */
>> +    ret = css_create_css_image(VIRTUAL_CSSID, true);
>> +    assert(ret == 0);
>> +
>> +
>> +    s390_set_up_kernel(env, kernel_filename, kernel_cmdline, 
>> initrd_filename);
>> +
>> +    /* Create VirtIO network adapters */
>> +    s390_create_virtio_net((BusState *)ccw_bus, "virtio-net-ccw");
>> +
>> +}
>> +
>> +static QEMUMachine ccw_machine = {
>> +    .name = "s390-ccw-virtio",
>> +    .alias = "s390-ccw",
>> +    .desc = "VirtIO-ccw based S390 machine",
>> +    .init = ccw_init,
>> +    .no_cdrom = 1,
>> +    .no_floppy = 1,
>> +    .no_serial = 1,
>> +    .no_parallel = 1,
>> +    .no_sdcard = 1,
>> +    .use_virtcon = 1,
> 
> The ccw machine should use the ASCII console as default.

In fact, here is a patch doing this based on the code base that this patch set 
was on. It would be nice to include this for the next round of the virtio-ccw 
machine.


Alex

diff --git a/hw/boards.h b/hw/boards.h
index 813d0e5..7ab634a 100644
--- a/hw/boards.h
+++ b/hw/boards.h
@@ -29,6 +29,7 @@ typedef struct QEMUMachine {
     unsigned int no_serial:1,
         no_parallel:1,
         use_virtcon:1,
+        use_sclp:1,
         no_floppy:1,
         no_cdrom:1,
         no_sdcard:1;
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index e03ac52..3b908d6 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -483,7 +483,7 @@ static QEMUMachine ccw_machine = {
     .no_serial = 1,
     .no_parallel = 1,
     .no_sdcard = 1,
-    .use_virtcon = 1,
+    .use_sclp = 1,
     .max_cpus = 255,
     .is_default = 1,
 };
diff --git a/vl.c b/vl.c
index bee122e..803463e 100644
--- a/vl.c
+++ b/vl.c
@@ -176,6 +176,7 @@ int main(int argc, char **argv)
 #define DEFAULT_RAM_SIZE 512
 
 #define MAX_VIRTIO_CONSOLES 1
+#define MAX_SCLP_CONSOLES 1
 
 static const char *data_dir;
 const char *bios_name = NULL;
@@ -203,6 +204,7 @@ int no_quit = 0;
 CharDriverState *serial_hds[MAX_SERIAL_PORTS];
 CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
 CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
+CharDriverState *sclp_hds[MAX_SCLP_CONSOLES];
 int win2k_install_hack = 0;
 int singlestep = 0;
 int smp_cpus = 1;
@@ -272,6 +274,7 @@ static int tcg_tb_size;
 static int default_serial = 1;
 static int default_parallel = 1;
 static int default_virtcon = 1;
+static int default_sclp = 1;
 static int default_monitor = 1;
 static int default_floppy = 1;
 static int default_cdrom = 1;
@@ -2157,6 +2160,7 @@ struct device_config {
         DEV_VIRTCON,   /* -virtioconsole */
         DEV_DEBUGCON,  /* -debugcon */
         DEV_GDB,       /* -gdb, -s */
+        DEV_SCLP,      /* s390 sclp */
     } type;
     const char *cmdline;
     Location loc;
@@ -2275,6 +2279,39 @@ static int virtcon_parse(const char *devname)
     return 0;
 }
 
+static int sclp_parse(const char *devname)
+{
+    QemuOptsList *device = qemu_find_opts("device");
+    static int index = 0;
+    char label[32];
+    QemuOpts *dev_opts;
+
+    if (strcmp(devname, "none") == 0) {
+        return 0;
+    }
+    if (index == MAX_SCLP_CONSOLES) {
+        fprintf(stderr, "qemu: too many sclp consoles\n");
+        exit(1);
+    }
+
+    assert(arch_type == QEMU_ARCH_S390X);
+
+    dev_opts = qemu_opts_create(device, NULL, 0, NULL);
+    qemu_opt_set(dev_opts, "driver", "sclpconsole");
+
+    snprintf(label, sizeof(label), "sclpcon%d", index);
+    sclp_hds[index] = qemu_chr_new(label, devname, NULL);
+    if (!sclp_hds[index]) {
+        fprintf(stderr, "qemu: could not connect sclp console"
+                " to character backend '%s'\n", devname);
+        return -1;
+    }
+    qemu_opt_set(dev_opts, "chardev", label);
+
+    index++;
+    return 0;
+}
+
 static int debugcon_parse(const char *devname)
 {   
     QemuOpts *opts;
@@ -3654,6 +3691,9 @@ int main(int argc, char **argv, char **envp)
     if (!machine->use_virtcon) {
         default_virtcon = 0;
     }
+    if (!machine->use_sclp) {
+        default_sclp = 0;
+    }
     if (machine->no_floppy) {
         default_floppy = 0;
     }
@@ -3671,11 +3711,15 @@ int main(int argc, char **argv, char **envp)
             add_device_config(DEV_SERIAL, "mon:stdio");
         } else if (default_virtcon && default_monitor) {
             add_device_config(DEV_VIRTCON, "mon:stdio");
+        } else if (default_sclp && default_monitor) {
+            add_device_config(DEV_SCLP, "mon:stdio");
         } else {
             if (default_serial)
                 add_device_config(DEV_SERIAL, "stdio");
             if (default_virtcon)
                 add_device_config(DEV_VIRTCON, "stdio");
+            if (default_sclp)
+                add_device_config(DEV_SCLP, "stdio");
             if (default_monitor)
                 monitor_parse("stdio", "readline");
         }
@@ -3688,6 +3732,8 @@ int main(int argc, char **argv, char **envp)
             monitor_parse("vc:80Cx24C", "readline");
         if (default_virtcon)
             add_device_config(DEV_VIRTCON, "vc:80Cx24C");
+        if (default_sclp)
+            add_device_config(DEV_SCLP, "vc:80Cx24C");
     }
 
     socket_init();
@@ -3855,6 +3901,8 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     if (foreach_device_config(DEV_VIRTCON, virtcon_parse) < 0)
         exit(1);
+    if (foreach_device_config(DEV_SCLP, sclp_parse) < 0)
+        exit(1);
     if (foreach_device_config(DEV_DEBUGCON, debugcon_parse) < 0)
         exit(1);
 


reply via email to

[Prev in Thread] Current Thread [Next in Thread]