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>
This commit is contained in:
Alexander Yarygin 2015-07-13 15:04:36 +03:00 committed by Cornelia Huck
parent 9700230b0d
commit 04ca4b92ec
4 changed files with 90 additions and 10 deletions

View File

@ -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(),
};

View File

@ -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

View File

@ -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 \

View File

@ -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;