Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20181004' int…
Browse files Browse the repository at this point in the history
…o staging

Various s390x updates:
- fix several struct definitions so that sparc hosts do not trip over
  unaligned accesses
- fence enabling huge pages for pre-3.1 machines
- sysbus init -> realize conversion
- fixes and improvements in tcg (instruction flags and AFP registers)

# gpg: Signature made Thu 04 Oct 2018 16:22:20 BST
# gpg:                using RSA key DECF6B93C6F02FAF
# gpg: Good signature from "Cornelia Huck <conny@cornelia-huck.de>"
# gpg:                 aka "Cornelia Huck <huckc@linux.vnet.ibm.com>"
# gpg:                 aka "Cornelia Huck <cornelia.huck@de.ibm.com>"
# gpg:                 aka "Cornelia Huck <cohuck@kernel.org>"
# gpg:                 aka "Cornelia Huck <cohuck@redhat.com>"
# Primary key fingerprint: C3D0 D66D C362 4FF6 A8C0  18CE DECF 6B93 C6F0 2FAF

* remotes/cohuck/tags/s390x-20181004:
  hw/s390x/s390-pci-bus: Convert sysbus init function to realize function
  s390x/tcg: refactor specification checking
  s390x/tcg: fix FP register pair checks
  s390x/tcg: handle privileged instructions via flags
  s390x/tcg: check for AFP-register, BFP and DFP data exceptions
  s390x/tcg: add instruction flags for floating point instructions
  s390x/tcg: support flags for instructions
  s390x/tcg: store in the TB flags if AFP is enabled
  s390x/tcg: factor out and fix DATA exception injection
  s390x: move tcg_s390_program_interrupt() into TCG code and mark it noreturn
  target/s390x: exception on non-aligned LPSW(E)
  s390x: Fence huge pages prior to 3.1
  hw/s390x/ioinst: Fix alignment problem in struct SubchDev
  hw/s390x/css: Remove QEMU_PACKED from struct SenseId
  hw/s390x/ipl: Fix alignment problems of S390IPLState members

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Oct 5, 2018
2 parents d21ee59 + b576d58 commit ae7a4c0
Show file tree
Hide file tree
Showing 17 changed files with 430 additions and 383 deletions.
38 changes: 22 additions & 16 deletions hw/s390x/css.c
Expand Up @@ -750,20 +750,25 @@ static void sch_handle_halt_func(SubchDev *sch)

}

