s390x update

- support extended sccb and diagnose 0x318
 - implement additional instructions in tcg
 - bug fixes
 -----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEEw9DWbcNiT/aowBjO3s9rk8bwL68FAl93F3wSHGNvaHVja0By
 ZWRoYXQuY29tAAoJEN7Pa5PG8C+vL48QAJL3TtMixD/ZRxoHdlDeoVR8dy8oyWY0
 2fVojC8M1gs4aKR60e1LVbzSPSurLQWJKIYZQLJBw4OCuTbEv73YjaIpqZTpP4Mx
 KPp8cUITwq6yXWeFlHiSfGr7JlUVfPgzymxm570RCvsBLpdVB/Wt/15i+4ehZivj
 DCenh9T1PztDT/A0VW3HY2OfoodMWqygl1Jvq0Alkn+Rrmiq8qhtwk2XZD/c0JP+
 X6ScU4RZkDsT15YAib2eFcGunCS/NfnhwGDY8EJoae2aFPSD1D4AmvJogX8GpdYB
 z4NfxwceV8LCkFa5z4w4BjldsIlfvYKjNhSgn7SaJEx9ChAUI8beSOpY6LJKNgRe
 1eh6qUrwZ+lEGGUX3fEeDdJe0rv6rNl6zdzwlzd+mLOPp0IDRgYpEYMlhSfIDeYR
 a41ZKd2DlMrtq5ebdxCpdUdxPslrXDZAE4CHvjw8f25O60mRkv2am2Nvv/XZU8wo
 ZN4o0jkGLx4sSvnCQ+2CCcrFnuy5L1Cty+c1EG9cIKLUwj5ZLcUmg2cJR3PUGBA3
 eobFLzev/YlZzEwyL5QtjOeME5aLijF8hHKed5LIcXaBKEtRgsbU0kvrBOEFK4lk
 uqAth4nQ06k//xQ4b/oRUyRjLz8WDuHOAx9ES6tkDQW/tFsmoxPFjVVsRxQIWIrO
 a/c4O4aCswQP
 =soNE
 -----END PGP SIGNATURE-----

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

s390x update
- support extended sccb and diagnose 0x318
- implement additional instructions in tcg
- bug fixes

# gpg: Signature made Fri 02 Oct 2020 13:05:16 BST
# gpg:                using RSA key C3D0D66DC3624FF6A8C018CEDECF6B93C6F02FAF
# gpg:                issuer "cohuck@redhat.com"
# gpg: Good signature from "Cornelia Huck <conny@cornelia-huck.de>" [unknown]
# gpg:                 aka "Cornelia Huck <huckc@linux.vnet.ibm.com>" [full]
# gpg:                 aka "Cornelia Huck <cornelia.huck@de.ibm.com>" [full]
# gpg:                 aka "Cornelia Huck <cohuck@kernel.org>" [unknown]
# gpg:                 aka "Cornelia Huck <cohuck@redhat.com>" [unknown]
# Primary key fingerprint: C3D0 D66D C362 4FF6 A8C0  18CE DECF 6B93 C6F0 2FAF

* remotes/cohuck/tags/s390x-20201002:
  s390x/tcg: Implement CIPHER MESSAGE WITH AUTHENTICATION (KMA)
  s390x/tcg: We support Miscellaneous-Instruction-Extensions Facility 2
  s390x/tcg: Implement MULTIPLY SINGLE (MSC, MSGC, MSGRKC, MSRKC)
  s390x/tcg: Implement BRANCH INDIRECT ON CONDITION (BIC)
  s390x/tcg: Implement MULTIPLY HALFWORD (MGH)
  s390x/tcg: Implement MULTIPLY (MG, MGRK)
  s390x/tcg: Implement SUBTRACT HALFWORD (SGH)
  s390x/tcg: Implement ADD HALFWORD (AGH)
  s390x/cpumodel: S390_FEAT_MISC_INSTRUCTION_EXT -> S390_FEAT_MISC_INSTRUCTION_EXT2
  vfio-ccw: plug memory leak while getting region info
  s390x/tcg: Implement MONITOR CALL
  s390: guest support for diagnose 0x318
  s390/sclp: add extended-length sccb support for kvm guest
  s390/sclp: use cpu offset to locate cpu entries
  s390/sclp: check sccb len before filling in data
  s390/sclp: read sccb from mem based on provided length
  s390/sclp: rework sclp boundary checks
  s390/sclp: get machine once during read scp/cpu info
  hw/s390x/css: Remove double initialization

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2020-10-02 14:29:49 +01:00
commit dd8c1e808f
19 changed files with 342 additions and 47 deletions

View file

