Hopefully last big batch of s390x patches, including:

- bugfixes for LE host and for pci translation
 - MAINTAINERS update
 - hugetlbfs enablement (kernel patches pending)
 - boot from El Torito iso images on virtio-blk
   (boot from scsi pending)
 - cleanup in the ipl device code
 
 There's also a helper function for resetting busless devices in the
 qdev core in there.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJWQ3/GAAoJEN7Pa5PG8C+vPd0P/0eBJgcmg0fH7clB092Jk9BO
 lnhccPHcFR7gsl6BYZIvmYCnHLLZVC9Sbfgt0qf+7ea0iTgOgL7jSeN5lZ4HwLAm
 w61XIdWy1D4cQpJUz/IcuqQmpMLyZbEbBkCUYlrJ3fXQSP/qnvNK/TSLJEA0W5/T
 bHgCCjNKEyRTtjfXdNB4/WJtSjVd+I5r7DXRJtb6h1XWLyOc8Xy6CSRdArX1A7i1
 Xq17+aPsCcVpLGlqsXcvV2/ekbPCJMUehNrRq3+ji6RjqXfpQ8FpbSK6DTuxKqBk
 OmFYX010ibyoTpIcujvVddDrYeDFX8kWAFGpluIOwHT73qUk18vQt+izyU6GqS19
 CkfT9nU74SQR2ugFshmZ+9u4hMPyfDXgGHwnU6eP6neSDp6eyEGw+MvHOdLxvhIi
 eAP5t3scMvFlyWA2MNopvn9wWx+HO7W/2HRuzrg1gIA0Nu/u2IRVYc+LnQWMlP4f
 8Js1mBCDo3mBmkBpPUn665gOcADuIGzUPl6P9VSu6QyZYUxCoEvFb2xDSRBN2bWU
 zWCaIh/3739ZYXRuOtWMrSpgpwz/YMTehnfKddbjrs4myfc+uxlnNLGYmbwm6xJB
 twu5aCbkOlPwmTmTSTHziQm1l6AYGtxwV8hCTu2dUBhoOtF6ow6vFZ8HDX2P3WyO
 1m3DhTsGSnBTaHnqG/cT
 =c7KM
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20151111' into staging

Hopefully last big batch of s390x patches, including:
- bugfixes for LE host and for pci translation
- MAINTAINERS update
- hugetlbfs enablement (kernel patches pending)
- boot from El Torito iso images on virtio-blk
  (boot from scsi pending)
- cleanup in the ipl device code

There's also a helper function for resetting busless devices in the
qdev core in there.

# gpg: Signature made Wed 11 Nov 2015 17:49:58 GMT using RSA key ID C6F02FAF
# gpg: Good signature from "Cornelia Huck <huckc@linux.vnet.ibm.com>"
# gpg:                 aka "Cornelia Huck <cornelia.huck@de.ibm.com>"

* remotes/cohuck/tags/s390x-20151111:
  s390: deprecate the non-ccw machine in 2.5
  s390x/ipl: switch error reporting to error_setg
  s390x/ipl: clean up qom definitions and turn into TYPE_DEVICE
  qdev: provide qdev_reset_all_fn()
  pc-bios/s390-ccw: rebuild image
  pc-bios/s390-ccw: El Torito 16-bit boot image size field workaround
  pc-bios/s390-ccw: El Torito s390x boot entry check
  pc-bios/s390-ccw: ISO-9660 El Torito boot implementation
  pc-bios/s390-ccw: Always adjust virtio sector count
  s390x/kvm: don't enable CMMA when hugetlbfs will be used
  s390x: switch to memory_region_allocate_system_memory
  MAINTAINERS: update virtio-ccw/s390 git tree
  MAINTAINERS: update s390 file patterns
  s390x/pci : fix up s390 pci iommu translation function
  s390x/css: sense data endianness

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2015-11-11 18:23:08 +00:00
commit 31e49ac192
15 changed files with 506 additions and 77 deletions

View file

