diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/s390x/ipl.c | 18 | ||||
-rw-r--r-- | hw/s390x/ipl.h | 25 |
2 files changed, 40 insertions, 3 deletions
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index 0d06fc12b6..79f5a58adb 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -399,6 +399,21 @@ void s390_reipl_request(void) qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); } +static void s390_ipl_prepare_qipl(S390CPU *cpu) +{ + S390IPLState *ipl = get_ipl_device(); + uint8_t *addr; + uint64_t len = 4096; + + addr = cpu_physical_memory_map(cpu->env.psa, &len, 1); + if (!addr || len < QIPL_ADDRESS + sizeof(QemuIplParameters)) { + error_report("Cannot set QEMU IPL parameters"); + return; + } + memcpy(addr + QIPL_ADDRESS, &ipl->qipl, sizeof(QemuIplParameters)); + cpu_physical_memory_unmap(addr, len, 1, len); +} + void s390_ipl_prepare_cpu(S390CPU *cpu) { S390IPLState *ipl = get_ipl_device(); @@ -418,8 +433,9 @@ void s390_ipl_prepare_cpu(S390CPU *cpu) error_report_err(err); vm_stop(RUN_STATE_INTERNAL_ERROR); } - ipl->iplb.ccw.netboot_start_addr = cpu_to_be64(ipl->start_addr); + ipl->qipl.netboot_start_addr = cpu_to_be64(ipl->start_addr); } + s390_ipl_prepare_qipl(cpu); } static void s390_ipl_reset(DeviceState *dev) diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h index 8a705e0428..5cc3b770d4 100644 --- a/hw/s390x/ipl.h +++ b/hw/s390x/ipl.h @@ -16,8 +16,7 @@ #include "cpu.h" struct IplBlockCcw { - uint64_t netboot_start_addr; - uint8_t reserved0[77]; + uint8_t reserved0[85]; uint8_t ssid; uint16_t devno; uint8_t vm_flags; @@ -90,6 +89,27 @@ void s390_ipl_prepare_cpu(S390CPU *cpu); IplParameterBlock *s390_ipl_get_iplb(void); void s390_reipl_request(void); +#define QIPL_ADDRESS 0xcc + +/* + * The QEMU IPL Parameters will be stored at absolute address + * 204 (0xcc) which means it is 32-bit word aligned but not + * double-word aligned. + * Placement of data fields in this area must account for + * their alignment needs. E.g., netboot_start_address must + * have an offset of 4 + n * 8 bytes within the struct in order + * to keep it double-word aligned. + * The total size of the struct must never exceed 28 bytes. + * This definition must be kept in sync with the defininition + * in pc-bios/s390-ccw/iplb.h. + */ +struct QemuIplParameters { + uint8_t reserved1[4]; + uint64_t netboot_start_addr; + uint8_t reserved2[16]; +} QEMU_PACKED; +typedef struct QemuIplParameters QemuIplParameters; + #define TYPE_S390_IPL "s390-ipl" #define S390_IPL(obj) OBJECT_CHECK(S390IPLState, (obj), TYPE_S390_IPL) @@ -105,6 +125,7 @@ struct S390IPLState { bool iplb_valid; bool reipl_requested; bool netboot; + QemuIplParameters qipl; /*< public >*/ char *kernel; |