mirror of https://github.com/xqemu/xqemu.git
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:
commit
31e49ac192
20
MAINTAINERS
20
MAINTAINERS
|
@ -237,9 +237,14 @@ M: Cornelia Huck <cornelia.huck@de.ibm.com>
|
||||||
M: Alexander Graf <agraf@suse.de>
|
M: Alexander Graf <agraf@suse.de>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-s390x/kvm.c
|
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.c
|
||||||
F: hw/intc/s390_flic_kvm.c
|
F: hw/intc/s390_flic_kvm.c
|
||||||
F: include/hw/s390x/s390_flic.h
|
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
|
X86
|
||||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
@ -637,15 +642,13 @@ M: Christian Borntraeger <borntraeger@de.ibm.com>
|
||||||
M: Alexander Graf <agraf@suse.de>
|
M: Alexander Graf <agraf@suse.de>
|
||||||
S: Supported
|
S: Supported
|
||||||
F: hw/char/sclp*.[hc]
|
F: hw/char/sclp*.[hc]
|
||||||
F: hw/s390x/s390-virtio-ccw.c
|
F: hw/s390x/
|
||||||
F: hw/s390x/css.[hc]
|
X: hw/s390x/s390-virtio-bus.[ch]
|
||||||
F: hw/s390x/sclp*.[hc]
|
|
||||||
F: hw/s390x/ipl*.[hc]
|
|
||||||
F: hw/s390x/*pci*.[hc]
|
|
||||||
F: hw/s390x/s390-skeys*.c
|
|
||||||
F: include/hw/s390x/
|
F: include/hw/s390x/
|
||||||
F: pc-bios/s390-ccw/
|
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
|
UniCore32 Machines
|
||||||
-------------
|
-------------
|
||||||
|
@ -872,7 +875,8 @@ M: Cornelia Huck <cornelia.huck@de.ibm.com>
|
||||||
M: Christian Borntraeger <borntraeger@de.ibm.com>
|
M: Christian Borntraeger <borntraeger@de.ibm.com>
|
||||||
S: Supported
|
S: Supported
|
||||||
F: hw/s390x/virtio-ccw.[hc]
|
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
|
virtio-input
|
||||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||||
|
|
|
@ -325,6 +325,11 @@ void qdev_reset_all(DeviceState *dev)
|
||||||
qdev_walk_children(dev, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
|
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)
|
void qbus_reset_all(BusState *bus)
|
||||||
{
|
{
|
||||||
qbus_walk_children(bus, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
|
qbus_walk_children(bus, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
|
||||||
|
|
|
@ -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 a unit check is pending, copy sense data. */
|
||||||
if ((s->dstat & SCSW_DSTAT_UNIT_CHECK) &&
|
if ((s->dstat & SCSW_DSTAT_UNIT_CHECK) &&
|
||||||
(p->chars & PMCW_CHARS_MASK_CSENSE)) {
|
(p->chars & PMCW_CHARS_MASK_CSENSE)) {
|
||||||
|
int i;
|
||||||
|
|
||||||
irb.scsw.flags |= SCSW_FLAGS_MASK_ESWF | SCSW_FLAGS_MASK_ECTL;
|
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));
|
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);
|
irb.esw[1] = 0x01000000 | (sizeof(sch->sense_data) << 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
#include "hw/loader.h"
|
#include "hw/loader.h"
|
||||||
#include "hw/sysbus.h"
|
|
||||||
#include "hw/s390x/virtio-ccw.h"
|
#include "hw/s390x/virtio-ccw.h"
|
||||||
#include "hw/s390x/css.h"
|
#include "hw/s390x/css.h"
|
||||||
#include "ipl.h"
|
#include "ipl.h"
|
||||||
|
@ -29,44 +28,6 @@
|
||||||
#define ZIPL_IMAGE_START 0x009000UL
|
#define ZIPL_IMAGE_START 0x009000UL
|
||||||
#define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64)
|
#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 = {
|
static const VMStateDescription vmstate_iplb = {
|
||||||
.name = "ipl/iplb",
|
.name = "ipl/iplb",
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
|
@ -110,11 +71,12 @@ static uint64_t bios_translate_addr(void *opaque, uint64_t srcaddr)
|
||||||
return srcaddr + dstaddr;
|
return srcaddr + dstaddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int s390_ipl_init(SysBusDevice *dev)
|
static void s390_ipl_realize(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
S390IPLState *ipl = S390_IPL(dev);
|
S390IPLState *ipl = S390_IPL(dev);
|
||||||
uint64_t pentry = KERN_IMAGE_START;
|
uint64_t pentry = KERN_IMAGE_START;
|
||||||
int kernel_size;
|
int kernel_size;
|
||||||
|
Error *l_err = NULL;
|
||||||
|
|
||||||
int bios_size;
|
int bios_size;
|
||||||
char *bios_filename;
|
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);
|
bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
|
||||||
if (bios_filename == NULL) {
|
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,
|
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);
|
g_free(bios_filename);
|
||||||
|
|
||||||
if (bios_size == -1) {
|
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 */
|
/* 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);
|
kernel_size = load_image_targphys(ipl->kernel, 0, ram_size);
|
||||||
}
|
}
|
||||||
if (kernel_size < 0) {
|
if (kernel_size < 0) {
|
||||||
fprintf(stderr, "could not load kernel '%s'\n", ipl->kernel);
|
error_setg(&l_err, "could not load kernel '%s'\n", ipl->kernel);
|
||||||
return -1;
|
goto error;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Is it a Linux kernel (starting at 0x10000)? If yes, we fill in the
|
* 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,
|
initrd_size = load_image_targphys(ipl->initrd, initrd_offset,
|
||||||
ram_size - initrd_offset);
|
ram_size - initrd_offset);
|
||||||
if (initrd_size == -1) {
|
if (initrd_size == -1) {
|
||||||
fprintf(stderr, "qemu: could not load initrd '%s'\n",
|
error_setg(&l_err, "could not load initrd '%s'\n", ipl->initrd);
|
||||||
ipl->initrd);
|
goto error;
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -205,7 +168,9 @@ static int s390_ipl_init(SysBusDevice *dev)
|
||||||
stq_p(rom_ptr(INITRD_PARM_SIZE), initrd_size);
|
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[] = {
|
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)
|
static void s390_ipl_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
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->props = s390_ipl_properties;
|
||||||
dc->reset = s390_ipl_reset;
|
dc->reset = s390_ipl_reset;
|
||||||
dc->vmsd = &vmstate_ipl;
|
dc->vmsd = &vmstate_ipl;
|
||||||
|
@ -319,8 +283,8 @@ static void s390_ipl_class_init(ObjectClass *klass, void *data)
|
||||||
|
|
||||||
static const TypeInfo s390_ipl_info = {
|
static const TypeInfo s390_ipl_info = {
|
||||||
.class_init = s390_ipl_class_init,
|
.class_init = s390_ipl_class_init,
|
||||||
.parent = TYPE_SYS_BUS_DEVICE,
|
.parent = TYPE_DEVICE,
|
||||||
.name = "s390-ipl",
|
.name = TYPE_S390_IPL,
|
||||||
.instance_size = sizeof(S390IPLState),
|
.instance_size = sizeof(S390IPLState),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#ifndef HW_S390_IPL_H
|
#ifndef HW_S390_IPL_H
|
||||||
#define HW_S390_IPL_H
|
#define HW_S390_IPL_H
|
||||||
|
|
||||||
|
#include "hw/qdev.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
|
||||||
typedef struct IplParameterBlock {
|
typedef struct IplParameterBlock {
|
||||||
|
@ -25,4 +26,28 @@ void s390_ipl_prepare_cpu(S390CPU *cpu);
|
||||||
IplParameterBlock *s390_ipl_get_iplb(void);
|
IplParameterBlock *s390_ipl_get_iplb(void);
|
||||||
void s390_reipl_request(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
|
#endif
|
||||||
|
|
|
@ -309,8 +309,7 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr,
|
||||||
uint64_t pte;
|
uint64_t pte;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
S390PCIBusDevice *pbdev = container_of(iommu, S390PCIBusDevice, mr);
|
S390PCIBusDevice *pbdev = container_of(iommu, S390PCIBusDevice, mr);
|
||||||
S390pciState *s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pbdev->pdev)
|
S390pciState *s;
|
||||||
->qbus.parent);
|
|
||||||
IOMMUTLBEntry ret = {
|
IOMMUTLBEntry ret = {
|
||||||
.target_as = &address_space_memory,
|
.target_as = &address_space_memory,
|
||||||
.iova = 0,
|
.iova = 0,
|
||||||
|
@ -319,8 +318,13 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr,
|
||||||
.perm = IOMMU_NONE,
|
.perm = IOMMU_NONE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!pbdev->configured || !pbdev->pdev) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
DPRINTF("iommu trans addr 0x%" PRIx64 "\n", addr);
|
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
|
/* s390 does not have an APIC mapped to main storage so we use
|
||||||
* a separate AddressSpace only for msix notifications
|
* a separate AddressSpace only for msix notifications
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -104,8 +104,7 @@ void s390_memory_init(ram_addr_t mem_size)
|
||||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||||
|
|
||||||
/* allocate RAM for core */
|
/* allocate RAM for core */
|
||||||
memory_region_init_ram(ram, NULL, "s390.ram", mem_size, &error_fatal);
|
memory_region_allocate_system_memory(ram, NULL, "s390.ram", mem_size);
|
||||||
vmstate_register_ram_global(ram);
|
|
||||||
memory_region_add_subregion(sysmem, 0, ram);
|
memory_region_add_subregion(sysmem, 0, ram);
|
||||||
|
|
||||||
/* Initialize storage key device */
|
/* Initialize storage key device */
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
#include "hw/loader.h"
|
#include "hw/loader.h"
|
||||||
#include "hw/virtio/virtio.h"
|
#include "hw/virtio/virtio.h"
|
||||||
#include "hw/sysbus.h"
|
|
||||||
#include "sysemu/kvm.h"
|
#include "sysemu/kvm.h"
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
|
|
||||||
|
@ -151,9 +150,9 @@ void s390_init_ipl_dev(const char *kernel_filename,
|
||||||
const char *firmware,
|
const char *firmware,
|
||||||
bool enforce_bios)
|
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) {
|
if (kernel_filename) {
|
||||||
qdev_prop_set_string(dev, "kernel", 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, "cmdline", kernel_cmdline);
|
||||||
qdev_prop_set_string(dev, "firmware", firmware);
|
qdev_prop_set_string(dev, "firmware", firmware);
|
||||||
qdev_prop_set_bit(dev, "enforce_bios", enforce_bios);
|
qdev_prop_set_bit(dev, "enforce_bios", enforce_bios);
|
||||||
object_property_add_child(qdev_get_machine(), "s390-ipl",
|
object_property_add_child(qdev_get_machine(), TYPE_S390_IPL,
|
||||||
OBJECT(dev), NULL);
|
new, NULL);
|
||||||
|
object_unref(new);
|
||||||
qdev_init_nofail(dev);
|
qdev_init_nofail(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,6 +268,10 @@ static void s390_init(MachineState *machine)
|
||||||
hwaddr virtio_region_len;
|
hwaddr virtio_region_len;
|
||||||
hwaddr virtio_region_start;
|
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) {
|
if (machine->ram_slots) {
|
||||||
error_report("Memory hotplug not supported by the selected machine.");
|
error_report("Memory hotplug not supported by the selected machine.");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
@ -334,7 +338,7 @@ static void s390_machine_class_init(ObjectClass *oc, void *data)
|
||||||
NMIClass *nc = NMI_CLASS(oc);
|
NMIClass *nc = NMI_CLASS(oc);
|
||||||
|
|
||||||
mc->alias = "s390";
|
mc->alias = "s390";
|
||||||
mc->desc = "VirtIO based S390 machine";
|
mc->desc = "VirtIO based S390 machine (deprecated)";
|
||||||
mc->init = s390_init;
|
mc->init = s390_init;
|
||||||
mc->reset = s390_machine_reset;
|
mc->reset = s390_machine_reset;
|
||||||
mc->block_default_type = IF_VIRTIO;
|
mc->block_default_type = IF_VIRTIO;
|
||||||
|
|
|
@ -337,6 +337,7 @@ int qdev_walk_children(DeviceState *dev,
|
||||||
void *opaque);
|
void *opaque);
|
||||||
|
|
||||||
void qdev_reset_all(DeviceState *dev);
|
void qdev_reset_all(DeviceState *dev);
|
||||||
|
void qdev_reset_all_fn(void *opaque);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @qbus_reset_all:
|
* @qbus_reset_all:
|
||||||
|
|
Binary file not shown.
|
@ -444,6 +444,206 @@ static void ipl_scsi(void)
|
||||||
zipl_run(prog_table_entry); /* no return */
|
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
|
* IPL starts here
|
||||||
*/
|
*/
|
||||||
|
@ -463,6 +663,12 @@ void zipl_load(void)
|
||||||
ipl_scsi(); /* no return */
|
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 */
|
/* We have failed to follow the SCSI scheme, so */
|
||||||
if (virtio_guessed_disk_nature()) {
|
if (virtio_guessed_disk_nature()) {
|
||||||
sclp_print("Using guessed DASD geometry.\n");
|
sclp_print("Using guessed DASD geometry.\n");
|
||||||
|
|
|
@ -341,4 +341,210 @@ static inline bool magic_match(const void *data, const void *magic)
|
||||||
return *((uint32_t *)data) == *((uint32_t *)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 */
|
#endif /* _PC_BIOS_S390_CCW_BOOTMAP_H */
|
||||||
|
|
|
@ -278,6 +278,13 @@ void virtio_assume_scsi(void)
|
||||||
blk_cfg.physical_block_exp = 0;
|
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)
|
void virtio_assume_eckd(void)
|
||||||
{
|
{
|
||||||
guessed_disk_nature = true;
|
guessed_disk_nature = true;
|
||||||
|
|
|
@ -187,6 +187,7 @@ typedef struct VirtioBlkConfig {
|
||||||
bool virtio_guessed_disk_nature(void);
|
bool virtio_guessed_disk_nature(void);
|
||||||
void virtio_assume_scsi(void);
|
void virtio_assume_scsi(void);
|
||||||
void virtio_assume_eckd(void);
|
void virtio_assume_eckd(void);
|
||||||
|
void virtio_assume_iso9660(void);
|
||||||
|
|
||||||
extern bool virtio_disk_is_scsi(void);
|
extern bool virtio_disk_is_scsi(void);
|
||||||
extern bool virtio_disk_is_eckd(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
|
#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)
|
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 */
|
#endif /* VIRTIO_H */
|
||||||
|
|
|
@ -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_mem_op = kvm_check_extension(s, KVM_CAP_S390_MEM_OP);
|
||||||
cap_s390_irq = kvm_check_extension(s, KVM_CAP_S390_INJECT_IRQ);
|
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)
|
if (!kvm_check_extension(s, KVM_CAP_S390_GMAP)
|
||||||
|| !kvm_check_extension(s, KVM_CAP_S390_COW)) {
|
|| !kvm_check_extension(s, KVM_CAP_S390_COW)) {
|
||||||
|
|
Loading…
Reference in New Issue