@ -237,9 +237,14 @@ M: Cornelia Huck <cornelia.huck@de.ibm.com>
M: Alexander Graf <agraf@suse.de>
S: Maintained
F: target-s390x/kvm.c
F: target-s390x/ioinst.[ch]
F: target-s390x/machine.c
F: hw/intc/s390_flic.c
F: hw/intc/s390_flic_kvm.c
F: include/hw/s390x/s390_flic.h
F: gdb-xml/s390*.xml
T: git git://github.com/cohuck/qemu.git s390-next
T: git git://github.com/borntraeger/qemu.git s390-next
X86
M: Paolo Bonzini <pbonzini@redhat.com>
@ -637,15 +642,13 @@ M: Christian Borntraeger <borntraeger@de.ibm.com>
M: Alexander Graf <agraf@suse.de>
S: Supported
F: hw/char/sclp*.[hc]
F: hw/s390x/s390-virtio-ccw.c
F: hw/s390x/css.[hc]
F: hw/s390x/sclp*.[hc]
F: hw/s390x/ipl*.[hc]
F: hw/s390x/*pci*.[hc]
F: hw/s390x/s390-skeys*.c
F: hw/s390x/
X: hw/s390x/s390-virtio-bus.[ch]
F: include/hw/s390x/
F: pc-bios/s390-ccw/
T: git git://github.com/cohuck/qemu virtio-ccw-upstr
F: hw/watchdog/wdt_diag288.c
T: git git://github.com/cohuck/qemu.git s390-next
T: git git://github.com/borntraeger/qemu.git s390-next
UniCore32 Machines
-------------
@ -872,7 +875,8 @@ M: Cornelia Huck <cornelia.huck@de.ibm.com>
M: Christian Borntraeger <borntraeger@de.ibm.com>
S: Supported
F: hw/s390x/virtio-ccw.[hc]
T: git git://github.com/cohuck/qemu virtio-ccw-upstr
T: git git://github.com/cohuck/qemu.git s390-next
T: git git://github.com/borntraeger/qemu.git s390-next
virtio-input
M: Gerd Hoffmann <kraxel@redhat.com>

View file

@ -325,6 +325,11 @@ void qdev_reset_all(DeviceState *dev)
qdev_walk_children(dev, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
}
void qdev_reset_all_fn(void *opaque)
{
qdev_reset_all(DEVICE(opaque));
}
void qbus_reset_all(BusState *bus)
{
qbus_walk_children(bus, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);

View file

@ -892,8 +892,14 @@ int css_do_tsch_get_irb(SubchDev *sch, IRB *target_irb, int *irb_len)
/* If a unit check is pending, copy sense data. */
if ((s->dstat & SCSW_DSTAT_UNIT_CHECK) &&
(p->chars & PMCW_CHARS_MASK_CSENSE)) {
int i;
irb.scsw.flags |= SCSW_FLAGS_MASK_ESWF | SCSW_FLAGS_MASK_ECTL;
/* Attention: sense_data is already BE! */
memcpy(irb.ecw, sch->sense_data, sizeof(sch->sense_data));
for (i = 0; i < ARRAY_SIZE(irb.ecw); i++) {
irb.ecw[i] = be32_to_cpu(irb.ecw[i]);
}
irb.esw[1] = 0x01000000 | (sizeof(sch->sense_data) << 8);
}
}

View file