static void copy_sense_id_to_guest(SenseId *dest, SenseId *src)
/*
* As the SenseId struct cannot be packed (would cause unaligned accesses), we
* have to copy the individual fields to an unstructured area using the correct
* layout (see SA22-7204-01 "Common I/O-Device Commands").
*/
static void copy_sense_id_to_guest(uint8_t *dest, SenseId *src)
{
int i;

dest->reserved = src->reserved;
dest->cu_type = cpu_to_be16(src->cu_type);
dest->cu_model = src->cu_model;
dest->dev_type = cpu_to_be16(src->dev_type);
dest->dev_model = src->dev_model;
dest->unused = src->unused;
for (i = 0; i < ARRAY_SIZE(dest->ciw); i++) {
dest->ciw[i].type = src->ciw[i].type;
dest->ciw[i].command = src->ciw[i].command;
dest->ciw[i].count = cpu_to_be16(src->ciw[i].count);
dest[0] = src->reserved;
stw_be_p(dest + 1, src->cu_type);
dest[3] = src->cu_model;
stw_be_p(dest + 4, src->dev_type);
dest[6] = src->dev_model;
dest[7] = src->unused;
for (i = 0; i < ARRAY_SIZE(src->ciw); i++) {
dest[8 + i * 4] = src->ciw[i].type;
dest[9 + i * 4] = src->ciw[i].command;
stw_be_p(dest + 10 + i * 4, src->ciw[i].count);
}
}

Expand Down Expand Up @@ -1044,9 +1049,10 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
break;
case CCW_CMD_SENSE_ID:
{
SenseId sense_id;
/* According to SA22-7204-01, Sense-ID can store up to 256 bytes */
uint8_t sense_id[256];

copy_sense_id_to_guest(&sense_id, &sch->id);
copy_sense_id_to_guest(sense_id, &sch->id);
/* Sense ID information is device specific. */
if (check_len) {
if (ccw.count != sizeof(sense_id)) {
Expand All @@ -1060,11 +1066,11 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
* have enough place to store at least bytes 0-3.
*/
if (len >= 4) {
sense_id.reserved = 0xff;
sense_id[0] = 0xff;
} else {
sense_id.reserved = 0;
sense_id[0] = 0;
}
ccw_dstream_write_buf(&sch->cds, &sense_id, len);
ccw_dstream_write_buf(&sch->cds, sense_id, len);
sch->curr_status.scsw.count = ccw_dstream_residual_count(&sch->cds);
ret = 0;
break;
Expand Down
5 changes: 3 additions & 2 deletions hw/s390x/ipl.h
Expand Up @@ -132,15 +132,15 @@ typedef struct QemuIplParameters QemuIplParameters;
struct S390IPLState {
/*< private >*/
DeviceState parent_obj;
IplParameterBlock iplb;
QemuIplParameters qipl;
uint64_t start_addr;
uint64_t compat_start_addr;
uint64_t bios_start_addr;
uint64_t compat_bios_start_addr;
bool enforce_bios;
IplParameterBlock iplb;
bool iplb_valid;
bool netboot;
QemuIplParameters qipl;
/* reset related properties don't have to be migrated or reset */
enum s390_reset reset_type;
int reset_cpu_index;
Expand All @@ -157,6 +157,7 @@ struct S390IPLState {
bool iplbext_migration;
};
typedef struct S390IPLState S390IPLState;
QEMU_BUILD_BUG_MSG(offsetof(S390IPLState, iplb) & 3, "alignment of iplb wrong");

#define S390_IPL_TYPE_FCP 0x00
#define S390_IPL_TYPE_CCW 0x02
Expand Down
34 changes: 21 additions & 13 deletions hw/s390x/s390-pci-bus.c
Expand Up @@ -692,27 +692,35 @@ static void s390_pci_iommu_free(S390pciState *s, PCIBus *bus, int32_t devfn)
object_unref(OBJECT(iommu));
}

static int s390_pcihost_init(SysBusDevice *dev)
static void s390_pcihost_realize(DeviceState *dev, Error **errp)
{
PCIBus *b;
BusState *bus;
PCIHostState *phb = PCI_HOST_BRIDGE(dev);
S390pciState *s = S390_PCI_HOST_BRIDGE(dev);
Error *local_err = NULL;

DPRINTF("host_init\n");

b = pci_register_root_bus(DEVICE(dev), NULL,
s390_pci_set_irq, s390_pci_map_irq, NULL,
get_system_memory(), get_system_io(), 0, 64,
TYPE_PCI_BUS);
b = pci_register_root_bus(dev, NULL, s390_pci_set_irq, s390_pci_map_irq,
NULL, get_system_memory(), get_system_io(), 0,
64, TYPE_PCI_BUS);
pci_setup_iommu(b, s390_pci_dma_iommu, s);

bus = BUS(b);
qbus_set_hotplug_handler(bus, DEVICE(dev), NULL);
qbus_set_hotplug_handler(bus, dev, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
phb->bus = b;

s->bus = S390_PCI_BUS(qbus_create(TYPE_S390_PCI_BUS, DEVICE(s), NULL));
qbus_set_hotplug_handler(BUS(s->bus), DEVICE(s), NULL);
s->bus = S390_PCI_BUS(qbus_create(TYPE_S390_PCI_BUS, dev, NULL));
qbus_set_hotplug_handler(BUS(s->bus), dev, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}

s->iommu_table = g_hash_table_new_full(g_int64_hash, g_int64_equal,
NULL, g_free);
Expand All @@ -722,9 +730,10 @@ static int s390_pcihost_init(SysBusDevice *dev)
QTAILQ_INIT(&s->zpci_devs);

css_register_io_adapters(CSS_IO_ADAPTER_PCI, true, false,
S390_ADAPTER_SUPPRESSIBLE, &error_abort);

return 0;
S390_ADAPTER_SUPPRESSIBLE, &local_err);
if (local_err) {
error_propagate(errp, local_err);
}
}

static int s390_pci_msix_init(S390PCIBusDevice *pbdev)
Expand Down Expand Up @@ -1018,12 +1027,11 @@ static void s390_pcihost_reset(DeviceState *dev)

static void s390_pcihost_class_init(ObjectClass *klass, void *data)
{
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);

dc->reset = s390_pcihost_reset;
k->init = s390_pcihost_init;
dc->realize = s390_pcihost_realize;
hc->plug = s390_pcihost_hot_plug;
hc->unplug = s390_pcihost_hot_unplug;
msi_nonbroken = true;
Expand Down
10 changes: 10 additions & 0 deletions hw/s390x/s390-virtio-ccw.c
Expand Up @@ -456,6 +456,7 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data)
s390mc->ri_allowed = true;
s390mc->cpu_model_allowed = true;
s390mc->css_migration_enabled = true;
s390mc->hpage_1m_allowed = true;
mc->init = ccw_init;
mc->reset = s390_machine_reset;
mc->hot_add_cpu = s390_hot_add_cpu;
Expand Down Expand Up @@ -535,6 +536,12 @@ bool cpu_model_allowed(void)
return get_machine_class()->cpu_model_allowed;
}

bool hpage_1m_allowed(void)
{
/* for "none" machine this results in true */
return get_machine_class()->hpage_1m_allowed;
}

static char *machine_get_loadparm(Object *obj, Error **errp)
{
S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
Expand Down Expand Up @@ -747,6 +754,9 @@ static void ccw_machine_3_0_instance_options(MachineState *machine)

static void ccw_machine_3_0_class_options(MachineClass *mc)
{
S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);

s390mc->hpage_1m_allowed = false;
ccw_machine_3_1_class_options(mc);
SET_MACHINE_COMPAT(mc, CCW_COMPAT_3_0);
}
Expand Down
6 changes: 3 additions & 3 deletions include/hw/s390x/css.h
Expand Up @@ -48,7 +48,7 @@ typedef struct SenseId {
uint8_t unused; /* padding byte */
/* extended part */
CIW ciw[MAX_CIWS]; /* variable # of CIWs */
} QEMU_PACKED SenseId;
} SenseId; /* Note: No QEMU_PACKED due to unaligned members */

/* Channel measurements, from linux/drivers/s390/cio/cmf.c. */
typedef struct CMB {
Expand Down Expand Up @@ -118,11 +118,12 @@ typedef enum IOInstEnding {
typedef struct SubchDev SubchDev;
struct SubchDev {
/* channel-subsystem related things: */
SCHIB curr_status; /* Needs alignment and thus must come first */
ORB orb;
uint8_t cssid;
uint8_t ssid;
uint16_t schid;
uint16_t devno;
SCHIB curr_status;
uint8_t sense_data[32];
hwaddr channel_prog;
CCW1 last_cmd;
Expand All @@ -131,7 +132,6 @@ struct SubchDev {
bool thinint_active;
uint8_t ccw_no_data_cnt;
uint16_t migrated_schid; /* used for missmatch detection */
ORB orb;
CcwDataStream cds;
/* transport-provided data: */
int (*ccw_cb) (SubchDev *, CCW1);
Expand Down
21 changes: 14 additions & 7 deletions include/hw/s390x/ioinst.h
Expand Up @@ -25,7 +25,8 @@ typedef struct SCSW {
uint8_t dstat;
uint8_t cstat;
uint16_t count;
} QEMU_PACKED SCSW;
} SCSW;
QEMU_BUILD_BUG_MSG(sizeof(SCSW) != 12, "size of SCSW is wrong");

#define SCSW_FLAGS_MASK_KEY 0xf000
#define SCSW_FLAGS_MASK_SCTL 0x0800
Expand Down Expand Up @@ -94,7 +95,8 @@ typedef struct PMCW {
uint8_t pam;
uint8_t chpid[8];
uint32_t chars;
} QEMU_PACKED PMCW;
} PMCW;
QEMU_BUILD_BUG_MSG(sizeof(PMCW) != 28, "size of PMCW is wrong");

#define PMCW_FLAGS_MASK_QF 0x8000
#define PMCW_FLAGS_MASK_W 0x4000
Expand Down Expand Up @@ -127,7 +129,8 @@ typedef struct IRB {
uint32_t esw[5];
uint32_t ecw[8];
uint32_t emw[8];
} QEMU_PACKED IRB;
} IRB;
QEMU_BUILD_BUG_MSG(sizeof(IRB) != 96, "size of IRB is wrong");

/* operation request block */
typedef struct ORB {
Expand All @@ -136,7 +139,8 @@ typedef struct ORB {
uint8_t lpm;
uint8_t ctrl1;
uint32_t cpa;
} QEMU_PACKED ORB;
} ORB;
QEMU_BUILD_BUG_MSG(sizeof(ORB) != 12, "size of ORB is wrong");

#define ORB_CTRL0_MASK_KEY 0xf000
#define ORB_CTRL0_MASK_SPND 0x0800
Expand Down Expand Up @@ -165,15 +169,17 @@ typedef struct CCW0 {
uint8_t flags;
uint8_t reserved;
uint16_t count;
} QEMU_PACKED CCW0;
} CCW0;
QEMU_BUILD_BUG_MSG(sizeof(CCW0) != 8, "size of CCW0 is wrong");

/* channel command word (type 1) */
typedef struct CCW1 {
uint8_t cmd_code;
uint8_t flags;
uint16_t count;
uint32_t cda;
} QEMU_PACKED CCW1;
} CCW1;
QEMU_BUILD_BUG_MSG(sizeof(CCW1) != 8, "size of CCW1 is wrong");