@ -353,7 +353,6 @@ static ChannelSubSys channel_subsys = {
.pending_crws = QTAILQ_HEAD_INITIALIZER(channel_subsys.pending_crws), .pending_crws = QTAILQ_HEAD_INITIALIZER(channel_subsys.pending_crws),
.do_crw_mchk = true, .do_crw_mchk = true,
.sei_pending = false, .sei_pending = false,
.do_crw_mchk = true,
.crws_lost = false, .crws_lost = false,
.chnmon_active = false, .chnmon_active = false,
.indicator_addresses = .indicator_addresses =

View file

@ -213,7 +213,7 @@ static uint16_t handle_sccb_read_events(SCLPEventFacility *ef, SCCB *sccb,
event_buf = &red->ebh; event_buf = &red->ebh;
event_buf->length = 0; event_buf->length = 0;
slen = sizeof(sccb->data); slen = sccb_data_len(sccb);
rc = SCLP_RC_NO_EVENT_BUFFERS_STORED; rc = SCLP_RC_NO_EVENT_BUFFERS_STORED;

View file

@ -49,9 +49,37 @@ static inline bool sclp_command_code_valid(uint32_t code)
return false; return false;
} }
static void prepare_cpu_entries(SCLPDevice *sclp, CPUEntry *entry, int *count) static bool sccb_verify_boundary(uint64_t sccb_addr, uint16_t sccb_len,
uint32_t code)
{
uint64_t sccb_max_addr = sccb_addr + sccb_len - 1;
uint64_t sccb_boundary = (sccb_addr & PAGE_MASK) + PAGE_SIZE;
switch (code & SCLP_CMD_CODE_MASK) {
case SCLP_CMDW_READ_SCP_INFO:
case SCLP_CMDW_READ_SCP_INFO_FORCED:
case SCLP_CMDW_READ_CPU_INFO:
/*
* An extended-length SCCB is only allowed for Read SCP/CPU Info and
* is allowed to exceed the 4k boundary. The respective commands will
* set the length field to the required length if an insufficient
* SCCB length is provided.
*/
if (s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB)) {
return true;
}
/* fallthrough */
default:
if (sccb_max_addr < sccb_boundary) {
return true;
}
}
return false;
}
static void prepare_cpu_entries(MachineState *ms, CPUEntry *entry, int *count)
{ {
MachineState *ms = MACHINE(qdev_get_machine());
uint8_t features[SCCB_CPU_FEATURE_LEN] = { 0 }; uint8_t features[SCCB_CPU_FEATURE_LEN] = { 0 };
int i; int i;
@ -67,6 +95,14 @@ static void prepare_cpu_entries(SCLPDevice *sclp, CPUEntry *entry, int *count)
} }
} }
#define SCCB_REQ_LEN(s, max_cpus) (sizeof(s) + max_cpus * sizeof(CPUEntry))
static inline bool ext_len_sccb_supported(SCCBHeader header)
{
return s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB) &&
header.control_mask[2] & SCLP_VARIABLE_LENGTH_RESPONSE;
}
/* Provide information about the configuration, CPUs and storage */ /* Provide information about the configuration, CPUs and storage */
static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb) static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
{ {
@ -75,27 +111,39 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
int cpu_count; int cpu_count;
int rnsize, rnmax; int rnsize, rnmax;
IplParameterBlock *ipib = s390_ipl_get_iplb(); IplParameterBlock *ipib = s390_ipl_get_iplb();
int required_len = SCCB_REQ_LEN(ReadInfo, machine->possible_cpus->len);
int offset_cpu = s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB) ?
offsetof(ReadInfo, entries) :
SCLP_READ_SCP_INFO_FIXED_CPU_OFFSET;
CPUEntry *entries_start = (void *)sccb + offset_cpu;
/* CPU information */ if (be16_to_cpu(sccb->h.length) < required_len) {
prepare_cpu_entries(sclp, read_info->entries, &cpu_count); if (ext_len_sccb_supported(sccb->h)) {
read_info->entries_cpu = cpu_to_be16(cpu_count); sccb->h.length = cpu_to_be16(required_len);
read_info->offset_cpu = cpu_to_be16(offsetof(ReadInfo, entries)); }
read_info->highest_cpu = cpu_to_be16(machine->smp.max_cpus - 1);
read_info->ibc_val = cpu_to_be32(s390_get_ibc_val());
if (be16_to_cpu(sccb->h.length) <
(sizeof(ReadInfo) + cpu_count * sizeof(CPUEntry))) {
sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH); sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
return; return;
} }
/* CPU information */
prepare_cpu_entries(machine, entries_start, &cpu_count);
read_info->entries_cpu = cpu_to_be16(cpu_count);
read_info->offset_cpu = cpu_to_be16(offset_cpu);
read_info->highest_cpu = cpu_to_be16(machine->smp.max_cpus - 1);
read_info->ibc_val = cpu_to_be32(s390_get_ibc_val());
/* Configuration Characteristic (Extension) */ /* Configuration Characteristic (Extension) */
s390_get_feat_block(S390_FEAT_TYPE_SCLP_CONF_CHAR, s390_get_feat_block(S390_FEAT_TYPE_SCLP_CONF_CHAR,
read_info->conf_char); read_info->conf_char);
s390_get_feat_block(S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, s390_get_feat_block(S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT,
read_info->conf_char_ext); read_info->conf_char_ext);
if (s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB)) {
s390_get_feat_block(S390_FEAT_TYPE_SCLP_FAC134,
&read_info->fac134);
}
read_info->facilities = cpu_to_be64(SCLP_HAS_CPU_INFO | read_info->facilities = cpu_to_be64(SCLP_HAS_CPU_INFO |
SCLP_HAS_IOA_RECONFIG); SCLP_HAS_IOA_RECONFIG);
@ -132,20 +180,24 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
/* Provide information about the CPU */ /* Provide information about the CPU */
static void sclp_read_cpu_info(SCLPDevice *sclp, SCCB *sccb) static void sclp_read_cpu_info(SCLPDevice *sclp, SCCB *sccb)
{ {
MachineState *machine = MACHINE(qdev_get_machine());
ReadCpuInfo *cpu_info = (ReadCpuInfo *) sccb; ReadCpuInfo *cpu_info = (ReadCpuInfo *) sccb;
int cpu_count; int cpu_count;
int required_len = SCCB_REQ_LEN(ReadCpuInfo, machine->possible_cpus->len);
prepare_cpu_entries(sclp, cpu_info->entries, &cpu_count); if (be16_to_cpu(sccb->h.length) < required_len) {
cpu_info->nr_configured = cpu_to_be16(cpu_count); if (ext_len_sccb_supported(sccb->h)) {
cpu_info->offset_configured = cpu_to_be16(offsetof(ReadCpuInfo, entries)); sccb->h.length = cpu_to_be16(required_len);
cpu_info->nr_standby = cpu_to_be16(0); }
if (be16_to_cpu(sccb->h.length) <
(sizeof(ReadCpuInfo) + cpu_count * sizeof(CPUEntry))) {
sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH); sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
return; return;
} }
prepare_cpu_entries(machine, cpu_info->entries, &cpu_count);
cpu_info->nr_configured = cpu_to_be16(cpu_count);
cpu_info->offset_configured = cpu_to_be16(offsetof(ReadCpuInfo, entries));
cpu_info->nr_standby = cpu_to_be16(0);
/* The standby offset is 16-byte for each CPU */ /* The standby offset is 16-byte for each CPU */
cpu_info->offset_standby = cpu_to_be16(cpu_info->offset_configured cpu_info->offset_standby = cpu_to_be16(cpu_info->offset_configured
+ cpu_info->nr_configured*sizeof(CPUEntry)); + cpu_info->nr_configured*sizeof(CPUEntry));
@ -219,20 +271,29 @@ int sclp_service_call_protected(CPUS390XState *env, uint64_t sccb,
{ {
SCLPDevice *sclp = get_sclp_device(); SCLPDevice *sclp = get_sclp_device();
SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp); SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
SCCB work_sccb; SCCBHeader header;
hwaddr sccb_len = sizeof(SCCB); g_autofree SCCB *work_sccb = NULL;
s390_cpu_pv_mem_read(env_archcpu(env), 0, &work_sccb, sccb_len); s390_cpu_pv_mem_read(env_archcpu(env), 0, &header, sizeof(SCCBHeader));
work_sccb = g_malloc0(be16_to_cpu(header.length));
s390_cpu_pv_mem_read(env_archcpu(env), 0, work_sccb,
be16_to_cpu(header.length));
if (!sclp_command_code_valid(code)) { if (!sclp_command_code_valid(code)) {
work_sccb.h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND); work_sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
goto out_write; goto out_write;
} }
sclp_c->execute(sclp, &work_sccb, code); if (!sccb_verify_boundary(sccb, be16_to_cpu(work_sccb->h.length), code)) {
work_sccb->h.response_code = cpu_to_be16(SCLP_RC_SCCB_BOUNDARY_VIOLATION);
goto out_write;
}
sclp_c->execute(sclp, work_sccb, code);
out_write: out_write:
s390_cpu_pv_mem_write(env_archcpu(env), 0, &work_sccb, s390_cpu_pv_mem_write(env_archcpu(env), 0, work_sccb,
be16_to_cpu(work_sccb.h.length)); be16_to_cpu(work_sccb->h.length));
sclp_c->service_interrupt(sclp, SCLP_PV_DUMMY_ADDR); sclp_c->service_interrupt(sclp, SCLP_PV_DUMMY_ADDR);
return 0; return 0;
} }
@ -241,9 +302,8 @@ int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code)
{ {
SCLPDevice *sclp = get_sclp_device(); SCLPDevice *sclp = get_sclp_device();
SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp); SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
SCCB work_sccb; SCCBHeader header;
g_autofree SCCB *work_sccb = NULL;
hwaddr sccb_len = sizeof(SCCB);
/* first some basic checks on program checks */ /* first some basic checks on program checks */
if (env->psw.mask & PSW_MASK_PSTATE) { if (env->psw.mask & PSW_MASK_PSTATE) {
@ -257,32 +317,36 @@ int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code)
return -PGM_SPECIFICATION; return -PGM_SPECIFICATION;
} }
/* the header contains the actual length of the sccb */
cpu_physical_memory_read(sccb, &header, sizeof(SCCBHeader));
/* Valid sccb sizes */
if (be16_to_cpu(header.length) < sizeof(SCCBHeader)) {
return -PGM_SPECIFICATION;
}
/* /*
* we want to work on a private copy of the sccb, to prevent guests * we want to work on a private copy of the sccb, to prevent guests
* from playing dirty tricks by modifying the memory content after * from playing dirty tricks by modifying the memory content after
* the host has checked the values * the host has checked the values
*/ */
cpu_physical_memory_read(sccb, &work_sccb, sccb_len); work_sccb = g_malloc0(be16_to_cpu(header.length));
cpu_physical_memory_read(sccb, work_sccb, be16_to_cpu(header.length));
/* Valid sccb sizes */
if (be16_to_cpu(work_sccb.h.length) < sizeof(SCCBHeader)) {
return -PGM_SPECIFICATION;
}
if (!sclp_command_code_valid(code)) { if (!sclp_command_code_valid(code)) {
work_sccb.h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND); work_sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
goto out_write; goto out_write;
} }
if ((sccb + be16_to_cpu(work_sccb.h.length)) > ((sccb & PAGE_MASK) + PAGE_SIZE)) { if (!sccb_verify_boundary(sccb, be16_to_cpu(work_sccb->h.length), code)) {
work_sccb.h.response_code = cpu_to_be16(SCLP_RC_SCCB_BOUNDARY_VIOLATION); work_sccb->h.response_code = cpu_to_be16(SCLP_RC_SCCB_BOUNDARY_VIOLATION);
goto out_write; goto out_write;
} }
sclp_c->execute(sclp, &work_sccb, code); sclp_c->execute(sclp, work_sccb, code);
out_write: out_write:
cpu_physical_memory_write(sccb, &work_sccb, cpu_physical_memory_write(sccb, work_sccb,
be16_to_cpu(work_sccb.h.length)); be16_to_cpu(work_sccb->h.length));
sclp_c->service_interrupt(sclp, sccb); sclp_c->service_interrupt(sclp, sccb);