@ -15,7 +15,6 @@
#include "cpu.h"
#include "elf.h"
#include "hw/loader.h"
#include "hw/sysbus.h"
#include "hw/s390x/virtio-ccw.h"
#include "hw/s390x/css.h"
#include "ipl.h"
@ -29,44 +28,6 @@
#define ZIPL_IMAGE_START 0x009000UL
#define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64)
#define TYPE_S390_IPL "s390-ipl"
#define S390_IPL(obj) \
OBJECT_CHECK(S390IPLState, (obj), TYPE_S390_IPL)
#if 0
#define S390_IPL_CLASS(klass) \
OBJECT_CLASS_CHECK(S390IPLState, (klass), TYPE_S390_IPL)
#define S390_IPL_GET_CLASS(obj) \
OBJECT_GET_CLASS(S390IPLState, (obj), TYPE_S390_IPL)
#endif
typedef struct S390IPLClass {
/*< private >*/
SysBusDeviceClass parent_class;
/*< public >*/
void (*parent_reset) (SysBusDevice *dev);
} S390IPLClass;
typedef struct S390IPLState {
/*< private >*/
SysBusDevice parent_obj;
uint64_t start_addr;
uint64_t bios_start_addr;
bool enforce_bios;
IplParameterBlock iplb;
bool iplb_valid;
bool reipl_requested;
/*< public >*/
char *kernel;
char *initrd;
char *cmdline;
char *firmware;
uint8_t cssid;
uint8_t ssid;
uint16_t devno;
} S390IPLState;
static const VMStateDescription vmstate_iplb = {
.name = "ipl/iplb",
.version_id = 0,
@ -110,11 +71,12 @@ static uint64_t bios_translate_addr(void *opaque, uint64_t srcaddr)
return srcaddr + dstaddr;
}
static int s390_ipl_init(SysBusDevice *dev)
static void s390_ipl_realize(DeviceState *dev, Error **errp)
{
S390IPLState *ipl = S390_IPL(dev);
uint64_t pentry = KERN_IMAGE_START;
int kernel_size;
Error *l_err = NULL;
int bios_size;
char *bios_filename;
@ -132,7 +94,8 @@ static int s390_ipl_init(SysBusDevice *dev)
bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (bios_filename == NULL) {
hw_error("could not find stage1 bootloader\n");
error_setg(&l_err, "could not find stage1 bootloader\n");
goto error;
}
bios_size = load_elf(bios_filename, bios_translate_addr, &fwbase,
@ -150,7 +113,8 @@ static int s390_ipl_init(SysBusDevice *dev)
g_free(bios_filename);
if (bios_size == -1) {
hw_error("could not load bootloader '%s'\n", bios_name);
error_setg(&l_err, "could not load bootloader '%s'\n", bios_name);
goto error;
}
/* default boot target is the bios */
@ -164,8 +128,8 @@ static int s390_ipl_init(SysBusDevice *dev)
kernel_size = load_image_targphys(ipl->kernel, 0, ram_size);
}
if (kernel_size < 0) {
fprintf(stderr, "could not load kernel '%s'\n", ipl->kernel);
return -1;
error_setg(&l_err, "could not load kernel '%s'\n", ipl->kernel);
goto error;
}
/*
* Is it a Linux kernel (starting at 0x10000)? If yes, we fill in the
@ -192,9 +156,8 @@ static int s390_ipl_init(SysBusDevice *dev)
initrd_size = load_image_targphys(ipl->initrd, initrd_offset,
ram_size - initrd_offset);
if (initrd_size == -1) {
fprintf(stderr, "qemu: could not load initrd '%s'\n",
ipl->initrd);
exit(1);
error_setg(&l_err, "could not load initrd '%s'\n", ipl->initrd);
goto error;
}
/*
@ -205,7 +168,9 @@ static int s390_ipl_init(SysBusDevice *dev)
stq_p(rom_ptr(INITRD_PARM_SIZE), initrd_size);
}
}
return 0;
qemu_register_reset(qdev_reset_all_fn, dev);
error:
error_propagate(errp, l_err);
}
static Property s390_ipl_properties[] = {
@ -308,9 +273,8 @@ static void s390_ipl_reset(DeviceState *dev)
static void s390_ipl_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = s390_ipl_init;
dc->realize = s390_ipl_realize;
dc->props = s390_ipl_properties;
dc->reset = s390_ipl_reset;
dc->vmsd = &vmstate_ipl;
@ -319,8 +283,8 @@ static void s390_ipl_class_init(ObjectClass *klass, void *data)
static const TypeInfo s390_ipl_info = {
.class_init = s390_ipl_class_init,
.parent = TYPE_SYS_BUS_DEVICE,
.name = "s390-ipl",
.parent = TYPE_DEVICE,
.name = TYPE_S390_IPL,
.instance_size = sizeof(S390IPLState),
};

View file

@ -12,6 +12,7 @@
#ifndef HW_S390_IPL_H
#define HW_S390_IPL_H
#include "hw/qdev.h"
#include "cpu.h"
typedef struct IplParameterBlock {
@ -25,4 +26,28 @@ void s390_ipl_prepare_cpu(S390CPU *cpu);
IplParameterBlock *s390_ipl_get_iplb(void);
void s390_reipl_request(void);
#define TYPE_S390_IPL "s390-ipl"
#define S390_IPL(obj) OBJECT_CHECK(S390IPLState, (obj), TYPE_S390_IPL)
struct S390IPLState {
/*< private >*/
DeviceState parent_obj;
uint64_t start_addr;
uint64_t bios_start_addr;
bool enforce_bios;
IplParameterBlock iplb;
bool iplb_valid;
bool reipl_requested;
/*< public >*/
char *kernel;
char *initrd;
char *cmdline;
char *firmware;
uint8_t cssid;
uint8_t ssid;
uint16_t devno;
};
typedef struct S390IPLState S390IPLState;
#endif

View file

@ -309,8 +309,7 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr,
uint64_t pte;
uint32_t flags;
S390PCIBusDevice *pbdev = container_of(iommu, S390PCIBusDevice, mr);
S390pciState *s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pbdev->pdev)
->qbus.parent);
S390pciState *s;
IOMMUTLBEntry ret = {
.target_as = &address_space_memory,
.iova = 0,
@ -319,8 +318,13 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr,
.perm = IOMMU_NONE,
};
if (!pbdev->configured || !pbdev->pdev) {
return ret;
}
DPRINTF("iommu trans addr 0x%" PRIx64 "\n", addr);
s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pbdev->pdev)->qbus.parent);
/* s390 does not have an APIC mapped to main storage so we use
* a separate AddressSpace only for msix notifications
*/

View file

@ -104,8 +104,7 @@ void s390_memory_init(ram_addr_t mem_size)
MemoryRegion *ram = g_new(MemoryRegion, 1);
/* allocate RAM for core */
memory_region_init_ram(ram, NULL, "s390.ram", mem_size, &error_fatal);
vmstate_register_ram_global(ram);
memory_region_allocate_system_memory(ram, NULL, "s390.ram", mem_size);
memory_region_add_subregion(sysmem, 0, ram);
/* Initialize storage key device */

