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

s390x updates:
- tcg: support the floating-point extension facility
- vfio-ap: support hot(un)plug of vfio-ap device
- fixes + cleanups

# gpg: Signature made Mon 04 Mar 2019 11:55:39 GMT
# 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-20190304: (27 commits)
  s390x: Add floating-point extension facility to "qemu" cpu model
  s390x/tcg: Handle all rounding modes overwritten by BFP instructions
  s390x/tcg: Implement rounding mode and XxC for LOAD ROUNDED
  s390x/tcg: Implement XxC and checks for most FP instructions
  s390x/tcg: Prepare for IEEE-inexact-exception control (XxC)
  s390x/tcg: Refactor saving/restoring the bfp rounding mode
  s390x/tcg: Check for exceptions in SET BFP ROUNDING MODE
  s390x/tcg: Handle SET FPC AND LOAD FPC 3-bit BFP rounding modes
  s390x/tcg: Fix simulated-IEEE exceptions
  s390x/tcg: Refactor SET FPC AND SIGNAL handling
  s390x/tcg: Hide IEEE underflows in some scenarios
  s390x/tcg: Fix parts of IEEE exception handling
  s390x/tcg: Factor out conversion of softfloat exceptions
  s390x/tcg: Fix rounding from float128 to uint64_t/uint32_t
  s390x/tcg: Fix TEST DATA CLASS instructions
  s390x/tcg: Implement LOAD COUNT TO BLOCK BOUNDARY
  s390x/tcg: Implement LOAD LENGTHENED short HFP to long HFP
  s390x/tcg: Factor out gen_addi_and_wrap_i64() from get_address()
  s390x/tcg: Factor out vec_full_reg_offset()
  s390x/tcg: Clarify terminology in vec_reg_offset()
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2019-03-04 13:38:54 +00:00
13 changed files with 791 additions and 372 deletions
+56 -5
View File
@@ -440,8 +440,7 @@ unassign_control_domain
'unassign_domain' file. This may be done multiple times to unassign more than
one control domain.
Notes: Hot plug/unplug is not currently supported for mediated AP matrix
devices, so no changes to the AP matrix will be allowed while a guest using
Notes: No changes to the AP matrix will be allowed while a guest using
the mediated matrix device is running. Attempts to assign an adapter,
domain or control domain will be rejected and an error (EBUSY) returned.
@@ -562,6 +561,54 @@ facilities:
for guest usage, no AP devices can be made accessible to a
guest started without APFT installed.
Hot plug a vfio-ap device into a running guest:
==============================================
Only one vfio-ap device can be attached to the virtual machine's ap-bus, so a
vfio-ap device can be hot plugged if and only if no vfio-ap device is attached
to the bus already, whether via the QEMU command line or a prior hot plug
action.
To hot plug a vfio-ap device, use the QEMU device_add command:
(qemu) device_add vfio-ap,sysfsdev="$path-to-mdev"
Where the '$path-to-mdev' value specifies the absolute path to a mediated
device to which AP resources to be used by the guest have been assigned.
Note that on Linux guests, the AP devices will be created in the
/sys/bus/ap/devices directory when the AP bus subsequently performs its periodic
scan, so there may be a short delay before the AP devices are accessible on the
guest.
The command will fail if:
* A vfio-ap device has already been attached to the virtual machine's ap-bus.
* The CPU model features for controlling guest access to AP facilities are not
enabled (see 'CPU model features' subsection in the previous section).
Hot unplug a vfio-ap device from a running guest:
================================================
A vfio-ap device can be unplugged from a running KVM guest if a vfio-ap device
has been attached to the virtual machine's ap-bus via the QEMU command line
or a prior hot plug action.
To hot unplug a vfio-ap device, use the QEMU device_del command:
(qemu) device_del vfio-ap,sysfsdev="$path-to-mdev"
Where $path-to-mdev is the same as the path specified when the vfio-ap
device was attached to the virtual machine's ap-bus.
On a Linux guest, the AP devices will be removed from the /sys/bus/ap/devices
directory on the guest when the AP bus subsequently performs its periodic scan,
so there may be a short delay before the AP devices are no longer accessible by
the guest.
The command will fail if the $path-to-mdev specified on the device_del command
does not match the value specified when the vfio-ap device was attached to
the virtual machine's ap-bus.
Example: Configure AP Matrixes for Three Linux Guests:
=====================================================
Let's now provide an example to illustrate how KVM guests may be given
@@ -819,7 +866,11 @@ Limitations
assigned lest the host be given access to the private data of the AP queue
device, such as a private key configured specifically for the guest.
* Dynamically modifying the AP matrix for a running guest (which would amount to
hot(un)plug of AP devices for the guest) is currently not supported
* Dynamically assigning AP resources to or unassigning AP resources from a
mediated matrix device - see 'Configuring an AP matrix for a linux guest'
section above - while a running guest is using it is currently not supported.
* Live guest migration is not supported for guests using AP devices.
* Live guest migration is not supported for guests using AP devices. If a guest
is using AP devices, the vfio-ap device configured for the guest must be
unplugged before migrating the guest (see 'Hot unplug a vfio-ap device from a
running guest' section above.
+11 -1
View File
@@ -39,6 +39,7 @@ static const TypeInfo ap_bus_info = {
void s390_init_ap(void)
{
DeviceState *dev;
BusState *bus;
/* If no AP instructions then no need for AP bridge */
if (!s390_has_feat(S390_FEAT_AP)) {
@@ -52,13 +53,18 @@ void s390_init_ap(void)
qdev_init_nofail(dev);
/* Create bus on bridge device */
qbus_create(TYPE_AP_BUS, dev, TYPE_AP_BUS);
bus = qbus_create(TYPE_AP_BUS, dev, TYPE_AP_BUS);
/* Enable hotplugging */
qbus_set_hotplug_handler(bus, OBJECT(dev), &error_abort);
}
static void ap_bridge_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
hc->unplug = qdev_simple_device_unplug_cb;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
}
@@ -67,6 +73,10 @@ static const TypeInfo ap_bridge_info = {
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = 0,
.class_init = ap_bridge_class_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_HOTPLUG_HANDLER },
{ }
}
};
static void ap_register(void)
+1 -1
View File
@@ -169,7 +169,7 @@ static void vfio_ap_class_init(ObjectClass *klass, void *data)
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
dc->realize = vfio_ap_realize;
dc->unrealize = vfio_ap_unrealize;
dc->hotpluggable = false;
dc->hotpluggable = true;
dc->reset = vfio_ap_reset;
dc->bus_type = TYPE_AP_BUS;
}
+8
View File
@@ -397,6 +397,11 @@ static uint32_t cc_calc_flogr(uint64_t dst)
return dst ? 2 : 0;
}
static uint32_t cc_calc_lcbb(uint64_t dst)
{
return dst == 16 ? 0 : 3;
}
static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
uint64_t src, uint64_t dst, uint64_t vr)
{
@@ -506,6 +511,9 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
case CC_OP_FLOGR:
r = cc_calc_flogr(dst);
break;
case CC_OP_LCBB:
r = cc_calc_lcbb(dst);
break;
case CC_OP_NZ_F32:
r = set_cc_nz_f32(dst);
+44 -2
View File
@@ -347,10 +347,41 @@ static void do_io_interrupt(CPUS390XState *env)
load_psw(env, mask, addr);
}
typedef struct MchkExtSaveArea {
uint64_t vregs[32][2]; /* 0x0000 */
uint8_t pad_0x0200[0x0400 - 0x0200]; /* 0x0200 */
} MchkExtSaveArea;
QEMU_BUILD_BUG_ON(sizeof(MchkExtSaveArea) != 1024);
static int mchk_store_vregs(CPUS390XState *env, uint64_t mcesao)
{
hwaddr len = sizeof(MchkExtSaveArea);
MchkExtSaveArea *sa;
int i;
sa = cpu_physical_memory_map(mcesao, &len, 1);
if (!sa) {
return -EFAULT;
}
if (len != sizeof(MchkExtSaveArea)) {
cpu_physical_memory_unmap(sa, len, 1, 0);
return -EFAULT;
}
for (i = 0; i < 32; i++) {
sa->vregs[i][0] = cpu_to_be64(env->vregs[i][0].ll);
sa->vregs[i][1] = cpu_to_be64(env->vregs[i][1].ll);
}
cpu_physical_memory_unmap(sa, len, 1, len);
return 0;
}
static void do_mchk_interrupt(CPUS390XState *env)
{
QEMUS390FLICState *flic = QEMU_S390_FLIC(s390_get_flic());
uint64_t mask, addr;
uint64_t mcic = s390_build_validity_mcic() | MCIC_SC_CP;
uint64_t mask, addr, mcesao = 0;
LowCore *lowcore;
int i;
@@ -362,6 +393,17 @@ static void do_mchk_interrupt(CPUS390XState *env)
lowcore = cpu_map_lowcore(env);
/* extended save area */
if (mcic & MCIC_VB_VR) {
/* length and alignment is 1024 bytes */
mcesao = be64_to_cpu(lowcore->mcesad) & ~0x3ffull;
}
/* try to store vector registers */
if (!mcesao || mchk_store_vregs(env, mcesao)) {
mcic &= ~MCIC_VB_VR;
}
/* we are always in z/Architecture mode */
lowcore->ar_access_id = 1;
@@ -377,7 +419,7 @@ static void do_mchk_interrupt(CPUS390XState *env)
lowcore->cpu_timer_save_area = cpu_to_be64(env->cputm);
lowcore->clock_comp_save_area = cpu_to_be64(env->ckc >> 8);
lowcore->mcic = cpu_to_be64(s390_build_validity_mcic() | MCIC_SC_CP);
lowcore->mcic = cpu_to_be64(mcic);
lowcore->mcck_old_psw.mask = cpu_to_be64(get_psw_mask(env));
lowcore->mcck_old_psw.addr = cpu_to_be64(env->psw.addr);
mask = be64_to_cpu(lowcore->mcck_new_psw.mask);
+329 -210
View File
File diff suppressed because it is too large Load Diff
+5
View File
@@ -601,6 +601,11 @@ static uint16_t qemu_V3_1[] = {
};
static uint16_t qemu_LATEST[] = {
/*
* Only BFP bits are implemented (HFP, DFP, PFPO and DIVIDE TO INTEGER not
* implemented yet).
*/
S390_FEAT_FLOATING_POINT_EXT,
S390_FEAT_ZPCI,
};
+26 -14
View File
@@ -211,7 +211,7 @@ void s390_cpu_recompute_watchpoints(CPUState *cs)
}
}
struct sigp_save_area {
typedef struct SigpSaveArea {
uint64_t fprs[16]; /* 0x0000 */
uint64_t grs[16]; /* 0x0080 */
PSW psw; /* 0x0100 */
@@ -225,13 +225,13 @@ struct sigp_save_area {
uint8_t pad_0x0138[0x0140 - 0x0138]; /* 0x0138 */
uint32_t ars[16]; /* 0x0140 */
uint64_t crs[16]; /* 0x0384 */
};
QEMU_BUILD_BUG_ON(sizeof(struct sigp_save_area) != 512);
} SigpSaveArea;
QEMU_BUILD_BUG_ON(sizeof(SigpSaveArea) != 512);
int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch)
{
static const uint8_t ar_id = 1;
struct sigp_save_area *sa;
SigpSaveArea *sa;
hwaddr len = sizeof(*sa);
int i;
@@ -272,32 +272,43 @@ int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch)
return 0;
}
#define ADTL_GS_OFFSET 1024 /* offset of GS data in adtl save area */
typedef struct SigpAdtlSaveArea {
uint64_t vregs[32][2]; /* 0x0000 */
uint8_t pad_0x0200[0x0400 - 0x0200]; /* 0x0200 */
uint64_t gscb[4]; /* 0x0400 */
uint8_t pad_0x0420[0x1000 - 0x0420]; /* 0x0420 */
} SigpAdtlSaveArea;
QEMU_BUILD_BUG_ON(sizeof(SigpAdtlSaveArea) != 4096);
#define ADTL_GS_MIN_SIZE 2048 /* minimal size of adtl save area for GS */
int s390_store_adtl_status(S390CPU *cpu, hwaddr addr, hwaddr len)
{
SigpAdtlSaveArea *sa;
hwaddr save = len;
void *mem;
int i;
mem = cpu_physical_memory_map(addr, &save, 1);
if (!mem) {
sa = cpu_physical_memory_map(addr, &save, 1);
if (!sa) {
return -EFAULT;
}
if (save != len) {
cpu_physical_memory_unmap(mem, len, 1, 0);
cpu_physical_memory_unmap(sa, len, 1, 0);
return -EFAULT;
}
/* FIXME: as soon as TCG supports these features, convert cpu->be */
if (s390_has_feat(S390_FEAT_VECTOR)) {
memcpy(mem, &cpu->env.vregs, 512);
for (i = 0; i < 32; i++) {
sa->vregs[i][0] = cpu_to_be64(cpu->env.vregs[i][0].ll);
sa->vregs[i][1] = cpu_to_be64(cpu->env.vregs[i][1].ll);
}
}
if (s390_has_feat(S390_FEAT_GUARDED_STORAGE) && len >= ADTL_GS_MIN_SIZE) {
memcpy(mem + ADTL_GS_OFFSET, &cpu->env.gscb, 32);
for (i = 0; i < 4; i++) {
sa->gscb[i] = cpu_to_be64(cpu->env.gscb[i]);
}
}
cpu_physical_memory_unmap(mem, len, 1, len);
cpu_physical_memory_unmap(sa, len, 1, len);
return 0;
}
#endif /* CONFIG_USER_ONLY */
@@ -406,6 +417,7 @@ const char *cc_name(enum cc_op cc_op)
[CC_OP_SLA_32] = "CC_OP_SLA_32",
[CC_OP_SLA_64] = "CC_OP_SLA_64",
[CC_OP_FLOGR] = "CC_OP_FLOGR",
[CC_OP_LCBB] = "CC_OP_LCBB",
};
return cc_names[cc_op];
+5 -4
View File
@@ -53,11 +53,11 @@ DEF_HELPER_FLAGS_3(mdb, TCG_CALL_NO_WG, i64, env, i64, i64)
DEF_HELPER_FLAGS_5(mxb, TCG_CALL_NO_WG, i64, env, i64, i64, i64, i64)
DEF_HELPER_FLAGS_4(mxdb, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
DEF_HELPER_FLAGS_2(ldeb, TCG_CALL_NO_WG, i64, env, i64)
DEF_HELPER_FLAGS_3(ldxb, TCG_CALL_NO_WG, i64, env, i64, i64)
DEF_HELPER_FLAGS_4(ldxb, TCG_CALL_NO_WG, i64, env, i64, i64, i32)
DEF_HELPER_FLAGS_2(lxdb, TCG_CALL_NO_WG, i64, env, i64)
DEF_HELPER_FLAGS_2(lxeb, TCG_CALL_NO_WG, i64, env, i64)
DEF_HELPER_FLAGS_2(ledb, TCG_CALL_NO_WG, i64, env, i64)
DEF_HELPER_FLAGS_3(lexb, TCG_CALL_NO_WG, i64, env, i64, i64)
DEF_HELPER_FLAGS_3(ledb, TCG_CALL_NO_WG, i64, env, i64, i32)
DEF_HELPER_FLAGS_4(lexb, TCG_CALL_NO_WG, i64, env, i64, i64, i32)
DEF_HELPER_FLAGS_3(ceb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
DEF_HELPER_FLAGS_3(cdb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
DEF_HELPER_FLAGS_5(cxb, TCG_CALL_NO_WG_SE, i32, env, i64, i64, i64, i64)
@@ -104,8 +104,9 @@ DEF_HELPER_4(trtr, i32, env, i32, i64, i64)
DEF_HELPER_5(trXX, i32, env, i32, i32, i32, i32)
DEF_HELPER_4(cksm, i64, env, i64, i64, i64)
DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64)
DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_RWG, void, env, i64)
DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_WG, void, env, i64)
DEF_HELPER_FLAGS_2(sfas, TCG_CALL_NO_WG, void, env, i64)
DEF_HELPER_FLAGS_2(srnm, TCG_CALL_NO_WG, void, env, i64)
DEF_HELPER_FLAGS_1(popcnt, TCG_CALL_NO_RWG_SE, i64, i64)
DEF_HELPER_2(stfle, i32, env, i64)
DEF_HELPER_FLAGS_2(lpq, TCG_CALL_NO_WG, i64, env, i64)
+10 -6
View File
@@ -479,6 +479,8 @@
F(0xb313, LCDBR, RRE, Z, 0, f2, new, f1, negf64, f64, IF_BFP)
F(0xb343, LCXBR, RRE, Z, x2h, x2l, new_P, x1, negf128, f128, IF_BFP)
F(0xb373, LCDFR, RRE, FPSSH, 0, f2, new, f1, negf64, 0, IF_AFP1 | IF_AFP2)
/* LOAD COUNT TO BLOCK BOUNDARY */
C(0xe727, LCBB, RXE, V, la2, 0, r1, 0, lcbb, 0)
/* LOAD HALFWORD */
C(0xb927, LHR, RRE, EI, 0, r2_16s, 0, r1_32, mov2, 0)
C(0xb907, LGHR, RRE, EI, 0, r2_16s, 0, r1, mov2, 0)
@@ -598,10 +600,12 @@
F(0xed04, LDEB, RXE, Z, 0, m2_32u, new, f1, ldeb, 0, IF_BFP)
F(0xed05, LXDB, RXE, Z, 0, m2_64, new_P, x1, lxdb, 0, IF_BFP)
F(0xed06, LXEB, RXE, Z, 0, m2_32u, new_P, x1, lxeb, 0, IF_BFP)
F(0xb324, LDER, RXE, Z, 0, e2, new, f1, lde, 0, IF_AFP1)
F(0xed24, LDE, RXE, Z, 0, m2_32u, new, f1, lde, 0, IF_AFP1)
/* LOAD ROUNDED */
F(0xb344, LEDBR, RRE, Z, 0, f2, new, e1, ledb, 0, IF_BFP)
F(0xb345, LDXBR, RRE, Z, x2h, x2l, new, f1, ldxb, 0, IF_BFP)
F(0xb346, LEXBR, RRE, Z, x2h, x2l, new, e1, lexb, 0, IF_BFP)
F(0xb344, LEDBR, RRF_e, Z, 0, f2, new, e1, ledb, 0, IF_BFP)
F(0xb345, LDXBR, RRF_e, Z, x2h, x2l, new, f1, ldxb, 0, IF_BFP)
F(0xb346, LEXBR, RRF_e, Z, x2h, x2l, new, e1, lexb, 0, IF_BFP)
/* LOAD MULTIPLE */
C(0x9800, LM, RS_a, Z, 0, a2, 0, 0, lm32, 0)
@@ -759,10 +763,10 @@
/* SET FPC AND SIGNAL */
F(0xb385, SFASR, RRE, IEEEE_SIM, 0, r1_o, 0, 0, sfas, 0, IF_DFP)
/* SET BFP ROUNDING MODE */
F(0xb299, SRNM, S, Z, 0, 0, 0, 0, srnm, 0, IF_BFP)
F(0xb2b8, SRNMB, S, FPE, 0, 0, 0, 0, srnm, 0, IF_BFP)
F(0xb299, SRNM, S, Z, la2, 0, 0, 0, srnm, 0, IF_BFP)
F(0xb2b8, SRNMB, S, FPE, la2, 0, 0, 0, srnmb, 0, IF_BFP)
/* SET DFP ROUNDING MODE */
F(0xb2b9, SRNMT, S, DFPR, 0, 0, 0, 0, srnm, 0, IF_DFP)
F(0xb2b9, SRNMT, S, DFPR, la2, 0, 0, 0, srnmt, 0, IF_DFP)
/* SET PROGRAM MASK */
C(0x0400, SPM, RR_a, Z, r1, 0, 0, 0, spm, 0)
+1 -1
View File
@@ -36,7 +36,7 @@ F3(RSY_a, R(1, 8), BDL(2), R(3,12))
F3(RSY_b, R(1, 8), BDL(2), M(3,12))
F2(RX_a, R(1, 8), BXD(2))
F2(RX_b, M(1, 8), BXD(2))
F2(RXE, R(1, 8), BXD(2))
F3(RXE, R(1, 8), BXD(2), M(3,32))
F3(RXF, R(1,32), BXD(2), R(3, 8))
F2(RXY_a, R(1, 8), BXDL(2))
F2(RXY_b, M(1, 8), BXDL(2))
+13 -1
View File
@@ -101,7 +101,9 @@ typedef struct LowCore {
/* whether the kernel died with panic() or not */
uint32_t panic_magic; /* 0xe00 */
uint8_t pad13[0x11b8 - 0xe04]; /* 0xe04 */
uint8_t pad13[0x11b0 - 0xe04]; /* 0xe04 */
uint64_t mcesad; /* 0x11B0 */
/* 64 bit extparam used for pfault, diag 250 etc */
uint64_t ext_params2; /* 0x11B8 */
@@ -234,6 +236,7 @@ enum cc_op {
CC_OP_SLA_32, /* Calculate shift left signed (32bit) */
CC_OP_SLA_64, /* Calculate shift left signed (64bit) */
CC_OP_FLOGR, /* find leftmost one */
CC_OP_LCBB, /* load count to block boundary */
CC_OP_MAX
};
@@ -308,6 +311,15 @@ void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
uint32_t set_cc_nz_f32(float32 v);
uint32_t set_cc_nz_f64(float64 v);
uint32_t set_cc_nz_f128(float128 v);
#define S390_IEEE_MASK_INVALID 0x80
#define S390_IEEE_MASK_DIVBYZERO 0x40
#define S390_IEEE_MASK_OVERFLOW 0x20
#define S390_IEEE_MASK_UNDERFLOW 0x10
#define S390_IEEE_MASK_INEXACT 0x08
#define S390_IEEE_MASK_QUANTUM 0x04
uint8_t s390_softfloat_exc_to_ieee(unsigned int exc);
int s390_swap_bfp_rounding_mode(CPUS390XState *env, int m3);
void s390_restore_bfp_rounding_mode(CPUS390XState *env, int old_mode);
/* gdbstub.c */
+282 -127
View File
File diff suppressed because it is too large Load Diff