#define CCW_FLAG_DC 0x80
#define CCW_FLAG_CC 0x40
Expand All @@ -192,7 +198,8 @@ typedef struct CCW1 {
typedef struct CRW {
uint16_t flags;
uint16_t rsid;
} QEMU_PACKED CRW;
} CRW;
QEMU_BUILD_BUG_MSG(sizeof(CRW) != 4, "size of CRW is wrong");

#define CRW_FLAGS_MASK_S 0x4000
#define CRW_FLAGS_MASK_R 0x2000
Expand Down
3 changes: 3 additions & 0 deletions include/hw/s390x/s390-virtio-ccw.h
Expand Up @@ -39,12 +39,15 @@ typedef struct S390CcwMachineClass {
bool ri_allowed;
bool cpu_model_allowed;
bool css_migration_enabled;
bool hpage_1m_allowed;
} S390CcwMachineClass;

/* runtime-instrumentation allowed by the machine */
bool ri_allowed(void);
/* cpu model allowed by the machine */
bool cpu_model_allowed(void);
/* 1M huge page mappings allowed by the machine */
bool hpage_1m_allowed(void);

/**
* Returns true if (vmstate based) migration of the channel subsystem
Expand Down
9 changes: 9 additions & 0 deletions target/s390x/cpu.h
Expand Up @@ -255,6 +255,7 @@ extern const struct VMStateDescription vmstate_s390_cpu;

/* PSW defines */
#undef PSW_MASK_PER
#undef PSW_MASK_UNUSED_2
#undef PSW_MASK_DAT
#undef PSW_MASK_IO
#undef PSW_MASK_EXT
Expand All @@ -273,6 +274,7 @@ extern const struct VMStateDescription vmstate_s390_cpu;
#undef PSW_MASK_ESA_ADDR

