summaryrefslogtreecommitdiffstats
path: root/qemu/pc-bios/s390-ccw
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/pc-bios/s390-ccw')
-rw-r--r--qemu/pc-bios/s390-ccw/Makefile28
-rw-r--r--qemu/pc-bios/s390-ccw/bootmap.c746
-rw-r--r--qemu/pc-bios/s390-ccw/bootmap.h541
-rw-r--r--qemu/pc-bios/s390-ccw/cio.h342
-rw-r--r--qemu/pc-bios/s390-ccw/main.c111
-rw-r--r--qemu/pc-bios/s390-ccw/s390-ccw.h192
-rw-r--r--qemu/pc-bios/s390-ccw/sclp-ascii.c82
-rw-r--r--qemu/pc-bios/s390-ccw/sclp.h107
-rw-r--r--qemu/pc-bios/s390-ccw/scsi.h184
-rw-r--r--qemu/pc-bios/s390-ccw/start.S65
-rw-r--r--qemu/pc-bios/s390-ccw/virtio-scsi.c342
-rw-r--r--qemu/pc-bios/s390-ccw/virtio-scsi.h72
-rw-r--r--qemu/pc-bios/s390-ccw/virtio.c608
-rw-r--r--qemu/pc-bios/s390-ccw/virtio.h292
14 files changed, 0 insertions, 3712 deletions
diff --git a/qemu/pc-bios/s390-ccw/Makefile b/qemu/pc-bios/s390-ccw/Makefile
deleted file mode 100644
index 4208cb429..000000000
--- a/qemu/pc-bios/s390-ccw/Makefile
+++ /dev/null
@@ -1,28 +0,0 @@
-all: build-all
-# Dummy command so that make thinks it has done something
- @true
-
-include ../../config-host.mak
-include $(SRC_PATH)/rules.mak
-
-$(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw)
-
-.PHONY : all clean build-all
-
-OBJECTS = start.o main.o bootmap.o sclp-ascii.o virtio.o virtio-scsi.o
-CFLAGS += -fPIE -fno-stack-protector -ffreestanding -march=z900
-CFLAGS += -fno-delete-null-pointer-checks -msoft-float
-LDFLAGS += -Wl,-pie -nostdlib
-
-build-all: s390-ccw.img
-
-s390-ccw.elf: $(OBJECTS)
- $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $(OBJECTS)," Building $(TARGET_DIR)$@")
-
-s390-ccw.img: s390-ccw.elf
- $(call quiet-command,strip --strip-unneeded $< -o $@," Stripping $(TARGET_DIR)$@")
-
-$(OBJECTS): Makefile
-
-clean:
- rm -f *.o *.d *.img *.elf *~
diff --git a/qemu/pc-bios/s390-ccw/bootmap.c b/qemu/pc-bios/s390-ccw/bootmap.c
deleted file mode 100644
index 611102e3e..000000000
--- a/qemu/pc-bios/s390-ccw/bootmap.c
+++ /dev/null
@@ -1,746 +0,0 @@
-/*
- * QEMU S390 bootmap interpreter
- *
- * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
- *
- * 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.
- */
-
-#include "s390-ccw.h"
-#include "bootmap.h"
-#include "virtio.h"
-
-#ifdef DEBUG
-/* #define DEBUG_FALLBACK */
-#endif
-
-#ifdef DEBUG_FALLBACK
-#define dputs(txt) \
- do { sclp_print("zipl: " txt); } while (0)
-#else
-#define dputs(fmt, ...) \
- do { } while (0)
-#endif
-
-/* Scratch space */
-static uint8_t sec[MAX_SECTOR_SIZE*4] __attribute__((__aligned__(PAGE_SIZE)));
-
-typedef struct ResetInfo {
- uint32_t ipl_mask;
- uint32_t ipl_addr;
- uint32_t ipl_continue;
-} ResetInfo;
-
-static ResetInfo save;
-
-static void jump_to_IPL_2(void)
-{
- ResetInfo *current = 0;
-
- void (*ipl)(void) = (void *) (uint64_t) current->ipl_continue;
- *current = save;
- ipl(); /* should not return */
-}
-
-static void jump_to_IPL_code(uint64_t address)
-{
- /* store the subsystem information _after_ the bootmap was loaded */
- write_subsystem_identification();
- /*
- * The IPL PSW is at address 0. We also must not overwrite the
- * content of non-BIOS memory after we loaded the guest, so we
- * save the original content and restore it in jump_to_IPL_2.
- */
- ResetInfo *current = 0;
-
- save = *current;
- current->ipl_addr = (uint32_t) (uint64_t) &jump_to_IPL_2;
- current->ipl_continue = address & 0x7fffffff;
-
- debug_print_int("set IPL addr to", current->ipl_continue);
-
- /* Ensure the guest output starts fresh */
- sclp_print("\n");
-
- /*
- * HACK ALERT.
- * We use the load normal reset to keep r15 unchanged. jump_to_IPL_2
- * can then use r15 as its stack pointer.
- */
- asm volatile("lghi 1,1\n\t"
- "diag 1,1,0x308\n\t"
- : : : "1", "memory");
- panic("\n! IPL returns !\n");
-}
-
-/***********************************************************************
- * IPL an ECKD DASD (CDL or LDL/CMS format)
- */
-
-static unsigned char _bprs[8*1024]; /* guessed "max" ECKD sector size */
-static const int max_bprs_entries = sizeof(_bprs) / sizeof(ExtEckdBlockPtr);
-
-static inline void verify_boot_info(BootInfo *bip)
-{
- IPL_assert(magic_match(bip->magic, ZIPL_MAGIC), "No zIPL sig in BootInfo");
- IPL_assert(bip->version == BOOT_INFO_VERSION, "Wrong zIPL version");
- IPL_assert(bip->bp_type == BOOT_INFO_BP_TYPE_IPL, "DASD is not for IPL");
- IPL_assert(bip->dev_type == BOOT_INFO_DEV_TYPE_ECKD, "DASD is not ECKD");
- IPL_assert(bip->flags == BOOT_INFO_FLAGS_ARCH, "Not for this arch");
- IPL_assert(block_size_ok(bip->bp.ipl.bm_ptr.eckd.bptr.size),
- "Bad block size in zIPL section of the 1st record.");
-}
-
-static block_number_t eckd_block_num(BootMapPointer *p)
-{
- const uint64_t sectors = virtio_get_sectors();
- const uint64_t heads = virtio_get_heads();
- const uint64_t cylinder = p->eckd.cylinder
- + ((p->eckd.head & 0xfff0) << 12);
- const uint64_t head = p->eckd.head & 0x000f;
- const block_number_t block = sectors * heads * cylinder
- + sectors * head
- + p->eckd.sector
- - 1; /* block nr starts with zero */
- return block;
-}
-
-static bool eckd_valid_address(BootMapPointer *p)
-{
- const uint64_t head = p->eckd.head & 0x000f;
-
- if (head >= virtio_get_heads()
- || p->eckd.sector > virtio_get_sectors()
- || p->eckd.sector <= 0) {
- return false;
- }
-
- if (!virtio_guessed_disk_nature() &&
- eckd_block_num(p) >= virtio_get_blocks()) {
- return false;
- }
-
- return true;
-}
-
-static block_number_t load_eckd_segments(block_number_t blk, uint64_t *address)
-{
- block_number_t block_nr;
- int j, rc;
- BootMapPointer *bprs = (void *)_bprs;
- bool more_data;
-
- memset(_bprs, FREE_SPACE_FILLER, sizeof(_bprs));
- read_block(blk, bprs, "BPRS read failed");
-
- do {
- more_data = false;
- for (j = 0;; j++) {
- block_nr = eckd_block_num((void *)&(bprs[j].xeckd));
- if (is_null_block_number(block_nr)) { /* end of chunk */
- break;
- }
-
- /* we need the updated blockno for the next indirect entry
- * in the chain, but don't want to advance address
- */
- if (j == (max_bprs_entries - 1)) {
- break;
- }
-
- IPL_assert(block_size_ok(bprs[j].xeckd.bptr.size),
- "bad chunk block size");
- IPL_assert(eckd_valid_address(&bprs[j]), "bad chunk ECKD addr");
-
- if ((bprs[j].xeckd.bptr.count == 0) && unused_space(&(bprs[j+1]),
- sizeof(EckdBlockPtr))) {
- /* This is a "continue" pointer.
- * This ptr should be the last one in the current
- * script section.
- * I.e. the next ptr must point to the unused memory area
- */
- memset(_bprs, FREE_SPACE_FILLER, sizeof(_bprs));
- read_block(block_nr, bprs, "BPRS continuation read failed");
- more_data = true;
- break;
- }
-
- /* Load (count+1) blocks of code at (block_nr)
- * to memory (address).
- */
- rc = virtio_read_many(block_nr, (void *)(*address),
- bprs[j].xeckd.bptr.count+1);
- IPL_assert(rc == 0, "code chunk read failed");
-
- *address += (bprs[j].xeckd.bptr.count+1) * virtio_get_block_size();
- }
- } while (more_data);
- return block_nr;
-}
-
-static void run_eckd_boot_script(block_number_t mbr_block_nr)
-{
- int i;
- block_number_t block_nr;
- uint64_t address;
- ScsiMbr *scsi_mbr = (void *)sec;
- BootMapScript *bms = (void *)sec;
-
- memset(sec, FREE_SPACE_FILLER, sizeof(sec));
- read_block(mbr_block_nr, sec, "Cannot read MBR");
-
- block_nr = eckd_block_num((void *)&(scsi_mbr->blockptr));
-
- memset(sec, FREE_SPACE_FILLER, sizeof(sec));
- read_block(block_nr, sec, "Cannot read Boot Map Script");
-
- for (i = 0; bms->entry[i].type == BOOT_SCRIPT_LOAD; i++) {
- address = bms->entry[i].address.load_address;
- block_nr = eckd_block_num(&(bms->entry[i].blkptr));
-
- do {
- block_nr = load_eckd_segments(block_nr, &address);
- } while (block_nr != -1);
- }
-
- IPL_assert(bms->entry[i].type == BOOT_SCRIPT_EXEC,
- "Unknown script entry type");
- jump_to_IPL_code(bms->entry[i].address.load_address); /* no return */
-}
-
-static void ipl_eckd_cdl(void)
-{
- XEckdMbr *mbr;
- Ipl2 *ipl2 = (void *)sec;
- IplVolumeLabel *vlbl = (void *)sec;
- block_number_t block_nr;
-
- /* we have just read the block #0 and recognized it as "IPL1" */
- sclp_print("CDL\n");
-
- memset(sec, FREE_SPACE_FILLER, sizeof(sec));
- read_block(1, ipl2, "Cannot read IPL2 record at block 1");
-
- mbr = &ipl2->u.x.mbr;
- IPL_assert(magic_match(mbr, ZIPL_MAGIC), "No zIPL section in IPL2 record.");
- IPL_assert(block_size_ok(mbr->blockptr.xeckd.bptr.size),
- "Bad block size in zIPL section of IPL2 record.");
- IPL_assert(mbr->dev_type == DEV_TYPE_ECKD,
- "Non-ECKD device type in zIPL section of IPL2 record.");
-
- /* save pointer to Boot Script */
- block_nr = eckd_block_num((void *)&(mbr->blockptr));
-
- memset(sec, FREE_SPACE_FILLER, sizeof(sec));
- read_block(2, vlbl, "Cannot read Volume Label at block 2");
- IPL_assert(magic_match(vlbl->key, VOL1_MAGIC),
- "Invalid magic of volume label block");
- IPL_assert(magic_match(vlbl->f.key, VOL1_MAGIC),
- "Invalid magic of volser block");
- print_volser(vlbl->f.volser);
-
- run_eckd_boot_script(block_nr);
- /* no return */
-}
-
-static void print_eckd_ldl_msg(ECKD_IPL_mode_t mode)
-{
- LDL_VTOC *vlbl = (void *)sec; /* already read, 3rd block */
- char msg[4] = { '?', '.', '\n', '\0' };
-
- sclp_print((mode == ECKD_CMS) ? "CMS" : "LDL");
- sclp_print(" version ");
- switch (vlbl->LDL_version) {
- case LDL1_VERSION:
- msg[0] = '1';
- break;
- case LDL2_VERSION:
- msg[0] = '2';
- break;
- default:
- msg[0] = vlbl->LDL_version;
- msg[0] &= 0x0f; /* convert EBCDIC */
- msg[0] |= 0x30; /* to ASCII (digit) */
- msg[1] = '?';
- break;
- }
- sclp_print(msg);
- print_volser(vlbl->volser);
-}
-
-static void ipl_eckd_ldl(ECKD_IPL_mode_t mode)
-{
- block_number_t block_nr;
- BootInfo *bip = (void *)(sec + 0x70); /* BootInfo is MBR for LDL */
-
- if (mode != ECKD_LDL_UNLABELED) {
- print_eckd_ldl_msg(mode);
- }
-
- /* DO NOT read BootMap pointer (only one, xECKD) at block #2 */
-
- memset(sec, FREE_SPACE_FILLER, sizeof(sec));
- read_block(0, sec, "Cannot read block 0 to grab boot info.");
- if (mode == ECKD_LDL_UNLABELED) {
- if (!magic_match(bip->magic, ZIPL_MAGIC)) {
- return; /* not applicable layout */
- }
- sclp_print("unlabeled LDL.\n");
- }
- verify_boot_info(bip);
-
- block_nr = eckd_block_num((void *)&(bip->bp.ipl.bm_ptr.eckd.bptr));
- run_eckd_boot_script(block_nr);
- /* no return */
-}
-
-static void print_eckd_msg(void)
-{
- char msg[] = "Using ECKD scheme (block size *****), ";
- char *p = &msg[34], *q = &msg[30];
- int n = virtio_get_block_size();
-
- /* Fill in the block size and show up the message */
- if (n > 0 && n <= 99999) {
- while (n) {
- *p-- = '0' + (n % 10);
- n /= 10;
- }
- while (p >= q) {
- *p-- = ' ';
- }
- }
- sclp_print(msg);
-}
-
-static void ipl_eckd(void)
-{
- ScsiMbr *mbr = (void *)sec;
- LDL_VTOC *vlbl = (void *)sec;
-
- print_eckd_msg();
-
- /* Grab the MBR again */
- memset(sec, FREE_SPACE_FILLER, sizeof(sec));
- read_block(0, mbr, "Cannot read block 0 on DASD");
-
- if (magic_match(mbr->magic, IPL1_MAGIC)) {
- ipl_eckd_cdl(); /* no return */
- }
-
- /* LDL/CMS? */
- memset(sec, FREE_SPACE_FILLER, sizeof(sec));
- read_block(2, vlbl, "Cannot read block 2");
-
- if (magic_match(vlbl->magic, CMS1_MAGIC)) {
- ipl_eckd_ldl(ECKD_CMS); /* no return */
- }
- if (magic_match(vlbl->magic, LNX1_MAGIC)) {
- ipl_eckd_ldl(ECKD_LDL); /* no return */
- }
-
- ipl_eckd_ldl(ECKD_LDL_UNLABELED); /* it still may return */
- /*
- * Ok, it is not a LDL by any means.
- * It still might be a CDL with zero record keys for IPL1 and IPL2
- */
- ipl_eckd_cdl();
-}
-
-/***********************************************************************
- * IPL a SCSI disk
- */
-
-static void zipl_load_segment(ComponentEntry *entry)
-{
- const int max_entries = (MAX_SECTOR_SIZE / sizeof(ScsiBlockPtr));
- ScsiBlockPtr *bprs = (void *)sec;
- const int bprs_size = sizeof(sec);
- block_number_t blockno;
- uint64_t address;
- int i;
- char err_msg[] = "zIPL failed to read BPRS at 0xZZZZZZZZZZZZZZZZ";
- char *blk_no = &err_msg[30]; /* where to print blockno in (those ZZs) */
-
- blockno = entry->data.blockno;
- address = entry->load_address;
-
- debug_print_int("loading segment at block", blockno);
- debug_print_int("addr", address);
-
- do {
- memset(bprs, FREE_SPACE_FILLER, bprs_size);
- fill_hex_val(blk_no, &blockno, sizeof(blockno));
- read_block(blockno, bprs, err_msg);
-
- for (i = 0;; i++) {
- uint64_t *cur_desc = (void *)&bprs[i];
-
- blockno = bprs[i].blockno;
- if (!blockno) {
- break;
- }
-
- /* we need the updated blockno for the next indirect entry in the
- chain, but don't want to advance address */
- if (i == (max_entries - 1)) {
- break;
- }
-
- if (bprs[i].blockct == 0 && unused_space(&bprs[i + 1],
- sizeof(ScsiBlockPtr))) {
- /* This is a "continue" pointer.
- * This ptr is the last one in the current script section.
- * I.e. the next ptr must point to the unused memory area.
- * The blockno is not zero, so the upper loop must continue
- * reading next section of BPRS.
- */
- break;
- }
- address = virtio_load_direct(cur_desc[0], cur_desc[1], 0,
- (void *)address);
- IPL_assert(address != -1, "zIPL load segment failed");
- }
- } while (blockno);
-}
-
-/* Run a zipl program */
-static void zipl_run(ScsiBlockPtr *pte)
-{
- ComponentHeader *header;
- ComponentEntry *entry;
- uint8_t tmp_sec[MAX_SECTOR_SIZE];
-
- read_block(pte->blockno, tmp_sec, "Cannot read header");
- header = (ComponentHeader *)tmp_sec;
-
- IPL_assert(magic_match(tmp_sec, ZIPL_MAGIC), "No zIPL magic in header");
- IPL_assert(header->type == ZIPL_COMP_HEADER_IPL, "Bad header type");
-
- dputs("start loading images\n");
-
- /* Load image(s) into RAM */
- entry = (ComponentEntry *)(&header[1]);
- while (entry->component_type == ZIPL_COMP_ENTRY_LOAD) {
- zipl_load_segment(entry);
-
- entry++;
-
- IPL_assert((uint8_t *)(&entry[1]) <= (tmp_sec + MAX_SECTOR_SIZE),
- "Wrong entry value");
- }
-
- IPL_assert(entry->component_type == ZIPL_COMP_ENTRY_EXEC, "No EXEC entry");
-
- /* should not return */
- jump_to_IPL_code(entry->load_address);
-}
-
-static void ipl_scsi(void)
-{
- ScsiMbr *mbr = (void *)sec;
- uint8_t *ns, *ns_end;
- int program_table_entries = 0;
- const int pte_len = sizeof(ScsiBlockPtr);
- ScsiBlockPtr *prog_table_entry;
-
- /* Grab the MBR */
- memset(sec, FREE_SPACE_FILLER, sizeof(sec));
- read_block(0, mbr, "Cannot read block 0");
-
- if (!magic_match(mbr->magic, ZIPL_MAGIC)) {
- return;
- }
-
- sclp_print("Using SCSI scheme.\n");
- debug_print_int("MBR Version", mbr->version_id);
- IPL_check(mbr->version_id == 1,
- "Unknown MBR layout version, assuming version 1");
- debug_print_int("program table", mbr->blockptr.blockno);
- IPL_assert(mbr->blockptr.blockno, "No Program Table");
-
- /* Parse the program table */
- read_block(mbr->blockptr.blockno, sec,
- "Error reading Program Table");
-
- IPL_assert(magic_match(sec, ZIPL_MAGIC), "No zIPL magic in PT");
-
- ns_end = sec + virtio_get_block_size();
- for (ns = (sec + pte_len); (ns + pte_len) < ns_end; ns += pte_len) {
- prog_table_entry = (ScsiBlockPtr *)ns;
- if (!prog_table_entry->blockno) {
- break;
- }
-
- program_table_entries++;
- }
-
- debug_print_int("program table entries", program_table_entries);
-
- IPL_assert(program_table_entries != 0, "Empty Program Table");
-
- /* Run the default entry */
-
- prog_table_entry = (ScsiBlockPtr *)(sec + pte_len);
-
- zipl_run(prog_table_entry); /* no return */
-}
-
-/***********************************************************************
- * IPL El Torito ISO9660 image or DVD
- */
-
-static bool is_iso_bc_entry_compatible(IsoBcSection *s)
-{
- uint8_t *magic_sec = (uint8_t *)(sec + ISO_SECTOR_SIZE);
-
- if (s->unused || !s->sector_count) {
- return false;
- }
- read_iso_sector(bswap32(s->load_rba), magic_sec,
- "Failed to read image sector 0");
-
- /* Checking bytes 8 - 32 for S390 Linux magic */
- return !_memcmp(magic_sec + 8, linux_s390_magic, 24);
-}
-
-/* Location of the current sector of the directory */
-static uint32_t sec_loc[ISO9660_MAX_DIR_DEPTH];
-/* Offset in the current sector of the directory */
-static uint32_t sec_offset[ISO9660_MAX_DIR_DEPTH];
-/* Remained directory space in bytes */
-static uint32_t dir_rem[ISO9660_MAX_DIR_DEPTH];
-
-static inline uint32_t iso_get_file_size(uint32_t load_rba)
-{
- IsoVolDesc *vd = (IsoVolDesc *)sec;
- IsoDirHdr *cur_record = &vd->vd.primary.rootdir;
- uint8_t *temp = sec + ISO_SECTOR_SIZE;
- int level = 0;
-
- read_iso_sector(ISO_PRIMARY_VD_SECTOR, sec,
- "Failed to read ISO primary descriptor");
- sec_loc[0] = iso_733_to_u32(cur_record->ext_loc);
- dir_rem[0] = 0;
- sec_offset[0] = 0;
-
- while (level >= 0) {
- IPL_assert(sec_offset[level] <= ISO_SECTOR_SIZE,
- "Directory tree structure violation");
-
- cur_record = (IsoDirHdr *)(temp + sec_offset[level]);
-
- if (sec_offset[level] == 0) {
- read_iso_sector(sec_loc[level], temp,
- "Failed to read ISO directory");
- if (dir_rem[level] == 0) {
- /* Skip self and parent records */
- dir_rem[level] = iso_733_to_u32(cur_record->data_len) -
- cur_record->dr_len;
- sec_offset[level] += cur_record->dr_len;
-
- cur_record = (IsoDirHdr *)(temp + sec_offset[level]);
- dir_rem[level] -= cur_record->dr_len;
- sec_offset[level] += cur_record->dr_len;
- continue;
- }
- }
-
- if (!cur_record->dr_len || sec_offset[level] == ISO_SECTOR_SIZE) {
- /* Zero-padding and/or the end of current sector */
- dir_rem[level] -= ISO_SECTOR_SIZE - sec_offset[level];
- sec_offset[level] = 0;
- sec_loc[level]++;
- } else {
- /* The directory record is valid */
- if (load_rba == iso_733_to_u32(cur_record->ext_loc)) {
- return iso_733_to_u32(cur_record->data_len);
- }
-
- dir_rem[level] -= cur_record->dr_len;
- sec_offset[level] += cur_record->dr_len;
-
- if (cur_record->file_flags & 0x2) {
- /* Subdirectory */
- if (level == ISO9660_MAX_DIR_DEPTH - 1) {
- sclp_print("ISO-9660 directory depth limit exceeded\n");
- } else {
- level++;
- sec_loc[level] = iso_733_to_u32(cur_record->ext_loc);
- sec_offset[level] = 0;
- dir_rem[level] = 0;
- continue;
- }
- }
- }
-
- if (dir_rem[level] == 0) {
- /* Nothing remaining */
- level--;
- read_iso_sector(sec_loc[level], temp,
- "Failed to read ISO directory");
- }
- }
-
- return 0;
-}
-
-static void load_iso_bc_entry(IsoBcSection *load)
-{
- IsoBcSection s = *load;
- /*
- * According to spec, extent for each file
- * is padded and ISO_SECTOR_SIZE bytes aligned
- */
- uint32_t blks_to_load = bswap16(s.sector_count) >> ET_SECTOR_SHIFT;
- uint32_t real_size = iso_get_file_size(bswap32(s.load_rba));
-
- if (real_size) {
- /* Round up blocks to load */
- blks_to_load = (real_size + ISO_SECTOR_SIZE - 1) / ISO_SECTOR_SIZE;
- sclp_print("ISO boot image size verified\n");
- } else {
- sclp_print("ISO boot image size could not be verified\n");
- }
-
- read_iso_boot_image(bswap32(s.load_rba),
- (void *)((uint64_t)bswap16(s.load_segment)),
- blks_to_load);
-
- /* Trying to get PSW at zero address */
- if (*((uint64_t *)0) & IPL_PSW_MASK) {
- jump_to_IPL_code((*((uint64_t *)0)) & 0x7fffffff);
- }
-
- /* Try default linux start address */
- jump_to_IPL_code(KERN_IMAGE_START);
-}
-
-static uint32_t find_iso_bc(void)
-{
- IsoVolDesc *vd = (IsoVolDesc *)sec;
- uint32_t block_num = ISO_PRIMARY_VD_SECTOR;
-
- if (virtio_read_many(block_num++, sec, 1)) {
- /* If primary vd cannot be read, there is no boot catalog */
- return 0;
- }
-
- while (is_iso_vd_valid(vd) && vd->type != VOL_DESC_TERMINATOR) {
- if (vd->type == VOL_DESC_TYPE_BOOT) {
- IsoVdElTorito *et = &vd->vd.boot;
-
- if (!_memcmp(&et->el_torito[0], el_torito_magic, 32)) {
- return bswap32(et->bc_offset);
- }
- }
- read_iso_sector(block_num++, sec,
- "Failed to read ISO volume descriptor");
- }
-
- return 0;
-}
-
-static IsoBcSection *find_iso_bc_entry(void)
-{
- IsoBcEntry *e = (IsoBcEntry *)sec;
- uint32_t offset = find_iso_bc();
- int i;
-
- if (!offset) {
- return NULL;
- }
-
- read_iso_sector(offset, sec, "Failed to read El Torito boot catalog");
-
- if (!is_iso_bc_valid(e)) {
- /* The validation entry is mandatory */
- panic("No valid boot catalog found!\n");
- return NULL;
- }
-
- /*
- * Each entry has 32 bytes size, so one sector cannot contain > 64 entries.
- * We consider only boot catalogs with no more than 64 entries.
- */
- for (i = 1; i < ISO_BC_ENTRY_PER_SECTOR; i++) {
- if (e[i].id == ISO_BC_BOOTABLE_SECTION) {
- if (is_iso_bc_entry_compatible(&e[i].body.sect)) {
- return &e[i].body.sect;
- }
- }
- }
-
- panic("No suitable boot entry found on ISO-9660 media!\n");
-
- return NULL;
-}
-
-static void ipl_iso_el_torito(void)
-{
- IsoBcSection *s = find_iso_bc_entry();
-
- if (s) {
- load_iso_bc_entry(s);
- /* no return */
- }
-}
-
-/***********************************************************************
- * Bus specific IPL sequences
- */
-
-static void zipl_load_vblk(void)
-{
- if (virtio_guessed_disk_nature()) {
- virtio_assume_iso9660();
- }
- ipl_iso_el_torito();
-
- if (virtio_guessed_disk_nature()) {
- sclp_print("Using guessed DASD geometry.\n");
- virtio_assume_eckd();
- }
- ipl_eckd();
-}
-
-static void zipl_load_vscsi(void)
-{
- if (virtio_get_block_size() == VIRTIO_ISO_BLOCK_SIZE) {
- /* Is it an ISO image in non-CD drive? */
- ipl_iso_el_torito();
- }
-
- sclp_print("Using guessed DASD geometry.\n");
- virtio_assume_eckd();
- ipl_eckd();
-}
-
-/***********************************************************************
- * IPL starts here
- */
-
-void zipl_load(void)
-{
- if (virtio_get_device()->is_cdrom) {
- ipl_iso_el_torito();
- panic("\n! Cannot IPL this ISO image !\n");
- }
-
- ipl_scsi();
-
- switch (virtio_get_device_type()) {
- case VIRTIO_ID_BLOCK:
- zipl_load_vblk();
- break;
- case VIRTIO_ID_SCSI:
- zipl_load_vscsi();
- break;
- default:
- panic("\n! Unknown IPL device type !\n");
- }
-
- panic("\n* this can never happen *\n");
-}
diff --git a/qemu/pc-bios/s390-ccw/bootmap.h b/qemu/pc-bios/s390-ccw/bootmap.h
deleted file mode 100644
index bea168714..000000000
--- a/qemu/pc-bios/s390-ccw/bootmap.h
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
- * QEMU S390 bootmap interpreter -- declarations
- *
- * Copyright 2014 IBM Corp.
- * Author(s): Eugene (jno) Dvurechenski <jno@linux.vnet.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 _PC_BIOS_S390_CCW_BOOTMAP_H
-#define _PC_BIOS_S390_CCW_BOOTMAP_H
-
-#include "s390-ccw.h"
-#include "virtio.h"
-
-typedef uint64_t block_number_t;
-#define NULL_BLOCK_NR 0xffffffffffffffffULL
-
-#define FREE_SPACE_FILLER '\xAA'
-
-typedef struct ScsiBlockPtr {
- uint64_t blockno;
- uint16_t size;
- uint16_t blockct;
- uint8_t reserved[4];
-} __attribute__ ((packed)) ScsiBlockPtr;
-
-typedef struct FbaBlockPtr {
- uint32_t blockno;
- uint16_t size;
- uint16_t blockct;
-} __attribute__ ((packed)) FbaBlockPtr;
-
-typedef struct EckdBlockPtr {
- uint16_t cylinder; /* cylinder/head/sector is an address of the block */
- uint16_t head;
- uint8_t sector;
- uint16_t size;
- uint8_t count; /* (size_in_blocks-1);
- * it's 0 for TablePtr, ScriptPtr, and SectionPtr */
-} __attribute__ ((packed)) EckdBlockPtr;
-
-typedef struct ExtEckdBlockPtr {
- EckdBlockPtr bptr;
- uint8_t reserved[8];
-} __attribute__ ((packed)) ExtEckdBlockPtr;
-
-typedef union BootMapPointer {
- ScsiBlockPtr scsi;
- FbaBlockPtr fba;
- EckdBlockPtr eckd;
- ExtEckdBlockPtr xeckd;
-} __attribute__ ((packed)) BootMapPointer;
-
-typedef struct ComponentEntry {
- ScsiBlockPtr data;
- uint8_t pad[7];
- uint8_t component_type;
- uint64_t load_address;
-} __attribute((packed)) ComponentEntry;
-
-typedef struct ComponentHeader {
- uint8_t magic[4]; /* == "zIPL" */
- uint8_t type; /* == ZIPL_COMP_HEADER_* */
- uint8_t reserved[27];
-} __attribute((packed)) ComponentHeader;
-
-typedef struct ScsiMbr {
- uint8_t magic[4];
- uint32_t version_id;
- uint8_t reserved[8];
- ScsiBlockPtr blockptr;
-} __attribute__ ((packed)) ScsiMbr;
-
-#define ZIPL_MAGIC "zIPL"
-#define IPL1_MAGIC "\xc9\xd7\xd3\xf1" /* == "IPL1" in EBCDIC */
-#define IPL2_MAGIC "\xc9\xd7\xd3\xf2" /* == "IPL2" in EBCDIC */
-#define VOL1_MAGIC "\xe5\xd6\xd3\xf1" /* == "VOL1" in EBCDIC */
-#define LNX1_MAGIC "\xd3\xd5\xe7\xf1" /* == "LNX1" in EBCDIC */
-#define CMS1_MAGIC "\xc3\xd4\xe2\xf1" /* == "CMS1" in EBCDIC */
-
-#define LDL1_VERSION '\x40' /* == ' ' in EBCDIC */
-#define LDL2_VERSION '\xf2' /* == '2' in EBCDIC */
-
-#define ZIPL_COMP_HEADER_IPL 0x00
-#define ZIPL_COMP_HEADER_DUMP 0x01
-
-#define ZIPL_COMP_ENTRY_LOAD 0x02
-#define ZIPL_COMP_ENTRY_EXEC 0x01
-
-typedef struct XEckdMbr {
- uint8_t magic[4]; /* == "xIPL" */
- uint8_t version;
- uint8_t bp_type;
- uint8_t dev_type; /* == DEV_TYPE_* */
-#define DEV_TYPE_ECKD 0x00
-#define DEV_TYPE_FBA 0x01
- uint8_t flags;
- BootMapPointer blockptr;
- uint8_t reserved[8];
-} __attribute__ ((packed)) XEckdMbr; /* see also BootInfo */
-
-typedef struct BootMapScriptEntry {
- BootMapPointer blkptr;
- uint8_t pad[7];
- uint8_t type; /* == BOOT_SCRIPT_* */
-#define BOOT_SCRIPT_EXEC 0x01
-#define BOOT_SCRIPT_LOAD 0x02
- union {
- uint64_t load_address;
- uint64_t load_psw;
- } address;
-} __attribute__ ((packed)) BootMapScriptEntry;
-
-typedef struct BootMapScriptHeader {
- uint32_t magic;
- uint8_t type;
-#define BOOT_SCRIPT_HDR_IPL 0x00
- uint8_t reserved[27];
-} __attribute__ ((packed)) BootMapScriptHeader;
-
-typedef struct BootMapScript {
- BootMapScriptHeader header;
- BootMapScriptEntry entry[0];
-} __attribute__ ((packed)) BootMapScript;
-
-/*
- * These aren't real VTOCs, but referred to this way in some docs.
- * They are "volume labels" actually.
- *
- * Some structures looks similar to described above, but left
- * separate as there is no indication that they are the same.
- * So, the value definitions are left separate too.
- */
-typedef struct LDL_VTOC { /* @ rec.3 cyl.0 trk.0 for ECKD */
- char magic[4]; /* "LNX1", EBCDIC */
- char volser[6]; /* volser, EBCDIC */
- uint8_t reserved[69]; /* reserved, 0x40 */
- uint8_t LDL_version; /* 0x40 or 0xF2 */
- uint64_t formatted_blocks; /* if LDL_version >= 0xF2 */
-} __attribute__ ((packed)) LDL_VTOC;
-
-typedef struct format_date {
- uint8_t YY;
- uint8_t MM;
- uint8_t DD;
- uint8_t hh;
- uint8_t mm;
- uint8_t ss;
-} __attribute__ ((packed)) format_date_t;
-
-typedef struct CMS_VTOC { /* @ rec.3 cyl.0 trk.0 for ECKD */
- /* @ blk.1 (zero based) for FBA */
- char magic[4]; /* 'CMS1', EBCDIC */
- char volser[6]; /* volser, EBCDIC */
- uint16_t version; /* = 0 */
- uint32_t block_size; /* = 512, 1024, 2048, or 4096 */
- uint32_t disk_origin; /* = 4 or 5 */
- uint32_t blocks; /* Number of usable cyls/blocks */
- uint32_t formatted; /* Max number of fmtd cyls/blks */
- uint32_t CMS_blocks; /* disk size in CMS blocks */
- uint32_t CMS_used; /* Number of CMS blocks in use */
- uint32_t FST_size; /* = 64, bytes */
- uint32_t FST_per_CMS_blk; /* */
- format_date_t format_date; /* YYMMDDhhmmss as 6 bytes */
- uint8_t reserved1[2]; /* = 0 */
- uint32_t offset; /* disk offset when reserved */
- uint32_t next_hole; /* block nr */
- uint32_t HBLK_hole_offset; /* >> HBLK data of next hole */
- uint32_t alloc_map_usr_off; /* >> user part of Alloc map */
- uint8_t reserved2[4]; /* = 0 */
- char shared_seg_name[8]; /* */
-} __attribute__ ((packed)) CMS_VTOC;
-
-/* from zipl/include/boot.h */
-typedef struct BootInfoBpIpl {
- union {
- ExtEckdBlockPtr eckd;
- ScsiBlockPtr linr;
- } bm_ptr;
- uint8_t unused[16];
-} __attribute__ ((packed)) BootInfoBpIpl;
-
-typedef struct EckdDumpParam {
- uint32_t start_blk;
- uint32_t end_blk;
- uint16_t blocksize;
- uint8_t num_heads;
- uint8_t bpt;
- char reserved[4];
-} __attribute((packed, may_alias)) EckdDumpParam;
-
-typedef struct FbaDumpParam {
- uint64_t start_blk;
- uint64_t blockct;
-} __attribute((packed)) FbaDumpParam;
-
-typedef struct BootInfoBpDump {
- union {
- EckdDumpParam eckd;
- FbaDumpParam fba;
- } param;
- uint8_t unused[16];
-} __attribute__ ((packed)) BootInfoBpDump;
-
-typedef struct BootInfo { /* @ 0x70, record #0 */
- unsigned char magic[4]; /* = 'zIPL', ASCII */
- uint8_t version; /* = 1 */
-#define BOOT_INFO_VERSION 1
- uint8_t bp_type; /* = 0 */
-#define BOOT_INFO_BP_TYPE_IPL 0x00
-#define BOOT_INFO_BP_TYPE_DUMP 0x01
- uint8_t dev_type; /* = 0 */
-#define BOOT_INFO_DEV_TYPE_ECKD 0x00
-#define BOOT_INFO_DEV_TYPE_FBA 0x01
- uint8_t flags; /* = 1 */
-#ifdef __s390x__
-#define BOOT_INFO_FLAGS_ARCH 0x01
-#else
-#define BOOT_INFO_FLAGS_ARCH 0x00
-#endif
- union {
- BootInfoBpDump dump;
- BootInfoBpIpl ipl;
- } bp;
-} __attribute__ ((packed)) BootInfo; /* see also XEckdMbr */
-
-typedef struct Ipl1 {
- unsigned char key[4]; /* == "IPL1" */
- unsigned char data[24];
-} __attribute__((packed)) Ipl1;
-
-typedef struct Ipl2 {
- unsigned char key[4]; /* == "IPL2" */
- union {
- unsigned char data[144];
- struct {
- unsigned char reserved1[92-4];
- XEckdMbr mbr;
- unsigned char reserved2[144-(92-4)-sizeof(XEckdMbr)];
- } x;
- } u;
-} __attribute__((packed)) Ipl2;
-
-typedef struct IplVolumeLabel {
- unsigned char key[4]; /* == "VOL1" */
- union {
- unsigned char data[80];
- struct {
- unsigned char key[4]; /* == "VOL1" */
- unsigned char volser[6];
- unsigned char reserved[6];
- } f;
- };
-} __attribute__((packed)) IplVolumeLabel;
-
-typedef enum {
- ECKD_NO_IPL,
- ECKD_CMS,
- ECKD_LDL,
- ECKD_LDL_UNLABELED,
-} ECKD_IPL_mode_t;
-
-/* utility code below */
-
-static const unsigned char ebc2asc[256] =
- /* 0123456789abcdef0123456789abcdef */
- "................................" /* 1F */
- "................................" /* 3F */
- " ...........<(+|&.........!$*);." /* 5F first.chr.here.is.real.space */
- "-/.........,%_>?.........`:#@'=\""/* 7F */
- ".abcdefghi.......jklmnopqr......" /* 9F */
- "..stuvwxyz......................" /* BF */
- ".ABCDEFGHI.......JKLMNOPQR......" /* DF */
- "..STUVWXYZ......0123456789......";/* FF */
-
-static inline void ebcdic_to_ascii(const char *src,
- char *dst,
- unsigned int size)
-{
- unsigned int i;
- for (i = 0; i < size; i++) {
- unsigned c = src[i];
- dst[i] = ebc2asc[c];
- }
-}
-
-static inline void print_volser(const void *volser)
-{
- char ascii[8];
-
- ebcdic_to_ascii((char *)volser, ascii, 6);
- ascii[6] = '\0';
- sclp_print("VOLSER=[");
- sclp_print(ascii);
- sclp_print("]\n");
-}
-
-static inline bool unused_space(const void *p, size_t size)
-{
- size_t i;
- const unsigned char *m = p;
-
- for (i = 0; i < size; i++) {
- if (m[i] != FREE_SPACE_FILLER) {
- return false;
- }
- }
- return true;
-}
-
-static inline bool is_null_block_number(block_number_t x)
-{
- return x == NULL_BLOCK_NR;
-}
-
-static inline void read_block(block_number_t blockno,
- void *buffer,
- const char *errmsg)
-{
- IPL_assert(virtio_read(blockno, buffer) == 0, errmsg);
-}
-
-static inline bool block_size_ok(uint32_t block_size)
-{
- return block_size == virtio_get_block_size();
-}
-
-static inline bool magic_match(const void *data, const void *magic)
-{
- return *((uint32_t *)data) == *((uint32_t *)magic);
-}
-
-static inline int _memcmp(const void *s1, const void *s2, size_t n)
-{
- int i;
- const uint8_t *p1 = s1, *p2 = s2;
-
- for (i = 0; i < n; i++) {
- if (p1[i] != p2[i]) {
- return p1[i] > p2[i] ? 1 : -1;
- }
- }
-
- return 0;
-}
-
-/* from include/qemu/bswap.h */
-
-/* El Torito is always little-endian */
-static inline uint16_t bswap16(uint16_t x)
-{
- return ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8);
-}
-
-static inline uint32_t bswap32(uint32_t x)
-{
- return ((x & 0x000000ffU) << 24) | ((x & 0x0000ff00U) << 8) |
- ((x & 0x00ff0000U) >> 8) | ((x & 0xff000000U) >> 24);
-}
-
-static inline uint64_t bswap64(uint64_t x)
-{
- return ((x & 0x00000000000000ffULL) << 56) |
- ((x & 0x000000000000ff00ULL) << 40) |
- ((x & 0x0000000000ff0000ULL) << 24) |
- ((x & 0x00000000ff000000ULL) << 8) |
- ((x & 0x000000ff00000000ULL) >> 8) |
- ((x & 0x0000ff0000000000ULL) >> 24) |
- ((x & 0x00ff000000000000ULL) >> 40) |
- ((x & 0xff00000000000000ULL) >> 56);
-}
-
-static inline uint32_t iso_733_to_u32(uint64_t x)
-{
- return (uint32_t)x;
-}
-
-#define ISO_SECTOR_SIZE 2048
-/* El Torito specifies boot image size in 512 byte blocks */
-#define ET_SECTOR_SHIFT 2
-#define KERN_IMAGE_START 0x010000UL
-#define PSW_MASK_64 0x0000000100000000ULL
-#define PSW_MASK_32 0x0000000080000000ULL
-#define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64)
-
-#define ISO_PRIMARY_VD_SECTOR 16
-
-static inline void read_iso_sector(uint32_t block_offset, void *buf,
- const char *errmsg)
-{
- IPL_assert(virtio_read_many(block_offset, buf, 1) == 0, errmsg);
-}
-
-static inline void read_iso_boot_image(uint32_t block_offset, void *load_addr,
- uint32_t blks_to_load)
-{
- IPL_assert(virtio_read_many(block_offset, load_addr, blks_to_load) == 0,
- "Failed to read boot image!");
-}
-
-const uint8_t el_torito_magic[] = "EL TORITO SPECIFICATION"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
-
-#define ISO9660_MAX_DIR_DEPTH 8
-
-typedef struct IsoDirHdr {
- uint8_t dr_len;
- uint8_t ear_len;
- uint64_t ext_loc;
- uint64_t data_len;
- uint8_t recording_datetime[7];
- uint8_t file_flags;
- uint8_t file_unit_size;
- uint8_t gap_size;
- uint32_t vol_seqnum;
- uint8_t fileid_len;
-} __attribute__((packed)) IsoDirHdr;
-
-typedef struct IsoVdElTorito {
- uint8_t el_torito[32]; /* must contain el_torito_magic value */
- uint8_t unused0[32];
- uint32_t bc_offset;
- uint8_t unused1[1974];
-} __attribute__((packed)) IsoVdElTorito;
-
-typedef struct IsoVdPrimary {
- uint8_t unused1;
- uint8_t sys_id[32];
- uint8_t vol_id[32];
- uint8_t unused2[8];
- uint64_t vol_space_size;
- uint8_t unused3[32];
- uint32_t vol_set_size;
- uint32_t vol_seqnum;
- uint32_t log_block_size;
- uint64_t path_table_size;
- uint32_t l_path_table;
- uint32_t opt_l_path_table;
- uint32_t m_path_table;
- uint32_t opt_m_path_table;
- IsoDirHdr rootdir;
- uint8_t root_null;
- uint8_t reserved2[1858];
-} __attribute__((packed)) IsoVdPrimary;
-
-typedef struct IsoVolDesc {
- uint8_t type;
- uint8_t ident[5];
- uint8_t version;
- union {
- IsoVdElTorito boot;
- IsoVdPrimary primary;
- } vd;
-} __attribute__((packed)) IsoVolDesc;
-
-const uint8_t vol_desc_magic[] = "CD001";
-#define VOL_DESC_TYPE_BOOT 0
-#define VOL_DESC_TYPE_PRIMARY 1
-#define VOL_DESC_TYPE_SUPPLEMENT 2
-#define VOL_DESC_TYPE_PARTITION 3
-#define VOL_DESC_TERMINATOR 255
-
-static inline bool is_iso_vd_valid(IsoVolDesc *vd)
-{
- return !_memcmp(&vd->ident[0], vol_desc_magic, 5) &&
- vd->version == 0x1 &&
- vd->type <= VOL_DESC_TYPE_PARTITION;
-}
-
-typedef struct IsoBcValid {
- uint8_t platform_id;
- uint16_t reserved;
- uint8_t id[24];
- uint16_t checksum;
- uint8_t key[2];
-} __attribute__((packed)) IsoBcValid;
-
-typedef struct IsoBcSection {
- uint8_t boot_type;
- uint16_t load_segment;
- uint8_t sys_type;
- uint8_t unused;
- uint16_t sector_count;
- uint32_t load_rba;
- uint8_t selection[20];
-} __attribute__((packed)) IsoBcSection;
-
-typedef struct IsoBcHdr {
- uint8_t platform_id;
- uint16_t sect_num;
- uint8_t id[28];
-} __attribute__((packed)) IsoBcHdr;
-
-/*
- * Match two CCWs located after PSW and eight filler bytes.
- * From libmagic and arch/s390/kernel/head.S.
- */
-const uint8_t linux_s390_magic[] = "\x02\x00\x00\x18\x60\x00\x00\x50\x02\x00"
- "\x00\x68\x60\x00\x00\x50\x40\x40\x40\x40"
- "\x40\x40\x40\x40";
-
-typedef struct IsoBcEntry {
- uint8_t id;
- union {
- IsoBcValid valid; /* id == 0x01 */
- IsoBcSection sect; /* id == 0x88 || id == 0x0 */
- IsoBcHdr hdr; /* id == 0x90 || id == 0x91 */
- } body;
-} __attribute__((packed)) IsoBcEntry;
-
-#define ISO_BC_ENTRY_PER_SECTOR (ISO_SECTOR_SIZE / sizeof(IsoBcEntry))
-#define ISO_BC_HDR_VALIDATION 0x01
-#define ISO_BC_BOOTABLE_SECTION 0x88
-#define ISO_BC_MAGIC_55 0x55
-#define ISO_BC_MAGIC_AA 0xaa
-#define ISO_BC_PLATFORM_X86 0x0
-#define ISO_BC_PLATFORM_PPC 0x1
-#define ISO_BC_PLATFORM_MAC 0x2
-
-static inline bool is_iso_bc_valid(IsoBcEntry *e)
-{
- IsoBcValid *v = &e->body.valid;
-
- if (e->id != ISO_BC_HDR_VALIDATION) {
- return false;
- }
-
- if (v->platform_id != ISO_BC_PLATFORM_X86 &&
- v->platform_id != ISO_BC_PLATFORM_PPC &&
- v->platform_id != ISO_BC_PLATFORM_MAC) {
- return false;
- }
-
- return v->key[0] == ISO_BC_MAGIC_55 &&
- v->key[1] == ISO_BC_MAGIC_AA &&
- v->reserved == 0x0;
-}
-
-#endif /* _PC_BIOS_S390_CCW_BOOTMAP_H */
diff --git a/qemu/pc-bios/s390-ccw/cio.h b/qemu/pc-bios/s390-ccw/cio.h
deleted file mode 100644
index f5b4549ea..000000000
--- a/qemu/pc-bios/s390-ccw/cio.h
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * Channel IO definitions
- *
- * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
- *
- * Inspired by various s390 headers in Linux 3.9.
- *
- * 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 CIO_H
-#define CIO_H
-
-/*
- * path management control word
- */
-struct pmcw {
- __u32 intparm; /* interruption parameter */
- __u32 qf : 1; /* qdio facility */
- __u32 w : 1;
- __u32 isc : 3; /* interruption sublass */
- __u32 res5 : 3; /* reserved zeros */
- __u32 ena : 1; /* enabled */
- __u32 lm : 2; /* limit mode */
- __u32 mme : 2; /* measurement-mode enable */
- __u32 mp : 1; /* multipath mode */
- __u32 tf : 1; /* timing facility */
- __u32 dnv : 1; /* device number valid */
- __u32 dev : 16; /* device number */
- __u8 lpm; /* logical path mask */
- __u8 pnom; /* path not operational mask */
- __u8 lpum; /* last path used mask */
- __u8 pim; /* path installed mask */
- __u16 mbi; /* measurement-block index */
- __u8 pom; /* path operational mask */
- __u8 pam; /* path available mask */
- __u8 chpid[8]; /* CHPID 0-7 (if available) */
- __u32 unused1 : 8; /* reserved zeros */
- __u32 st : 3; /* subchannel type */
- __u32 unused2 : 18; /* reserved zeros */
- __u32 mbfc : 1; /* measurement block format control */
- __u32 xmwme : 1; /* extended measurement word mode enable */
- __u32 csense : 1; /* concurrent sense; can be enabled ...*/
- /* ... per MSCH, however, if facility */
- /* ... is not installed, this results */
- /* ... in an operand exception. */
-} __attribute__ ((packed));
-
-/* Target SCHIB configuration. */
-struct schib_config {
- __u64 mba;
- __u32 intparm;
- __u16 mbi;
- __u32 isc:3;
- __u32 ena:1;
- __u32 mme:2;
- __u32 mp:1;
- __u32 csense:1;
- __u32 mbfc:1;
-} __attribute__ ((packed));
-
-struct scsw {
- __u16 flags;
- __u16 ctrl;
- __u32 cpa;
- __u8 dstat;
- __u8 cstat;
- __u16 count;
-} __attribute__ ((packed));
-
-#define SCSW_FCTL_CLEAR_FUNC 0x1000
-#define SCSW_FCTL_HALT_FUNC 0x2000
-#define SCSW_FCTL_START_FUNC 0x4000
-
-/*
- * subchannel information block
- */
-struct schib {
- struct pmcw pmcw; /* path management control word */
- struct scsw scsw; /* subchannel status word */
- __u64 mba; /* measurement block address */
- __u8 mda[4]; /* model dependent area */
-} __attribute__ ((packed,aligned(4)));
-
-struct subchannel_id {
- __u32 cssid : 8;
- __u32 : 4;
- __u32 m : 1;
- __u32 ssid : 2;
- __u32 one : 1;
- __u32 sch_no : 16;
-} __attribute__ ((packed, aligned(4)));
-
-struct chsc_header {
- __u16 length;
- __u16 code;
-} __attribute__((packed));
-
-struct chsc_area_sda {
- struct chsc_header request;
- __u8 reserved1:4;
- __u8 format:4;
- __u8 reserved2;
- __u16 operation_code;
- __u32 reserved3;
- __u32 reserved4;
- __u32 operation_data_area[252];
- struct chsc_header response;
- __u32 reserved5:4;
- __u32 format2:4;
- __u32 reserved6:24;
-} __attribute__((packed));
-
-/*
- * TPI info structure
- */
-struct tpi_info {
- struct subchannel_id schid;
- __u32 intparm; /* interruption parameter */
- __u32 adapter_IO : 1;
- __u32 reserved2 : 1;
- __u32 isc : 3;
- __u32 reserved3 : 12;
- __u32 int_type : 3;
- __u32 reserved4 : 12;
-} __attribute__ ((packed));
-
-/* channel command word (type 1) */
-struct ccw1 {
- __u8 cmd_code;
- __u8 flags;
- __u16 count;
- __u32 cda;
-} __attribute__ ((packed));
-
-#define CCW_FLAG_DC 0x80
-#define CCW_FLAG_CC 0x40
-#define CCW_FLAG_SLI 0x20
-#define CCW_FLAG_SKIP 0x10
-#define CCW_FLAG_PCI 0x08
-#define CCW_FLAG_IDA 0x04
-#define CCW_FLAG_SUSPEND 0x02
-
-#define CCW_CMD_NOOP 0x03
-#define CCW_CMD_BASIC_SENSE 0x04
-#define CCW_CMD_TIC 0x08
-#define CCW_CMD_SENSE_ID 0xe4
-
-#define CCW_CMD_SET_VQ 0x13
-#define CCW_CMD_VDEV_RESET 0x33
-#define CCW_CMD_READ_FEAT 0x12
-#define CCW_CMD_WRITE_FEAT 0x11
-#define CCW_CMD_READ_CONF 0x22
-#define CCW_CMD_WRITE_CONF 0x21
-#define CCW_CMD_WRITE_STATUS 0x31
-#define CCW_CMD_SET_IND 0x43
-#define CCW_CMD_SET_CONF_IND 0x53
-#define CCW_CMD_READ_VQ_CONF 0x32
-
-/*
- * Command-mode operation request block
- */
-struct cmd_orb {
- __u32 intparm; /* interruption parameter */
- __u32 key:4; /* flags, like key, suspend control, etc. */
- __u32 spnd:1; /* suspend control */
- __u32 res1:1; /* reserved */
- __u32 mod:1; /* modification control */
- __u32 sync:1; /* synchronize control */
- __u32 fmt:1; /* format control */
- __u32 pfch:1; /* prefetch control */
- __u32 isic:1; /* initial-status-interruption control */
- __u32 alcc:1; /* address-limit-checking control */
- __u32 ssic:1; /* suppress-suspended-interr. control */
- __u32 res2:1; /* reserved */
- __u32 c64:1; /* IDAW/QDIO 64 bit control */
- __u32 i2k:1; /* IDAW 2/4kB block size control */
- __u32 lpm:8; /* logical path mask */
- __u32 ils:1; /* incorrect length */
- __u32 zero:6; /* reserved zeros */
- __u32 orbx:1; /* ORB extension control */
- __u32 cpa; /* channel program address */
-} __attribute__ ((packed, aligned(4)));
-
-struct ciw {
- __u8 type;
- __u8 command;
- __u16 count;
-};
-
-/*
- * sense-id response buffer layout
- */
-struct senseid {
- /* common part */
- __u8 reserved; /* always 0x'FF' */
- __u16 cu_type; /* control unit type */
- __u8 cu_model; /* control unit model */
- __u16 dev_type; /* device type */
- __u8 dev_model; /* device model */
- __u8 unused; /* padding byte */
- /* extended part */
- struct ciw ciw[62];
-} __attribute__ ((packed, aligned(4)));
-
-/* interruption response block */
-struct irb {
- struct scsw scsw;
- __u32 esw[5];
- __u32 ecw[8];
- __u32 emw[8];
-} __attribute__ ((packed, aligned(4)));
-
-/*
- * Some S390 specific IO instructions as inline
- */
-
-static inline int stsch_err(struct subchannel_id schid, struct schib *addr)
-{
- register struct subchannel_id reg1 asm ("1") = schid;
- int ccode = -EIO;
-
- asm volatile(
- " stsch 0(%3)\n"
- "0: ipm %0\n"
- " srl %0,28\n"
- "1:\n"
- : "+d" (ccode), "=m" (*addr)
- : "d" (reg1), "a" (addr)
- : "cc");
- return ccode;
-}
-
-static inline int msch(struct subchannel_id schid, struct schib *addr)
-{
- register struct subchannel_id reg1 asm ("1") = schid;
- int ccode;
-
- asm volatile(
- " msch 0(%2)\n"
- " ipm %0\n"
- " srl %0,28"
- : "=d" (ccode)
- : "d" (reg1), "a" (addr), "m" (*addr)
- : "cc");
- return ccode;
-}
-
-static inline int msch_err(struct subchannel_id schid, struct schib *addr)
-{
- register struct subchannel_id reg1 asm ("1") = schid;
- int ccode = -EIO;
-
- asm volatile(
- " msch 0(%2)\n"
- "0: ipm %0\n"
- " srl %0,28\n"
- "1:\n"
- : "+d" (ccode)
- : "d" (reg1), "a" (addr), "m" (*addr)
- : "cc");
- return ccode;
-}
-
-static inline int tsch(struct subchannel_id schid, struct irb *addr)
-{
- register struct subchannel_id reg1 asm ("1") = schid;
- int ccode;
-
- asm volatile(
- " tsch 0(%3)\n"
- " ipm %0\n"
- " srl %0,28"
- : "=d" (ccode), "=m" (*addr)
- : "d" (reg1), "a" (addr)
- : "cc");
- return ccode;
-}
-
-static inline int ssch(struct subchannel_id schid, struct cmd_orb *addr)
-{
- register struct subchannel_id reg1 asm("1") = schid;
- int ccode = -EIO;
-
- asm volatile(
- " ssch 0(%2)\n"
- "0: ipm %0\n"
- " srl %0,28\n"
- "1:\n"
- : "+d" (ccode)
- : "d" (reg1), "a" (addr), "m" (*addr)
- : "cc", "memory");
- return ccode;
-}
-
-static inline int csch(struct subchannel_id schid)
-{
- register struct subchannel_id reg1 asm("1") = schid;
- int ccode;
-
- asm volatile(
- " csch\n"
- " ipm %0\n"
- " srl %0,28"
- : "=d" (ccode)
- : "d" (reg1)
- : "cc");
- return ccode;
-}
-
-static inline int tpi(struct tpi_info *addr)
-{
- int ccode;
-
- asm volatile(
- " tpi 0(%2)\n"
- " ipm %0\n"
- " srl %0,28"
- : "=d" (ccode), "=m" (*addr)
- : "a" (addr)
- : "cc");
- return ccode;
-}
-
-static inline int chsc(void *chsc_area)
-{
- typedef struct { char _[4096]; } addr_type;
- int cc;
-
- asm volatile(
- " .insn rre,0xb25f0000,%2,0\n"
- " ipm %0\n"
- " srl %0,28\n"
- : "=d" (cc), "=m" (*(addr_type *) chsc_area)
- : "d" (chsc_area), "m" (*(addr_type *) chsc_area)
- : "cc");
- return cc;
-}
-
-#endif /* CIO_H */
diff --git a/qemu/pc-bios/s390-ccw/main.c b/qemu/pc-bios/s390-ccw/main.c
deleted file mode 100644
index 1c9e0791a..000000000
--- a/qemu/pc-bios/s390-ccw/main.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * S390 virtio-ccw loading program
- *
- * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
- *
- * 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.
- */
-
-#include "s390-ccw.h"
-#include "virtio.h"
-
-char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
-uint64_t boot_value;
-static SubChannelId blk_schid = { .one = 1 };
-
-/*
- * Priniciples of Operations (SA22-7832-09) chapter 17 requires that
- * a subsystem-identification is at 184-187 and bytes 188-191 are zero
- * after list-directed-IPL and ccw-IPL.
- */
-void write_subsystem_identification(void)
-{
- SubChannelId *schid = (SubChannelId *) 184;
- uint32_t *zeroes = (uint32_t *) 188;
-
- *schid = blk_schid;
- *zeroes = 0;
-}
-
-
-void panic(const char *string)
-{
- sclp_print(string);
- disabled_wait();
- while (1) { }
-}
-
-static bool find_dev(Schib *schib, int dev_no)
-{
- int i, r;
-
- for (i = 0; i < 0x10000; i++) {
- blk_schid.sch_no = i;
- r = stsch_err(blk_schid, schib);
- if ((r == 3) || (r == -EIO)) {
- break;
- }
- if (!schib->pmcw.dnv) {
- continue;
- }
- if (!virtio_is_supported(blk_schid)) {
- continue;
- }
- if ((dev_no < 0) || (schib->pmcw.dev == dev_no)) {
- return true;
- }
- }
-
- return false;
-}
-
-static void virtio_setup(uint64_t dev_info)
-{
- Schib schib;
- int ssid;
- bool found = false;
- uint16_t dev_no;
-
- /*
- * We unconditionally enable mss support. In every sane configuration,
- * this will succeed; and even if it doesn't, stsch_err() can deal
- * with the consequences.
- */
- enable_mss_facility();
-
- if (dev_info != -1) {
- dev_no = dev_info & 0xffff;
- debug_print_int("device no. ", dev_no);
- blk_schid.ssid = (dev_info >> 16) & 0x3;
- debug_print_int("ssid ", blk_schid.ssid);
- found = find_dev(&schib, dev_no);
- } else {
- for (ssid = 0; ssid < 0x3; ssid++) {
- blk_schid.ssid = ssid;
- found = find_dev(&schib, -1);
- if (found) {
- break;
- }
- }
- }
-
- IPL_assert(found, "No virtio device found");
-
- virtio_setup_device(blk_schid);
-
- IPL_assert(virtio_ipl_disk_is_valid(), "No valid IPL device detected");
-}
-
-int main(void)
-{
- sclp_setup();
- debug_print_int("boot reg[7] ", boot_value);
- virtio_setup(boot_value);
-
- zipl_load(); /* no return */
-
- panic("Failed to load OS from hard disk\n");
- return 0; /* make compiler happy */
-}
diff --git a/qemu/pc-bios/s390-ccw/s390-ccw.h b/qemu/pc-bios/s390-ccw/s390-ccw.h
deleted file mode 100644
index 616d96738..000000000
--- a/qemu/pc-bios/s390-ccw/s390-ccw.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * S390 CCW boot loader
- *
- * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
- *
- * 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 S390_CCW_H
-#define S390_CCW_H
-
-/* #define DEBUG */
-
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned int u32;
-typedef unsigned long long u64;
-typedef unsigned long ulong;
-typedef long size_t;
-typedef int bool;
-typedef unsigned char uint8_t;
-typedef unsigned short uint16_t;
-typedef unsigned int uint32_t;
-typedef unsigned long long uint64_t;
-typedef unsigned char __u8;
-typedef unsigned short __u16;
-typedef unsigned int __u32;
-typedef unsigned long long __u64;
-
-#define true 1
-#define false 0
-#define PAGE_SIZE 4096
-
-#ifndef EIO
-#define EIO 1
-#endif
-#ifndef EBUSY
-#define EBUSY 2
-#endif
-#ifndef NULL
-#define NULL 0
-#endif
-
-#include "cio.h"
-
-typedef struct irb Irb;
-typedef struct ccw1 Ccw1;
-typedef struct cmd_orb CmdOrb;
-typedef struct schib Schib;
-typedef struct chsc_area_sda ChscAreaSda;
-typedef struct senseid SenseId;
-typedef struct subchannel_id SubChannelId;
-
-/* start.s */
-void disabled_wait(void);
-void consume_sclp_int(void);
-
-/* main.c */
-void panic(const char *string);
-void write_subsystem_identification(void);
-extern char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
-extern uint64_t boot_value;
-
-/* sclp-ascii.c */
-void sclp_print(const char *string);
-void sclp_setup(void);
-
-/* virtio.c */
-unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
- ulong subchan_id, void *load_addr);
-bool virtio_is_supported(SubChannelId schid);
-void virtio_setup_device(SubChannelId schid);
-int virtio_read(ulong sector, void *load_addr);
-int enable_mss_facility(void);
-ulong get_second(void);
-
-/* bootmap.c */
-void zipl_load(void);
-
-static inline void *memset(void *s, int c, size_t n)
-{
- int i;
- unsigned char *p = s;
-
- for (i = 0; i < n; i++) {
- p[i] = c;
- }
-
- return s;
-}
-
-static inline void fill_hex(char *out, unsigned char val)
-{
- const char hex[] = "0123456789abcdef";
-
- out[0] = hex[(val >> 4) & 0xf];
- out[1] = hex[val & 0xf];
-}
-
-static inline void fill_hex_val(char *out, void *ptr, unsigned size)
-{
- unsigned char *value = ptr;
- unsigned int i;
-
- for (i = 0; i < size; i++) {
- fill_hex(&out[i*2], value[i]);
- }
-}
-
-static inline void print_int(const char *desc, u64 addr)
-{
- char out[] = ": 0xffffffffffffffff\n";
-
- fill_hex_val(&out[4], &addr, sizeof(addr));
-
- sclp_print(desc);
- sclp_print(out);
-}
-
-static inline void debug_print_int(const char *desc, u64 addr)
-{
-#ifdef DEBUG
- print_int(desc, addr);
-#endif
-}
-
-static inline void debug_print_addr(const char *desc, void *p)
-{
-#ifdef DEBUG
- debug_print_int(desc, (unsigned int)(unsigned long)p);
-#endif
-}
-
-/***********************************************
- * Hypercall functions *
- ***********************************************/
-
-#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
-
-static inline void yield(void)
-{
- asm volatile ("diag 0,0,0x44"
- : :
- : "memory", "cc");
-}
-
-#define MAX_SECTOR_SIZE 4096
-
-static inline void sleep(unsigned int seconds)
-{
- ulong target = get_second() + seconds;
-
- while (get_second() < target) {
- yield();
- }
-}
-
-static inline void *memcpy(void *s1, const void *s2, size_t n)
-{
- uint8_t *p1 = s1;
- const uint8_t *p2 = s2;
-
- while (n--) {
- p1[n] = p2[n];
- }
- return s1;
-}
-
-static inline void IPL_assert(bool term, const char *message)
-{
- if (!term) {
- sclp_print("\n! ");
- sclp_print(message);
- panic(" !\n"); /* no return */
- }
-}
-
-static inline void IPL_check(bool term, const char *message)
-{
- if (!term) {
- sclp_print("\n! WARNING: ");
- sclp_print(message);
- sclp_print(" !\n");
- }
-}
-
-#endif /* S390_CCW_H */
diff --git a/qemu/pc-bios/s390-ccw/sclp-ascii.c b/qemu/pc-bios/s390-ccw/sclp-ascii.c
deleted file mode 100644
index dc1c3e4f4..000000000
--- a/qemu/pc-bios/s390-ccw/sclp-ascii.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * SCLP ASCII access driver
- *
- * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
- *
- * 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.
- */
-
-#include "s390-ccw.h"
-#include "sclp.h"
-
-static char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096)));
-
-/* Perform service call. Return 0 on success, non-zero otherwise. */
-static int sclp_service_call(unsigned int command, void *sccb)
-{
- int cc;
-
- asm volatile(
- " .insn rre,0xb2200000,%1,%2\n" /* servc %1,%2 */
- " ipm %0\n"
- " srl %0,28"
- : "=&d" (cc) : "d" (command), "a" (__pa(sccb))
- : "cc", "memory");
- consume_sclp_int();
- if (cc == 3)
- return -EIO;
- if (cc == 2)
- return -EBUSY;
- return 0;
-}
-
-static void sclp_set_write_mask(void)
-{
- WriteEventMask *sccb = (void *)_sccb;
-
- sccb->h.length = sizeof(WriteEventMask);
- sccb->mask_length = sizeof(unsigned int);
- sccb->receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
- sccb->cp_receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
- sccb->send_mask = SCLP_EVENT_MASK_MSG_ASCII;
- sccb->cp_send_mask = SCLP_EVENT_MASK_MSG_ASCII;
-
- sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb);
-}
-
-void sclp_setup(void)
-{
- sclp_set_write_mask();
-}
-
-static int _strlen(const char *str)
-{
- int i;
- for (i = 0; *str; i++)
- str++;
- return i;
-}
-
-static void _memcpy(char *dest, const char *src, int len)
-{
- int i;
- for (i = 0; i < len; i++)
- dest[i] = src[i];
-}
-
-void sclp_print(const char *str)
-{
- int len = _strlen(str);
- WriteEventData *sccb = (void *)_sccb;
-
- sccb->h.length = sizeof(WriteEventData) + len;
- sccb->h.function_code = SCLP_FC_NORMAL_WRITE;
- sccb->ebh.length = sizeof(EventBufferHeader) + len;
- sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA;
- sccb->ebh.flags = 0;
- _memcpy(sccb->data, str, len);
-
- sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb);
-}
diff --git a/qemu/pc-bios/s390-ccw/sclp.h b/qemu/pc-bios/s390-ccw/sclp.h
deleted file mode 100644
index 3cbfb7893..000000000
--- a/qemu/pc-bios/s390-ccw/sclp.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * SCLP ASCII access driver
- *
- * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
- *
- * 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 SCLP_H
-#define SCLP_H
-
-/* SCLP command codes */
-#define SCLP_CMDW_READ_SCP_INFO 0x00020001
-#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001
-#define SCLP_CMD_READ_EVENT_DATA 0x00770005
-#define SCLP_CMD_WRITE_EVENT_DATA 0x00760005
-#define SCLP_CMD_READ_EVENT_DATA 0x00770005
-#define SCLP_CMD_WRITE_EVENT_DATA 0x00760005
-#define SCLP_CMD_WRITE_EVENT_MASK 0x00780005
-
-/* SCLP response codes */
-#define SCLP_RC_NORMAL_READ_COMPLETION 0x0010
-#define SCLP_RC_NORMAL_COMPLETION 0x0020
-#define SCLP_RC_INVALID_SCLP_COMMAND 0x01f0
-#define SCLP_RC_CONTAINED_EQUIPMENT_CHECK 0x0340
-#define SCLP_RC_INSUFFICIENT_SCCB_LENGTH 0x0300
-#define SCLP_RC_INVALID_FUNCTION 0x40f0
-#define SCLP_RC_NO_EVENT_BUFFERS_STORED 0x60f0
-#define SCLP_RC_INVALID_SELECTION_MASK 0x70f0
-#define SCLP_RC_INCONSISTENT_LENGTHS 0x72f0
-#define SCLP_RC_EVENT_BUFFER_SYNTAX_ERROR 0x73f0
-#define SCLP_RC_INVALID_MASK_LENGTH 0x74f0
-
-/* Service Call Control Block (SCCB) and its elements */
-
-#define SCCB_SIZE 4096
-
-#define SCLP_VARIABLE_LENGTH_RESPONSE 0x80
-#define SCLP_EVENT_BUFFER_ACCEPTED 0x80
-
-#define SCLP_FC_NORMAL_WRITE 0
-
-typedef struct SCCBHeader {
- uint16_t length;
- uint8_t function_code;
- uint8_t control_mask[3];
- uint16_t response_code;
-} __attribute__((packed)) SCCBHeader;
-
-#define SCCB_DATA_LEN (SCCB_SIZE - sizeof(SCCBHeader))
-
-typedef struct ReadInfo {
- SCCBHeader h;
- uint16_t rnmax;
- uint8_t rnsize;
-} __attribute__((packed)) ReadInfo;
-
-typedef struct SCCB {
- SCCBHeader h;
- char data[SCCB_DATA_LEN];
- } __attribute__((packed)) SCCB;
-
-/* SCLP event types */
-#define SCLP_EVENT_ASCII_CONSOLE_DATA 0x1a
-#define SCLP_EVENT_SIGNAL_QUIESCE 0x1d
-
-/* SCLP event masks */
-#define SCLP_EVENT_MASK_SIGNAL_QUIESCE 0x00000008
-#define SCLP_EVENT_MASK_MSG_ASCII 0x00000040
-
-#define SCLP_UNCONDITIONAL_READ 0x00
-#define SCLP_SELECTIVE_READ 0x01
-
-typedef struct WriteEventMask {
- SCCBHeader h;
- uint16_t _reserved;
- uint16_t mask_length;
- uint32_t cp_receive_mask;
- uint32_t cp_send_mask;
- uint32_t send_mask;
- uint32_t receive_mask;
-} __attribute__((packed)) WriteEventMask;
-
-typedef struct EventBufferHeader {
- uint16_t length;
- uint8_t type;
- uint8_t flags;
- uint16_t _reserved;
-} __attribute__((packed)) EventBufferHeader;
-
-typedef struct WriteEventData {
- SCCBHeader h;
- EventBufferHeader ebh;
- char data[0];
-} __attribute__((packed)) WriteEventData;
-
-typedef struct ReadEventData {
- SCCBHeader h;
- EventBufferHeader ebh;
- uint32_t mask;
-} __attribute__((packed)) ReadEventData;
-
-#define __pa(x) (x)
-
-#endif /* SCLP_H */
diff --git a/qemu/pc-bios/s390-ccw/scsi.h b/qemu/pc-bios/s390-ccw/scsi.h
deleted file mode 100644
index fc830f7e5..000000000
--- a/qemu/pc-bios/s390-ccw/scsi.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * SCSI definitions for s390 machine loader for qemu
- *
- * Copyright 2015 IBM Corp.
- * Author: Eugene "jno" Dvurechenski <jno@linux.vnet.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 SCSI_H
-#define SCSI_H
-
-#include "s390-ccw.h"
-
-#define SCSI_DEFAULT_CDB_SIZE 32
-#define SCSI_DEFAULT_SENSE_SIZE 96
-
-#define CDB_STATUS_GOOD 0
-#define CDB_STATUS_CHECK_CONDITION 0x02U
-#define CDB_STATUS_VALID(status) (((status) & ~0x3eU) == 0)
-
-#define SCSI_SENSE_CODE_MASK 0x7fU
-#define SCSI_SENSE_KEY_MASK 0x0fU
-#define SCSI_SENSE_KEY_NO_SENSE 0
-#define SCSI_SENSE_KEY_UNIT_ATTENTION 6
-
-union ScsiLun {
- uint64_t v64; /* numeric shortcut */
- uint8_t v8[8]; /* generic 8 bytes representation */
- uint16_t v16[4]; /* 4-level big-endian LUN as specified by SAM-2 */
-};
-typedef union ScsiLun ScsiLun;
-
-struct ScsiSense70 {
- uint8_t b0; /* b0 & 7f = resp code (0x70 or 0x71) */
- uint8_t b1, b2; /* b2 & 0f = sense key */
- uint8_t u1[1 * 4 + 1 + 1 * 4]; /* b7 = N - 7 */
- uint8_t additional_sense_code; /* b12 */
- uint8_t additional_sense_code_qualifier; /* b13 */
- uint8_t u2[1 + 3 + 0]; /* up to N (<=252) bytes */
-} __attribute__((packed));
-typedef struct ScsiSense70 ScsiSense70;
-
-/* don't confuse with virtio-scsi response/status fields! */
-
-static inline uint8_t scsi_sense_response(const void *p)
-{
- return ((const ScsiSense70 *)p)->b0 & SCSI_SENSE_CODE_MASK;
-}
-
-static inline uint8_t scsi_sense_key(const void *p)
-{
- return ((const ScsiSense70 *)p)->b2 & SCSI_SENSE_KEY_MASK;
-}
-
-#define SCSI_INQ_RDT_CDROM 0x05
-
-struct ScsiInquiryStd {
- uint8_t peripheral_qdt; /* b0, use (b0 & 0x1f) to get SCSI_INQ_RDT */
- uint8_t b1; /* Removable Media Bit = b1 & 0x80 */
- uint8_t spc_version; /* b2 */
- uint8_t b3; /* b3 & 0x0f == resp_data_fmt == 2, must! */
- uint8_t u1[1 + 1 + 1 + 1 + 8]; /* b4..b15 unused, b4 = (N - 1) */
- char prod_id[16]; /* "QEMU CD-ROM" is here */
- uint8_t u2[4 /* b32..b35 unused, mandatory */
- + 8 + 12 + 1 + 1 + 8 * 2 + 22 /* b36..95 unused, optional*/
- + 0]; /* b96..bN unused, vendor specific */
- /* byte N */
-} __attribute__((packed));
-typedef struct ScsiInquiryStd ScsiInquiryStd;
-
-struct ScsiCdbInquiry {
- uint8_t command; /* b0, == 0x12 */
- uint8_t b1; /* b1, |= 0x01 (evpd) */
- uint8_t b2; /* b2; if evpd==1 */
- uint16_t alloc_len; /* b3, b4 */
- uint8_t control; /* b5 */
-} __attribute__((packed));
-typedef struct ScsiCdbInquiry ScsiCdbInquiry;
-
-struct ScsiCdbRead10 {
- uint8_t command; /* =0x28 */
- uint8_t b1;
- uint32_t lba;
- uint8_t b6;
- uint16_t xfer_length;
- uint8_t control;
-} __attribute__((packed));
-typedef struct ScsiCdbRead10 ScsiCdbRead10;
-
-struct ScsiCdbTestUnitReady {
- uint8_t command; /* =0x00 */
- uint8_t b1_b4[4];
- uint8_t control;
-} __attribute__((packed));
-typedef struct ScsiCdbTestUnitReady ScsiCdbTestUnitReady;
-
-struct ScsiCdbReportLuns {
- uint8_t command; /* =0xa0 */
- uint8_t b1;
- uint8_t select_report; /* =0x02, "all" */
- uint8_t b3_b5[3];
- uint32_t alloc_len;
- uint8_t b10;
- uint8_t control;
-} __attribute__((packed));
-typedef struct ScsiCdbReportLuns ScsiCdbReportLuns;
-
-struct ScsiLunReport {
- uint32_t lun_list_len;
- uint32_t b4_b7;
- ScsiLun lun[1]; /* space for at least 1 lun must be allocated */
-} __attribute__((packed));
-typedef struct ScsiLunReport ScsiLunReport;
-
-struct ScsiCdbReadCapacity16 {
- uint8_t command; /* =0x9e = "service action in 16" */
- uint8_t service_action; /* 5 bits, =0x10 = "read capacity 16" */
- uint64_t b2_b9;
- uint32_t alloc_len;
- uint8_t b14;
- uint8_t control;
-} __attribute__((packed));
-typedef struct ScsiCdbReadCapacity16 ScsiCdbReadCapacity16;
-
-struct ScsiReadCapacity16Data {
- uint64_t ret_lba; /* get it, 0..7 */
- uint32_t lb_len; /* bytes, 8..11 */
- uint8_t u1[2 + 1 * 2 + 16]; /* b12..b31, unused */
-} __attribute__((packed));
-typedef struct ScsiReadCapacity16Data ScsiReadCapacity16Data;
-
-static inline ScsiLun make_lun(uint16_t channel, uint16_t target, uint32_t lun)
-{
- ScsiLun r = { .v64 = 0 };
-
- /* See QEMU code to choose the way to handle LUNs.
- *
- * So, a valid LUN must have (always channel #0):
- * lun[0] == 1
- * lun[1] - target, any value
- * lun[2] == 0 or (LUN, MSB, 0x40 set, 0x80 clear)
- * lun[3] - LUN, LSB, any value
- */
- r.v8[0] = 1;
- r.v8[1] = target & 0xffU;
- r.v8[2] = (lun >> 8) & 0x3fU;
- if (r.v8[2]) {
- r.v8[2] |= 0x40;
- }
- r.v8[3] = lun & 0xffU;
-
- return r;
-}
-
-static inline const char *scsi_cdb_status_msg(uint8_t status)
-{
- static char err_msg[] = "STATUS=XX";
- uint8_t v = status & 0x3eU;
-
- fill_hex_val(err_msg + 7, &v, 1);
- return err_msg;
-}
-
-static inline const char *scsi_cdb_asc_msg(const void *s)
-{
- static char err_msg[] = "RSPN=XX KEY=XX CODE=XX QLFR=XX";
- const ScsiSense70 *p = s;
- uint8_t sr = scsi_sense_response(s);
- uint8_t sk = scsi_sense_key(s);
- uint8_t ac = p->additional_sense_code;
- uint8_t cq = p->additional_sense_code_qualifier;
-
- fill_hex_val(err_msg + 5, &sr, 1);
- fill_hex_val(err_msg + 12, &sk, 1);
- fill_hex_val(err_msg + 20, &ac, 1);
- fill_hex_val(err_msg + 28, &cq, 1);
-
- return err_msg;
-}
-
-#endif /* SCSI_H */
diff --git a/qemu/pc-bios/s390-ccw/start.S b/qemu/pc-bios/s390-ccw/start.S
deleted file mode 100644
index b6dd8c2fb..000000000
--- a/qemu/pc-bios/s390-ccw/start.S
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * First stage boot loader for virtio devices. The compiled output goes
- * into the pc-bios directory of qemu.
- *
- * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
- * Copyright 2013 IBM Corp.
- *
- * 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.
- */
-
- .globl _start
-_start:
-
-larl %r15, stack + 0x8000 /* Set up stack */
-larl %r6, boot_value
-stg %r7, 0(%r6) /* save the boot_value before any function calls */
-j main /* And call C */
-
-/*
- * void disabled_wait(void)
- *
- * stops the current guest cpu.
- */
- .globl disabled_wait
-disabled_wait:
- larl %r1,disabled_wait_psw
- lpswe 0(%r1)
-
-
-/*
- * void consume_sclp_int(void)
- *
- * eats one sclp interrupt
- */
- .globl consume_sclp_int
-consume_sclp_int:
- /* enable service interrupts in cr0 */
- stctg 0,0,0(15)
- oi 6(15), 0x2
- lctlg 0,0,0(15)
- /* prepare external call handler */
- larl %r1, external_new_code
- stg %r1, 0x1b8
- larl %r1, external_new_mask
- mvc 0x1b0(8),0(%r1)
- /* load enabled wait PSW */
- larl %r1, enabled_wait_psw
- lpswe 0(%r1)
-
-external_new_code:
- /* disable service interrupts in cr0 */
- stctg 0,0,0(15)
- ni 6(15), 0xfd
- lctlg 0,0,0(15)
- br 14
-
- .align 8
-disabled_wait_psw:
- .quad 0x0002000180000000,0x0000000000000000
-enabled_wait_psw:
- .quad 0x0302000180000000,0x0000000000000000
-external_new_mask:
- .quad 0x0000000180000000
diff --git a/qemu/pc-bios/s390-ccw/virtio-scsi.c b/qemu/pc-bios/s390-ccw/virtio-scsi.c
deleted file mode 100644
index 3bb48e917..000000000
--- a/qemu/pc-bios/s390-ccw/virtio-scsi.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * Virtio-SCSI implementation for s390 machine loader for qemu
- *
- * Copyright 2015 IBM Corp.
- * Author: Eugene "jno" Dvurechenski <jno@linux.vnet.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.
- */
-
-#include "s390-ccw.h"
-#include "virtio.h"
-#include "scsi.h"
-#include "virtio-scsi.h"
-
-static ScsiDevice default_scsi_device;
-static VirtioScsiCmdReq req;
-static VirtioScsiCmdResp resp;
-
-static uint8_t scsi_inquiry_std_response[256];
-
-static inline void vs_assert(bool term, const char **msgs)
-{
- if (!term) {
- int i = 0;
-
- sclp_print("\n! ");
- while (msgs[i]) {
- sclp_print(msgs[i++]);
- }
- panic(" !\n");
- }
-}
-
-static void virtio_scsi_verify_response(VirtioScsiCmdResp *resp,
- const char *title)
-{
- const char *mr[] = {
- title, ": response ", virtio_scsi_response_msg(resp), 0
- };
- const char *ms[] = {
- title,
- CDB_STATUS_VALID(resp->status) ? ": " : ": invalid ",
- scsi_cdb_status_msg(resp->status),
- resp->status == CDB_STATUS_CHECK_CONDITION ? " " : 0,
- resp->sense_len ? scsi_cdb_asc_msg(resp->sense)
- : "no sense data",
- scsi_sense_response(resp->sense) == 0x70 ? ", sure" : "?",
- 0
- };
-
- vs_assert(resp->response == VIRTIO_SCSI_S_OK, mr);
- vs_assert(resp->status == CDB_STATUS_GOOD, ms);
-}
-
-static void prepare_request(VDev *vdev, const void *cdb, int cdb_size,
- void *data, uint32_t data_size)
-{
- const ScsiDevice *sdev = vdev->scsi_device;
-
- memset(&req, 0, sizeof(req));
- req.lun = make_lun(sdev->channel, sdev->target, sdev->lun);
- memcpy(&req.cdb, cdb, cdb_size);
-
- memset(&resp, 0, sizeof(resp));
- resp.status = 0xff; /* set invalid */
- resp.response = 0xff; /* */
-
- if (data && data_size) {
- memset(data, 0, data_size);
- }
-}
-
-static inline void vs_io_assert(bool term, const char *msg)
-{
- if (!term) {
- virtio_scsi_verify_response(&resp, msg);
- }
-}
-
-static void vs_run(const char *title, VirtioCmd *cmd, VDev *vdev,
- const void *cdb, int cdb_size,
- void *data, uint32_t data_size)
-{
- prepare_request(vdev, cdb, cdb_size, data, data_size);
- vs_io_assert(virtio_run(vdev, VR_REQUEST, cmd) == 0, title);
-}
-
-/* SCSI protocol implementation routines */
-
-static bool scsi_inquiry(VDev *vdev, void *data, uint32_t data_size)
-{
- ScsiCdbInquiry cdb = {
- .command = 0x12,
- .alloc_len = data_size < 65535 ? data_size : 65535,
- };
- VirtioCmd inquiry[] = {
- { &req, sizeof(req), VRING_DESC_F_NEXT },
- { &resp, sizeof(resp), VRING_DESC_F_WRITE | VRING_DESC_F_NEXT },
- { data, data_size, VRING_DESC_F_WRITE },
- };
-
- vs_run("inquiry", inquiry, vdev, &cdb, sizeof(cdb), data, data_size);
-
- return virtio_scsi_response_ok(&resp);
-}
-
-static bool scsi_test_unit_ready(VDev *vdev)
-{
- ScsiCdbTestUnitReady cdb = {
- .command = 0x00,
- };
- VirtioCmd test_unit_ready[] = {
- { &req, sizeof(req), VRING_DESC_F_NEXT },
- { &resp, sizeof(resp), VRING_DESC_F_WRITE },
- };
-
- prepare_request(vdev, &cdb, sizeof(cdb), 0, 0);
- virtio_run(vdev, VR_REQUEST, test_unit_ready); /* ignore errors here */
-
- return virtio_scsi_response_ok(&resp);
-}
-
-static bool scsi_report_luns(VDev *vdev, void *data, uint32_t data_size)
-{
- ScsiCdbReportLuns cdb = {
- .command = 0xa0,
- .select_report = 0x02, /* REPORT ALL */
- .alloc_len = data_size,
- };
- VirtioCmd report_luns[] = {
- { &req, sizeof(req), VRING_DESC_F_NEXT },
- { &resp, sizeof(resp), VRING_DESC_F_WRITE | VRING_DESC_F_NEXT },
- { data, data_size, VRING_DESC_F_WRITE },
- };
-
- vs_run("report luns", report_luns,
- vdev, &cdb, sizeof(cdb), data, data_size);
-
- return virtio_scsi_response_ok(&resp);
-}
-
-static bool scsi_read_10(VDev *vdev,
- ulong sector, int sectors, void *data)
-{
- int f = vdev->blk_factor;
- unsigned int data_size = sectors * virtio_get_block_size() * f;
- ScsiCdbRead10 cdb = {
- .command = 0x28,
- .lba = sector * f,
- .xfer_length = sectors * f,
- };
- VirtioCmd read_10[] = {
- { &req, sizeof(req), VRING_DESC_F_NEXT },
- { &resp, sizeof(resp), VRING_DESC_F_WRITE | VRING_DESC_F_NEXT },
- { data, data_size * f, VRING_DESC_F_WRITE },
- };
-
- debug_print_int("read_10 sector", sector);
- debug_print_int("read_10 sectors", sectors);
-
- vs_run("read(10)", read_10, vdev, &cdb, sizeof(cdb), data, data_size);
-
- return virtio_scsi_response_ok(&resp);
-}
-
-static bool scsi_read_capacity(VDev *vdev,
- void *data, uint32_t data_size)
-{
- ScsiCdbReadCapacity16 cdb = {
- .command = 0x9e, /* SERVICE_ACTION_IN_16 */
- .service_action = 0x10, /* SA_READ_CAPACITY */
- .alloc_len = data_size,
- };
- VirtioCmd read_capacity_16[] = {
- { &req, sizeof(req), VRING_DESC_F_NEXT },
- { &resp, sizeof(resp), VRING_DESC_F_WRITE | VRING_DESC_F_NEXT },
- { data, data_size, VRING_DESC_F_WRITE },
- };
-
- vs_run("read capacity", read_capacity_16,
- vdev, &cdb, sizeof(cdb), data, data_size);
-
- return virtio_scsi_response_ok(&resp);
-}
-
-/* virtio-scsi routines */
-
-static void virtio_scsi_locate_device(VDev *vdev)
-{
- const uint16_t channel = 0; /* again, it's what QEMU does */
- uint16_t target;
- static uint8_t data[16 + 8 * 63];
- ScsiLunReport *r = (void *) data;
- ScsiDevice *sdev = vdev->scsi_device;
- int i, luns;
-
- /* QEMU has hardcoded channel #0 in many places.
- * If this hardcoded value is ever changed, we'll need to add code for
- * vdev->config.scsi.max_channel != 0 here.
- */
- debug_print_int("config.scsi.max_channel", vdev->config.scsi.max_channel);
- debug_print_int("config.scsi.max_target ", vdev->config.scsi.max_target);
- debug_print_int("config.scsi.max_lun ", vdev->config.scsi.max_lun);
-
- for (target = 0; target <= vdev->config.scsi.max_target; target++) {
- sdev->channel = channel;
- sdev->target = target; /* sdev->lun will be 0 here */
- if (!scsi_report_luns(vdev, data, sizeof(data))) {
- if (resp.response == VIRTIO_SCSI_S_BAD_TARGET) {
- continue;
- }
- print_int("target", target);
- virtio_scsi_verify_response(&resp, "SCSI cannot report LUNs");
- }
- if (r->lun_list_len == 0) {
- print_int("no LUNs for target", target);
- continue;
- }
- luns = r->lun_list_len / 8;
- debug_print_int("LUNs reported", luns);
- if (luns == 1) {
- /* There is no ",lun=#" arg for -device or ",lun=0" given.
- * Hence, the only LUN reported.
- * Usually, it's 0.
- */
- sdev->lun = r->lun[0].v16[0]; /* it's returned this way */
- debug_print_int("Have to use LUN", sdev->lun);
- return; /* we have to use this device */
- }
- for (i = 0; i < luns; i++) {
- if (r->lun[i].v64) {
- /* Look for non-zero LUN - we have where to choose from */
- sdev->lun = r->lun[i].v16[0];
- debug_print_int("Will use LUN", sdev->lun);
- return; /* we have found a device */
- }
- }
- }
- panic("\n! Cannot locate virtio-scsi device !\n");
-}
-
-int virtio_scsi_read_many(VDev *vdev,
- ulong sector, void *load_addr, int sec_num)
-{
- if (!scsi_read_10(vdev, sector, sec_num, load_addr)) {
- virtio_scsi_verify_response(&resp, "virtio-scsi:read_many");
- }
-
- return 0;
-}
-
-static bool virtio_scsi_inquiry_response_is_cdrom(void *data)
-{
- const ScsiInquiryStd *response = data;
- const int resp_data_fmt = response->b3 & 0x0f;
- int i;
-
- IPL_check(resp_data_fmt == 2, "Wrong INQUIRY response format");
- if (resp_data_fmt != 2) {
- return false; /* cannot decode */
- }
-
- if ((response->peripheral_qdt & 0x1f) == SCSI_INQ_RDT_CDROM) {
- return true;
- }
-
- for (i = 0; i < sizeof(response->prod_id); i++) {
- if (response->prod_id[i] != QEMU_CDROM_SIGNATURE[i]) {
- return false;
- }
- }
- return true;
-}
-
-static void scsi_parse_capacity_report(void *data,
- uint64_t *last_lba, uint32_t *lb_len)
-{
- ScsiReadCapacity16Data *p = data;
-
- if (last_lba) {
- *last_lba = p->ret_lba;
- }
-
- if (lb_len) {
- *lb_len = p->lb_len;
- }
-}
-
-void virtio_scsi_setup(VDev *vdev)
-{
- int retry_test_unit_ready = 3;
- uint8_t data[256];
- uint32_t data_size = sizeof(data);
-
- vdev->scsi_device = &default_scsi_device;
- virtio_scsi_locate_device(vdev);
-
- /* We have to "ping" the device before it becomes readable */
- while (!scsi_test_unit_ready(vdev)) {
-
- if (!virtio_scsi_response_ok(&resp)) {
- uint8_t code = resp.sense[0] & SCSI_SENSE_CODE_MASK;
- uint8_t sense_key = resp.sense[2] & SCSI_SENSE_KEY_MASK;
-
- IPL_assert(resp.sense_len != 0, "virtio-scsi:setup: no SENSE data");
-
- IPL_assert(retry_test_unit_ready && code == 0x70 &&
- sense_key == SCSI_SENSE_KEY_UNIT_ATTENTION,
- "virtio-scsi:setup: cannot retry");
-
- /* retry on CHECK_CONDITION/UNIT_ATTENTION as it
- * may not designate a real error, but it may be
- * a result of device reset, etc.
- */
- retry_test_unit_ready--;
- sleep(1);
- continue;
- }
-
- virtio_scsi_verify_response(&resp, "virtio-scsi:setup");
- }
-
- /* read and cache SCSI INQUIRY response */
- if (!scsi_inquiry(vdev, scsi_inquiry_std_response,
- sizeof(scsi_inquiry_std_response))) {
- virtio_scsi_verify_response(&resp, "virtio-scsi:setup:inquiry");
- }
-
- if (virtio_scsi_inquiry_response_is_cdrom(scsi_inquiry_std_response)) {
- sclp_print("SCSI CD-ROM detected.\n");
- vdev->is_cdrom = true;
- vdev->scsi_block_size = VIRTIO_ISO_BLOCK_SIZE;
- }
-
- if (!scsi_read_capacity(vdev, data, data_size)) {
- virtio_scsi_verify_response(&resp, "virtio-scsi:setup:read_capacity");
- }
- scsi_parse_capacity_report(data, &vdev->scsi_last_block,
- (uint32_t *) &vdev->scsi_block_size);
-}
diff --git a/qemu/pc-bios/s390-ccw/virtio-scsi.h b/qemu/pc-bios/s390-ccw/virtio-scsi.h
deleted file mode 100644
index f50b38b18..000000000
--- a/qemu/pc-bios/s390-ccw/virtio-scsi.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Virtio-SCSI definitions for s390 machine loader for qemu
- *
- * Copyright 2015 IBM Corp.
- * Author: Eugene "jno" Dvurechenski <jno@linux.vnet.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 VIRTIO_SCSI_H
-#define VIRTIO_SCSI_H
-
-#include "s390-ccw.h"
-#include "virtio.h"
-#include "scsi.h"
-
-#define VIRTIO_SCSI_CDB_SIZE SCSI_DEFAULT_CDB_SIZE
-#define VIRTIO_SCSI_SENSE_SIZE SCSI_DEFAULT_SENSE_SIZE
-
-/* command-specific response values */
-#define VIRTIO_SCSI_S_OK 0x00
-#define VIRTIO_SCSI_S_BAD_TARGET 0x03
-
-#define QEMU_CDROM_SIGNATURE "QEMU CD-ROM "
-
-enum virtio_scsi_vq_id {
- VR_CONTROL = 0,
- VR_EVENT = 1,
- VR_REQUEST = 2,
-};
-
-struct VirtioScsiCmdReq {
- ScsiLun lun;
- uint64_t id;
- uint8_t task_attr; /* = 0 = VIRTIO_SCSI_S_SIMPLE */
- uint8_t prio;
- uint8_t crn; /* = 0 */
- uint8_t cdb[VIRTIO_SCSI_CDB_SIZE];
-} __attribute__((packed));
-typedef struct VirtioScsiCmdReq VirtioScsiCmdReq;
-
-struct VirtioScsiCmdResp {
- uint32_t sense_len;
- uint32_t residual;
- uint16_t status_qualifier;
- uint8_t status; /* first check for .response */
- uint8_t response; /* then for .status */
- uint8_t sense[VIRTIO_SCSI_SENSE_SIZE];
-} __attribute__((packed));
-typedef struct VirtioScsiCmdResp VirtioScsiCmdResp;
-
-static inline const char *virtio_scsi_response_msg(const VirtioScsiCmdResp *r)
-{
- static char err_msg[] = "VS RESP=XX";
- uint8_t v = r->response;
-
- fill_hex_val(err_msg + 8, &v, 1);
- return err_msg;
-}
-
-static inline bool virtio_scsi_response_ok(const VirtioScsiCmdResp *r)
-{
- return r->response == VIRTIO_SCSI_S_OK && r->status == CDB_STATUS_GOOD;
-}
-
-void virtio_scsi_setup(VDev *vdev);
-int virtio_scsi_read_many(VDev *vdev,
- ulong sector, void *load_addr, int sec_num);
-
-#endif /* VIRTIO_SCSI_H */
diff --git a/qemu/pc-bios/s390-ccw/virtio.c b/qemu/pc-bios/s390-ccw/virtio.c
deleted file mode 100644
index 1d34e8c1a..000000000
--- a/qemu/pc-bios/s390-ccw/virtio.c
+++ /dev/null
@@ -1,608 +0,0 @@
-/*
- * Virtio driver bits
- *
- * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
- *
- * 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.
- */
-
-#include "s390-ccw.h"
-#include "virtio.h"
-#include "virtio-scsi.h"
-
-#define VRING_WAIT_REPLY_TIMEOUT 3
-
-static VRing block[VIRTIO_MAX_VQS];
-static char ring_area[VIRTIO_RING_SIZE * VIRTIO_MAX_VQS]
- __attribute__((__aligned__(PAGE_SIZE)));
-
-static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
-
-static VDev vdev = {
- .nr_vqs = 1,
- .vrings = block,
- .cmd_vr_idx = 0,
- .ring_area = ring_area,
- .wait_reply_timeout = VRING_WAIT_REPLY_TIMEOUT,
- .schid = { .one = 1 },
- .scsi_block_size = VIRTIO_SCSI_BLOCK_SIZE,
- .blk_factor = 1,
-};
-
-VDev *virtio_get_device(void)
-{
- return &vdev;
-}
-
-VirtioDevType virtio_get_device_type(void)
-{
- return vdev.senseid.cu_model;
-}
-
-/* virtio spec v1.0 para 4.3.3.2 */
-static long kvm_hypercall(unsigned long nr, unsigned long param1,
- unsigned long param2, unsigned long param3)
-{
- register ulong r_nr asm("1") = nr;
- register ulong r_param1 asm("2") = param1;
- register ulong r_param2 asm("3") = param2;
- register ulong r_param3 asm("4") = param3;
- register long retval asm("2");
-
- asm volatile ("diag 2,4,0x500"
- : "=d" (retval)
- : "d" (r_nr), "0" (r_param1), "r"(r_param2), "d"(r_param3)
- : "memory", "cc");
-
- return retval;
-}
-
-static long virtio_notify(SubChannelId schid, int vq_idx, long cookie)
-{
- return kvm_hypercall(KVM_S390_VIRTIO_CCW_NOTIFY, *(u32 *)&schid,
- vq_idx, cookie);
-}
-
-/***********************************************
- * Virtio functions *
- ***********************************************/
-
-static int drain_irqs(SubChannelId schid)
-{
- Irb irb = {};
- int r = 0;
-
- while (1) {
- /* FIXME: make use of TPI, for that enable subchannel and isc */
- if (tsch(schid, &irb)) {
- /* Might want to differentiate error codes later on. */
- if (irb.scsw.cstat) {
- r = -EIO;
- } else if (irb.scsw.dstat != 0xc) {
- r = -EIO;
- }
- return r;
- }
- }
-}
-
-static int run_ccw(VDev *vdev, int cmd, void *ptr, int len)
-{
- Ccw1 ccw = {};
- CmdOrb orb = {};
- Schib schib;
- int r;
-
- /* start command processing */
- stsch_err(vdev->schid, &schib);
- schib.scsw.ctrl = SCSW_FCTL_START_FUNC;
- msch(vdev->schid, &schib);
-
- /* start subchannel command */
- orb.fmt = 1;
- orb.cpa = (u32)(long)&ccw;
- orb.lpm = 0x80;
-
- ccw.cmd_code = cmd;
- ccw.cda = (long)ptr;
- ccw.count = len;
-
- r = ssch(vdev->schid, &orb);
- /*
- * XXX Wait until device is done processing the CCW. For now we can
- * assume that a simple tsch will have finished the CCW processing,
- * but the architecture allows for asynchronous operation
- */
- if (!r) {
- r = drain_irqs(vdev->schid);
- }
- return r;
-}
-
-static void vring_init(VRing *vr, VqInfo *info)
-{
- void *p = (void *) info->queue;
-
- debug_print_addr("init p", p);
- vr->id = info->index;
- vr->num = info->num;
- vr->desc = p;
- vr->avail = p + info->num * sizeof(VRingDesc);
- vr->used = (void *)(((unsigned long)&vr->avail->ring[info->num]
- + info->align - 1) & ~(info->align - 1));
-
- /* Zero out all relevant field */
- vr->avail->flags = 0;
- vr->avail->idx = 0;
-
- /* We're running with interrupts off anyways, so don't bother */
- vr->used->flags = VRING_USED_F_NO_NOTIFY;
- vr->used->idx = 0;
- vr->used_idx = 0;
- vr->next_idx = 0;
- vr->cookie = 0;
-
- debug_print_addr("init vr", vr);
-}
-
-static bool vring_notify(VRing *vr)
-{
- vr->cookie = virtio_notify(vr->schid, vr->id, vr->cookie);
- return vr->cookie >= 0;
-}
-
-static void vring_send_buf(VRing *vr, void *p, int len, int flags)
-{
- /* For follow-up chains we need to keep the first entry point */
- if (!(flags & VRING_HIDDEN_IS_CHAIN)) {
- vr->avail->ring[vr->avail->idx % vr->num] = vr->next_idx;
- }
-
- vr->desc[vr->next_idx].addr = (ulong)p;
- vr->desc[vr->next_idx].len = len;
- vr->desc[vr->next_idx].flags = flags & ~VRING_HIDDEN_IS_CHAIN;
- vr->desc[vr->next_idx].next = vr->next_idx;
- vr->desc[vr->next_idx].next++;
- vr->next_idx++;
-
- /* Chains only have a single ID */
- if (!(flags & VRING_DESC_F_NEXT)) {
- vr->avail->idx++;
- }
-}
-
-static u64 get_clock(void)
-{
- u64 r;
-
- asm volatile("stck %0" : "=Q" (r) : : "cc");
- return r;
-}
-
-ulong get_second(void)
-{
- return (get_clock() >> 12) / 1000000;
-}
-
-static int vr_poll(VRing *vr)
-{
- if (vr->used->idx == vr->used_idx) {
- vring_notify(vr);
- yield();
- return 0;
- }
-
- vr->used_idx = vr->used->idx;
- vr->next_idx = 0;
- vr->desc[0].len = 0;
- vr->desc[0].flags = 0;
- return 1; /* vr has been updated */
-}
-
-/*
- * Wait for the host to reply.
- *
- * timeout is in seconds if > 0.
- *
- * Returns 0 on success, 1 on timeout.
- */
-static int vring_wait_reply(void)
-{
- ulong target_second = get_second() + vdev.wait_reply_timeout;
-
- /* Wait for any queue to be updated by the host */
- do {
- int i, r = 0;
-
- for (i = 0; i < vdev.nr_vqs; i++) {
- r += vr_poll(&vdev.vrings[i]);
- }
- yield();
- if (r) {
- return 0;
- }
- } while (!vdev.wait_reply_timeout || (get_second() < target_second));
-
- return 1;
-}
-
-int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd)
-{
- VRing *vr = &vdev->vrings[vqid];
- int i = 0;
-
- do {
- vring_send_buf(vr, cmd[i].data, cmd[i].size,
- cmd[i].flags | (i ? VRING_HIDDEN_IS_CHAIN : 0));
- } while (cmd[i++].flags & VRING_DESC_F_NEXT);
-
- vring_wait_reply();
- if (drain_irqs(vr->schid)) {
- return -1;
- }
- return 0;
-}
-
-/***********************************************
- * Virtio block *
- ***********************************************/
-
-static int virtio_blk_read_many(VDev *vdev,
- ulong sector, void *load_addr, int sec_num)
-{
- VirtioBlkOuthdr out_hdr;
- u8 status;
- VRing *vr = &vdev->vrings[vdev->cmd_vr_idx];
-
- /* Tell the host we want to read */
- out_hdr.type = VIRTIO_BLK_T_IN;
- out_hdr.ioprio = 99;
- out_hdr.sector = virtio_sector_adjust(sector);
-
- vring_send_buf(vr, &out_hdr, sizeof(out_hdr), VRING_DESC_F_NEXT);
-
- /* This is where we want to receive data */
- vring_send_buf(vr, load_addr, virtio_get_block_size() * sec_num,
- VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN |
- VRING_DESC_F_NEXT);
-
- /* status field */
- vring_send_buf(vr, &status, sizeof(u8),
- VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN);
-
- /* Now we can tell the host to read */
- vring_wait_reply();
-
- if (drain_irqs(vr->schid)) {
- /* Well, whatever status is supposed to contain... */
- status = 1;
- }
- return status;
-}
-
-int virtio_read_many(ulong sector, void *load_addr, int sec_num)
-{
- switch (vdev.senseid.cu_model) {
- case VIRTIO_ID_BLOCK:
- return virtio_blk_read_many(&vdev, sector, load_addr, sec_num);
- case VIRTIO_ID_SCSI:
- return virtio_scsi_read_many(&vdev, sector, load_addr, sec_num);
- }
- panic("\n! No readable IPL device !\n");
- return -1;
-}
-
-unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
- ulong subchan_id, void *load_addr)
-{
- u8 status;
- int sec = rec_list1;
- int sec_num = ((rec_list2 >> 32) & 0xffff) + 1;
- int sec_len = rec_list2 >> 48;
- ulong addr = (ulong)load_addr;
-
- if (sec_len != virtio_get_block_size()) {
- return -1;
- }
-
- sclp_print(".");
- status = virtio_read_many(sec, (void *)addr, sec_num);
- if (status) {
- panic("I/O Error");
- }
- addr += sec_num * virtio_get_block_size();
-
- return addr;
-}
-
-int virtio_read(ulong sector, void *load_addr)
-{
- return virtio_read_many(sector, load_addr, 1);
-}
-
-/*
- * Other supported value pairs, if any, would need to be added here.
- * Note: head count is always 15.
- */
-static inline u8 virtio_eckd_sectors_for_block_size(int size)
-{
- switch (size) {
- case 512:
- return 49;
- case 1024:
- return 33;
- case 2048:
- return 21;
- case 4096:
- return 12;
- }
- return 0;
-}
-
-VirtioGDN virtio_guessed_disk_nature(void)
-{
- return vdev.guessed_disk_nature;
-}
-
-void virtio_assume_scsi(void)
-{
- switch (vdev.senseid.cu_model) {
- case VIRTIO_ID_BLOCK:
- vdev.guessed_disk_nature = VIRTIO_GDN_SCSI;
- vdev.config.blk.blk_size = VIRTIO_SCSI_BLOCK_SIZE;
- vdev.config.blk.physical_block_exp = 0;
- vdev.blk_factor = 1;
- break;
- case VIRTIO_ID_SCSI:
- vdev.scsi_block_size = VIRTIO_SCSI_BLOCK_SIZE;
- break;
- }
-}
-
-void virtio_assume_iso9660(void)
-{
- switch (vdev.senseid.cu_model) {
- case VIRTIO_ID_BLOCK:
- vdev.guessed_disk_nature = VIRTIO_GDN_SCSI;
- vdev.config.blk.blk_size = VIRTIO_ISO_BLOCK_SIZE;
- vdev.config.blk.physical_block_exp = 0;
- vdev.blk_factor = VIRTIO_ISO_BLOCK_SIZE / VIRTIO_SECTOR_SIZE;
- break;
- case VIRTIO_ID_SCSI:
- vdev.scsi_block_size = VIRTIO_ISO_BLOCK_SIZE;
- break;
- }
-}
-
-void virtio_assume_eckd(void)
-{
- vdev.guessed_disk_nature = VIRTIO_GDN_DASD;
- vdev.blk_factor = 1;
- vdev.config.blk.physical_block_exp = 0;
- switch (vdev.senseid.cu_model) {
- case VIRTIO_ID_BLOCK:
- vdev.config.blk.blk_size = 4096;
- break;
- case VIRTIO_ID_SCSI:
- vdev.config.blk.blk_size = vdev.scsi_block_size;
- break;
- }
- vdev.config.blk.geometry.heads = 15;
- vdev.config.blk.geometry.sectors =
- virtio_eckd_sectors_for_block_size(vdev.config.blk.blk_size);
-}
-
-bool virtio_disk_is_scsi(void)
-{
- if (vdev.guessed_disk_nature == VIRTIO_GDN_SCSI) {
- return true;
- }
- switch (vdev.senseid.cu_model) {
- case VIRTIO_ID_BLOCK:
- return (vdev.config.blk.geometry.heads == 255)
- && (vdev.config.blk.geometry.sectors == 63)
- && (virtio_get_block_size() == VIRTIO_SCSI_BLOCK_SIZE);
- case VIRTIO_ID_SCSI:
- return true;
- }
- return false;
-}
-
-bool virtio_disk_is_eckd(void)
-{
- const int block_size = virtio_get_block_size();
-
- if (vdev.guessed_disk_nature == VIRTIO_GDN_DASD) {
- return true;
- }
- switch (vdev.senseid.cu_model) {
- case VIRTIO_ID_BLOCK:
- return (vdev.config.blk.geometry.heads == 15)
- && (vdev.config.blk.geometry.sectors ==
- virtio_eckd_sectors_for_block_size(block_size));
- case VIRTIO_ID_SCSI:
- return false;
- }
- return false;
-}
-
-bool virtio_ipl_disk_is_valid(void)
-{
- return virtio_disk_is_scsi() || virtio_disk_is_eckd();
-}
-
-int virtio_get_block_size(void)
-{
- switch (vdev.senseid.cu_model) {
- case VIRTIO_ID_BLOCK:
- return vdev.config.blk.blk_size << vdev.config.blk.physical_block_exp;
- case VIRTIO_ID_SCSI:
- return vdev.scsi_block_size;
- }
- return 0;
-}
-
-uint8_t virtio_get_heads(void)
-{
- switch (vdev.senseid.cu_model) {
- case VIRTIO_ID_BLOCK:
- return vdev.config.blk.geometry.heads;
- case VIRTIO_ID_SCSI:
- return vdev.guessed_disk_nature == VIRTIO_GDN_DASD
- ? vdev.config.blk.geometry.heads : 255;
- }
- return 0;
-}
-
-uint8_t virtio_get_sectors(void)
-{
- switch (vdev.senseid.cu_model) {
- case VIRTIO_ID_BLOCK:
- return vdev.config.blk.geometry.sectors;
- case VIRTIO_ID_SCSI:
- return vdev.guessed_disk_nature == VIRTIO_GDN_DASD
- ? vdev.config.blk.geometry.sectors : 63;
- }
- return 0;
-}
-
-uint64_t virtio_get_blocks(void)
-{
- const uint64_t factor = virtio_get_block_size() / VIRTIO_SECTOR_SIZE;
- switch (vdev.senseid.cu_model) {
- case VIRTIO_ID_BLOCK:
- return vdev.config.blk.capacity / factor;
- case VIRTIO_ID_SCSI:
- return vdev.scsi_last_block / factor;
- }
- return 0;
-}
-
-static void virtio_setup_ccw(VDev *vdev)
-{
- int i, cfg_size = 0;
- unsigned char status = VIRTIO_CONFIG_S_DRIVER_OK;
-
- IPL_assert(virtio_is_supported(vdev->schid), "PE");
- /* device ID has been established now */
-
- vdev->config.blk.blk_size = 0; /* mark "illegal" - setup started... */
- vdev->guessed_disk_nature = VIRTIO_GDN_NONE;
-
- run_ccw(vdev, CCW_CMD_VDEV_RESET, NULL, 0);
-
- switch (vdev->senseid.cu_model) {
- case VIRTIO_ID_BLOCK:
- vdev->nr_vqs = 1;
- vdev->cmd_vr_idx = 0;
- cfg_size = sizeof(vdev->config.blk);
- break;
- case VIRTIO_ID_SCSI:
- vdev->nr_vqs = 3;
- vdev->cmd_vr_idx = VR_REQUEST;
- cfg_size = sizeof(vdev->config.scsi);
- break;
- default:
- panic("Unsupported virtio device\n");
- }
- IPL_assert(run_ccw(vdev, CCW_CMD_READ_CONF, &vdev->config, cfg_size) == 0,
- "Could not get block device configuration");
-
- /*
- * Skipping CCW_CMD_READ_FEAT. We're not doing anything fancy, and
- * we'll just stop dead anyway if anything does not work like we
- * expect it.
- */
-
- for (i = 0; i < vdev->nr_vqs; i++) {
- VqInfo info = {
- .queue = (unsigned long long) ring_area + (i * VIRTIO_RING_SIZE),
- .align = KVM_S390_VIRTIO_RING_ALIGN,
- .index = i,
- .num = 0,
- };
- VqConfig config = {
- .index = i,
- .num = 0,
- };
-
- IPL_assert(
- run_ccw(vdev, CCW_CMD_READ_VQ_CONF, &config, sizeof(config)) == 0,
- "Could not get block device VQ configuration");
- info.num = config.num;
- vring_init(&vdev->vrings[i], &info);
- vdev->vrings[i].schid = vdev->schid;
- IPL_assert(run_ccw(vdev, CCW_CMD_SET_VQ, &info, sizeof(info)) == 0,
- "Cannot set VQ info");
- }
- IPL_assert(
- run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status)) == 0,
- "Could not write status to host");
-}
-
-void virtio_setup_device(SubChannelId schid)
-{
- vdev.schid = schid;
- virtio_setup_ccw(&vdev);
-
- switch (vdev.senseid.cu_model) {
- case VIRTIO_ID_BLOCK:
- sclp_print("Using virtio-blk.\n");
- if (!virtio_ipl_disk_is_valid()) {
- /* make sure all getters but blocksize return 0 for
- * invalid IPL disk
- */
- memset(&vdev.config.blk, 0, sizeof(vdev.config.blk));
- virtio_assume_scsi();
- }
- break;
- case VIRTIO_ID_SCSI:
- IPL_assert(vdev.config.scsi.sense_size == VIRTIO_SCSI_SENSE_SIZE,
- "Config: sense size mismatch");
- IPL_assert(vdev.config.scsi.cdb_size == VIRTIO_SCSI_CDB_SIZE,
- "Config: CDB size mismatch");
-
- sclp_print("Using virtio-scsi.\n");
- virtio_scsi_setup(&vdev);
- break;
- default:
- panic("\n! No IPL device available !\n");
- }
-}
-
-bool virtio_is_supported(SubChannelId schid)
-{
- vdev.schid = schid;
- memset(&vdev.senseid, 0, sizeof(vdev.senseid));
- /* run sense id command */
- if (run_ccw(&vdev, CCW_CMD_SENSE_ID, &vdev.senseid, sizeof(vdev.senseid))) {
- return false;
- }
- if (vdev.senseid.cu_type == 0x3832) {
- switch (vdev.senseid.cu_model) {
- case VIRTIO_ID_BLOCK:
- case VIRTIO_ID_SCSI:
- return true;
- }
- }
- return false;
-}
-
-int enable_mss_facility(void)
-{
- int ret;
- ChscAreaSda *sda_area = (ChscAreaSda *) chsc_page;
-
- memset(sda_area, 0, PAGE_SIZE);
- sda_area->request.length = 0x0400;
- sda_area->request.code = 0x0031;
- sda_area->operation_code = 0x2;
-
- ret = chsc(sda_area);
- if ((ret == 0) && (sda_area->response.code == 0x0001)) {
- return 0;
- }
- return -EIO;
-}
diff --git a/qemu/pc-bios/s390-ccw/virtio.h b/qemu/pc-bios/s390-ccw/virtio.h
deleted file mode 100644
index 3c6e91510..000000000
--- a/qemu/pc-bios/s390-ccw/virtio.h
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Virtio driver bits
- *
- * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
- *
- * 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 VIRTIO_H
-#define VIRTIO_H
-
-#include "s390-ccw.h"
-
-/* Status byte for guest to report progress, and synchronize features. */
-/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
-#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
-/* We have found a driver for the device. */
-#define VIRTIO_CONFIG_S_DRIVER 2
-/* Driver has used its parts of the config, and is happy */
-#define VIRTIO_CONFIG_S_DRIVER_OK 4
-/* We've given up on this device. */
-#define VIRTIO_CONFIG_S_FAILED 0x80
-
-enum VirtioDevType {
- VIRTIO_ID_NET = 1,
- VIRTIO_ID_BLOCK = 2,
- VIRTIO_ID_CONSOLE = 3,
- VIRTIO_ID_BALLOON = 5,
- VIRTIO_ID_SCSI = 8,
-};
-typedef enum VirtioDevType VirtioDevType;
-
-struct VirtioDevHeader {
- VirtioDevType type:8;
- uint8_t num_vq;
- uint8_t feature_len;
- uint8_t config_len;
- uint8_t status;
- uint8_t vqconfig[];
-} __attribute__((packed));
-typedef struct VirtioDevHeader VirtioDevHeader;
-
-struct VirtioVqConfig {
- uint64_t token;
- uint64_t address;
- uint16_t num;
- uint8_t pad[6];
-} __attribute__((packed));
-typedef struct VirtioVqConfig VirtioVqConfig;
-
-struct VqInfo {
- uint64_t queue;
- uint32_t align;
- uint16_t index;
- uint16_t num;
-} __attribute__((packed));
-typedef struct VqInfo VqInfo;
-
-struct VqConfig {
- uint16_t index;
- uint16_t num;
-} __attribute__((packed));
-typedef struct VqConfig VqConfig;
-
-struct VirtioDev {
- VirtioDevHeader *header;
- VirtioVqConfig *vqconfig;
- char *host_features;
- char *guest_features;
- char *config;
-};
-typedef struct VirtioDev VirtioDev;
-
-#define VIRTIO_RING_SIZE (PAGE_SIZE * 8)
-#define VIRTIO_MAX_VQS 3
-#define KVM_S390_VIRTIO_RING_ALIGN 4096
-
-#define VRING_USED_F_NO_NOTIFY 1
-
-/* This marks a buffer as continuing via the next field. */
-#define VRING_DESC_F_NEXT 1
-/* This marks a buffer as write-only (otherwise read-only). */
-#define VRING_DESC_F_WRITE 2
-/* This means the buffer contains a list of buffer descriptors. */
-#define VRING_DESC_F_INDIRECT 4
-
-/* Internal flag to mark follow-up segments as such */
-#define VRING_HIDDEN_IS_CHAIN 256
-
-/* Virtio ring descriptors: 16 bytes. These can chain together via "next". */
-struct VRingDesc {
- /* Address (guest-physical). */
- uint64_t addr;
- /* Length. */
- uint32_t len;
- /* The flags as indicated above. */
- uint16_t flags;
- /* We chain unused descriptors via this, too */
- uint16_t next;
-} __attribute__((packed));
-typedef struct VRingDesc VRingDesc;
-
-struct VRingAvail {
- uint16_t flags;
- uint16_t idx;
- uint16_t ring[];
-} __attribute__((packed));
-typedef struct VRingAvail VRingAvail;
-
-/* uint32_t is used here for ids for padding reasons. */
-struct VRingUsedElem {
- /* Index of start of used descriptor chain. */
- uint32_t id;
- /* Total length of the descriptor chain which was used (written to) */
- uint32_t len;
-} __attribute__((packed));
-typedef struct VRingUsedElem VRingUsedElem;
-
-struct VRingUsed {
- uint16_t flags;
- uint16_t idx;
- VRingUsedElem ring[];
-} __attribute__((packed));
-typedef struct VRingUsed VRingUsed;
-
-struct VRing {
- unsigned int num;
- int next_idx;
- int used_idx;
- VRingDesc *desc;
- VRingAvail *avail;
- VRingUsed *used;
- SubChannelId schid;
- long cookie;
- int id;
-};
-typedef struct VRing VRing;
-
-
-/***********************************************
- * Virtio block *
- ***********************************************/
-
-/*
- * Command types
- *
- * Usage is a bit tricky as some bits are used as flags and some are not.
- *
- * Rules:
- * VIRTIO_BLK_T_OUT may be combined with VIRTIO_BLK_T_SCSI_CMD or
- * VIRTIO_BLK_T_BARRIER. VIRTIO_BLK_T_FLUSH is a command of its own
- * and may not be combined with any of the other flags.
- */
-
-/* These two define direction. */
-#define VIRTIO_BLK_T_IN 0
-#define VIRTIO_BLK_T_OUT 1
-
-/* This bit says it's a scsi command, not an actual read or write. */
-#define VIRTIO_BLK_T_SCSI_CMD 2
-
-/* Cache flush command */
-#define VIRTIO_BLK_T_FLUSH 4
-
-/* Barrier before this op. */
-#define VIRTIO_BLK_T_BARRIER 0x80000000
-
-/* This is the first element of the read scatter-gather list. */
-struct VirtioBlkOuthdr {
- /* VIRTIO_BLK_T* */
- uint32_t type;
- /* io priority. */
- uint32_t ioprio;
- /* Sector (ie. 512 byte offset) */
- uint64_t sector;
-};
-typedef struct VirtioBlkOuthdr VirtioBlkOuthdr;
-
-struct VirtioBlkConfig {
- uint64_t capacity; /* in 512-byte sectors */
- uint32_t size_max; /* max segment size (if VIRTIO_BLK_F_SIZE_MAX) */
- uint32_t seg_max; /* max number of segments (if VIRTIO_BLK_F_SEG_MAX) */
-
- struct VirtioBlkGeometry {
- uint16_t cylinders;
- uint8_t heads;
- uint8_t sectors;
- } geometry; /* (if VIRTIO_BLK_F_GEOMETRY) */
-
- uint32_t blk_size; /* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */
-
- /* the next 4 entries are guarded by VIRTIO_BLK_F_TOPOLOGY */
- uint8_t physical_block_exp; /* exponent for physical blk per logical blk */
- uint8_t alignment_offset; /* alignment offset in logical blocks */
- uint16_t min_io_size; /* min I/O size without performance penalty
- in logical blocks */
- uint32_t opt_io_size; /* optimal sustained I/O size in logical blks */
-
- uint8_t wce; /* writeback mode (if VIRTIO_BLK_F_CONFIG_WCE) */
-} __attribute__((packed));
-typedef struct VirtioBlkConfig VirtioBlkConfig;
-
-enum guessed_disk_nature_type {
- VIRTIO_GDN_NONE = 0,
- VIRTIO_GDN_DASD = 1,
- VIRTIO_GDN_CDROM = 2,
- VIRTIO_GDN_SCSI = 3,
-};
-typedef enum guessed_disk_nature_type VirtioGDN;
-
-VirtioGDN virtio_guessed_disk_nature(void);
-void virtio_assume_scsi(void);
-void virtio_assume_eckd(void);
-void virtio_assume_iso9660(void);
-
-extern bool virtio_disk_is_scsi(void);
-extern bool virtio_disk_is_eckd(void);
-extern bool virtio_ipl_disk_is_valid(void);
-extern int virtio_get_block_size(void);
-extern uint8_t virtio_get_heads(void);
-extern uint8_t virtio_get_sectors(void);
-extern uint64_t virtio_get_blocks(void);
-extern int virtio_read_many(ulong sector, void *load_addr, int sec_num);
-
-#define VIRTIO_SECTOR_SIZE 512
-#define VIRTIO_ISO_BLOCK_SIZE 2048
-#define VIRTIO_SCSI_BLOCK_SIZE 512
-
-static inline ulong virtio_sector_adjust(ulong sector)
-{
- return sector * (virtio_get_block_size() / VIRTIO_SECTOR_SIZE);
-}
-
-struct VirtioScsiConfig {
- uint32_t num_queues;
- uint32_t seg_max;
- uint32_t max_sectors;
- uint32_t cmd_per_lun;
- uint32_t event_info_size;
- uint32_t sense_size;
- uint32_t cdb_size;
- uint16_t max_channel;
- uint16_t max_target;
- uint32_t max_lun;
-} __attribute__((packed));
-typedef struct VirtioScsiConfig VirtioScsiConfig;
-
-struct ScsiDevice {
- uint16_t channel; /* Always 0 in QEMU */
- uint16_t target; /* will be scanned over */
- uint32_t lun; /* will be reported */
-};
-typedef struct ScsiDevice ScsiDevice;
-
-struct VDev {
- int nr_vqs;
- VRing *vrings;
- int cmd_vr_idx;
- void *ring_area;
- long wait_reply_timeout;
- VirtioGDN guessed_disk_nature;
- SubChannelId schid;
- SenseId senseid;
- union {
- VirtioBlkConfig blk;
- VirtioScsiConfig scsi;
- } config;
- ScsiDevice *scsi_device;
- bool is_cdrom;
- int scsi_block_size;
- int blk_factor;
- uint64_t scsi_last_block;
- uint32_t scsi_dev_cyls;
- uint8_t scsi_dev_heads;
-};
-typedef struct VDev VDev;
-
-VDev *virtio_get_device(void);
-VirtioDevType virtio_get_device_type(void);
-
-struct VirtioCmd {
- void *data;
- int size;
- int flags;
-};
-typedef struct VirtioCmd VirtioCmd;
-
-int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd);
-
-#endif /* VIRTIO_H */