View file

@ -491,6 +491,7 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
vcdev->io_region_offset = info->offset; vcdev->io_region_offset = info->offset;
vcdev->io_region = g_malloc0(info->size); vcdev->io_region = g_malloc0(info->size);
g_free(info);
/* check for the optional async command region */ /* check for the optional async command region */
ret = vfio_get_dev_region_info(vdev, VFIO_REGION_TYPE_CCW, ret = vfio_get_dev_region_info(vdev, VFIO_REGION_TYPE_CCW,
@ -503,6 +504,7 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
} }
vcdev->async_cmd_region_offset = info->offset; vcdev->async_cmd_region_offset = info->offset;
vcdev->async_cmd_region = g_malloc0(info->size); vcdev->async_cmd_region = g_malloc0(info->size);
g_free(info);
} }
ret = vfio_get_dev_region_info(vdev, VFIO_REGION_TYPE_CCW, ret = vfio_get_dev_region_info(vdev, VFIO_REGION_TYPE_CCW,
@ -515,6 +517,7 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
} }
vcdev->schib_region_offset = info->offset; vcdev->schib_region_offset = info->offset;
vcdev->schib_region = g_malloc(info->size); vcdev->schib_region = g_malloc(info->size);
g_free(info);
} }
ret = vfio_get_dev_region_info(vdev, VFIO_REGION_TYPE_CCW, ret = vfio_get_dev_region_info(vdev, VFIO_REGION_TYPE_CCW,
@ -528,9 +531,9 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
} }
vcdev->crw_region_offset = info->offset; vcdev->crw_region_offset = info->offset;
vcdev->crw_region = g_malloc(info->size); vcdev->crw_region = g_malloc(info->size);
g_free(info);
} }
g_free(info);
return; return;
out_err: out_err:

View file

