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

s390x update:
- tcg: implement the vector enhancements facility and bump the
  'qemu' cpu model to a stripped-down z14 GA2
- fix psw.mask handling in signals
- fix vfio-ccw sense data handling

# gpg: Signature made Mon 21 Jun 2021 10:53:00 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-gitlab/tags/s390x-20210621: (37 commits)
  s390x/css: Add passthrough IRB
  s390x/css: Refactor IRB construction
  s390x/css: Split out the IRB sense data
  s390x/css: Introduce an ESW struct
  linux-user/s390x: Save and restore psw.mask properly
  target/s390x: Use s390_cpu_{set_psw, get_psw_mask} in gdbstub
  target/s390x: Improve s390_cpu_dump_state vs cc_op
  target/s390x: Do not modify cpu state in s390_cpu_get_psw_mask
  target/s390x: Expose load_psw and get_psw_mask to cpu.h
  configure: Check whether we can compile the s390-ccw bios with -msoft-float
  s390x/cpumodel: Bump up QEMU model to a stripped-down IBM z14 GA2
  s390x/tcg: We support Vector enhancements facility
  linux-user: elf: s390x: Prepare for Vector enhancements facility
  s390x/tcg: Implement VECTOR FP (MAXIMUM|MINIMUM)
  s390x/tcg: Implement VECTOR FP NEGATIVE MULTIPLY AND (ADD|SUBTRACT)
  s390x/tcg: Implement 32/128 bit for VECTOR FP MULTIPLY AND (ADD|SUBTRACT)
  s390x/tcg: Implement 32/128 bit for VECTOR FP TEST DATA CLASS IMMEDIATE
  s390x/tcg: Implement 32/128 bit for VECTOR FP PERFORM SIGN OPERATION
  s390x/tcg: Implement 128 bit for VECTOR FP LOAD ROUNDED
  s390x/tcg: Implement 64 bit for VECTOR FP LOAD LENGTHENED
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2021-06-22 14:36:58 +01:00
30 changed files with 1649 additions and 619 deletions
Vendored
+1 -1
View File
@@ -5424,7 +5424,7 @@ if test "$cpu" = "s390x" ; then
write_c_skeleton
compile_prog "-march=z900" ""
has_z900=$?
if [ $has_z900 = 0 ] || compile_prog "-march=z10" ""; then
if [ $has_z900 = 0 ] || compile_object "-march=z10 -msoft-float -Werror"; then
if [ $has_z900 != 0 ]; then
echo "WARNING: Your compiler does not support the z900!"
echo " The s390-ccw bios will only work with guest CPUs >= z10."
+1
View File
@@ -129,6 +129,7 @@ static void emulated_ccw_3270_realize(DeviceState *ds, Error **errp)
EMULATED_CCW_3270_CHPID_TYPE);
sch->do_subchannel_work = do_subchannel_work_virtual;
sch->ccw_cb = emulated_ccw_3270_cb;
sch->irb_cb = build_irb_virtual;
ck->init(dev, &err);
if (err) {
+63 -24
View File
@@ -1335,6 +1335,14 @@ static void copy_schib_to_guest(SCHIB *dest, const SCHIB *src)
}
}
void copy_esw_to_guest(ESW *dest, const ESW *src)
{
dest->word0 = cpu_to_be32(src->word0);
dest->erw = cpu_to_be32(src->erw);
dest->word2 = cpu_to_be64(src->word2);
dest->word4 = cpu_to_be32(src->word4);
}
IOInstEnding css_do_stsch(SubchDev *sch, SCHIB *schib)
{
int ret;
@@ -1604,9 +1612,8 @@ static void copy_irb_to_guest(IRB *dest, const IRB *src, const PMCW *pmcw,
copy_scsw_to_guest(&dest->scsw, &src->scsw);
for (i = 0; i < ARRAY_SIZE(dest->esw); i++) {
dest->esw[i] = cpu_to_be32(src->esw[i]);
}
copy_esw_to_guest(&dest->esw, &src->esw);
for (i = 0; i < ARRAY_SIZE(dest->ecw); i++) {
dest->ecw[i] = cpu_to_be32(src->ecw[i]);
}
@@ -1632,6 +1639,55 @@ static void copy_irb_to_guest(IRB *dest, const IRB *src, const PMCW *pmcw,
*irb_len = sizeof(*dest);
}
static void build_irb_sense_data(SubchDev *sch, IRB *irb)
{
int i;
/* Attention: sense_data is already BE! */
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]);
}
}
void build_irb_passthrough(SubchDev *sch, IRB *irb)
{
/* Copy ESW from hardware */
irb->esw = sch->esw;
/*
* If (irb->esw.erw & ESW_ERW_SENSE) is true, then the contents
* of the ECW is sense data. If false, then it is model-dependent
* information. Either way, copy it into the IRB for the guest to
* read/decide what to do with.
*/
build_irb_sense_data(sch, irb);
}
void build_irb_virtual(SubchDev *sch, IRB *irb)
{
SCHIB *schib = &sch->curr_status;
uint16_t stctl = schib->scsw.ctrl & SCSW_CTRL_MASK_STCTL;
if (stctl & SCSW_STCTL_STATUS_PEND) {
if (schib->scsw.cstat & (SCSW_CSTAT_DATA_CHECK |
SCSW_CSTAT_CHN_CTRL_CHK |
SCSW_CSTAT_INTF_CTRL_CHK)) {
irb->scsw.flags |= SCSW_FLAGS_MASK_ESWF;
irb->esw.word0 = 0x04804000;
} else {
irb->esw.word0 = 0x00800000;
}
/* If a unit check is pending, copy sense data. */
if ((schib->scsw.dstat & SCSW_DSTAT_UNIT_CHECK) &&
(schib->pmcw.chars & PMCW_CHARS_MASK_CSENSE)) {
irb->scsw.flags |= SCSW_FLAGS_MASK_ESWF | SCSW_FLAGS_MASK_ECTL;
build_irb_sense_data(sch, irb);
irb->esw.erw = ESW_ERW_SENSE | (sizeof(sch->sense_data) << 8);
}
}
}
int css_do_tsch_get_irb(SubchDev *sch, IRB *target_irb, int *irb_len)
{
SCHIB *schib = &sch->curr_status;
@@ -1650,29 +1706,12 @@ int css_do_tsch_get_irb(SubchDev *sch, IRB *target_irb, int *irb_len)
/* Copy scsw from current status. */
irb.scsw = schib->scsw;
if (stctl & SCSW_STCTL_STATUS_PEND) {
if (schib->scsw.cstat & (SCSW_CSTAT_DATA_CHECK |
SCSW_CSTAT_CHN_CTRL_CHK |
SCSW_CSTAT_INTF_CTRL_CHK)) {
irb.scsw.flags |= SCSW_FLAGS_MASK_ESWF;
irb.esw[0] = 0x04804000;
} else {
irb.esw[0] = 0x00800000;
}
/* If a unit check is pending, copy sense data. */
if ((schib->scsw.dstat & SCSW_DSTAT_UNIT_CHECK) &&
(schib->pmcw.chars & PMCW_CHARS_MASK_CSENSE)) {
int i;
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));
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);
}
/* Build other IRB data, if necessary */
if (sch->irb_cb) {
sch->irb_cb(sch, &irb);
}
/* Store the irb to the guest. */
p = schib->pmcw;
copy_irb_to_guest(target_irb, &irb, &p, irb_len);
+1
View File
@@ -124,6 +124,7 @@ static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp)
}
sch->driver_data = cdev;
sch->do_subchannel_work = do_subchannel_work_passthrough;
sch->irb_cb = build_irb_passthrough;
ccw_dev->sch = sch;
ret = css_sch_build_schib(sch, &cdev->hostid);
+3
View File
@@ -802,7 +802,10 @@ DEFINE_CCW_MACHINE(6_1, "6.1", true);
static void ccw_machine_6_0_instance_options(MachineState *machine)
{
static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V6_0 };
ccw_machine_6_1_instance_options(machine);
s390_set_qemu_cpu_model(0x2964, 13, 2, qemu_cpu_feat);
}
static void ccw_machine_6_0_class_options(MachineClass *mc)
+1
View File
@@ -753,6 +753,7 @@ static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp)
sch->id.reserved = 0xff;
sch->id.cu_type = VIRTIO_CCW_CU_TYPE;
sch->do_subchannel_work = do_subchannel_work_virtual;
sch->irb_cb = build_irb_virtual;
ccw_dev->sch = sch;
dev->indicators = NULL;
dev->revision = -1;
+4
View File
@@ -321,6 +321,7 @@ static void vfio_ccw_io_notifier_handler(void *opaque)
SCHIB *schib = &sch->curr_status;
SCSW s;
IRB irb;
ESW esw;
int size;
if (!event_notifier_test_and_clear(&vcdev->io_notifier)) {
@@ -371,6 +372,9 @@ static void vfio_ccw_io_notifier_handler(void *opaque)
copy_scsw_to_guest(&s, &irb.scsw);
schib->scsw = s;
copy_esw_to_guest(&esw, &irb.esw);
sch->esw = esw;
/* If a uint check is pending, copy sense data. */
if ((schib->scsw.dstat & SCSW_DSTAT_UNIT_CHECK) &&
(schib->pmcw.chars & PMCW_CHARS_MASK_CSENSE)) {
+7
View File
@@ -605,6 +605,13 @@ typedef struct {
#define HWCAP_S390_HIGH_GPRS 512
#define HWCAP_S390_TE 1024
#define HWCAP_S390_VXRS 2048
#define HWCAP_S390_VXRS_BCD 4096
#define HWCAP_S390_VXRS_EXT 8192
#define HWCAP_S390_GS 16384
#define HWCAP_S390_VXRS_EXT2 32768
#define HWCAP_S390_VXRS_PDE 65536
#define HWCAP_S390_SORT 131072
#define HWCAP_S390_DFLT 262144
/* M68K specific definitions. */
/* We use the top 24 bits to encode information about the
+5
View File
@@ -138,8 +138,10 @@ struct SubchDev {
int (*ccw_cb) (SubchDev *, CCW1);
void (*disable_cb)(SubchDev *);
IOInstEnding (*do_subchannel_work) (SubchDev *);
void (*irb_cb)(SubchDev *, IRB *);
SenseId id;
void *driver_data;
ESW esw;
};
static inline void sch_gen_unit_exception(SubchDev *sch)
@@ -201,6 +203,7 @@ int css_sch_build_schib(SubchDev *sch, CssDevId *dev_id);
unsigned int css_find_free_chpid(uint8_t cssid);
uint16_t css_build_subchannel_id(SubchDev *sch);
void copy_scsw_to_guest(SCSW *dest, const SCSW *src);
void copy_esw_to_guest(ESW *dest, const ESW *src);
void css_inject_io_interrupt(SubchDev *sch);
void css_reset(void);
void css_reset_sch(SubchDev *sch);
@@ -215,6 +218,8 @@ void css_clear_sei_pending(void);
IOInstEnding s390_ccw_cmd_request(SubchDev *sch);
IOInstEnding do_subchannel_work_virtual(SubchDev *sub);
IOInstEnding do_subchannel_work_passthrough(SubchDev *sub);
void build_irb_passthrough(SubchDev *sch, IRB *irb);
void build_irb_virtual(SubchDev *sch, IRB *irb);
int s390_ccw_halt(SubchDev *sch);
int s390_ccw_clear(SubchDev *sch);
+11 -1
View File
@@ -123,10 +123,20 @@ typedef struct SCHIB {
uint8_t mda[4];
} QEMU_PACKED SCHIB;
/* format-0 extended-status word */
typedef struct ESW {
uint32_t word0; /* subchannel logout for format 0 */
uint32_t erw;
uint64_t word2; /* failing-storage address for format 0 */
uint32_t word4; /* secondary-CCW address for format 0 */
} QEMU_PACKED ESW;
#define ESW_ERW_SENSE 0x01000000
/* interruption response block */
typedef struct IRB {
SCSW scsw;
uint32_t esw[5];
ESW esw;
uint32_t ecw[8];
uint32_t emw[8];
} IRB;
+1
View File
@@ -1376,6 +1376,7 @@ static uint32_t get_elf_hwcap(void)
hwcap |= HWCAP_S390_ETF3EH;
}
GET_FEATURE(S390_FEAT_VECTOR, HWCAP_S390_VXRS);
GET_FEATURE(S390_FEAT_VECTOR_ENH, HWCAP_S390_VXRS_EXT);
return hwcap;
}
+32 -5
View File
@@ -112,15 +112,23 @@ get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
return (sp - frame_size) & -8ul;
}
#define PSW_USER_BITS (PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | \
PSW_MASK_MCHECK | PSW_MASK_PSTATE | PSW_ASC_PRIMARY)
#define PSW_MASK_USER (PSW_MASK_ASC | PSW_MASK_CC | PSW_MASK_PM | \
PSW_MASK_64 | PSW_MASK_32)
static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
{
uint64_t psw_mask = s390_cpu_get_psw_mask(env);
int i;
/*
* Copy a 'clean' PSW mask to the user to avoid leaking
* information about whether PER is currently on.
* TODO: qemu does not support PSW_MASK_RI; it will never be set.
*/
__put_user(env->psw.mask, &sregs->regs.psw.mask);
psw_mask = PSW_USER_BITS | (psw_mask & PSW_MASK_USER);
__put_user(psw_mask, &sregs->regs.psw.mask);
__put_user(env->psw.addr, &sregs->regs.psw.addr);
for (i = 0; i < 16; i++) {
@@ -289,7 +297,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
static void restore_sigregs(CPUS390XState *env, target_sigregs *sc)
{
target_ulong prev_addr;
uint64_t prev_addr, prev_mask, mask, addr;
int i;
for (i = 0; i < 16; i++) {
@@ -297,9 +305,28 @@ static void restore_sigregs(CPUS390XState *env, target_sigregs *sc)
}
prev_addr = env->psw.addr;
__get_user(env->psw.mask, &sc->regs.psw.mask);
__get_user(env->psw.addr, &sc->regs.psw.addr);
trace_user_s390x_restore_sigregs(env, env->psw.addr, prev_addr);
__get_user(mask, &sc->regs.psw.mask);
__get_user(addr, &sc->regs.psw.addr);
trace_user_s390x_restore_sigregs(env, addr, prev_addr);
/*
* Use current psw.mask to preserve PER bit.
* TODO:
* if (!is_ri_task(current) && (user_sregs.regs.psw.mask & PSW_MASK_RI))
* return -EINVAL;
* Simply do not allow it to be set in mask.
*/
prev_mask = s390_cpu_get_psw_mask(env);
mask = (prev_mask & ~PSW_MASK_USER) | (mask & PSW_MASK_USER);
/* Check for invalid user address space control. */
if ((mask & PSW_MASK_ASC) == PSW_ASC_HOME) {
mask = (mask & ~PSW_MASK_ASC) | PSW_ASC_PRIMARY;
}
/* Check for invalid amode. */
if (mask & PSW_MASK_64) {
mask |= PSW_MASK_32;
}
s390_cpu_set_psw(env, mask, addr);
for (i = 0; i < 16; i++) {
__get_user(env->aregs[i], &sc->regs.acrs[i]);
+1 -1
View File
@@ -509,7 +509,7 @@ uint32_t HELPER(calc_cc)(CPUS390XState *env, uint32_t cc_op, uint64_t src,
#ifndef CONFIG_USER_ONLY
void HELPER(load_psw)(CPUS390XState *env, uint64_t mask, uint64_t addr)
{
load_psw(env, mask, addr);
s390_cpu_set_psw(env, mask, addr);
cpu_loop_exit(env_cpu(env));
}
+3
View File
@@ -845,6 +845,9 @@ int s390_cpu_pv_mem_rw(S390CPU *cpu, unsigned int offset, void *hostbuf,
int s390_cpu_restart(S390CPU *cpu);
void s390_init_sigp(void);
/* helper.c */
void s390_cpu_set_psw(CPUS390XState *env, uint64_t mask, uint64_t addr);
uint64_t s390_cpu_get_psw_mask(CPUS390XState *env);
/* outside of target/s390x/ */
S390CPU *s390_cpu_addr2state(uint16_t cpu_addr);
+2 -2
View File
@@ -90,8 +90,8 @@ static S390CPUDef s390_cpu_defs[] = {
CPUDEF_INIT(0x8562, 15, 1, 47, 0x08000000U, "gen15b", "IBM z15 T02 GA1"),
};
#define QEMU_MAX_CPU_TYPE 0x2964
#define QEMU_MAX_CPU_GEN 13
#define QEMU_MAX_CPU_TYPE 0x3906
#define QEMU_MAX_CPU_GEN 14
#define QEMU_MAX_CPU_EC_GA 2
static const S390FeatInit qemu_max_cpu_feat_init = { S390_FEAT_LIST_QEMU_MAX };
static S390FeatBitmap qemu_max_cpu_feat;
+15 -13
View File
@@ -252,7 +252,7 @@ static void do_program_interrupt(CPUS390XState *env)
lowcore->pgm_ilen = cpu_to_be16(ilen);
lowcore->pgm_code = cpu_to_be16(env->int_pgm_code);
lowcore->program_old_psw.mask = cpu_to_be64(get_psw_mask(env));
lowcore->program_old_psw.mask = cpu_to_be64(s390_cpu_get_psw_mask(env));
lowcore->program_old_psw.addr = cpu_to_be64(env->psw.addr);
mask = be64_to_cpu(lowcore->program_new_psw.mask);
addr = be64_to_cpu(lowcore->program_new_psw.addr);
@@ -260,7 +260,7 @@ static void do_program_interrupt(CPUS390XState *env)
cpu_unmap_lowcore(lowcore);
load_psw(env, mask, addr);
s390_cpu_set_psw(env, mask, addr);
}
static void do_svc_interrupt(CPUS390XState *env)
@@ -272,14 +272,14 @@ static void do_svc_interrupt(CPUS390XState *env)
lowcore->svc_code = cpu_to_be16(env->int_svc_code);
lowcore->svc_ilen = cpu_to_be16(env->int_svc_ilen);
lowcore->svc_old_psw.mask = cpu_to_be64(get_psw_mask(env));
lowcore->svc_old_psw.mask = cpu_to_be64(s390_cpu_get_psw_mask(env));
lowcore->svc_old_psw.addr = cpu_to_be64(env->psw.addr + env->int_svc_ilen);
mask = be64_to_cpu(lowcore->svc_new_psw.mask);
addr = be64_to_cpu(lowcore->svc_new_psw.addr);
cpu_unmap_lowcore(lowcore);
load_psw(env, mask, addr);
s390_cpu_set_psw(env, mask, addr);
/* When a PER event is pending, the PER exception has to happen
immediately after the SERVICE CALL one. */
@@ -348,12 +348,12 @@ static void do_ext_interrupt(CPUS390XState *env)
mask = be64_to_cpu(lowcore->external_new_psw.mask);
addr = be64_to_cpu(lowcore->external_new_psw.addr);
lowcore->external_old_psw.mask = cpu_to_be64(get_psw_mask(env));
lowcore->external_old_psw.mask = cpu_to_be64(s390_cpu_get_psw_mask(env));
lowcore->external_old_psw.addr = cpu_to_be64(env->psw.addr);
cpu_unmap_lowcore(lowcore);
load_psw(env, mask, addr);
s390_cpu_set_psw(env, mask, addr);
}
static void do_io_interrupt(CPUS390XState *env)
@@ -373,7 +373,7 @@ static void do_io_interrupt(CPUS390XState *env)
lowcore->subchannel_nr = cpu_to_be16(io->nr);
lowcore->io_int_parm = cpu_to_be32(io->parm);
lowcore->io_int_word = cpu_to_be32(io->word);
lowcore->io_old_psw.mask = cpu_to_be64(get_psw_mask(env));
lowcore->io_old_psw.mask = cpu_to_be64(s390_cpu_get_psw_mask(env));
lowcore->io_old_psw.addr = cpu_to_be64(env->psw.addr);
mask = be64_to_cpu(lowcore->io_new_psw.mask);
addr = be64_to_cpu(lowcore->io_new_psw.addr);
@@ -381,7 +381,7 @@ static void do_io_interrupt(CPUS390XState *env)
cpu_unmap_lowcore(lowcore);
g_free(io);
load_psw(env, mask, addr);
s390_cpu_set_psw(env, mask, addr);
}
typedef struct MchkExtSaveArea {
@@ -457,14 +457,14 @@ static void do_mchk_interrupt(CPUS390XState *env)
lowcore->clock_comp_save_area = cpu_to_be64(env->ckc >> 8);
lowcore->mcic = cpu_to_be64(mcic);
lowcore->mcck_old_psw.mask = cpu_to_be64(get_psw_mask(env));
lowcore->mcck_old_psw.mask = cpu_to_be64(s390_cpu_get_psw_mask(env));
lowcore->mcck_old_psw.addr = cpu_to_be64(env->psw.addr);
mask = be64_to_cpu(lowcore->mcck_new_psw.mask);
addr = be64_to_cpu(lowcore->mcck_new_psw.addr);
cpu_unmap_lowcore(lowcore);
load_psw(env, mask, addr);
s390_cpu_set_psw(env, mask, addr);
}
void s390_cpu_do_interrupt(CPUState *cs)
@@ -592,9 +592,11 @@ void s390x_cpu_debug_excp_handler(CPUState *cs)
and MVCS instrutions are not used. */
env->per_perc_atmid |= env->psw.mask & (PSW_MASK_ASC) >> 46;
/* Remove all watchpoints to re-execute the code. A PER exception
will be triggered, it will call load_psw which will recompute
the watchpoints. */
/*
* Remove all watchpoints to re-execute the code. A PER exception
* will be triggered, it will call s390_cpu_set_psw which will
* recompute the watchpoints.
*/
cpu_watchpoint_remove_all(cs, BP_CPU);
cpu_loop_exit_noexc(cs);
}
+37 -4
View File
@@ -509,6 +509,9 @@ uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, xxc_from_m34(m34), GETPC());
if (float32_is_any_nan(v2)) {
return INT64_MIN;
}
return ret;
}
@@ -520,6 +523,9 @@ uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, xxc_from_m34(m34), GETPC());
if (float64_is_any_nan(v2)) {
return INT64_MIN;
}
return ret;
}
@@ -532,6 +538,9 @@ uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, xxc_from_m34(m34), GETPC());
if (float128_is_any_nan(v2)) {
return INT64_MIN;
}
return ret;
}
@@ -543,6 +552,9 @@ uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, xxc_from_m34(m34), GETPC());
if (float32_is_any_nan(v2)) {
return INT32_MIN;
}
return ret;
}
@@ -554,6 +566,9 @@ uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, xxc_from_m34(m34), GETPC());
if (float64_is_any_nan(v2)) {
return INT32_MIN;
}
return ret;
}
@@ -566,6 +581,9 @@ uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, xxc_from_m34(m34), GETPC());
if (float128_is_any_nan(v2)) {
return INT32_MIN;
}
return ret;
}
@@ -573,12 +591,12 @@ uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
uint64_t ret;
v2 = float32_to_float64(v2, &env->fpu_status);
ret = float64_to_uint64(v2, &env->fpu_status);
uint64_t ret = float32_to_uint64(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, xxc_from_m34(m34), GETPC());
if (float32_is_any_nan(v2)) {
return 0;
}
return ret;
}
@@ -590,6 +608,9 @@ uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, xxc_from_m34(m34), GETPC());
if (float64_is_any_nan(v2)) {
return 0;
}
return ret;
}
@@ -601,6 +622,9 @@ uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, xxc_from_m34(m34), GETPC());
if (float128_is_any_nan(make_float128(h, l))) {
return 0;
}
return ret;
}
@@ -612,6 +636,9 @@ uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, xxc_from_m34(m34), GETPC());
if (float32_is_any_nan(v2)) {
return 0;
}
return ret;
}
@@ -623,6 +650,9 @@ uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, xxc_from_m34(m34), GETPC());
if (float64_is_any_nan(v2)) {
return 0;
}
return ret;
}
@@ -634,6 +664,9 @@ uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, xxc_from_m34(m34), GETPC());
if (float128_is_any_nan(make_float128(h, l))) {
return 0;
}
return ret;
}
+2 -13
View File
@@ -31,18 +31,10 @@ int s390_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
S390CPU *cpu = S390_CPU(cs);
CPUS390XState *env = &cpu->env;
uint64_t val;
int cc_op;
switch (n) {
case S390_PSWM_REGNUM:
if (tcg_enabled()) {
cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst,
env->cc_vr);
val = deposit64(env->psw.mask, 44, 2, cc_op);
return gdb_get_regl(mem_buf, val);
}
return gdb_get_regl(mem_buf, env->psw.mask);
return gdb_get_regl(mem_buf, s390_cpu_get_psw_mask(env));
case S390_PSWA_REGNUM:
return gdb_get_regl(mem_buf, env->psw.addr);
case S390_R0_REGNUM ... S390_R15_REGNUM:
@@ -59,10 +51,7 @@ int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
switch (n) {
case S390_PSWM_REGNUM:
env->psw.mask = tmpl;
if (tcg_enabled()) {
env->cc_op = extract64(tmpl, 44, 2);
}
s390_cpu_set_psw(env, tmpl, env->psw.addr);
break;
case S390_PSWA_REGNUM:
env->psw.addr = tmpl;
+9 -5
View File
@@ -706,20 +706,23 @@ static uint16_t qemu_V4_1[] = {
S390_FEAT_VECTOR,
};
static uint16_t qemu_LATEST[] = {
static uint16_t qemu_V6_0[] = {
S390_FEAT_ACCESS_EXCEPTION_FS_INDICATION,
S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2,
S390_FEAT_ESOP,
};
static uint16_t qemu_LATEST[] = {
S390_FEAT_INSTRUCTION_EXEC_PROT,
S390_FEAT_MISC_INSTRUCTION_EXT2,
S390_FEAT_MSA_EXT_8,
S390_FEAT_VECTOR_ENH,
};
/* add all new definitions before this point */
static uint16_t qemu_MAX[] = {
/* generates a dependency warning, leave it out for now */
S390_FEAT_MSA_EXT_5,
/* features introduced after the z13 */
S390_FEAT_INSTRUCTION_EXEC_PROT,
S390_FEAT_MISC_INSTRUCTION_EXT2,
S390_FEAT_MSA_EXT_8,
};
/****** END FEATURE DEFS ******/
@@ -838,6 +841,7 @@ static FeatGroupDefSpec QemuFeatDef[] = {
QEMU_FEAT_INITIALIZER(V3_1),
QEMU_FEAT_INITIALIZER(V4_0),
QEMU_FEAT_INITIALIZER(V4_1),
QEMU_FEAT_INITIALIZER(V6_0),
QEMU_FEAT_INITIALIZER(LATEST),
QEMU_FEAT_INITIALIZER(MAX),
};
+55 -46
View File
@@ -104,44 +104,6 @@ void s390_handle_wait(S390CPU *cpu)
}
}
void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
{
uint64_t old_mask = env->psw.mask;
env->psw.addr = addr;
env->psw.mask = mask;
/* KVM will handle all WAITs and trigger a WAIT exit on disabled_wait */
if (!tcg_enabled()) {
return;
}
env->cc_op = (mask >> 44) & 3;
if ((old_mask ^ mask) & PSW_MASK_PER) {
s390_cpu_recompute_watchpoints(env_cpu(env));
}
if (mask & PSW_MASK_WAIT) {
s390_handle_wait(env_archcpu(env));
}
}
uint64_t get_psw_mask(CPUS390XState *env)
{
uint64_t r = env->psw.mask;
if (tcg_enabled()) {
env->cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst,
env->cc_vr);
r &= ~PSW_MASK_CC;
assert(!(env->cc_op & ~3));
r |= (uint64_t)env->cc_op << 44;
}
return r;
}
LowCore *cpu_map_lowcore(CPUS390XState *env)
{
LowCore *lowcore;
@@ -168,7 +130,7 @@ void do_restart_interrupt(CPUS390XState *env)
lowcore = cpu_map_lowcore(env);
lowcore->restart_old_psw.mask = cpu_to_be64(get_psw_mask(env));
lowcore->restart_old_psw.mask = cpu_to_be64(s390_cpu_get_psw_mask(env));
lowcore->restart_old_psw.addr = cpu_to_be64(env->psw.addr);
mask = be64_to_cpu(lowcore->restart_new_psw.mask);
addr = be64_to_cpu(lowcore->restart_new_psw.addr);
@@ -176,7 +138,7 @@ void do_restart_interrupt(CPUS390XState *env)
cpu_unmap_lowcore(lowcore);
env->pending_int &= ~INTERRUPT_RESTART;
load_psw(env, mask, addr);
s390_cpu_set_psw(env, mask, addr);
}
void s390_cpu_recompute_watchpoints(CPUState *cs)
@@ -266,7 +228,7 @@ int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch)
sa->grs[i] = cpu_to_be64(cpu->env.regs[i]);
}
sa->psw.addr = cpu_to_be64(cpu->env.psw.addr);
sa->psw.mask = cpu_to_be64(get_psw_mask(&cpu->env));
sa->psw.mask = cpu_to_be64(s390_cpu_get_psw_mask(&cpu->env));
sa->prefix = cpu_to_be32(cpu->env.psa);
sa->fpc = cpu_to_be32(cpu->env.fpc);
sa->todpr = cpu_to_be32(cpu->env.todpr);
@@ -323,20 +285,67 @@ int s390_store_adtl_status(S390CPU *cpu, hwaddr addr, hwaddr len)
cpu_physical_memory_unmap(sa, len, 1, len);
return 0;
}
#else
/* For user-only, tcg is always enabled. */
#define tcg_enabled() true
#endif /* CONFIG_USER_ONLY */
void s390_cpu_set_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
{
#ifndef CONFIG_USER_ONLY
uint64_t old_mask = env->psw.mask;
#endif
env->psw.addr = addr;
env->psw.mask = mask;
/* KVM will handle all WAITs and trigger a WAIT exit on disabled_wait */
if (!tcg_enabled()) {
return;
}
env->cc_op = (mask >> 44) & 3;
#ifndef CONFIG_USER_ONLY
if ((old_mask ^ mask) & PSW_MASK_PER) {
s390_cpu_recompute_watchpoints(env_cpu(env));
}
if (mask & PSW_MASK_WAIT) {
s390_handle_wait(env_archcpu(env));
}
#endif
}
uint64_t s390_cpu_get_psw_mask(CPUS390XState *env)
{
uint64_t r = env->psw.mask;
if (tcg_enabled()) {
uint64_t cc = calc_cc(env, env->cc_op, env->cc_src,
env->cc_dst, env->cc_vr);
assert(cc <= 3);
r &= ~PSW_MASK_CC;
r |= cc << 44;
}
return r;
}
void s390_cpu_dump_state(CPUState *cs, FILE *f, int flags)
{
S390CPU *cpu = S390_CPU(cs);
CPUS390XState *env = &cpu->env;
int i;
if (env->cc_op > 3) {
qemu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64 " cc %15s\n",
env->psw.mask, env->psw.addr, cc_name(env->cc_op));
qemu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64,
s390_cpu_get_psw_mask(env), env->psw.addr);
if (!tcg_enabled()) {
qemu_fprintf(f, "\n");
} else if (env->cc_op > 3) {
qemu_fprintf(f, " cc %15s\n", cc_name(env->cc_op));
} else {
qemu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64 " cc %02x\n",
env->psw.mask, env->psw.addr, env->cc_op);
qemu_fprintf(f, " cc %02x\n", env->cc_op);
}
for (i = 0; i < 16; i++) {

Some files were not shown because too many files have changed in this diff Show More