aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Yarygin <yarygin@linux.vnet.ibm.com>2015-07-13 15:04:36 +0300
committerCornelia Huck <cornelia.huck@de.ibm.com>2016-05-17 15:50:29 +0200
commit04ca4b92ecb33703b03b8501bfb3d8b0c551e2e5 (patch)
tree0ffae5df7694133b51642c830344d3c592a63f7a
parent9700230b0d6d68d8650206ffd10d132219678db1 (diff)
s390x/ipl: Extend the IplParameterBlock struct
The IplParameterBlock struct currently has only 200 bytes filled, but it can be up to 4K. This patch converts the struct to union with a fully populated struct inside it and second struct with old values. For compatibility reasons we disable migration of the extended iplb field for pre-2.7 machines. Also a guest still can read/write only the first 200 bytes of IPLB for now. Signed-off-by: Alexander Yarygin <yarygin@linux.vnet.ibm.com> Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Acked-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
-rw-r--r--hw/s390x/ipl.c24
-rw-r--r--hw/s390x/ipl.h61
-rw-r--r--hw/s390x/s390-virtio-ccw.c8
-rw-r--r--target-s390x/misc_helper.c7
4 files changed, 90 insertions, 10 deletions
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index f104200273..236e2c937f 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -30,6 +30,24 @@
#define ZIPL_IMAGE_START 0x009000UL
#define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64)
+static bool iplb_extended_needed(void *opaque)
+{
+ S390IPLState *ipl = S390_IPL(object_resolve_path(TYPE_S390_IPL, NULL));
+
+ return ipl->iplbext_migration;
+}
+
+static const VMStateDescription vmstate_iplb_extended = {
+ .name = "ipl/iplb_extended",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .needed = iplb_extended_needed,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8_ARRAY(reserved_ext, IplParameterBlock, 4096 - 200),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const VMStateDescription vmstate_iplb = {
.name = "ipl/iplb",
.version_id = 0,
@@ -39,6 +57,10 @@ static const VMStateDescription vmstate_iplb = {
VMSTATE_UINT16(devno, IplParameterBlock),
VMSTATE_UINT8_ARRAY(reserved2, IplParameterBlock, 88),
VMSTATE_END_OF_LIST()
+ },
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_iplb_extended,
+ NULL
}
};
@@ -181,6 +203,8 @@ static Property s390_ipl_properties[] = {
DEFINE_PROP_STRING("cmdline", S390IPLState, cmdline),
DEFINE_PROP_STRING("firmware", S390IPLState, firmware),
DEFINE_PROP_BOOL("enforce_bios", S390IPLState, enforce_bios, false),
+ DEFINE_PROP_BOOL("iplbext_migration", S390IPLState, iplbext_migration,
+ true),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h
index 6b48ed7b93..73b86e3f81 100644
--- a/hw/s390x/ipl.h
+++ b/hw/s390x/ipl.h
@@ -15,11 +15,59 @@
#include "hw/qdev.h"
#include "cpu.h"
-typedef struct IplParameterBlock {
- uint8_t reserved1[110];
- uint16_t devno;
- uint8_t reserved2[88];
-} IplParameterBlock;
+struct IplBlockCcw {
+ uint8_t reserved0[86];
+ uint16_t devno;
+ uint8_t vm_flags;
+ uint8_t reserved3[3];
+ uint32_t vm_parm_len;
+ uint8_t nss_name[8];
+ uint8_t vm_parm[64];
+ uint8_t reserved4[8];
+} QEMU_PACKED;
+typedef struct IplBlockCcw IplBlockCcw;
+
+struct IplBlockFcp {
+ uint8_t reserved1[305 - 1];
+ uint8_t opt;
+ uint8_t reserved2[3];
+ uint16_t reserved3;
+ uint16_t devno;
+ uint8_t reserved4[4];
+ uint64_t wwpn;
+ uint64_t lun;
+ uint32_t bootprog;
+ uint8_t reserved5[12];
+ uint64_t br_lba;
+ uint32_t scp_data_len;
+ uint8_t reserved6[260];
+ uint8_t scp_data[];
+} QEMU_PACKED;
+typedef struct IplBlockFcp IplBlockFcp;
+
+union IplParameterBlock {
+ struct {
+ uint32_t len;
+ uint8_t reserved0[3];
+ uint8_t version;
+ uint32_t blk0_len;
+ uint8_t pbt;
+ uint8_t flags;
+ uint16_t reserved01;
+ uint8_t loadparm[8];
+ union {
+ IplBlockCcw ccw;
+ IplBlockFcp fcp;
+ };
+ } QEMU_PACKED;
+ struct {
+ uint8_t reserved1[110];
+ uint16_t devno;
+ uint8_t reserved2[88];
+ uint8_t reserved_ext[4096 - 200];
+ } QEMU_PACKED;
+} QEMU_PACKED;
+typedef union IplParameterBlock IplParameterBlock;
void s390_ipl_update_diag308(IplParameterBlock *iplb);
void s390_ipl_prepare_cpu(S390CPU *cpu);
@@ -47,7 +95,10 @@ struct S390IPLState {
uint8_t cssid;
uint8_t ssid;
uint16_t devno;
+ bool iplbext_migration;
};
typedef struct S390IPLState S390IPLState;
+#define S390_IPLB_MIN_CCW_LEN 200
+
#endif
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 1390a98391..4456fce9f1 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -25,6 +25,7 @@
#include "s390-pci-bus.h"
#include "hw/s390x/storage-keys.h"
#include "hw/compat.h"
+#include "ipl.h"
#include "hw/s390x/s390-virtio-ccw.h"
static const char *const reset_dev_types[] = {
@@ -317,7 +318,12 @@ static const TypeInfo ccw_machine_info = {
type_init(ccw_machine_register_##suffix)
#define CCW_COMPAT_2_6 \
- HW_COMPAT_2_6
+ HW_COMPAT_2_6 \
+ {\
+ .driver = TYPE_S390_IPL,\
+ .property = "iplbext_migration",\
+ .value = "off",\
+ },
#define CCW_COMPAT_2_5 \
CCW_COMPAT_2_6 \
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 71cbe34e05..fab7f87a8f 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -232,8 +232,8 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3)
program_interrupt(env, PGM_ADDRESSING, ILEN_LATER_INC);
return;
}
- iplb = g_malloc0(sizeof(struct IplParameterBlock));
- cpu_physical_memory_read(addr, iplb, sizeof(struct IplParameterBlock));
+ iplb = g_malloc0(sizeof(IplParameterBlock));
+ cpu_physical_memory_read(addr, iplb, S390_IPLB_MIN_CCW_LEN);
s390_ipl_update_diag308(iplb);
env->regs[r1 + 1] = DIAG_308_RC_OK;
g_free(iplb);
@@ -250,8 +250,7 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3)
}
iplb = s390_ipl_get_iplb();
if (iplb) {
- cpu_physical_memory_write(addr, iplb,
- sizeof(struct IplParameterBlock));
+ cpu_physical_memory_write(addr, iplb, S390_IPLB_MIN_CCW_LEN);
env->regs[r1 + 1] = DIAG_308_RC_OK;
} else {
env->regs[r1 + 1] = DIAG_308_RC_NO_CONF;