Annotation of qemu/hw/s390-virtio.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * QEMU S390 virtio target
                      3:  *
                      4:  * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
                      5:  *
                      6:  * This library is free software; you can redistribute it and/or
                      7:  * modify it under the terms of the GNU Lesser General Public
                      8:  * License as published by the Free Software Foundation; either
                      9:  * version 2 of the License, or (at your option) any later version.
                     10:  *
                     11:  * This library is distributed in the hope that it will be useful,
                     12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     14:  * Lesser General Public License for more details.
                     15:  *
                     16:  * You should have received a copy of the GNU Lesser General Public
                     17:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
                     18:  */
                     19: 
                     20: #include "hw.h"
                     21: #include "block.h"
                     22: #include "sysemu.h"
                     23: #include "net.h"
                     24: #include "boards.h"
                     25: #include "monitor.h"
                     26: #include "loader.h"
                     27: #include "elf.h"
                     28: #include "hw/virtio.h"
                     29: #include "hw/virtio-console.h"
                     30: #include "hw/sysbus.h"
                     31: #include "kvm.h"
                     32: 
                     33: #include "hw/s390-virtio-bus.h"
                     34: 
                     35: //#define DEBUG_S390
                     36: 
                     37: #ifdef DEBUG_S390
                     38: #define dprintf(fmt, ...) \
                     39:     do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
                     40: #else
                     41: #define dprintf(fmt, ...) \
                     42:     do { } while (0)
                     43: #endif
                     44: 
                     45: #define KVM_S390_VIRTIO_NOTIFY          0
                     46: #define KVM_S390_VIRTIO_RESET           1
                     47: #define KVM_S390_VIRTIO_SET_STATUS      2
                     48: 
                     49: #define KERN_IMAGE_START                0x010000UL
                     50: #define KERN_PARM_AREA                  0x010480UL
                     51: #define INITRD_START                    0x800000UL
                     52: #define INITRD_PARM_START               0x010408UL
                     53: #define INITRD_PARM_SIZE                0x010410UL
                     54: #define PARMFILE_START                  0x001000UL
                     55: 
                     56: #define MAX_BLK_DEVS                    10
                     57: 
                     58: static VirtIOS390Bus *s390_bus;
                     59: static CPUState **ipi_states;
                     60: 
                     61: void irq_info(Monitor *mon);
                     62: void pic_info(Monitor *mon);
                     63: 
                     64: void irq_info(Monitor *mon)
                     65: {
                     66: }
                     67: 
                     68: void pic_info(Monitor *mon)
                     69: {
                     70: }
                     71: 
                     72: CPUState *s390_cpu_addr2state(uint16_t cpu_addr)
                     73: {
                     74:     if (cpu_addr >= smp_cpus) {
                     75:         return NULL;
                     76:     }
                     77: 
                     78:     return ipi_states[cpu_addr];
                     79: }
                     80: 
                     81: int s390_virtio_hypercall(CPUState *env)
                     82: {
                     83:     int r = 0, i;
                     84:     target_ulong mem = env->regs[2];
                     85: 
                     86:     dprintf("KVM hypercall: %ld\n", env->regs[1]);
                     87:     switch (env->regs[1]) {
                     88:     case KVM_S390_VIRTIO_NOTIFY:
                     89:         if (mem > ram_size) {
                     90:             VirtIOS390Device *dev = s390_virtio_bus_find_vring(s390_bus,
                     91:                                                                mem, &i);
                     92:             if (dev) {
                     93:                 virtio_queue_notify(dev->vdev, i);
                     94:             } else {
                     95:                 r = -EINVAL;
                     96:             }
                     97:         } else {
                     98:             /* Early printk */
                     99:         }
                    100:         break;
                    101:     case KVM_S390_VIRTIO_RESET:
                    102:     {
                    103:         /* Virtio_reset resets the internal addresses, so we'd have to sync
                    104:            them up again. We don't want to reallocate a vring though, so let's
                    105:            just not reset. */
                    106:         /* virtio_reset(dev->vdev); */
                    107:         break;
                    108:     }
                    109:     case KVM_S390_VIRTIO_SET_STATUS:
                    110:     {
                    111:         VirtIOS390Device *dev;
                    112: 
                    113:         dev = s390_virtio_bus_find_mem(s390_bus, mem);
                    114:         if (dev) {
                    115:             s390_virtio_device_update_status(dev);
                    116:         } else {
                    117:             r = -EINVAL;
                    118:         }
                    119:         break;
                    120:     }
                    121:     default:
                    122:         r = -EINVAL;
                    123:         break;
                    124:     }
                    125: 
                    126:     env->regs[2] = r;
                    127:     return 0;
                    128: }
                    129: 
                    130: /* PC hardware initialisation */
                    131: static void s390_init(ram_addr_t ram_size,
                    132:                       const char *boot_device,
                    133:                       const char *kernel_filename,
                    134:                       const char *kernel_cmdline,
                    135:                       const char *initrd_filename,
                    136:                       const char *cpu_model)
                    137: {
                    138:     CPUState *env = NULL;
                    139:     ram_addr_t ram_addr;
                    140:     ram_addr_t kernel_size = 0;
                    141:     ram_addr_t initrd_offset;
                    142:     ram_addr_t initrd_size = 0;
                    143:     int i;
                    144: 
                    145:     /* XXX we only work on KVM for now */
                    146: 
                    147:     if (!kvm_enabled()) {
                    148:         fprintf(stderr, "The S390 target only works with KVM enabled\n");
                    149:         exit(1);
                    150:     }
                    151: 
                    152:     /* get a BUS */
                    153:     s390_bus = s390_virtio_bus_init(&ram_size);
                    154: 
                    155:     /* allocate RAM */
                    156:     ram_addr = qemu_ram_alloc(ram_size);
                    157:     cpu_register_physical_memory(0, ram_size, ram_addr);
                    158: 
                    159:     /* init CPUs */
                    160:     if (cpu_model == NULL) {
                    161:         cpu_model = "host";
                    162:     }
                    163: 
                    164:     ipi_states = qemu_malloc(sizeof(CPUState *) * smp_cpus);
                    165: 
                    166:     for (i = 0; i < smp_cpus; i++) {
                    167:         CPUState *tmp_env;
                    168: 
                    169:         tmp_env = cpu_init(cpu_model);
                    170:         if (!env) {
                    171:             env = tmp_env;
                    172:         }
                    173:         ipi_states[i] = tmp_env;
                    174:         tmp_env->halted = 1;
                    175:         tmp_env->exception_index = EXCP_HLT;
                    176:     }
                    177: 
                    178:     env->halted = 0;
                    179:     env->exception_index = 0;
                    180: 
                    181:     if (kernel_filename) {
                    182:         kernel_size = load_image(kernel_filename, qemu_get_ram_ptr(0));
                    183: 
                    184:         if (lduw_phys(KERN_IMAGE_START) != 0x0dd0) {
                    185:             fprintf(stderr, "Specified image is not an s390 boot image\n");
                    186:             exit(1);
                    187:         }
                    188: 
                    189:         cpu_synchronize_state(env);
                    190:         env->psw.addr = KERN_IMAGE_START;
                    191:         env->psw.mask = 0x0000000180000000ULL;
                    192:     }
                    193: 
                    194:     if (initrd_filename) {
                    195:         initrd_offset = INITRD_START;
                    196:         while (kernel_size + 0x100000 > initrd_offset) {
                    197:             initrd_offset += 0x100000;
                    198:         }
                    199:         initrd_size = load_image(initrd_filename, qemu_get_ram_ptr(initrd_offset));
                    200: 
                    201:         stq_phys(INITRD_PARM_START, initrd_offset);
                    202:         stq_phys(INITRD_PARM_SIZE, initrd_size);
                    203:     }
                    204: 
                    205:     if (kernel_cmdline) {
                    206:         cpu_physical_memory_rw(KERN_PARM_AREA, (uint8_t *)kernel_cmdline,
                    207:                                strlen(kernel_cmdline), 1);
                    208:     }
                    209: 
                    210:     /* Create VirtIO console */
                    211:     for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
                    212:         if (virtcon_hds[i]) {
                    213:             qdev_init_nofail(qdev_create((BusState *)s390_bus, "virtio-console-s390"));
                    214:         }
                    215:     }
                    216: 
                    217:     /* Create VirtIO network adapters */
                    218:     for(i = 0; i < nb_nics; i++) {
                    219:         NICInfo *nd = &nd_table[i];
                    220:         DeviceState *dev;
                    221: 
                    222:         if (!nd->model) {
                    223:             nd->model = qemu_strdup("virtio");
                    224:         }
                    225: 
                    226:         if (strcmp(nd->model, "virtio")) {
                    227:             fprintf(stderr, "S390 only supports VirtIO nics\n");
                    228:             exit(1);
                    229:         }
                    230: 
                    231:         dev = qdev_create((BusState *)s390_bus, "virtio-net-s390");
                    232:         qdev_set_nic_properties(dev, nd);
                    233:         qdev_init_nofail(dev);
                    234:     }
                    235: 
                    236:     /* Create VirtIO disk drives */
                    237:     for(i = 0; i < MAX_BLK_DEVS; i++) {
                    238:         DriveInfo *dinfo;
                    239:         DeviceState *dev;
                    240: 
                    241:         dinfo = drive_get(IF_IDE, 0, i);
                    242:         if (!dinfo) {
                    243:             continue;
                    244:         }
                    245: 
                    246:         dev = qdev_create((BusState *)s390_bus, "virtio-blk-s390");
                    247:         qdev_prop_set_drive(dev, "drive", dinfo);
                    248:         qdev_init_nofail(dev);
                    249:     }
                    250: }
                    251: 
                    252: static QEMUMachine s390_machine = {
                    253:     .name = "s390-virtio",
                    254:     .alias = "s390",
                    255:     .desc = "VirtIO based S390 machine",
                    256:     .init = s390_init,
                    257:     .no_serial = 1,
                    258:     .no_parallel = 1,
                    259:     .use_virtcon = 1,
                    260:     .no_vga = 1,
                    261:     .max_cpus = 255,
                    262:     .is_default = 1,
                    263: };
                    264: 
                    265: static void s390_machine_init(void)
                    266: {
                    267:     qemu_register_machine(&s390_machine);
                    268: }
                    269: 
                    270: machine_init(s390_machine_init);

unix.superglobalmegacorp.com