#define PSW_MASK_PER 0x4000000000000000ULL
#define PSW_MASK_UNUSED_2 0x2000000000000000ULL
#define PSW_MASK_DAT 0x0400000000000000ULL
#define PSW_MASK_IO 0x0200000000000000ULL
#define PSW_MASK_EXT 0x0100000000000000ULL
Expand Down Expand Up @@ -318,10 +320,14 @@ extern const struct VMStateDescription vmstate_s390_cpu;
#define FLAG_MASK_PSW (FLAG_MASK_PER | FLAG_MASK_DAT | FLAG_MASK_PSTATE \
| FLAG_MASK_ASC | FLAG_MASK_64 | FLAG_MASK_32)

/* we'll use some unused PSW positions to store CR flags in tb flags */
#define FLAG_MASK_AFP (PSW_MASK_UNUSED_2 >> FLAG_MASK_PSW_SHIFT)

/* Control register 0 bits */
#define CR0_LOWPROT 0x0000000010000000ULL
#define CR0_SECONDARY 0x0000000004000000ULL
#define CR0_EDAT 0x0000000000800000ULL
#define CR0_AFP 0x0000000000040000ULL
#define CR0_EMERGENCY_SIGNAL_SC 0x0000000000004000ULL
#define CR0_EXTERNAL_CALL_SC 0x0000000000002000ULL
#define CR0_CKC_SC 0x0000000000000800ULL
Expand Down Expand Up @@ -363,6 +369,9 @@ static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc,
*pc = env->psw.addr;
*cs_base = env->ex_value;
*flags = (env->psw.mask >> FLAG_MASK_PSW_SHIFT) & FLAG_MASK_PSW;
if (env->cregs[0] & CR0_AFP) {
*flags |= FLAG_MASK_AFP;
}
}

/* PER bits from control register 9 */
Expand Down

0 comments on commit ae7a4c0

Please sign in to comment.