@ -111,6 +111,7 @@ typedef struct CPUEntry {
uint8_t reserved1; uint8_t reserved1;
} QEMU_PACKED CPUEntry; } QEMU_PACKED CPUEntry;
#define SCLP_READ_SCP_INFO_FIXED_CPU_OFFSET 128
typedef struct ReadInfo { typedef struct ReadInfo {
SCCBHeader h; SCCBHeader h;
uint16_t rnmax; uint16_t rnmax;
@ -133,7 +134,15 @@ typedef struct ReadInfo {
uint16_t highest_cpu; uint16_t highest_cpu;
uint8_t _reserved5[124 - 122]; /* 122-123 */ uint8_t _reserved5[124 - 122]; /* 122-123 */
uint32_t hmfai; uint32_t hmfai;
uint8_t _reserved7[134 - 128]; /* 128-133 */
uint8_t fac134;
uint8_t _reserved8[144 - 135]; /* 135-143 */
struct CPUEntry entries[]; struct CPUEntry entries[];
/*
* When the Extended-Length SCCB (ELS) feature is enabled the
* start of the entries field begins at an offset denoted by the
* offset_cpu field, otherwise it's at an offset of 128.
*/
} QEMU_PACKED ReadInfo; } QEMU_PACKED ReadInfo;
typedef struct ReadCpuInfo { typedef struct ReadCpuInfo {
@ -178,7 +187,7 @@ typedef struct IoaCfgSccb {
typedef struct SCCB { typedef struct SCCB {
SCCBHeader h; SCCBHeader h;
char data[SCCB_DATA_LEN]; char data[];
} QEMU_PACKED SCCB; } QEMU_PACKED SCCB;
#define TYPE_SCLP "sclp" #define TYPE_SCLP "sclp"

View file

@ -417,6 +417,32 @@ static uint32_t cc_calc_vc(uint64_t low, uint64_t high)
} }
} }
static uint32_t cc_calc_muls_32(int64_t res)
{
const int64_t tmp = res >> 31;
if (!res) {
return 0;
} else if (tmp && tmp != -1) {
return 3;
} else if (res < 0) {
return 1;
}
return 2;
}
static uint64_t cc_calc_muls_64(int64_t res_high, uint64_t res_low)
{
if (!res_high && !res_low) {
return 0;
} else if (res_high + (res_low >> 63) != 0) {
return 3;
} else if (res_high < 0) {
return 1;
}
return 2;
}
static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
uint64_t src, uint64_t dst, uint64_t vr) uint64_t src, uint64_t dst, uint64_t vr)
{ {
@ -484,6 +510,9 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
case CC_OP_COMP_64: case CC_OP_COMP_64:
r = cc_calc_comp_64(dst); r = cc_calc_comp_64(dst);
break; break;
case CC_OP_MULS_64:
r = cc_calc_muls_64(src, dst);
break;
case CC_OP_ADD_32: case CC_OP_ADD_32:
r = cc_calc_add_32(src, dst, vr); r = cc_calc_add_32(src, dst, vr);
@ -512,6 +541,9 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
case CC_OP_COMP_32: case CC_OP_COMP_32:
r = cc_calc_comp_32(dst); r = cc_calc_comp_32(dst);
break; break;
case CC_OP_MULS_32:
r = cc_calc_muls_32(dst);
break;
case CC_OP_ICM: case CC_OP_ICM:
r = cc_calc_icm(src, dst); r = cc_calc_icm(src, dst);

View file

@ -112,6 +112,8 @@ struct CPUS390XState {
uint16_t external_call_addr; uint16_t external_call_addr;
DECLARE_BITMAP(emergency_signals, S390_MAX_CPUS); DECLARE_BITMAP(emergency_signals, S390_MAX_CPUS);
uint64_t diag318_info;
/* Fields up to this point are cleared by a CPU reset */ /* Fields up to this point are cleared by a CPU reset */
struct {} end_reset_fields; struct {} end_reset_fields;

View file

@ -23,6 +23,7 @@ typedef enum {
S390_FEAT_TYPE_STFL, S390_FEAT_TYPE_STFL,
S390_FEAT_TYPE_SCLP_CONF_CHAR, S390_FEAT_TYPE_SCLP_CONF_CHAR,
S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT,
S390_FEAT_TYPE_SCLP_FAC134,
S390_FEAT_TYPE_SCLP_CPU, S390_FEAT_TYPE_SCLP_CPU,
S390_FEAT_TYPE_MISC, S390_FEAT_TYPE_MISC,
S390_FEAT_TYPE_PLO, S390_FEAT_TYPE_PLO,

View file

@ -72,7 +72,7 @@ DEF_FEAT(INTERLOCKED_ACCESS_2, "iacc2", STFL, 52, "Interlocked-access facility 2
DEF_FEAT(STFLE_53, "stfle53", STFL, 53, "Various facilities introduced with z13") DEF_FEAT(STFLE_53, "stfle53", STFL, 53, "Various facilities introduced with z13")
DEF_FEAT(ENTROPY_ENC_COMP, "eec", STFL, 54, "Entropy encoding compression facility") DEF_FEAT(ENTROPY_ENC_COMP, "eec", STFL, 54, "Entropy encoding compression facility")
DEF_FEAT(MSA_EXT_5, "msa5-base", STFL, 57, "Message-security-assist-extension-5 facility (excluding subfunctions)") DEF_FEAT(MSA_EXT_5, "msa5-base", STFL, 57, "Message-security-assist-extension-5 facility (excluding subfunctions)")
DEF_FEAT(MISC_INSTRUCTION_EXT, "minste2", STFL, 58, "Miscellaneous-instruction-extensions facility 2") DEF_FEAT(MISC_INSTRUCTION_EXT2, "minste2", STFL, 58, "Miscellaneous-instruction-extensions facility 2")
DEF_FEAT(SEMAPHORE_ASSIST, "sema", STFL, 59, "Semaphore-assist facility") DEF_FEAT(SEMAPHORE_ASSIST, "sema", STFL, 59, "Semaphore-assist facility")
DEF_FEAT(TIME_SLICE_INSTRUMENTATION, "tsi", STFL, 60, "Time-slice Instrumentation facility") DEF_FEAT(TIME_SLICE_INSTRUMENTATION, "tsi", STFL, 60, "Time-slice Instrumentation facility")
DEF_FEAT(MISC_INSTRUCTION_EXT3, "minste3", STFL, 61, "Miscellaneous-Instruction-Extensions Facility 3") DEF_FEAT(MISC_INSTRUCTION_EXT3, "minste3", STFL, 61, "Miscellaneous-Instruction-Extensions Facility 3")
@ -97,6 +97,7 @@ DEF_FEAT(GUARDED_STORAGE, "gs", STFL, 133, "Guarded-storage facility")
DEF_FEAT(VECTOR_PACKED_DECIMAL, "vxpd", STFL, 134, "Vector packed decimal facility") DEF_FEAT(VECTOR_PACKED_DECIMAL, "vxpd", STFL, 134, "Vector packed decimal facility")
DEF_FEAT(VECTOR_ENH, "vxeh", STFL, 135, "Vector enhancements facility") DEF_FEAT(VECTOR_ENH, "vxeh", STFL, 135, "Vector enhancements facility")
DEF_FEAT(MULTIPLE_EPOCH, "mepoch", STFL, 139, "Multiple-epoch facility") DEF_FEAT(MULTIPLE_EPOCH, "mepoch", STFL, 139, "Multiple-epoch facility")
DEF_FEAT(EXTENDED_LENGTH_SCCB, "els", STFL, 140, "Extended-length SCCB facility")
DEF_FEAT(TEST_PENDING_EXT_INTERRUPTION, "tpei", STFL, 144, "Test-pending-external-interruption facility") DEF_FEAT(TEST_PENDING_EXT_INTERRUPTION, "tpei", STFL, 144, "Test-pending-external-interruption facility")
DEF_FEAT(INSERT_REFERENCE_BITS_MULT, "irbm", STFL, 145, "Insert-reference-bits-multiple facility") DEF_FEAT(INSERT_REFERENCE_BITS_MULT, "irbm", STFL, 145, "Insert-reference-bits-multiple facility")
DEF_FEAT(MSA_EXT_8, "msa8-base", STFL, 146, "Message-security-assist-extension-8 facility (excluding subfunctions)") DEF_FEAT(MSA_EXT_8, "msa8-base", STFL, 146, "Message-security-assist-extension-8 facility (excluding subfunctions)")
@ -121,6 +122,9 @@ DEF_FEAT(SIE_CMMA, "cmma", SCLP_CONF_CHAR_EXT, 1, "SIE: Collaborative-memory-man
DEF_FEAT(SIE_PFMFI, "pfmfi", SCLP_CONF_CHAR_EXT, 9, "SIE: PFMF interpretation facility") DEF_FEAT(SIE_PFMFI, "pfmfi", SCLP_CONF_CHAR_EXT, 9, "SIE: PFMF interpretation facility")
DEF_FEAT(SIE_IBS, "ibs", SCLP_CONF_CHAR_EXT, 10, "SIE: Interlock-and-broadcast-suppression facility") DEF_FEAT(SIE_IBS, "ibs", SCLP_CONF_CHAR_EXT, 10, "SIE: Interlock-and-broadcast-suppression facility")
/* Features exposed via SCLP SCCB Facilities byte 134 (bit numbers relative to byte-134) */
DEF_FEAT(DIAG_318, "diag318", SCLP_FAC134, 0, "Control program name and version codes")
/* Features exposed via SCLP CPU info. */ /* Features exposed via SCLP CPU info. */
DEF_FEAT(SIE_F2, "sief2", SCLP_CPU, 4, "SIE: interception format 2 (Virtual SIE)") DEF_FEAT(SIE_F2, "sief2", SCLP_CPU, 4, "SIE: interception format 2 (Virtual SIE)")
DEF_FEAT(SIE_SKEY, "skey", SCLP_CPU, 5, "SIE: Storage-key facility") DEF_FEAT(SIE_SKEY, "skey", SCLP_CPU, 5, "SIE: Storage-key facility")

View file

@ -824,6 +824,7 @@ static void check_consistency(const S390CPUModel *model)
{ S390_FEAT_PTFF_STOE, S390_FEAT_MULTIPLE_EPOCH }, { S390_FEAT_PTFF_STOE, S390_FEAT_MULTIPLE_EPOCH },
{ S390_FEAT_PTFF_STOUE, S390_FEAT_MULTIPLE_EPOCH }, { S390_FEAT_PTFF_STOUE, S390_FEAT_MULTIPLE_EPOCH },
{ S390_FEAT_AP_QUEUE_INTERRUPT_CONTROL, S390_FEAT_AP }, { S390_FEAT_AP_QUEUE_INTERRUPT_CONTROL, S390_FEAT_AP },
{ S390_FEAT_DIAG_318, S390_FEAT_EXTENDED_LENGTH_SCCB },
}; };
int i; int i;

View file

@ -610,4 +610,27 @@ void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
tcg_s390_program_interrupt(env, PGM_SPECIFICATION, retaddr); tcg_s390_program_interrupt(env, PGM_SPECIFICATION, retaddr);
} }
static void QEMU_NORETURN monitor_event(CPUS390XState *env,
uint64_t monitor_code,
uint8_t monitor_class, uintptr_t ra)
{
/* Store the Monitor Code and the Monitor Class Number into the lowcore */
stq_phys(env_cpu(env)->as,
env->psa + offsetof(LowCore, monitor_code), monitor_code);
stw_phys(env_cpu(env)->as,
env->psa + offsetof(LowCore, mon_class_num), monitor_class);
tcg_s390_program_interrupt(env, PGM_MONITOR, ra);
}
void HELPER(monitor_call)(CPUS390XState *env, uint64_t monitor_code,
uint32_t monitor_class)
{
g_assert(monitor_class <= 0xff);
if (env->cregs[8] & (0x8000 >> monitor_class)) {
monitor_event(env, monitor_code, monitor_class, GETPC());
}
}
#endif /* CONFIG_USER_ONLY */ #endif /* CONFIG_USER_ONLY */

View file

@ -412,7 +412,7 @@ static uint16_t base_GEN13_GA1[] = {
static uint16_t base_GEN14_GA1[] = { static uint16_t base_GEN14_GA1[] = {
S390_FEAT_ENTROPY_ENC_COMP, S390_FEAT_ENTROPY_ENC_COMP,
S390_FEAT_MISC_INSTRUCTION_EXT, S390_FEAT_MISC_INSTRUCTION_EXT2,
S390_FEAT_SEMAPHORE_ASSIST, S390_FEAT_SEMAPHORE_ASSIST,
S390_FEAT_TIME_SLICE_INSTRUMENTATION, S390_FEAT_TIME_SLICE_INSTRUMENTATION,
S390_FEAT_ORDER_PRESERVING_COMPRESSION, S390_FEAT_ORDER_PRESERVING_COMPRESSION,
@ -522,6 +522,8 @@ static uint16_t full_GEN12_GA1[] = {
S390_FEAT_AP_QUEUE_INTERRUPT_CONTROL, S390_FEAT_AP_QUEUE_INTERRUPT_CONTROL,
S390_FEAT_AP_FACILITIES_TEST, S390_FEAT_AP_FACILITIES_TEST,
S390_FEAT_AP, S390_FEAT_AP,
S390_FEAT_EXTENDED_LENGTH_SCCB,
S390_FEAT_DIAG_318,
}; };
static uint16_t full_GEN12_GA2[] = { static uint16_t full_GEN12_GA2[] = {
@ -716,6 +718,8 @@ static uint16_t qemu_MAX[] = {
S390_FEAT_MSA_EXT_5, S390_FEAT_MSA_EXT_5,
/* features introduced after the z13 */ /* features introduced after the z13 */
S390_FEAT_INSTRUCTION_EXEC_PROT, S390_FEAT_INSTRUCTION_EXEC_PROT,
S390_FEAT_MISC_INSTRUCTION_EXT2,
S390_FEAT_MSA_EXT_8,
}; };
/****** END FEATURE DEFS ******/ /****** END FEATURE DEFS ******/

View file

@ -430,6 +430,8 @@ const char *cc_name(enum cc_op cc_op)
[CC_OP_FLOGR] = "CC_OP_FLOGR", [CC_OP_FLOGR] = "CC_OP_FLOGR",
[CC_OP_LCBB] = "CC_OP_LCBB", [CC_OP_LCBB] = "CC_OP_LCBB",
[CC_OP_VC] = "CC_OP_VC", [CC_OP_VC] = "CC_OP_VC",
[CC_OP_MULS_32] = "CC_OP_MULS_32",
[CC_OP_MULS_64] = "CC_OP_MULS_64",
}; };
return cc_names[cc_op]; return cc_names[cc_op];

View file

@ -349,4 +349,5 @@ DEF_HELPER_3(sic, void, env, i64, i64)
DEF_HELPER_3(rpcit, void, env, i32, i32) DEF_HELPER_3(rpcit, void, env, i32, i32)
DEF_HELPER_5(pcistb, void, env, i32, i32, i64, i32) DEF_HELPER_5(pcistb, void, env, i32, i32, i64, i32)
DEF_HELPER_4(mpcifc, void, env, i32, i64, i32) DEF_HELPER_4(mpcifc, void, env, i32, i64, i32)
DEF_HELPER_3(monitor_call, void, env, i64, i32)
#endif #endif

View file

@ -52,6 +52,7 @@
/* ADD HALFWORD */ /* ADD HALFWORD */
C(0x4a00, AH, RX_a, Z, r1, m2_16s, new, r1_32, add, adds32) C(0x4a00, AH, RX_a, Z, r1, m2_16s, new, r1_32, add, adds32)
C(0xe37a, AHY, RXY_a, LD, r1, m2_16s, new, r1_32, add, adds32) C(0xe37a, AHY, RXY_a, LD, r1, m2_16s, new, r1_32, add, adds32)
C(0xe338, AGH, RXY_a, MIE2,r1, m2_16s, r1, 0, add, adds64)
/* ADD HALFWORD IMMEDIATE */ /* ADD HALFWORD IMMEDIATE */
C(0xa70a, AHI, RI_a, Z, r1, i2, new, r1_32, add, adds32) C(0xa70a, AHI, RI_a, Z, r1, i2, new, r1_32, add, adds32)
C(0xa70b, AGHI, RI_a, Z, r1, i2, r1, 0, add, adds64) C(0xa70b, AGHI, RI_a, Z, r1, i2, r1, 0, add, adds64)
@ -114,6 +115,8 @@
/* BRANCH RELATIVE AND SAVE */ /* BRANCH RELATIVE AND SAVE */
C(0xa705, BRAS, RI_b, Z, 0, 0, r1, 0, basi, 0) C(0xa705, BRAS, RI_b, Z, 0, 0, r1, 0, basi, 0)
C(0xc005, BRASL, RIL_b, Z, 0, 0, r1, 0, basi, 0) C(0xc005, BRASL, RIL_b, Z, 0, 0, r1, 0, basi, 0)
/* BRANCH INDIRECT ON CONDITION */
C(0xe347, BIC, RXY_b, MIE2,0, m2_64w, 0, 0, bc, 0)
/* BRANCH ON CONDITION */ /* BRANCH ON CONDITION */
C(0x0700, BCR, RR_b, Z, 0, r2_nz, 0, 0, bc, 0) C(0x0700, BCR, RR_b, Z, 0, r2_nz, 0, 0, bc, 0)
C(0x4700, BC, RX_b, Z, 0, a2, 0, 0, bc, 0) C(0x4700, BC, RX_b, Z, 0, a2, 0, 0, bc, 0)
@ -617,6 +620,9 @@
C(0x9a00, LAM, RS_a, Z, 0, a2, 0, 0, lam, 0) C(0x9a00, LAM, RS_a, Z, 0, a2, 0, 0, lam, 0)
C(0xeb9a, LAMY, RSY_a, LD, 0, a2, 0, 0, lam, 0) C(0xeb9a, LAMY, RSY_a, LD, 0, a2, 0, 0, lam, 0)
/* MONITOR CALL */
C(0xaf00, MC, SI, Z, la1, 0, 0, 0, mc, 0)
/* MOVE */ /* MOVE */
C(0xd200, MVC, SS_a, Z, la1, a2, 0, 0, mvc, 0) C(0xd200, MVC, SS_a, Z, la1, a2, 0, 0, mvc, 0)
C(0xe544, MVHHI, SIL, GIE, la1, i2, 0, m1_16, mov2, 0) C(0xe544, MVHHI, SIL, GIE, la1, i2, 0, m1_16, mov2, 0)
@ -649,8 +655,10 @@
/* MULTIPLY */ /* MULTIPLY */
C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0) C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0)
C(0xb9ec, MGRK, RRF_a, MIE2,r3_o, r2_o, r1_P, 0, muls128, 0)
C(0x5c00, M, RX_a, Z, r1p1_32s, m2_32s, new, r1_D32, mul, 0) C(0x5c00, M, RX_a, Z, r1p1_32s, m2_32s, new, r1_D32, mul, 0)
C(0xe35c, MFY, RXY_a, GIE, r1p1_32s, m2_32s, new, r1_D32, mul, 0) C(0xe35c, MFY, RXY_a, GIE, r1p1_32s, m2_32s, new, r1_D32, mul, 0)
C(0xe384, MG, RXY_a, MIE2,r1p1_o, m2_64, r1_P, 0, muls128, 0)
F(0xb317, MEEBR, RRE, Z, e1, e2, new, e1, meeb, 0, IF_BFP) F(0xb317, MEEBR, RRE, Z, e1, e2, new, e1, meeb, 0, IF_BFP)
F(0xb31c, MDBR, RRE, Z, f1, f2, new, f1, mdb, 0, IF_BFP) F(0xb31c, MDBR, RRE, Z, f1, f2, new, f1, mdb, 0, IF_BFP)
F(0xb34c, MXBR, RRE, Z, x2h, x2l, x1, x1, mxb, 0, IF_BFP) F(0xb34c, MXBR, RRE, Z, x2h, x2l, x1, x1, mxb, 0, IF_BFP)
@ -663,6 +671,7 @@
/* MULTIPLY HALFWORD */ /* MULTIPLY HALFWORD */
C(0x4c00, MH, RX_a, Z, r1_o, m2_16s, new, r1_32, mul, 0) C(0x4c00, MH, RX_a, Z, r1_o, m2_16s, new, r1_32, mul, 0)
C(0xe37c, MHY, RXY_a, GIE, r1_o, m2_16s, new, r1_32, mul, 0) C(0xe37c, MHY, RXY_a, GIE, r1_o, m2_16s, new, r1_32, mul, 0)
C(0xe33c, MGH, RXY_a, MIE2,r1_o, m2_16s, r1, 0, mul, 0)
/* MULTIPLY HALFWORD IMMEDIATE */ /* MULTIPLY HALFWORD IMMEDIATE */
C(0xa70c, MHI, RI_a, Z, r1_o, i2, new, r1_32, mul, 0) C(0xa70c, MHI, RI_a, Z, r1_o, i2, new, r1_32, mul, 0)
C(0xa70d, MGHI, RI_a, Z, r1_o, i2, r1, 0, mul, 0) C(0xa70d, MGHI, RI_a, Z, r1_o, i2, r1, 0, mul, 0)
@ -673,11 +682,15 @@
C(0xe386, MLG, RXY_a, Z, r1p1, m2_64, r1_P, 0, mul128, 0) C(0xe386, MLG, RXY_a, Z, r1p1, m2_64, r1_P, 0, mul128, 0)
/* MULTIPLY SINGLE */ /* MULTIPLY SINGLE */
C(0xb252, MSR, RRE, Z, r1_o, r2_o, new, r1_32, mul, 0) C(0xb252, MSR, RRE, Z, r1_o, r2_o, new, r1_32, mul, 0)
C(0xb9fd, MSRKC, RRF_a, MIE2,r3_32s, r2_32s, new, r1_32, mul, muls32)
C(0x7100, MS, RX_a, Z, r1_o, m2_32s, new, r1_32, mul, 0) C(0x7100, MS, RX_a, Z, r1_o, m2_32s, new, r1_32, mul, 0)
C(0xe351, MSY, RXY_a, LD, r1_o, m2_32s, new, r1_32, mul, 0) C(0xe351, MSY, RXY_a, LD, r1_o, m2_32s, new, r1_32, mul, 0)
C(0xe353, MSC, RXY_a, MIE2,r1_32s, m2_32s, new, r1_32, mul, muls32)
C(0xb90c, MSGR, RRE, Z, r1_o, r2_o, r1, 0, mul, 0) C(0xb90c, MSGR, RRE, Z, r1_o, r2_o, r1, 0, mul, 0)
C(0xb9ed, MSGRKC, RRF_a, MIE2,r3_o, r2_o, new_P, out2_r1, muls128, muls64)
C(0xb91c, MSGFR, RRE, Z, r1_o, r2_32s, r1, 0, mul, 0) C(0xb91c, MSGFR, RRE, Z, r1_o, r2_32s, r1, 0, mul, 0)
C(0xe30c, MSG, RXY_a, Z, r1_o, m2_64, r1, 0, mul, 0) C(0xe30c, MSG, RXY_a, Z, r1_o, m2_64, r1, 0, mul, 0)
C(0xe383, MSGC, RXY_a, MIE2,r1_o, m2_64, new_P, out2_r1, muls128, muls64)
C(0xe31c, MSGF, RXY_a, Z, r1_o, m2_32s, r1, 0, mul, 0) C(0xe31c, MSGF, RXY_a, Z, r1_o, m2_32s, r1, 0, mul, 0)
/* MULTIPLY SINGLE IMMEDIATE */ /* MULTIPLY SINGLE IMMEDIATE */
C(0xc201, MSFI, RIL_a, GIE, r1_o, i2, new, r1_32, mul, 0) C(0xc201, MSFI, RIL_a, GIE, r1_o, i2, new, r1_32, mul, 0)
@ -882,6 +895,7 @@
/* SUBTRACT HALFWORD */ /* SUBTRACT HALFWORD */
C(0x4b00, SH, RX_a, Z, r1, m2_16s, new, r1_32, sub, subs32) C(0x4b00, SH, RX_a, Z, r1, m2_16s, new, r1_32, sub, subs32)
C(0xe37b, SHY, RXY_a, LD, r1, m2_16s, new, r1_32, sub, subs32) C(0xe37b, SHY, RXY_a, LD, r1, m2_16s, new, r1_32, sub, subs32)
C(0xe339, SGH, RXY_a, MIE2,r1, m2_16s, r1, 0, sub, subs64)
/* SUBTRACT HIGH */ /* SUBTRACT HIGH */
C(0xb9c9, SHHHR, RRF_a, HW, r2_sr32, r3_sr32, new, r1_32h, sub, subs32) C(0xb9c9, SHHHR, RRF_a, HW, r2_sr32, r3_sr32, new, r1_32h, sub, subs32)
C(0xb9d9, SHHLR, RRF_a, HW, r2_sr32, r3, new, r1_32h, sub, subs32) C(0xb9d9, SHHLR, RRF_a, HW, r2_sr32, r3, new, r1_32h, sub, subs32)
@ -968,6 +982,7 @@
D(0xb92d, KMCTR, RRF_b, MSA4, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KMCTR) D(0xb92d, KMCTR, RRF_b, MSA4, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KMCTR)
D(0xb92e, KM, RRE, MSA, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KM) D(0xb92e, KM, RRE, MSA, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KM)
D(0xb92f, KMC, RRE, MSA, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KMC) D(0xb92f, KMC, RRE, MSA, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KMC)
D(0xb929, KMA, RRF_b, MSA8, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KMA)
D(0xb93c, PPNO, RRE, MSA5, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_PPNO) D(0xb93c, PPNO, RRE, MSA5, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_PPNO)
D(0xb93e, KIMD, RRE, MSA, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KIMD) D(0xb93e, KIMD, RRE, MSA, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KIMD)
D(0xb93f, KLMD, RRE, MSA, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KLMD) D(0xb93f, KLMD, RRE, MSA, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KLMD)

View file

@ -175,6 +175,7 @@ enum cc_op {
CC_OP_SUBB_64, /* overflow on unsigned sub-borrow (64bit) */ CC_OP_SUBB_64, /* overflow on unsigned sub-borrow (64bit) */
CC_OP_ABS_64, /* sign eval on abs (64bit) */ CC_OP_ABS_64, /* sign eval on abs (64bit) */
CC_OP_NABS_64, /* sign eval on nabs (64bit) */ CC_OP_NABS_64, /* sign eval on nabs (64bit) */
CC_OP_MULS_64, /* overflow on signed multiply (64bit) */
CC_OP_ADD_32, /* overflow on add (32bit) */ CC_OP_ADD_32, /* overflow on add (32bit) */
CC_OP_ADDU_32, /* overflow on unsigned add (32bit) */ CC_OP_ADDU_32, /* overflow on unsigned add (32bit) */
@ -184,6 +185,7 @@ enum cc_op {
CC_OP_SUBB_32, /* overflow on unsigned sub-borrow (32bit) */ CC_OP_SUBB_32, /* overflow on unsigned sub-borrow (32bit) */
CC_OP_ABS_32, /* sign eval on abs (64bit) */ CC_OP_ABS_32, /* sign eval on abs (64bit) */
CC_OP_NABS_32, /* sign eval on nabs (64bit) */ CC_OP_NABS_32, /* sign eval on nabs (64bit) */
CC_OP_MULS_32, /* overflow on signed multiply (32bit) */
CC_OP_COMP_32, /* complement */ CC_OP_COMP_32, /* complement */
CC_OP_COMP_64, /* complement */ CC_OP_COMP_64, /* complement */

View file

@ -105,6 +105,7 @@
#define DIAG_TIMEREVENT 0x288 #define DIAG_TIMEREVENT 0x288
#define DIAG_IPL 0x308 #define DIAG_IPL 0x308
#define DIAG_SET_CONTROL_PROGRAM_CODES 0x318
#define DIAG_KVM_HYPERCALL 0x500 #define DIAG_KVM_HYPERCALL 0x500
#define DIAG_KVM_BREAKPOINT 0x501 #define DIAG_KVM_BREAKPOINT 0x501
@ -602,6 +603,11 @@ int kvm_arch_put_registers(CPUState *cs, int level)
cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_ETOKEN; cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_ETOKEN;
} }
if (can_sync_regs(cs, KVM_SYNC_DIAG318)) {
cs->kvm_run->s.regs.diag318 = env->diag318_info;
cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_DIAG318;
}
/* Finally the prefix */ /* Finally the prefix */
if (can_sync_regs(cs, KVM_SYNC_PREFIX)) { if (can_sync_regs(cs, KVM_SYNC_PREFIX)) {
cs->kvm_run->s.regs.prefix = env->psa; cs->kvm_run->s.regs.prefix = env->psa;
@ -741,6 +747,10 @@ int kvm_arch_get_registers(CPUState *cs)
} }
} }
if (can_sync_regs(cs, KVM_SYNC_DIAG318)) {
env->diag318_info = cs->kvm_run->s.regs.diag318;
}
return 0; return 0;
} }
@ -1601,6 +1611,27 @@ static int handle_sw_breakpoint(S390CPU *cpu, struct kvm_run *run)
return -ENOENT; return -ENOENT;
} }
static void handle_diag_318(S390CPU *cpu, struct kvm_run *run)
{
uint64_t reg = (run->s390_sieic.ipa & 0x00f0) >> 4;
uint64_t diag318_info = run->s.regs.gprs[reg];
/*
* DIAG 318 can only be enabled with KVM support. As such, let's
* ensure a guest cannot execute this instruction erroneously.
*/
if (!s390_has_feat(S390_FEAT_DIAG_318)) {
kvm_s390_program_interrupt(cpu, PGM_SPECIFICATION);
}
cpu->env.diag318_info = diag318_info;
if (can_sync_regs(CPU(cpu), KVM_SYNC_DIAG318)) {
run->s.regs.diag318 = diag318_info;
run->kvm_dirty_regs |= KVM_SYNC_DIAG318;
}
}
#define DIAG_KVM_CODE_MASK 0x000000000000ffff #define DIAG_KVM_CODE_MASK 0x000000000000ffff
static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb) static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb)
@ -1620,6 +1651,9 @@ static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb)
case DIAG_IPL: case DIAG_IPL:
kvm_handle_diag_308(cpu, run); kvm_handle_diag_308(cpu, run);
break; break;
case DIAG_SET_CONTROL_PROGRAM_CODES:
handle_diag_318(cpu, run);
break;
case DIAG_KVM_HYPERCALL: case DIAG_KVM_HYPERCALL:
r = handle_hypercall(cpu, run); r = handle_hypercall(cpu, run);
break; break;
@ -2456,6 +2490,19 @@ void kvm_s390_get_host_cpu_model(S390CPUModel *model, Error **errp)
KVM_S390_VM_CRYPTO_ENABLE_APIE)) { KVM_S390_VM_CRYPTO_ENABLE_APIE)) {
set_bit(S390_FEAT_AP, model->features); set_bit(S390_FEAT_AP, model->features);
} }
/*
* Extended-Length SCCB is handled entirely within QEMU.
* For PV guests this is completely fenced by the Ultravisor, as Service
* Call error checking and STFLE interpretation are handled via SIE.
*/
set_bit(S390_FEAT_EXTENDED_LENGTH_SCCB, model->features);
/* DIAGNOSE 0x318 is not supported under protected virtualization */
if (!s390_is_pv() && kvm_check_extension(kvm_state, KVM_CAP_S390_DIAG318)) {
set_bit(S390_FEAT_DIAG_318, model->features);
}
/* strip of features that are not part of the maximum model */ /* strip of features that are not part of the maximum model */
bitmap_and(model->features, model->features, model->def->full_feat, bitmap_and(model->features, model->features, model->def->full_feat,
S390_FEAT_MAX); S390_FEAT_MAX);