View file

@ -31,7 +31,6 @@
#include "hw/boards.h"
#include "hw/loader.h"
#include "hw/virtio/virtio.h"
#include "hw/sysbus.h"
#include "sysemu/kvm.h"
#include "exec/address-spaces.h"
@ -151,9 +150,9 @@ void s390_init_ipl_dev(const char *kernel_filename,
const char *firmware,
bool enforce_bios)
{
DeviceState *dev;
Object *new = object_new(TYPE_S390_IPL);
DeviceState *dev = DEVICE(new);
dev = qdev_create(NULL, "s390-ipl");
if (kernel_filename) {
qdev_prop_set_string(dev, "kernel", kernel_filename);
}
@ -163,8 +162,9 @@ void s390_init_ipl_dev(const char *kernel_filename,
qdev_prop_set_string(dev, "cmdline", kernel_cmdline);
qdev_prop_set_string(dev, "firmware", firmware);
qdev_prop_set_bit(dev, "enforce_bios", enforce_bios);
object_property_add_child(qdev_get_machine(), "s390-ipl",
OBJECT(dev), NULL);
object_property_add_child(qdev_get_machine(), TYPE_S390_IPL,
new, NULL);
object_unref(new);
qdev_init_nofail(dev);
}
@ -268,6 +268,10 @@ static void s390_init(MachineState *machine)
hwaddr virtio_region_len;
hwaddr virtio_region_start;
error_printf("WARNING\n"
"The s390-virtio machine (non-ccw) is deprecated.\n"
"It will be removed in 2.6. Please use s390-ccw-virtio\n");
if (machine->ram_slots) {
error_report("Memory hotplug not supported by the selected machine.");
exit(EXIT_FAILURE);
@ -334,7 +338,7 @@ static void s390_machine_class_init(ObjectClass *oc, void *data)
NMIClass *nc = NMI_CLASS(oc);
mc->alias = "s390";
mc->desc = "VirtIO based S390 machine";
mc->desc = "VirtIO based S390 machine (deprecated)";
mc->init = s390_init;
mc->reset = s390_machine_reset;
mc->block_default_type = IF_VIRTIO;

View file

@ -337,6 +337,7 @@ int qdev_walk_children(DeviceState *dev,
void *opaque);
void qdev_reset_all(DeviceState *dev);
void qdev_reset_all_fn(void *opaque);
/**
* @qbus_reset_all:

Binary file not shown.

View file

@ -444,6 +444,206 @@ static void ipl_scsi(void)
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 */
virtio_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;
}
}
}
virtio_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 */
}
}
/***********************************************************************
* IPL starts here
*/
@ -463,6 +663,12 @@ void zipl_load(void)
ipl_scsi(); /* no return */
}
/* Check if we can boot as ISO media */
if (virtio_guessed_disk_nature()) {
virtio_assume_iso9660();
}
ipl_iso_el_torito();
/* We have failed to follow the SCSI scheme, so */
if (virtio_guessed_disk_nature()) {
sclp_print("Using guessed DASD geometry.\n");

View file

@ -341,4 +341,210 @@ 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 */

View file

@ -278,6 +278,13 @@ void virtio_assume_scsi(void)
blk_cfg.physical_block_exp = 0;
}
void virtio_assume_iso9660(void)
{
guessed_disk_nature = true;
blk_cfg.blk_size = 2048;
blk_cfg.physical_block_exp = 0;
}
void virtio_assume_eckd(void)
{
guessed_disk_nature = true;

View file

@ -187,6 +187,7 @@ typedef struct VirtioBlkConfig {
bool 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);
@ -199,14 +200,9 @@ extern int virtio_read_many(ulong sector, void *load_addr, int sec_num);
#define VIRTIO_SECTOR_SIZE 512
static inline ulong virtio_eckd_sector_adjust(ulong sector)
{
return sector * (virtio_get_block_size() / VIRTIO_SECTOR_SIZE);
}
static inline ulong virtio_sector_adjust(ulong sector)
{
return virtio_disk_is_eckd() ? virtio_eckd_sector_adjust(sector) : sector;
return sector * (virtio_get_block_size() / VIRTIO_SECTOR_SIZE);
}
#endif /* VIRTIO_H */

View file

@ -258,7 +258,9 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
cap_mem_op = kvm_check_extension(s, KVM_CAP_S390_MEM_OP);
cap_s390_irq = kvm_check_extension(s, KVM_CAP_S390_INJECT_IRQ);
kvm_s390_enable_cmma(s);
if (!mem_path) {
kvm_s390_enable_cmma(s);
}
if (!kvm_check_extension(s, KVM_CAP_S390_GMAP)
|| !kvm_check_extension(s, KVM_CAP_S390_COW)) {