View file

@ -234,6 +234,22 @@ const VMStateDescription vmstate_etoken = {
} }
}; };
static bool diag318_needed(void *opaque)
{
return s390_has_feat(S390_FEAT_DIAG_318);
}
const VMStateDescription vmstate_diag318 = {
.name = "cpu/diag318",
.version_id = 1,
.minimum_version_id = 1,
.needed = diag318_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT64(env.diag318_info, S390CPU),
VMSTATE_END_OF_LIST()
}
};
const VMStateDescription vmstate_s390_cpu = { const VMStateDescription vmstate_s390_cpu = {
.name = "cpu", .name = "cpu",
.post_load = cpu_post_load, .post_load = cpu_post_load,
@ -270,6 +286,7 @@ const VMStateDescription vmstate_s390_cpu = {
&vmstate_gscb, &vmstate_gscb,
&vmstate_bpbc, &vmstate_bpbc,
&vmstate_etoken, &vmstate_etoken,
&vmstate_diag318,
NULL NULL
}, },
}; };

View file

@ -646,6 +646,7 @@ static void gen_op_calc_cc(DisasContext *s)
case CC_OP_NZ_F64: case CC_OP_NZ_F64:
case CC_OP_FLOGR: case CC_OP_FLOGR:
case CC_OP_LCBB: case CC_OP_LCBB:
case CC_OP_MULS_32:
/* 1 argument */ /* 1 argument */
gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy); gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy);
break; break;
@ -660,6 +661,7 @@ static void gen_op_calc_cc(DisasContext *s)
case CC_OP_SLA_64: case CC_OP_SLA_64:
case CC_OP_NZ_F128: case CC_OP_NZ_F128:
case CC_OP_VC: case CC_OP_VC:
case CC_OP_MULS_64:
/* 2 arguments */ /* 2 arguments */
gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, dummy); gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, dummy);
break; break;
@ -2708,6 +2710,12 @@ static DisasJumpType op_msa(DisasContext *s, DisasOps *o)
TCGv_i32 t_r1, t_r2, t_r3, type; TCGv_i32 t_r1, t_r2, t_r3, type;
switch (s->insn->data) { switch (s->insn->data) {
case S390_FEAT_TYPE_KMA:
if (r3 == r1 || r3 == r2) {
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
/* FALL THROUGH */
case S390_FEAT_TYPE_KMCTR: case S390_FEAT_TYPE_KMCTR:
if (r3 & 1 || !r3) { if (r3 & 1 || !r3) {
gen_program_exception(s, PGM_SPECIFICATION); gen_program_exception(s, PGM_SPECIFICATION);
@ -3302,6 +3310,27 @@ static DisasJumpType op_lcbb(DisasContext *s, DisasOps *o)
return DISAS_NEXT; return DISAS_NEXT;
} }
static DisasJumpType op_mc(DisasContext *s, DisasOps *o)
{
#if !defined(CONFIG_USER_ONLY)
TCGv_i32 i2;
#endif
const uint16_t monitor_class = get_field(s, i2);
if (monitor_class & 0xff00) {
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
#if !defined(CONFIG_USER_ONLY)
i2 = tcg_const_i32(monitor_class);
gen_helper_monitor_call(cpu_env, o->addr1, i2);
tcg_temp_free_i32(i2);
#endif
/* Defaults to a NOP. */
return DISAS_NEXT;
}
static DisasJumpType op_mov2(DisasContext *s, DisasOps *o) static DisasJumpType op_mov2(DisasContext *s, DisasOps *o)
{ {
o->out = o->in2; o->out = o->in2;
@ -3518,6 +3547,12 @@ static DisasJumpType op_mul128(DisasContext *s, DisasOps *o)
return DISAS_NEXT; return DISAS_NEXT;
} }
static DisasJumpType op_muls128(DisasContext *s, DisasOps *o)
{
tcg_gen_muls2_i64(o->out2, o->out, o->in1, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_meeb(DisasContext *s, DisasOps *o) static DisasJumpType op_meeb(DisasContext *s, DisasOps *o)
{ {
gen_helper_meeb(o->out, cpu_env, o->in1, o->in2); gen_helper_meeb(o->out, cpu_env, o->in1, o->in2);
@ -5283,6 +5318,17 @@ static void cout_tm64(DisasContext *s, DisasOps *o)
gen_op_update2_cc_i64(s, CC_OP_TM_64, o->in1, o->in2); gen_op_update2_cc_i64(s, CC_OP_TM_64, o->in1, o->in2);
} }
static void cout_muls32(DisasContext *s, DisasOps *o)
{
gen_op_update1_cc_i64(s, CC_OP_MULS_32, o->out);
}
static void cout_muls64(DisasContext *s, DisasOps *o)
{
/* out contains "high" part, out2 contains "low" part of 128 bit result */
gen_op_update2_cc_i64(s, CC_OP_MULS_64, o->out, o->out2);
}
/* ====================================================================== */ /* ====================================================================== */
/* The "PREParation" generators. These initialize the DisasOps.OUT fields /* The "PREParation" generators. These initialize the DisasOps.OUT fields
with the TCG register to which we will write. Used in combination with with the TCG register to which we will write. Used in combination with
@ -5338,6 +5384,12 @@ static void wout_r1(DisasContext *s, DisasOps *o)
} }
#define SPEC_wout_r1 0 #define SPEC_wout_r1 0
static void wout_out2_r1(DisasContext *s, DisasOps *o)
{
store_reg(get_field(s, r1), o->out2);
}
#define SPEC_wout_out2_r1 0
static void wout_r1_8(DisasContext *s, DisasOps *o) static void wout_r1_8(DisasContext *s, DisasOps *o)
{ {
int r1 = get_field(s, r1); int r1 = get_field(s, r1);
@ -5542,6 +5594,13 @@ static void in1_r1p1(DisasContext *s, DisasOps *o)
} }
#define SPEC_in1_r1p1 SPEC_r1_even #define SPEC_in1_r1p1 SPEC_r1_even
static void in1_r1p1_o(DisasContext *s, DisasOps *o)
{
o->in1 = regs[get_field(s, r1) + 1];
o->g_in1 = true;
}
#define SPEC_in1_r1p1_o SPEC_r1_even
static void in1_r1p1_32s(DisasContext *s, DisasOps *o) static void in1_r1p1_32s(DisasContext *s, DisasOps *o)
{ {
o->in1 = tcg_temp_new_i64(); o->in1 = tcg_temp_new_i64();
@ -5922,6 +5981,14 @@ static void in2_m2_64(DisasContext *s, DisasOps *o)
} }
#define SPEC_in2_m2_64 0 #define SPEC_in2_m2_64 0
static void in2_m2_64w(DisasContext *s, DisasOps *o)
{
in2_a2(s, o);
tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
gen_addi_and_wrap_i64(s, o->in2, o->in2, 0);
}
#define SPEC_in2_m2_64w 0
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
static void in2_m2_64a(DisasContext *s, DisasOps *o) static void in2_m2_64a(DisasContext *s, DisasOps *o)
{ {
@ -6093,11 +6160,13 @@ enum DisasInsnEnum {
#define FAC_MSA3 S390_FEAT_MSA_EXT_3 /* msa-extension-3 facility */ #define FAC_MSA3 S390_FEAT_MSA_EXT_3 /* msa-extension-3 facility */
#define FAC_MSA4 S390_FEAT_MSA_EXT_4 /* msa-extension-4 facility */ #define FAC_MSA4 S390_FEAT_MSA_EXT_4 /* msa-extension-4 facility */
#define FAC_MSA5 S390_FEAT_MSA_EXT_5 /* msa-extension-5 facility */ #define FAC_MSA5 S390_FEAT_MSA_EXT_5 /* msa-extension-5 facility */
#define FAC_MSA8 S390_FEAT_MSA_EXT_8 /* msa-extension-8 facility */
#define FAC_ECT S390_FEAT_EXTRACT_CPU_TIME #define FAC_ECT S390_FEAT_EXTRACT_CPU_TIME
#define FAC_PCI S390_FEAT_ZPCI /* z/PCI facility */ #define FAC_PCI S390_FEAT_ZPCI /* z/PCI facility */
#define FAC_AIS S390_FEAT_ADAPTER_INT_SUPPRESSION #define FAC_AIS S390_FEAT_ADAPTER_INT_SUPPRESSION
#define FAC_V S390_FEAT_VECTOR /* vector facility */ #define FAC_V S390_FEAT_VECTOR /* vector facility */
#define FAC_VE S390_FEAT_VECTOR_ENH /* vector enhancements facility 1 */ #define FAC_VE S390_FEAT_VECTOR_ENH /* vector enhancements facility 1 */
#define FAC_MIE2 S390_FEAT_MISC_INSTRUCTION_EXT2 /* miscellaneous-instruction-extensions facility 2 */
static const DisasInsn insn_info[] = { static const DisasInsn insn_info[] = {
#include "insn-data.def" #include "insn-data.def"