diff options
Diffstat (limited to 'include/hw/s390x')
-rw-r--r-- | include/hw/s390x/3270-ccw.h | 48 | ||||
-rw-r--r-- | include/hw/s390x/adapter.h | 23 | ||||
-rw-r--r-- | include/hw/s390x/ap-bridge.h | 19 | ||||
-rw-r--r-- | include/hw/s390x/ap-device.h | 27 | ||||
-rw-r--r-- | include/hw/s390x/css-bridge.h | 37 | ||||
-rw-r--r-- | include/hw/s390x/css.h | 336 | ||||
-rw-r--r-- | include/hw/s390x/ebcdic.h | 104 | ||||
-rw-r--r-- | include/hw/s390x/event-facility.h | 208 | ||||
-rw-r--r-- | include/hw/s390x/ioinst.h | 258 | ||||
-rw-r--r-- | include/hw/s390x/pv.h | 75 | ||||
-rw-r--r-- | include/hw/s390x/s390-ccw.h | 42 | ||||
-rw-r--r-- | include/hw/s390x/s390-pci-bus.h | 391 | ||||
-rw-r--r-- | include/hw/s390x/s390-pci-clp.h | 215 | ||||
-rw-r--r-- | include/hw/s390x/s390-pci-inst.h | 119 | ||||
-rw-r--r-- | include/hw/s390x/s390-pci-vfio.h | 39 | ||||
-rw-r--r-- | include/hw/s390x/s390-virtio-ccw.h | 57 | ||||
-rw-r--r-- | include/hw/s390x/s390_flic.h | 142 | ||||
-rw-r--r-- | include/hw/s390x/sclp.h | 232 | ||||
-rw-r--r-- | include/hw/s390x/storage-attributes.h | 79 | ||||
-rw-r--r-- | include/hw/s390x/storage-keys.h | 120 | ||||
-rw-r--r-- | include/hw/s390x/tod.h | 54 | ||||
-rw-r--r-- | include/hw/s390x/vfio-ccw.h | 27 |
22 files changed, 2652 insertions, 0 deletions
diff --git a/include/hw/s390x/3270-ccw.h b/include/hw/s390x/3270-ccw.h new file mode 100644 index 000000000..143988229 --- /dev/null +++ b/include/hw/s390x/3270-ccw.h @@ -0,0 +1,48 @@ +/* + * Emulated ccw-attached 3270 definitions + * + * Copyright 2017 IBM Corp. + * Author(s): Yang Chen <bjcyang@linux.vnet.ibm.com> + * Jing Liu <liujbjl@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef HW_S390X_3270_CCW_H +#define HW_S390X_3270_CCW_H + +#include "hw/sysbus.h" +#include "hw/s390x/css.h" +#include "hw/s390x/ccw-device.h" +#include "qom/object.h" + +#define EMULATED_CCW_3270_CU_TYPE 0x3270 +#define EMULATED_CCW_3270_CHPID_TYPE 0x1a + +#define TYPE_EMULATED_CCW_3270 "emulated-ccw-3270" + +/* Local Channel Commands */ +#define TC_WRITE 0x01 /* Write */ +#define TC_RDBUF 0x02 /* Read buffer */ +#define TC_EWRITE 0x05 /* Erase write */ +#define TC_READMOD 0x06 /* Read modified */ +#define TC_EWRITEA 0x0d /* Erase write alternate */ +#define TC_WRITESF 0x11 /* Write structured field */ + +OBJECT_DECLARE_TYPE(EmulatedCcw3270Device, EmulatedCcw3270Class, EMULATED_CCW_3270) + +struct EmulatedCcw3270Device { + CcwDevice parent_obj; +}; + +struct EmulatedCcw3270Class { + CCWDeviceClass parent_class; + + void (*init)(EmulatedCcw3270Device *, Error **); + int (*read_payload_3270)(EmulatedCcw3270Device *); + int (*write_payload_3270)(EmulatedCcw3270Device *, uint8_t); +}; + +#endif diff --git a/include/hw/s390x/adapter.h b/include/hw/s390x/adapter.h new file mode 100644 index 000000000..7f1703508 --- /dev/null +++ b/include/hw/s390x/adapter.h @@ -0,0 +1,23 @@ +/* + * s390 adapter definitions + * + * Copyright 2013,2014 IBM Corp. + * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef S390X_ADAPTER_H +#define S390X_ADAPTER_H + +struct AdapterInfo { + uint64_t ind_addr; + uint64_t summary_addr; + uint64_t ind_offset; + uint32_t summary_offset; + uint32_t adapter_id; +}; + +#endif diff --git a/include/hw/s390x/ap-bridge.h b/include/hw/s390x/ap-bridge.h new file mode 100644 index 000000000..470e439a9 --- /dev/null +++ b/include/hw/s390x/ap-bridge.h @@ -0,0 +1,19 @@ +/* + * ap bridge + * + * Copyright 2018 IBM Corp. + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef HW_S390X_AP_BRIDGE_H +#define HW_S390X_AP_BRIDGE_H + +#define TYPE_AP_BRIDGE "ap-bridge" +#define TYPE_AP_BUS "ap-bus" + +void s390_init_ap(void); + +#endif diff --git a/include/hw/s390x/ap-device.h b/include/hw/s390x/ap-device.h new file mode 100644 index 000000000..e502745de --- /dev/null +++ b/include/hw/s390x/ap-device.h @@ -0,0 +1,27 @@ +/* + * Adjunct Processor (AP) matrix device interfaces + * + * Copyright 2018 IBM Corp. + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef HW_S390X_AP_DEVICE_H +#define HW_S390X_AP_DEVICE_H + +#include "hw/qdev-core.h" +#include "qom/object.h" + +#define TYPE_AP_DEVICE "ap-device" + +struct APDevice { + DeviceState parent_obj; +}; +typedef struct APDevice APDevice; + +DECLARE_INSTANCE_CHECKER(APDevice, AP_DEVICE, + TYPE_AP_DEVICE) + +#endif /* HW_S390X_AP_DEVICE_H */ diff --git a/include/hw/s390x/css-bridge.h b/include/hw/s390x/css-bridge.h new file mode 100644 index 000000000..deb606d71 --- /dev/null +++ b/include/hw/s390x/css-bridge.h @@ -0,0 +1,37 @@ +/* + * virtual css bridge definition + * + * Copyright 2012,2016 IBM Corp. + * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> + * Pierre Morel <pmorel@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef HW_S390X_CSS_BRIDGE_H +#define HW_S390X_CSS_BRIDGE_H + +#include "qom/object.h" +#include "hw/sysbus.h" + +/* virtual css bridge */ +struct VirtualCssBridge { + SysBusDevice sysbus_dev; + bool css_dev_path; +}; + +#define TYPE_VIRTUAL_CSS_BRIDGE "virtual-css-bridge" +OBJECT_DECLARE_SIMPLE_TYPE(VirtualCssBridge, VIRTUAL_CSS_BRIDGE) + +/* virtual css bus type */ +struct VirtualCssBus { + BusState parent_obj; +}; + +#define TYPE_VIRTUAL_CSS_BUS "virtual-css-bus" +OBJECT_DECLARE_SIMPLE_TYPE(VirtualCssBus, VIRTUAL_CSS_BUS) +VirtualCssBus *virtual_css_bus_init(void); + +#endif diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h new file mode 100644 index 000000000..75e538161 --- /dev/null +++ b/include/hw/s390x/css.h @@ -0,0 +1,336 @@ +/* + * Channel subsystem structures and definitions. + * + * Copyright 2012 IBM Corp. + * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef CSS_H +#define CSS_H + +#include "hw/s390x/adapter.h" +#include "hw/s390x/s390_flic.h" +#include "hw/s390x/ioinst.h" +#include "sysemu/kvm.h" +#include "target/s390x/cpu-qom.h" + +/* Channel subsystem constants. */ +#define MAX_DEVNO 65535 +#define MAX_SCHID 65535 +#define MAX_SSID 3 +#define MAX_CSSID 255 +#define MAX_CHPID 255 + +#define MAX_ISC 7 + +#define MAX_CIWS 62 + +#define VIRTUAL_CSSID 0xfe +#define VIRTIO_CCW_CHPID 0 /* used by convention */ + +typedef struct CIW { + uint8_t type; + uint8_t command; + uint16_t count; +} QEMU_PACKED CIW; + +typedef struct SenseId { + /* common part */ + uint8_t reserved; /* always 0x'FF' */ + uint16_t cu_type; /* control unit type */ + uint8_t cu_model; /* control unit model */ + uint16_t dev_type; /* device type */ + uint8_t dev_model; /* device model */ + uint8_t unused; /* padding byte */ + /* extended part */ + CIW ciw[MAX_CIWS]; /* variable # of CIWs */ +} SenseId; /* Note: No QEMU_PACKED due to unaligned members */ + +/* Channel measurements, from linux/drivers/s390/cio/cmf.c. */ +typedef struct CMB { + uint16_t ssch_rsch_count; + uint16_t sample_count; + uint32_t device_connect_time; + uint32_t function_pending_time; + uint32_t device_disconnect_time; + uint32_t control_unit_queuing_time; + uint32_t device_active_only_time; + uint32_t reserved[2]; +} QEMU_PACKED CMB; + +typedef struct CMBE { + uint32_t ssch_rsch_count; + uint32_t sample_count; + uint32_t device_connect_time; + uint32_t function_pending_time; + uint32_t device_disconnect_time; + uint32_t control_unit_queuing_time; + uint32_t device_active_only_time; + uint32_t device_busy_time; + uint32_t initial_command_response_time; + uint32_t reserved[7]; +} QEMU_PACKED CMBE; + +typedef enum CcwDataStreamOp { + CDS_OP_R = 0, /* read, false when used as is_write */ + CDS_OP_W = 1, /* write, true when used as is_write */ + CDS_OP_A = 2 /* advance, should not be used as is_write */ +} CcwDataStreamOp; + +/* normal usage is via SuchchDev.cds instead of instantiating */ +typedef struct CcwDataStream { +#define CDS_F_IDA 0x01 +#define CDS_F_MIDA 0x02 +#define CDS_F_I2K 0x04 +#define CDS_F_C64 0x08 +#define CDS_F_FMT 0x10 /* CCW format-1 */ +#define CDS_F_STREAM_BROKEN 0x80 + uint8_t flags; + uint8_t at_idaw; + uint16_t at_byte; + uint16_t count; + uint32_t cda_orig; + int (*op_handler)(struct CcwDataStream *cds, void *buff, int len, + CcwDataStreamOp op); + hwaddr cda; + bool do_skip; +} CcwDataStream; + +/* + * IO instructions conclude according to this. Currently we have only + * cc codes. Valid values are 0, 1, 2, 3 and the generic semantic for + * IO instructions is described briefly. For more details consult the PoP. + */ +typedef enum IOInstEnding { + /* produced expected result */ + IOINST_CC_EXPECTED = 0, + /* status conditions were present or produced alternate result */ + IOINST_CC_STATUS_PRESENT = 1, + /* inst. ineffective because busy with previously initiated function */ + IOINST_CC_BUSY = 2, + /* inst. ineffective because not operational */ + IOINST_CC_NOT_OPERATIONAL = 3 +} 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; + uint8_t sense_data[32]; + hwaddr channel_prog; + CCW1 last_cmd; + bool last_cmd_valid; + bool ccw_fmt_1; + bool thinint_active; + uint8_t ccw_no_data_cnt; + uint16_t migrated_schid; /* used for mismatch detection */ + CcwDataStream cds; + /* transport-provided data: */ + 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) +{ + sch->curr_status.scsw.ctrl &= ~(SCSW_ACTL_DEVICE_ACTIVE | + SCSW_ACTL_SUBCH_ACTIVE); + sch->curr_status.scsw.ctrl |= SCSW_STCTL_PRIMARY | + SCSW_STCTL_SECONDARY | + SCSW_STCTL_ALERT | + SCSW_STCTL_STATUS_PEND; + sch->curr_status.scsw.cpa = sch->channel_prog + 8; + sch->curr_status.scsw.dstat = SCSW_DSTAT_UNIT_EXCEP; +} + +extern const VMStateDescription vmstate_subch_dev; + +/* + * Identify a device within the channel subsystem. + * Note that this can be used to identify either the subchannel or + * the attached I/O device, as there's always one I/O device per + * subchannel. + */ +typedef struct CssDevId { + uint8_t cssid; + uint8_t ssid; + uint16_t devid; + bool valid; +} CssDevId; + +extern const PropertyInfo css_devid_propinfo; + +#define DEFINE_PROP_CSS_DEV_ID(_n, _s, _f) \ + DEFINE_PROP(_n, _s, _f, css_devid_propinfo, CssDevId) + +typedef struct IndAddr { + hwaddr addr; + uint64_t map; + unsigned long refcnt; + int32_t len; + QTAILQ_ENTRY(IndAddr) sibling; +} IndAddr; + +extern const VMStateDescription vmstate_ind_addr; + +#define VMSTATE_PTR_TO_IND_ADDR(_f, _s) \ + VMSTATE_STRUCT(_f, _s, 1, vmstate_ind_addr, IndAddr*) + +IndAddr *get_indicator(hwaddr ind_addr, int len); +void release_indicator(AdapterInfo *adapter, IndAddr *indicator); +int map_indicator(AdapterInfo *adapter, IndAddr *indicator); + +typedef SubchDev *(*css_subch_cb_func)(uint8_t m, uint8_t cssid, uint8_t ssid, + uint16_t schid); +int css_create_css_image(uint8_t cssid, bool default_image); +bool css_devno_used(uint8_t cssid, uint8_t ssid, uint16_t devno); +void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid, + uint16_t devno, SubchDev *sch); +void css_sch_build_virtual_schib(SubchDev *sch, uint8_t chpid, uint8_t type); +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); +void css_crw_add_to_queue(CRW crw); +void css_queue_crw(uint8_t rsc, uint8_t erc, int solicited, + int chain, uint16_t rsid); +void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid, + int hotplugged, int add); +void css_generate_chp_crws(uint8_t cssid, uint8_t chpid); +void css_generate_css_crws(uint8_t cssid); +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); +IOInstEnding s390_ccw_store(SubchDev *sch); + +typedef enum { + CSS_IO_ADAPTER_VIRTIO = 0, + CSS_IO_ADAPTER_PCI = 1, + CSS_IO_ADAPTER_TYPE_NUMS, +} CssIoAdapterType; + +void css_adapter_interrupt(CssIoAdapterType type, uint8_t isc); +int css_do_sic(CPUS390XState *env, uint8_t isc, uint16_t mode); +uint32_t css_get_adapter_id(CssIoAdapterType type, uint8_t isc); +void css_register_io_adapters(CssIoAdapterType type, bool swap, bool maskable, + uint8_t flags, Error **errp); + +#ifndef CONFIG_USER_ONLY +SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid, + uint16_t schid); +bool css_subch_visible(SubchDev *sch); +void css_conditional_io_interrupt(SubchDev *sch); +IOInstEnding css_do_stsch(SubchDev *sch, SCHIB *schib); +bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid); +IOInstEnding css_do_msch(SubchDev *sch, const SCHIB *schib); +IOInstEnding css_do_xsch(SubchDev *sch); +IOInstEnding css_do_csch(SubchDev *sch); +IOInstEnding css_do_hsch(SubchDev *sch); +IOInstEnding css_do_ssch(SubchDev *sch, ORB *orb); +int css_do_tsch_get_irb(SubchDev *sch, IRB *irb, int *irb_len); +void css_do_tsch_update_subch(SubchDev *sch); +int css_do_stcrw(CRW *crw); +void css_undo_stcrw(CRW *crw); +int css_collect_chp_desc(int m, uint8_t cssid, uint8_t f_chpid, uint8_t l_chpid, + int rfmt, void *buf); +void css_do_schm(uint8_t mbk, int update, int dct, uint64_t mbo); +int css_enable_mcsse(void); +int css_enable_mss(void); +IOInstEnding css_do_rsch(SubchDev *sch); +int css_do_rchp(uint8_t cssid, uint8_t chpid); +bool css_present(uint8_t cssid); +#endif + +extern const PropertyInfo css_devid_ro_propinfo; + +#define DEFINE_PROP_CSS_DEV_ID_RO(_n, _s, _f) \ + DEFINE_PROP(_n, _s, _f, css_devid_ro_propinfo, CssDevId) + +/** + * Create a subchannel for the given bus id. + * + * If @p bus_id is valid, verify that it is not already in use, and find a + * free devno for it. + * If @p bus_id is not valid find a free subchannel id and device number + * across all subchannel sets and all css images starting from the default + * css image. + * + * If either of the former actions succeed, allocate a subchannel structure, + * initialise it with the bus id, subchannel id and device number, register + * it with the CSS and return it. Otherwise return NULL. + * + * The caller becomes owner of the returned subchannel structure and + * is responsible for unregistering and freeing it. + */ +SubchDev *css_create_sch(CssDevId bus_id, Error **errp); + +/** Turn on css migration */ +void css_register_vmstate(void); + + +void ccw_dstream_init(CcwDataStream *cds, CCW1 const *ccw, ORB const *orb); + +static inline void ccw_dstream_rewind(CcwDataStream *cds) +{ + cds->at_byte = 0; + cds->at_idaw = 0; + cds->cda = cds->cda_orig; +} + +static inline bool ccw_dstream_good(CcwDataStream *cds) +{ + return !(cds->flags & CDS_F_STREAM_BROKEN); +} + +static inline uint16_t ccw_dstream_residual_count(CcwDataStream *cds) +{ + return cds->count - cds->at_byte; +} + +static inline uint16_t ccw_dstream_avail(CcwDataStream *cds) +{ + return ccw_dstream_good(cds) ? ccw_dstream_residual_count(cds) : 0; +} + +static inline int ccw_dstream_advance(CcwDataStream *cds, int len) +{ + return cds->op_handler(cds, NULL, len, CDS_OP_A); +} + +static inline int ccw_dstream_write_buf(CcwDataStream *cds, void *buff, int len) +{ + return cds->op_handler(cds, buff, len, CDS_OP_W); +} + +static inline int ccw_dstream_read_buf(CcwDataStream *cds, void *buff, int len) +{ + return cds->op_handler(cds, buff, len, CDS_OP_R); +} + +#define ccw_dstream_read(cds, v) ccw_dstream_read_buf((cds), &(v), sizeof(v)) +#define ccw_dstream_write(cds, v) ccw_dstream_write_buf((cds), &(v), sizeof(v)) + +#endif diff --git a/include/hw/s390x/ebcdic.h b/include/hw/s390x/ebcdic.h new file mode 100644 index 000000000..69a04cab6 --- /dev/null +++ b/include/hw/s390x/ebcdic.h @@ -0,0 +1,104 @@ +/* + * EBCDIC/ASCII conversion Support + * + * Copyright (c) 2011 Alexander Graf + * Copyright IBM, Corp. 2013 + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at your + * option) any later version. See the COPYING file in the top-level directory. + * + */ + +#ifndef EBCDIC_H +#define EBCDIC_H + +/* EBCDIC handling */ +static const uint8_t ebcdic2ascii[] = { + 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F, + 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07, + 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07, + 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04, + 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A, + 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86, + 0x87, 0xA4, 0x5B, 0x2E, 0x3C, 0x28, 0x2B, 0x21, + 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07, + 0x8D, 0xE1, 0x5D, 0x24, 0x2A, 0x29, 0x3B, 0x5E, + 0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F, + 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, + 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, + 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1, + 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, + 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07, + 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07, + 0x9B, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC, + 0xAB, 0x07, 0xAA, 0x7C, 0x07, 0x07, 0x07, 0x07, + 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07, + 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, + 0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98, + 0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07, +}; + +static const uint8_t ascii2ebcdic[] = { + 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, + 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, + 0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F, + 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, + 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, + 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, + 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, + 0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D, + 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x59, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF +}; + +static inline void ebcdic_put(uint8_t *p, const char *ascii, int len) +{ + int i; + + for (i = 0; i < len; i++) { + p[i] = ascii2ebcdic[(uint8_t)ascii[i]]; + } +} + +static inline void ascii_put(uint8_t *p, const char *ebcdic, int len) +{ + int i; + + for (i = 0; i < len; i++) { + p[i] = ebcdic2ascii[(uint8_t)ebcdic[i]]; + } +} + +#endif /* EBCDIC_H */ diff --git a/include/hw/s390x/event-facility.h b/include/hw/s390x/event-facility.h new file mode 100644 index 000000000..3ffd575d8 --- /dev/null +++ b/include/hw/s390x/event-facility.h @@ -0,0 +1,208 @@ +/* + * SCLP + * Event Facility definitions + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Heinz Graalfs <graalfs@de.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at your + * option) any later version. See the COPYING file in the top-level directory. + * + */ + +#ifndef HW_S390_SCLP_EVENT_FACILITY_H +#define HW_S390_SCLP_EVENT_FACILITY_H + +#include "qemu/thread.h" +#include "hw/qdev-core.h" +#include "hw/s390x/sclp.h" +#include "qom/object.h" + +/* SCLP event types */ +#define SCLP_EVENT_OPRTNS_COMMAND 0x01 +#define SCLP_EVENT_MESSAGE 0x02 +#define SCLP_EVENT_CONFIG_MGT_DATA 0x04 +#define SCLP_EVENT_PMSGCMD 0x09 +#define SCLP_EVENT_ASCII_CONSOLE_DATA 0x1a +#define SCLP_EVENT_SIGNAL_QUIESCE 0x1d + +/* SCLP event masks */ +#define SCLP_EVMASK(T) (1ULL << (sizeof(sccb_mask_t) * 8 - (T))) + +#define SCLP_EVENT_MASK_OP_CMD SCLP_EVMASK(SCLP_EVENT_OPRTNS_COMMAND) +#define SCLP_EVENT_MASK_MSG SCLP_EVMASK(SCLP_EVENT_MESSAGE) +#define SCLP_EVENT_MASK_CONFIG_MGT_DATA SCLP_EVMASK(SCLP_EVENT_CONFIG_MGT_DATA) +#define SCLP_EVENT_MASK_PMSGCMD SCLP_EVMASK(SCLP_EVENT_PMSGCMD) +#define SCLP_EVENT_MASK_MSG_ASCII SCLP_EVMASK(SCLP_EVENT_ASCII_CONSOLE_DATA) +#define SCLP_EVENT_MASK_SIGNAL_QUIESCE SCLP_EVMASK(SCLP_EVENT_SIGNAL_QUIESCE) + +#define SCLP_UNCONDITIONAL_READ 0x00 +#define SCLP_SELECTIVE_READ 0x01 + +#define TYPE_SCLP_EVENT "s390-sclp-event-type" +OBJECT_DECLARE_TYPE(SCLPEvent, SCLPEventClass, + SCLP_EVENT) + +#define TYPE_SCLP_CPU_HOTPLUG "sclp-cpu-hotplug" +#define TYPE_SCLP_QUIESCE "sclpquiesce" + +#define SCLP_EVENT_MASK_LEN_MAX 1021 + +typedef struct WriteEventMask { + SCCBHeader h; + uint16_t _reserved; + uint16_t mask_length; + uint8_t masks[]; +/* + * Layout of the masks is + * uint8_t cp_receive_mask[mask_length]; + * uint8_t cp_send_mask[mask_length]; + * uint8_t receive_mask[mask_length]; + * uint8_t send_mask[mask_length]; + * where 1 <= mask_length <= SCLP_EVENT_MASK_LEN_MAX + */ +} QEMU_PACKED WriteEventMask; + +#define WEM_CP_RECEIVE_MASK(wem, mask_len) ((wem)->masks) +#define WEM_CP_SEND_MASK(wem, mask_len) ((wem)->masks + (mask_len)) +#define WEM_RECEIVE_MASK(wem, mask_len) ((wem)->masks + 2 * (mask_len)) +#define WEM_SEND_MASK(wem, mask_len) ((wem)->masks + 3 * (mask_len)) + +typedef uint64_t sccb_mask_t; + +typedef struct EventBufferHeader { + uint16_t length; + uint8_t type; + uint8_t flags; + uint16_t _reserved; +} QEMU_PACKED EventBufferHeader; + +typedef struct MdbHeader { + uint16_t length; + uint16_t type; + uint32_t tag; + uint32_t revision_code; +} QEMU_PACKED MdbHeader; + +typedef struct MTO { + uint16_t line_type_flags; + uint8_t alarm_control; + uint8_t _reserved[3]; + char message[]; +} QEMU_PACKED MTO; + +typedef struct GO { + uint32_t domid; + uint8_t hhmmss_time[8]; + uint8_t th_time[3]; + uint8_t _reserved_0; + uint8_t dddyyyy_date[7]; + uint8_t _reserved_1; + uint16_t general_msg_flags; + uint8_t _reserved_2[10]; + uint8_t originating_system_name[8]; + uint8_t job_guest_name[8]; +} QEMU_PACKED GO; + +#define MESSAGE_TEXT 0x0004 + +typedef struct MDBO { + uint16_t length; + uint16_t type; + union { + GO go; + MTO mto; + }; +} QEMU_PACKED MDBO; + +typedef struct MDB { + MdbHeader header; + MDBO mdbo[]; +} QEMU_PACKED MDB; + +typedef struct SclpMsg { + EventBufferHeader header; + MDB mdb; +} QEMU_PACKED SclpMsg; + +#define GDS_ID_MDSMU 0x1310 +#define GDS_ID_CPMSU 0x1212 +#define GDS_ID_TEXTCMD 0x1320 + +typedef struct GdsVector { + uint16_t length; + uint16_t gds_id; +} QEMU_PACKED GdsVector; + +#define GDS_KEY_SELFDEFTEXTMSG 0x31 +#define GDS_KEY_TEXTMSG 0x30 + +typedef struct GdsSubvector { + uint8_t length; + uint8_t key; +} QEMU_PACKED GdsSubvector; + +/* MDS Message Unit */ +typedef struct MDMSU { + GdsVector mdmsu; + GdsVector cpmsu; + GdsVector text_command; + GdsSubvector self_def_text_message; + GdsSubvector text_message; +} QEMU_PACKED MDMSU; + +typedef struct WriteEventData { + SCCBHeader h; + EventBufferHeader ebh; +} QEMU_PACKED WriteEventData; + +typedef struct ReadEventData { + SCCBHeader h; + union { + sccb_mask_t mask; + EventBufferHeader ebh; + }; +} QEMU_PACKED ReadEventData; + +struct SCLPEvent { + DeviceState qdev; + bool event_pending; + char *name; +}; + +struct SCLPEventClass { + DeviceClass parent_class; + int (*init)(SCLPEvent *event); + + /* get SCLP's send mask */ + sccb_mask_t (*get_send_mask)(void); + + /* get SCLP's receive mask */ + sccb_mask_t (*get_receive_mask)(void); + + int (*read_event_data)(SCLPEvent *event, EventBufferHeader *evt_buf_hdr, + int *slen); + + int (*write_event_data)(SCLPEvent *event, EventBufferHeader *evt_buf_hdr); + + /* can we handle this event type? */ + bool (*can_handle_event)(uint8_t type); +}; + +#define TYPE_SCLP_EVENT_FACILITY "s390-sclp-event-facility" +typedef struct SCLPEventFacility SCLPEventFacility; +typedef struct SCLPEventFacilityClass SCLPEventFacilityClass; +DECLARE_OBJ_CHECKERS(SCLPEventFacility, SCLPEventFacilityClass, + EVENT_FACILITY, TYPE_SCLP_EVENT_FACILITY) + +struct SCLPEventFacilityClass { + SysBusDeviceClass parent_class; + void (*command_handler)(SCLPEventFacility *ef, SCCB *sccb, uint64_t code); + bool (*event_pending)(SCLPEventFacility *ef); +}; + +BusState *sclp_get_event_facility_bus(void); + +#endif diff --git a/include/hw/s390x/ioinst.h b/include/hw/s390x/ioinst.h new file mode 100644 index 000000000..3771fff9d --- /dev/null +++ b/include/hw/s390x/ioinst.h @@ -0,0 +1,258 @@ +/* + * S/390 channel I/O instructions + * + * Copyright 2012 IBM Corp. + * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. +*/ + +#ifndef S390X_IOINST_H +#define S390X_IOINST_H + +/* + * Channel I/O related definitions, as defined in the Principles + * Of Operation (and taken from the Linux implementation). + */ + +/* subchannel status word (command mode only) */ +typedef struct SCSW { + uint16_t flags; + uint16_t ctrl; + uint32_t cpa; + uint8_t dstat; + uint8_t cstat; + uint16_t count; +} 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 +#define SCSW_FLAGS_MASK_ESWF 0x0400 +#define SCSW_FLAGS_MASK_CC 0x0300 +#define SCSW_FLAGS_MASK_FMT 0x0080 +#define SCSW_FLAGS_MASK_PFCH 0x0040 +#define SCSW_FLAGS_MASK_ISIC 0x0020 +#define SCSW_FLAGS_MASK_ALCC 0x0010 +#define SCSW_FLAGS_MASK_SSI 0x0008 +#define SCSW_FLAGS_MASK_ZCC 0x0004 +#define SCSW_FLAGS_MASK_ECTL 0x0002 +#define SCSW_FLAGS_MASK_PNO 0x0001 + +#define SCSW_CTRL_MASK_FCTL 0x7000 +#define SCSW_CTRL_MASK_ACTL 0x0fe0 +#define SCSW_CTRL_MASK_STCTL 0x001f + +#define SCSW_FCTL_CLEAR_FUNC 0x1000 +#define SCSW_FCTL_HALT_FUNC 0x2000 +#define SCSW_FCTL_START_FUNC 0x4000 + +#define SCSW_ACTL_SUSP 0x0020 +#define SCSW_ACTL_DEVICE_ACTIVE 0x0040 +#define SCSW_ACTL_SUBCH_ACTIVE 0x0080 +#define SCSW_ACTL_CLEAR_PEND 0x0100 +#define SCSW_ACTL_HALT_PEND 0x0200 +#define SCSW_ACTL_START_PEND 0x0400 +#define SCSW_ACTL_RESUME_PEND 0x0800 + +#define SCSW_STCTL_STATUS_PEND 0x0001 +#define SCSW_STCTL_SECONDARY 0x0002 +#define SCSW_STCTL_PRIMARY 0x0004 +#define SCSW_STCTL_INTERMEDIATE 0x0008 +#define SCSW_STCTL_ALERT 0x0010 + +#define SCSW_DSTAT_ATTENTION 0x80 +#define SCSW_DSTAT_STAT_MOD 0x40 +#define SCSW_DSTAT_CU_END 0x20 +#define SCSW_DSTAT_BUSY 0x10 +#define SCSW_DSTAT_CHANNEL_END 0x08 +#define SCSW_DSTAT_DEVICE_END 0x04 +#define SCSW_DSTAT_UNIT_CHECK 0x02 +#define SCSW_DSTAT_UNIT_EXCEP 0x01 + +#define SCSW_CSTAT_PCI 0x80 +#define SCSW_CSTAT_INCORR_LEN 0x40 +#define SCSW_CSTAT_PROG_CHECK 0x20 +#define SCSW_CSTAT_PROT_CHECK 0x10 +#define SCSW_CSTAT_DATA_CHECK 0x08 +#define SCSW_CSTAT_CHN_CTRL_CHK 0x04 +#define SCSW_CSTAT_INTF_CTRL_CHK 0x02 +#define SCSW_CSTAT_CHAIN_CHECK 0x01 + +/* path management control word */ +typedef struct PMCW { + uint32_t intparm; + uint16_t flags; + uint16_t devno; + uint8_t lpm; + uint8_t pnom; + uint8_t lpum; + uint8_t pim; + uint16_t mbi; + uint8_t pom; + uint8_t pam; + uint8_t chpid[8]; + uint32_t chars; +} 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 +#define PMCW_FLAGS_MASK_ISC 0x3800 +#define PMCW_FLAGS_MASK_ENA 0x0080 +#define PMCW_FLAGS_MASK_LM 0x0060 +#define PMCW_FLAGS_MASK_MME 0x0018 +#define PMCW_FLAGS_MASK_MP 0x0004 +#define PMCW_FLAGS_MASK_TF 0x0002 +#define PMCW_FLAGS_MASK_DNV 0x0001 +#define PMCW_FLAGS_MASK_INVALID 0x0700 + +#define PMCW_CHARS_MASK_ST 0x00e00000 +#define PMCW_CHARS_MASK_MBFC 0x00000004 +#define PMCW_CHARS_MASK_XMWME 0x00000002 +#define PMCW_CHARS_MASK_CSENSE 0x00000001 +#define PMCW_CHARS_MASK_INVALID 0xff1ffff8 + +/* subchannel information block */ +typedef struct SCHIB { + PMCW pmcw; + SCSW scsw; + uint64_t mba; + 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; + ESW esw; + uint32_t ecw[8]; + uint32_t emw[8]; +} IRB; +QEMU_BUILD_BUG_MSG(sizeof(IRB) != 96, "size of IRB is wrong"); + +/* operation request block */ +typedef struct ORB { + uint32_t intparm; + uint16_t ctrl0; + uint8_t lpm; + uint8_t ctrl1; + uint32_t cpa; +} 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 +#define ORB_CTRL0_MASK_STR 0x0400 +#define ORB_CTRL0_MASK_MOD 0x0200 +#define ORB_CTRL0_MASK_SYNC 0x0100 +#define ORB_CTRL0_MASK_FMT 0x0080 +#define ORB_CTRL0_MASK_PFCH 0x0040 +#define ORB_CTRL0_MASK_ISIC 0x0020 +#define ORB_CTRL0_MASK_ALCC 0x0010 +#define ORB_CTRL0_MASK_SSIC 0x0008 +#define ORB_CTRL0_MASK_C64 0x0002 +#define ORB_CTRL0_MASK_I2K 0x0001 +#define ORB_CTRL0_MASK_INVALID 0x0004 + +#define ORB_CTRL1_MASK_ILS 0x80 +#define ORB_CTRL1_MASK_MIDAW 0x40 +#define ORB_CTRL1_MASK_ORBX 0x01 +#define ORB_CTRL1_MASK_INVALID 0x3e + +/* channel command word (type 0) */ +typedef struct CCW0 { + uint8_t cmd_code; + uint8_t cda0; + uint16_t cda1; + uint8_t flags; + uint8_t reserved; + uint16_t count; +} 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; +} CCW1; +QEMU_BUILD_BUG_MSG(sizeof(CCW1) != 8, "size of CCW1 is wrong"); + +#define CCW_FLAG_DC 0x80 +#define CCW_FLAG_CC 0x40 +#define CCW_FLAG_SLI 0x20 +#define CCW_FLAG_SKIP 0x10 +#define CCW_FLAG_PCI 0x08 +#define CCW_FLAG_IDA 0x04 +#define CCW_FLAG_SUSPEND 0x02 +#define CCW_FLAG_MIDA 0x01 + +#define CCW_CMD_NOOP 0x03 +#define CCW_CMD_BASIC_SENSE 0x04 +#define CCW_CMD_TIC 0x08 +#define CCW_CMD_SENSE_ID 0xe4 + +typedef struct CRW { + uint16_t flags; + uint16_t rsid; +} 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 +#define CRW_FLAGS_MASK_C 0x1000 +#define CRW_FLAGS_MASK_RSC 0x0f00 +#define CRW_FLAGS_MASK_A 0x0080 +#define CRW_FLAGS_MASK_ERC 0x003f + +#define CRW_ERC_EVENT 0x00 /* event information pending */ +#define CRW_ERC_AVAIL 0x01 /* available */ +#define CRW_ERC_INIT 0x02 /* initialized */ +#define CRW_ERC_TERROR 0x03 /* temporary error */ +#define CRW_ERC_IPI 0x04 /* installed parm initialized */ +#define CRW_ERC_TERM 0x05 /* terminal */ +#define CRW_ERC_PERRN 0x06 /* perm. error, facility not init */ +#define CRW_ERC_PERRI 0x07 /* perm. error, facility init */ +#define CRW_ERC_PMOD 0x08 /* installed parameters modified */ +#define CRW_ERC_IPR 0x0A /* installed parameters restored */ + +#define CRW_RSC_SUBCH 0x3 +#define CRW_RSC_CHP 0x4 +#define CRW_RSC_CSS 0xb + +/* I/O interruption code */ +typedef struct IOIntCode { + uint32_t subsys_id; + uint32_t intparm; + uint32_t interrupt_id; +} QEMU_PACKED IOIntCode; + +/* schid disintegration */ +#define IOINST_SCHID_ONE(_schid) ((_schid & 0x00010000) >> 16) +#define IOINST_SCHID_M(_schid) ((_schid & 0x00080000) >> 19) +#define IOINST_SCHID_CSSID(_schid) ((_schid & 0xff000000) >> 24) +#define IOINST_SCHID_SSID(_schid) ((_schid & 0x00060000) >> 17) +#define IOINST_SCHID_NR(_schid) (_schid & 0x0000ffff) + +#define IO_INT_WORD_ISC(_int_word) ((_int_word & 0x38000000) >> 27) +#define ISC_TO_ISC_BITS(_isc) ((0x80 >> _isc) << 24) + +#define IO_INT_WORD_AI 0x80000000 + +int ioinst_disassemble_sch_ident(uint32_t value, int *m, int *cssid, int *ssid, + int *schid); + +#endif diff --git a/include/hw/s390x/pv.h b/include/hw/s390x/pv.h new file mode 100644 index 000000000..1f1f545bf --- /dev/null +++ b/include/hw/s390x/pv.h @@ -0,0 +1,75 @@ +/* + * Protected Virtualization header + * + * Copyright IBM Corp. 2020 + * Author(s): + * Janosch Frank <frankja@linux.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ +#ifndef HW_S390_PV_H +#define HW_S390_PV_H + +#include "qapi/error.h" +#include "sysemu/kvm.h" + +#ifdef CONFIG_KVM +#include "cpu.h" +#include "hw/s390x/s390-virtio-ccw.h" + +static inline bool s390_is_pv(void) +{ + static S390CcwMachineState *ccw; + Object *obj; + + if (ccw) { + return ccw->pv; + } + + /* we have to bail out for the "none" machine */ + obj = object_dynamic_cast(qdev_get_machine(), + TYPE_S390_CCW_MACHINE); + if (!obj) { + return false; + } + ccw = S390_CCW_MACHINE(obj); + return ccw->pv; +} + +int s390_pv_vm_enable(void); +void s390_pv_vm_disable(void); +int s390_pv_set_sec_parms(uint64_t origin, uint64_t length); +int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak); +void s390_pv_prep_reset(void); +int s390_pv_verify(void); +void s390_pv_unshare(void); +void s390_pv_inject_reset_error(CPUState *cs); +#else /* CONFIG_KVM */ +static inline bool s390_is_pv(void) { return false; } +static inline int s390_pv_vm_enable(void) { return 0; } +static inline void s390_pv_vm_disable(void) {} +static inline int s390_pv_set_sec_parms(uint64_t origin, uint64_t length) { return 0; } +static inline int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) { return 0; } +static inline void s390_pv_prep_reset(void) {} +static inline int s390_pv_verify(void) { return 0; } +static inline void s390_pv_unshare(void) {} +static inline void s390_pv_inject_reset_error(CPUState *cs) {}; +#endif /* CONFIG_KVM */ + +int s390_pv_kvm_init(ConfidentialGuestSupport *cgs, Error **errp); +static inline int s390_pv_init(ConfidentialGuestSupport *cgs, Error **errp) +{ + if (!cgs) { + return 0; + } + if (kvm_enabled()) { + return s390_pv_kvm_init(cgs, errp); + } + + error_setg(errp, "Protected Virtualization requires KVM"); + return -1; +} + +#endif /* HW_S390_PV_H */ diff --git a/include/hw/s390x/s390-ccw.h b/include/hw/s390x/s390-ccw.h new file mode 100644 index 000000000..2c807ee3a --- /dev/null +++ b/include/hw/s390x/s390-ccw.h @@ -0,0 +1,42 @@ +/* + * s390 CCW Assignment Support + * + * Copyright 2017 IBM Corp. + * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com> + * Xiao Feng Ren <renxiaof@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef HW_S390_CCW_H +#define HW_S390_CCW_H + +#include "hw/s390x/ccw-device.h" +#include "qom/object.h" + +#define TYPE_S390_CCW "s390-ccw" +typedef struct S390CCWDevice S390CCWDevice; +typedef struct S390CCWDeviceClass S390CCWDeviceClass; +DECLARE_OBJ_CHECKERS(S390CCWDevice, S390CCWDeviceClass, + S390_CCW_DEVICE, TYPE_S390_CCW) + +struct S390CCWDevice { + CcwDevice parent_obj; + CssDevId hostid; + char *mdevid; + int32_t bootindex; +}; + +struct S390CCWDeviceClass { + CCWDeviceClass parent_class; + void (*realize)(S390CCWDevice *dev, char *sysfsdev, Error **errp); + void (*unrealize)(S390CCWDevice *dev); + IOInstEnding (*handle_request) (SubchDev *sch); + int (*handle_halt) (SubchDev *sch); + int (*handle_clear) (SubchDev *sch); + IOInstEnding (*handle_store) (SubchDev *sch); +}; + +#endif diff --git a/include/hw/s390x/s390-pci-bus.h b/include/hw/s390x/s390-pci-bus.h new file mode 100644 index 000000000..aa891c178 --- /dev/null +++ b/include/hw/s390x/s390-pci-bus.h @@ -0,0 +1,391 @@ +/* + * s390 PCI BUS definitions + * + * Copyright 2014 IBM Corp. + * Author(s): Frank Blaschka <frank.blaschka@de.ibm.com> + * Hong Bo Li <lihbbj@cn.ibm.com> + * Yi Min Zhao <zyimin@cn.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef HW_S390_PCI_BUS_H +#define HW_S390_PCI_BUS_H + +#include "hw/pci/pci.h" +#include "hw/pci/pci_host.h" +#include "hw/s390x/sclp.h" +#include "hw/s390x/s390_flic.h" +#include "hw/s390x/css.h" +#include "hw/s390x/s390-pci-clp.h" +#include "qom/object.h" + +#define TYPE_S390_PCI_HOST_BRIDGE "s390-pcihost" +#define TYPE_S390_PCI_BUS "s390-pcibus" +#define TYPE_S390_PCI_DEVICE "zpci" +#define TYPE_S390_PCI_IOMMU "s390-pci-iommu" +#define TYPE_S390_IOMMU_MEMORY_REGION "s390-iommu-memory-region" +#define FH_MASK_ENABLE 0x80000000 +#define FH_MASK_INSTANCE 0x7f000000 +#define FH_MASK_SHM 0x00ff0000 +#define FH_MASK_INDEX 0x0000ffff +#define FH_SHM_VFIO 0x00010000 +#define FH_SHM_EMUL 0x00020000 +#define ZPCI_MAX_FID 0xffffffff +#define ZPCI_MAX_UID 0xffff +#define UID_UNDEFINED 0 +#define UID_CHECKING_ENABLED 0x01 + +OBJECT_DECLARE_SIMPLE_TYPE(S390pciState, S390_PCI_HOST_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(S390PCIBus, S390_PCI_BUS) +OBJECT_DECLARE_SIMPLE_TYPE(S390PCIBusDevice, S390_PCI_DEVICE) +OBJECT_DECLARE_SIMPLE_TYPE(S390PCIIOMMU, S390_PCI_IOMMU) + +#define HP_EVENT_TO_CONFIGURED 0x0301 +#define HP_EVENT_RESERVED_TO_STANDBY 0x0302 +#define HP_EVENT_DECONFIGURE_REQUEST 0x0303 +#define HP_EVENT_CONFIGURED_TO_STBRES 0x0304 +#define HP_EVENT_STANDBY_TO_RESERVED 0x0308 + +#define ERR_EVENT_INVALAS 0x1 +#define ERR_EVENT_OORANGE 0x2 +#define ERR_EVENT_INVALTF 0x3 +#define ERR_EVENT_TPROTE 0x4 +#define ERR_EVENT_APROTE 0x5 +#define ERR_EVENT_KEYE 0x6 +#define ERR_EVENT_INVALTE 0x7 +#define ERR_EVENT_INVALTL 0x8 +#define ERR_EVENT_TT 0x9 +#define ERR_EVENT_INVALMS 0xa +#define ERR_EVENT_SERR 0xb +#define ERR_EVENT_NOMSI 0x10 +#define ERR_EVENT_INVALBV 0x11 +#define ERR_EVENT_AIBV 0x12 +#define ERR_EVENT_AIRERR 0x13 +#define ERR_EVENT_FMBA 0x2a +#define ERR_EVENT_FMBUP 0x2b +#define ERR_EVENT_FMBPRO 0x2c +#define ERR_EVENT_CCONF 0x30 +#define ERR_EVENT_SERVAC 0x3a +#define ERR_EVENT_PERMERR 0x3b + +#define ERR_EVENT_Q_BIT 0x2 +#define ERR_EVENT_MVN_OFFSET 16 + +#define ZPCI_MSI_VEC_BITS 11 +#define ZPCI_MSI_VEC_MASK 0x7ff + +#define ZPCI_MSI_ADDR 0xfe00000000000000ULL +#define ZPCI_SDMA_ADDR 0x100000000ULL +#define ZPCI_EDMA_ADDR 0x1ffffffffffffffULL + +#define PAGE_DEFAULT_ACC 0 +#define PAGE_DEFAULT_KEY (PAGE_DEFAULT_ACC << 4) + +/* I/O Translation Anchor (IOTA) */ +enum ZpciIoatDtype { + ZPCI_IOTA_STO = 0, + ZPCI_IOTA_RTTO = 1, + ZPCI_IOTA_RSTO = 2, + ZPCI_IOTA_RFTO = 3, + ZPCI_IOTA_PFAA = 4, + ZPCI_IOTA_IOPFAA = 5, + ZPCI_IOTA_IOPTO = 7 +}; + +#define ZPCI_IOTA_IOT_ENABLED 0x800ULL +#define ZPCI_IOTA_DT_ST (ZPCI_IOTA_STO << 2) +#define ZPCI_IOTA_DT_RT (ZPCI_IOTA_RTTO << 2) +#define ZPCI_IOTA_DT_RS (ZPCI_IOTA_RSTO << 2) +#define ZPCI_IOTA_DT_RF (ZPCI_IOTA_RFTO << 2) +#define ZPCI_IOTA_DT_PF (ZPCI_IOTA_PFAA << 2) +#define ZPCI_IOTA_FS_4K 0 +#define ZPCI_IOTA_FS_1M 1 +#define ZPCI_IOTA_FS_2G 2 +#define ZPCI_KEY (PAGE_DEFAULT_KEY << 5) + +#define ZPCI_IOTA_STO_FLAG (ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_ST) +#define ZPCI_IOTA_RTTO_FLAG (ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_RT) +#define ZPCI_IOTA_RSTO_FLAG (ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_RS) +#define ZPCI_IOTA_RFTO_FLAG (ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_RF) +#define ZPCI_IOTA_RFAA_FLAG (ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY |\ + ZPCI_IOTA_DT_PF | ZPCI_IOTA_FS_2G) + +/* I/O Region and segment tables */ +#define ZPCI_INDEX_MASK 0x7ffULL + +#define ZPCI_TABLE_TYPE_MASK 0xc +#define ZPCI_TABLE_TYPE_RFX 0xc +#define ZPCI_TABLE_TYPE_RSX 0x8 +#define ZPCI_TABLE_TYPE_RTX 0x4 +#define ZPCI_TABLE_TYPE_SX 0x0 + +#define ZPCI_TABLE_LEN_RFX 0x3 +#define ZPCI_TABLE_LEN_RSX 0x3 +#define ZPCI_TABLE_LEN_RTX 0x3 + +#define ZPCI_TABLE_OFFSET_MASK 0xc0 +#define ZPCI_TABLE_SIZE 0x4000 +#define ZPCI_TABLE_ALIGN ZPCI_TABLE_SIZE +#define ZPCI_TABLE_ENTRY_SIZE (sizeof(unsigned long)) +#define ZPCI_TABLE_ENTRIES (ZPCI_TABLE_SIZE / ZPCI_TABLE_ENTRY_SIZE) + +#define ZPCI_TABLE_BITS 11 +#define ZPCI_PT_BITS 8 +#define ZPCI_ST_SHIFT (ZPCI_PT_BITS + TARGET_PAGE_BITS) +#define ZPCI_RT_SHIFT (ZPCI_ST_SHIFT + ZPCI_TABLE_BITS) + +#define ZPCI_RTE_FLAG_MASK 0x3fffULL +#define ZPCI_RTE_ADDR_MASK (~ZPCI_RTE_FLAG_MASK) +#define ZPCI_STE_FLAG_MASK 0x7ffULL +#define ZPCI_STE_ADDR_MASK (~ZPCI_STE_FLAG_MASK) + +#define ZPCI_SFAA_MASK (~((1ULL << 20) - 1)) + +/* I/O Page tables */ +#define ZPCI_PTE_VALID_MASK 0x400 +#define ZPCI_PTE_INVALID 0x400 +#define ZPCI_PTE_VALID 0x000 +#define ZPCI_PT_SIZE 0x800 +#define ZPCI_PT_ALIGN ZPCI_PT_SIZE +#define ZPCI_PT_ENTRIES (ZPCI_PT_SIZE / ZPCI_TABLE_ENTRY_SIZE) +#define ZPCI_PT_MASK (ZPCI_PT_ENTRIES - 1) + +#define ZPCI_PTE_FLAG_MASK 0xfffULL +#define ZPCI_PTE_ADDR_MASK (~ZPCI_PTE_FLAG_MASK) + +/* Shared bits */ +#define ZPCI_TABLE_VALID 0x00 +#define ZPCI_TABLE_INVALID 0x20 +#define ZPCI_TABLE_PROTECTED 0x200 +#define ZPCI_TABLE_UNPROTECTED 0x000 +#define ZPCI_TABLE_FC 0x400 + +#define ZPCI_TABLE_VALID_MASK 0x20 +#define ZPCI_TABLE_PROT_MASK 0x200 + +#define ZPCI_ETT_RT 1 +#define ZPCI_ETT_ST 0 +#define ZPCI_ETT_PT -1 + +/* PCI Function States + * + * reserved: default; device has just been plugged or is in progress of being + * unplugged + * standby: device is present but not configured; transition from any + * configured state/to this state via sclp configure/deconfigure + * + * The following states make up the "configured" meta-state: + * disabled: device is configured but not enabled; transition between this + * state and enabled via clp enable/disable + * enbaled: device is ready for use; transition to disabled via clp disable; + * may enter an error state + * blocked: ignore all DMA and interrupts; transition back to enabled or from + * error state via mpcifc + * error: an error occurred; transition back to enabled via mpcifc + * permanent error: an unrecoverable error occurred; transition to standby via + * sclp deconfigure + */ +typedef enum { + ZPCI_FS_RESERVED, + ZPCI_FS_STANDBY, + ZPCI_FS_DISABLED, + ZPCI_FS_ENABLED, + ZPCI_FS_BLOCKED, + ZPCI_FS_ERROR, + ZPCI_FS_PERMANENT_ERROR, +} ZpciState; + +typedef struct SeiContainer { + QTAILQ_ENTRY(SeiContainer) link; + uint32_t fid; + uint32_t fh; + uint8_t cc; + uint16_t pec; + uint64_t faddr; + uint32_t e; +} SeiContainer; + +typedef struct PciCcdfErr { + uint32_t reserved1; + uint32_t fh; + uint32_t fid; + uint32_t e; + uint64_t faddr; + uint32_t reserved3; + uint16_t reserved4; + uint16_t pec; +} QEMU_PACKED PciCcdfErr; + +typedef struct PciCcdfAvail { + uint32_t reserved1; + uint32_t fh; + uint32_t fid; + uint32_t reserved2; + uint32_t reserved3; + uint32_t reserved4; + uint32_t reserved5; + uint16_t reserved6; + uint16_t pec; +} QEMU_PACKED PciCcdfAvail; + +typedef struct ChscSeiNt2Res { + uint16_t length; + uint16_t code; + uint16_t reserved1; + uint8_t reserved2; + uint8_t nt; + uint8_t flags; + uint8_t reserved3; + uint8_t reserved4; + uint8_t cc; + uint32_t reserved5[13]; + uint8_t ccdf[4016]; +} QEMU_PACKED ChscSeiNt2Res; + +typedef struct S390MsixInfo { + uint8_t table_bar; + uint8_t pba_bar; + uint16_t entries; + uint32_t table_offset; + uint32_t pba_offset; +} S390MsixInfo; + +typedef struct S390IOTLBEntry { + uint64_t iova; + uint64_t translated_addr; + uint64_t len; + uint64_t perm; +} S390IOTLBEntry; + +typedef struct S390PCIDMACount { + int id; + int users; + uint32_t avail; + QTAILQ_ENTRY(S390PCIDMACount) link; +} S390PCIDMACount; + +struct S390PCIIOMMU { + Object parent_obj; + S390PCIBusDevice *pbdev; + AddressSpace as; + MemoryRegion mr; + IOMMUMemoryRegion iommu_mr; + bool enabled; + uint64_t g_iota; + uint64_t pba; + uint64_t pal; + GHashTable *iotlb; + S390PCIDMACount *dma_limit; +}; + +typedef struct S390PCIIOMMUTable { + uint64_t key; + S390PCIIOMMU *iommu[PCI_SLOT_MAX]; +} S390PCIIOMMUTable; + +/* Function Measurement Block */ +#define DEFAULT_MUI 4000 +#define UPDATE_U_BIT 0x1ULL +#define FMBK_MASK 0xfULL + +typedef struct ZpciFmbFmt0 { + uint64_t dma_rbytes; + uint64_t dma_wbytes; +} ZpciFmbFmt0; + +#define ZPCI_FMB_CNT_LD 0 +#define ZPCI_FMB_CNT_ST 1 +#define ZPCI_FMB_CNT_STB 2 +#define ZPCI_FMB_CNT_RPCIT 3 +#define ZPCI_FMB_CNT_MAX 4 + +#define ZPCI_FMB_FORMAT 0 + +typedef struct ZpciFmb { + uint32_t format; + uint32_t sample; + uint64_t last_update; + uint64_t counter[ZPCI_FMB_CNT_MAX]; + ZpciFmbFmt0 fmt0; +} ZpciFmb; +QEMU_BUILD_BUG_MSG(offsetof(ZpciFmb, fmt0) != 48, "padding in ZpciFmb"); + +#define ZPCI_DEFAULT_FN_GRP 0x20 +typedef struct S390PCIGroup { + ClpRspQueryPciGrp zpci_group; + int id; + QTAILQ_ENTRY(S390PCIGroup) link; +} S390PCIGroup; +S390PCIGroup *s390_group_create(int id); +S390PCIGroup *s390_group_find(int id); + +struct S390PCIBusDevice { + DeviceState qdev; + PCIDevice *pdev; + ZpciState state; + char *target; + uint16_t uid; + uint32_t idx; + uint32_t fh; + uint32_t fid; + bool fid_defined; + uint64_t fmb_addr; + ZpciFmb fmb; + QEMUTimer *fmb_timer; + uint8_t isc; + uint16_t noi; + uint16_t maxstbl; + uint8_t sum; + S390PCIGroup *pci_group; + ClpRspQueryPci zpci_fn; + S390MsixInfo msix; + AdapterRoutes routes; + S390PCIIOMMU *iommu; + MemoryRegion msix_notify_mr; + IndAddr *summary_ind; + IndAddr *indicator; + bool pci_unplug_request_processed; + bool unplug_requested; + QTAILQ_ENTRY(S390PCIBusDevice) link; +}; + +struct S390PCIBus { + BusState qbus; +}; + +struct S390pciState { + PCIHostState parent_obj; + uint32_t next_idx; + int bus_no; + S390PCIBus *bus; + GHashTable *iommu_table; + GHashTable *zpci_table; + QTAILQ_HEAD(, SeiContainer) pending_sei; + QTAILQ_HEAD(, S390PCIBusDevice) zpci_devs; + QTAILQ_HEAD(, S390PCIDMACount) zpci_dma_limit; + QTAILQ_HEAD(, S390PCIGroup) zpci_groups; +}; + +S390pciState *s390_get_phb(void); +int pci_chsc_sei_nt2_get_event(void *res); +int pci_chsc_sei_nt2_have_event(void); +void s390_pci_sclp_configure(SCCB *sccb); +void s390_pci_sclp_deconfigure(SCCB *sccb); +void s390_pci_iommu_enable(S390PCIIOMMU *iommu); +void s390_pci_iommu_disable(S390PCIIOMMU *iommu); +void s390_pci_generate_error_event(uint16_t pec, uint32_t fh, uint32_t fid, + uint64_t faddr, uint32_t e); +uint16_t s390_guest_io_table_walk(uint64_t g_iota, hwaddr addr, + S390IOTLBEntry *entry); +S390PCIBusDevice *s390_pci_find_dev_by_idx(S390pciState *s, uint32_t idx); +S390PCIBusDevice *s390_pci_find_dev_by_fh(S390pciState *s, uint32_t fh); +S390PCIBusDevice *s390_pci_find_dev_by_fid(S390pciState *s, uint32_t fid); +S390PCIBusDevice *s390_pci_find_dev_by_target(S390pciState *s, + const char *target); +S390PCIBusDevice *s390_pci_find_next_avail_dev(S390pciState *s, + S390PCIBusDevice *pbdev); + +#endif diff --git a/include/hw/s390x/s390-pci-clp.h b/include/hw/s390x/s390-pci-clp.h new file mode 100644 index 000000000..96b8e3f13 --- /dev/null +++ b/include/hw/s390x/s390-pci-clp.h @@ -0,0 +1,215 @@ +/* + * s390 CLP instruction definitions + * + * Copyright 2019 IBM Corp. + * Author(s): Pierre Morel <pmorel@de.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef HW_S390_PCI_CLP +#define HW_S390_PCI_CLP + +/* CLP common request & response block size */ +#define CLP_BLK_SIZE 4096 +#define PCI_BAR_COUNT 6 +#define PCI_MAX_FUNCTIONS 4096 + +typedef struct ClpReqHdr { + uint16_t len; + uint16_t cmd; +} QEMU_PACKED ClpReqHdr; + +typedef struct ClpRspHdr { + uint16_t len; + uint16_t rsp; +} QEMU_PACKED ClpRspHdr; + +/* CLP Response Codes */ +#define CLP_RC_OK 0x0010 /* Command request successfully */ +#define CLP_RC_CMD 0x0020 /* Command code not recognized */ +#define CLP_RC_PERM 0x0030 /* Command not authorized */ +#define CLP_RC_FMT 0x0040 /* Invalid command request format */ +#define CLP_RC_LEN 0x0050 /* Invalid command request length */ +#define CLP_RC_8K 0x0060 /* Command requires 8K LPCB */ +#define CLP_RC_RESNOT0 0x0070 /* Reserved field not zero */ +#define CLP_RC_NODATA 0x0080 /* No data available */ +#define CLP_RC_FC_UNKNOWN 0x0100 /* Function code not recognized */ + +/* + * Call Logical Processor - Command Codes + */ +#define CLP_LIST_PCI 0x0002 +#define CLP_QUERY_PCI_FN 0x0003 +#define CLP_QUERY_PCI_FNGRP 0x0004 +#define CLP_SET_PCI_FN 0x0005 + +/* PCI function handle list entry */ +typedef struct ClpFhListEntry { + uint16_t device_id; + uint16_t vendor_id; +#define CLP_FHLIST_MASK_CONFIG 0x80000000 + uint32_t config; + uint32_t fid; + uint32_t fh; +} QEMU_PACKED ClpFhListEntry; + +#define CLP_RC_SETPCIFN_FH 0x0101 /* Invalid PCI fn handle */ +#define CLP_RC_SETPCIFN_FHOP 0x0102 /* Fn handle not valid for op */ +#define CLP_RC_SETPCIFN_DMAAS 0x0103 /* Invalid DMA addr space */ +#define CLP_RC_SETPCIFN_RES 0x0104 /* Insufficient resources */ +#define CLP_RC_SETPCIFN_ALRDY 0x0105 /* Fn already in requested state */ +#define CLP_RC_SETPCIFN_ERR 0x0106 /* Fn in permanent error state */ +#define CLP_RC_SETPCIFN_RECPND 0x0107 /* Error recovery pending */ +#define CLP_RC_SETPCIFN_BUSY 0x0108 /* Fn busy */ +#define CLP_RC_LISTPCI_BADRT 0x010a /* Resume token not recognized */ +#define CLP_RC_QUERYPCIFG_PFGID 0x010b /* Unrecognized PFGID */ + +/* request or response block header length */ +#define LIST_PCI_HDR_LEN 32 + +/* Number of function handles fitting in response block */ +#define CLP_FH_LIST_NR_ENTRIES \ + ((CLP_BLK_SIZE - 2 * LIST_PCI_HDR_LEN) \ + / sizeof(ClpFhListEntry)) + +#define CLP_SET_ENABLE_PCI_FN 0 /* Yes, 0 enables it */ +#define CLP_SET_DISABLE_PCI_FN 1 /* Yes, 1 disables it */ + +#define CLP_UTIL_STR_LEN 64 +#define CLP_PFIP_NR_SEGMENTS 4 + +#define CLP_MASK_FMT 0xf0000000 + +/* List PCI functions request */ +typedef struct ClpReqListPci { + ClpReqHdr hdr; + uint32_t fmt; + uint64_t reserved1; + uint64_t resume_token; + uint64_t reserved2; +} QEMU_PACKED ClpReqListPci; + +/* List PCI functions response */ +typedef struct ClpRspListPci { + ClpRspHdr hdr; + uint32_t fmt; + uint64_t reserved1; + uint64_t resume_token; + uint32_t mdd; + uint16_t max_fn; + uint8_t flags; + uint8_t entry_size; + ClpFhListEntry fh_list[CLP_FH_LIST_NR_ENTRIES]; +} QEMU_PACKED ClpRspListPci; + +/* Query PCI function request */ +typedef struct ClpReqQueryPci { + ClpReqHdr hdr; + uint32_t fmt; + uint64_t reserved1; + uint32_t fh; /* function handle */ + uint32_t reserved2; + uint64_t reserved3; +} QEMU_PACKED ClpReqQueryPci; + +/* Query PCI function response */ +typedef struct ClpRspQueryPci { + ClpRspHdr hdr; + uint32_t fmt; + uint64_t reserved1; + uint16_t vfn; /* virtual fn number */ +#define CLP_RSP_QPCI_MASK_UTIL 0x01 + uint8_t flags; + uint8_t pfgid; + uint32_t fid; /* pci function id */ + uint8_t bar_size[PCI_BAR_COUNT]; + uint16_t pchid; + uint32_t bar[PCI_BAR_COUNT]; + uint8_t pfip[CLP_PFIP_NR_SEGMENTS]; + uint16_t reserved2; + uint8_t fmbl; + uint8_t pft; + uint64_t sdma; /* start dma as */ + uint64_t edma; /* end dma as */ + uint32_t reserved3[11]; + uint32_t uid; + uint8_t util_str[CLP_UTIL_STR_LEN]; /* utility string */ +} QEMU_PACKED ClpRspQueryPci; + +/* Query PCI function group request */ +typedef struct ClpReqQueryPciGrp { + ClpReqHdr hdr; + uint32_t fmt; + uint64_t reserved1; + uint8_t reserved2[3]; + uint8_t g; + uint32_t reserved3; + uint64_t reserved4; +} QEMU_PACKED ClpReqQueryPciGrp; + +/* Query PCI function group response */ +typedef struct ClpRspQueryPciGrp { + ClpRspHdr hdr; + uint32_t fmt; + uint64_t reserved1; +#define CLP_RSP_QPCIG_MASK_NOI 0xfff + uint16_t i; + uint8_t version; +#define CLP_RSP_QPCIG_MASK_FRAME 0x2 +#define CLP_RSP_QPCIG_MASK_REFRESH 0x1 + uint8_t fr; + uint16_t maxstbl; + uint16_t mui; + uint64_t reserved3; + uint64_t dasm; /* dma address space mask */ + uint64_t msia; /* MSI address */ + uint64_t reserved4; + uint64_t reserved5; +} QEMU_PACKED ClpRspQueryPciGrp; + +/* Set PCI function request */ +typedef struct ClpReqSetPci { + ClpReqHdr hdr; + uint32_t fmt; + uint64_t reserved1; + uint32_t fh; /* function handle */ + uint16_t reserved2; + uint8_t oc; /* operation controls */ + uint8_t ndas; /* number of dma spaces */ + uint64_t reserved3; +} QEMU_PACKED ClpReqSetPci; + +/* Set PCI function response */ +typedef struct ClpRspSetPci { + ClpRspHdr hdr; + uint32_t fmt; + uint64_t reserved1; + uint32_t fh; /* function handle */ + uint32_t reserved3; + uint64_t reserved4; +} QEMU_PACKED ClpRspSetPci; + +typedef struct ClpReqRspListPci { + ClpReqListPci request; + ClpRspListPci response; +} QEMU_PACKED ClpReqRspListPci; + +typedef struct ClpReqRspSetPci { + ClpReqSetPci request; + ClpRspSetPci response; +} QEMU_PACKED ClpReqRspSetPci; + +typedef struct ClpReqRspQueryPci { + ClpReqQueryPci request; + ClpRspQueryPci response; +} QEMU_PACKED ClpReqRspQueryPci; + +typedef struct ClpReqRspQueryPciGrp { + ClpReqQueryPciGrp request; + ClpRspQueryPciGrp response; +} QEMU_PACKED ClpReqRspQueryPciGrp; + +#endif diff --git a/include/hw/s390x/s390-pci-inst.h b/include/hw/s390x/s390-pci-inst.h new file mode 100644 index 000000000..a55c448aa --- /dev/null +++ b/include/hw/s390x/s390-pci-inst.h @@ -0,0 +1,119 @@ +/* + * s390 PCI instruction definitions + * + * Copyright 2014 IBM Corp. + * Author(s): Frank Blaschka <frank.blaschka@de.ibm.com> + * Hong Bo Li <lihbbj@cn.ibm.com> + * Yi Min Zhao <zyimin@cn.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef HW_S390_PCI_INST_H +#define HW_S390_PCI_INST_H + +#include "s390-pci-bus.h" +#include "sysemu/dma.h" + +/* Load/Store status codes */ +#define ZPCI_PCI_ST_FUNC_NOT_ENABLED 4 +#define ZPCI_PCI_ST_FUNC_IN_ERR 8 +#define ZPCI_PCI_ST_BLOCKED 12 +#define ZPCI_PCI_ST_INSUF_RES 16 +#define ZPCI_PCI_ST_INVAL_AS 20 +#define ZPCI_PCI_ST_FUNC_ALREADY_ENABLED 24 +#define ZPCI_PCI_ST_DMA_AS_NOT_ENABLED 28 +#define ZPCI_PCI_ST_2ND_OP_IN_INV_AS 36 +#define ZPCI_PCI_ST_FUNC_NOT_AVAIL 40 +#define ZPCI_PCI_ST_ALREADY_IN_RQ_STATE 44 + +/* Load/Store return codes */ +#define ZPCI_PCI_LS_OK 0 +#define ZPCI_PCI_LS_ERR 1 +#define ZPCI_PCI_LS_BUSY 2 +#define ZPCI_PCI_LS_INVAL_HANDLE 3 + +/* Modify PCI status codes */ +#define ZPCI_MOD_ST_RES_NOT_AVAIL 4 +#define ZPCI_MOD_ST_INSUF_RES 16 +#define ZPCI_MOD_ST_SEQUENCE 24 +#define ZPCI_MOD_ST_DMAAS_INVAL 28 +#define ZPCI_MOD_ST_FRAME_INVAL 32 +#define ZPCI_MOD_ST_ERROR_RECOVER 40 + +/* Modify PCI Function Controls */ +#define ZPCI_MOD_FC_REG_INT 2 +#define ZPCI_MOD_FC_DEREG_INT 3 +#define ZPCI_MOD_FC_REG_IOAT 4 +#define ZPCI_MOD_FC_DEREG_IOAT 5 +#define ZPCI_MOD_FC_REREG_IOAT 6 +#define ZPCI_MOD_FC_RESET_ERROR 7 +#define ZPCI_MOD_FC_RESET_BLOCK 9 +#define ZPCI_MOD_FC_SET_MEASURE 10 + +/* Store PCI Function Controls status codes */ +#define ZPCI_STPCIFC_ST_PERM_ERROR 8 +#define ZPCI_STPCIFC_ST_INVAL_DMAAS 28 +#define ZPCI_STPCIFC_ST_ERROR_RECOVER 40 + +/* Refresh PCI Translations status codes */ +#define ZPCI_RPCIT_ST_INSUFF_RES 16 + +/* FIB function controls */ +#define ZPCI_FIB_FC_ENABLED 0x80 +#define ZPCI_FIB_FC_ERROR 0x40 +#define ZPCI_FIB_FC_LS_BLOCKED 0x20 +#define ZPCI_FIB_FC_DMAAS_REG 0x10 + +/* FIB function controls */ +#define ZPCI_FIB_FC_ENABLED 0x80 +#define ZPCI_FIB_FC_ERROR 0x40 +#define ZPCI_FIB_FC_LS_BLOCKED 0x20 +#define ZPCI_FIB_FC_DMAAS_REG 0x10 + +/* Function Information Block */ +typedef struct ZpciFib { + uint8_t fmt; /* format */ + uint8_t reserved1[7]; + uint8_t fc; /* function controls */ + uint8_t reserved2; + uint16_t reserved3; + uint32_t reserved4; + uint64_t pba; /* PCI base address */ + uint64_t pal; /* PCI address limit */ + uint64_t iota; /* I/O Translation Anchor */ +#define FIB_DATA_ISC(x) (((x) >> 28) & 0x7) +#define FIB_DATA_NOI(x) (((x) >> 16) & 0xfff) +#define FIB_DATA_AIBVO(x) (((x) >> 8) & 0x3f) +#define FIB_DATA_SUM(x) (((x) >> 7) & 0x1) +#define FIB_DATA_AISBO(x) ((x) & 0x3f) + uint32_t data; + uint32_t reserved5; + uint64_t aibv; /* Adapter int bit vector address */ + uint64_t aisb; /* Adapter int summary bit address */ + uint64_t fmb_addr; /* Function measurement address and key */ + uint32_t reserved6; + uint32_t gd; +} QEMU_PACKED ZpciFib; + +int pci_dereg_irqs(S390PCIBusDevice *pbdev); +void pci_dereg_ioat(S390PCIIOMMU *iommu); +int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra); +int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra); +int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra); +int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra); +int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, + uint8_t ar, uintptr_t ra); +int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar, + uintptr_t ra); +int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar, + uintptr_t ra); +void fmb_timer_free(S390PCIBusDevice *pbdev); + +#define ZPCI_IO_BAR_MIN 0 +#define ZPCI_IO_BAR_MAX 5 +#define ZPCI_CONFIG_BAR 15 + +#endif diff --git a/include/hw/s390x/s390-pci-vfio.h b/include/hw/s390x/s390-pci-vfio.h new file mode 100644 index 000000000..ff708aef5 --- /dev/null +++ b/include/hw/s390x/s390-pci-vfio.h @@ -0,0 +1,39 @@ +/* + * s390 vfio-pci interfaces + * + * Copyright 2020 IBM Corp. + * Author(s): Matthew Rosato <mjrosato@linux.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef HW_S390_PCI_VFIO_H +#define HW_S390_PCI_VFIO_H + +#include "hw/s390x/s390-pci-bus.h" +#include CONFIG_DEVICES + +#ifdef CONFIG_VFIO +bool s390_pci_update_dma_avail(int fd, unsigned int *avail); +S390PCIDMACount *s390_pci_start_dma_count(S390pciState *s, + S390PCIBusDevice *pbdev); +void s390_pci_end_dma_count(S390pciState *s, S390PCIDMACount *cnt); +void s390_pci_get_clp_info(S390PCIBusDevice *pbdev); +#else +static inline bool s390_pci_update_dma_avail(int fd, unsigned int *avail) +{ + return false; +} +static inline S390PCIDMACount *s390_pci_start_dma_count(S390pciState *s, + S390PCIBusDevice *pbdev) +{ + return NULL; +} +static inline void s390_pci_end_dma_count(S390pciState *s, + S390PCIDMACount *cnt) { } +static inline void s390_pci_get_clp_info(S390PCIBusDevice *pbdev) { } +#endif + +#endif diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h new file mode 100644 index 000000000..3331990e0 --- /dev/null +++ b/include/hw/s390x/s390-virtio-ccw.h @@ -0,0 +1,57 @@ +/* + * virtio ccw machine definitions + * + * Copyright 2012, 2016 IBM Corp. + * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ +#ifndef HW_S390X_S390_VIRTIO_CCW_H +#define HW_S390X_S390_VIRTIO_CCW_H + +#include "hw/boards.h" +#include "qom/object.h" + +#define TYPE_S390_CCW_MACHINE "s390-ccw-machine" + +OBJECT_DECLARE_TYPE(S390CcwMachineState, S390CcwMachineClass, S390_CCW_MACHINE) + + +struct S390CcwMachineState { + /*< private >*/ + MachineState parent_obj; + + /*< public >*/ + bool aes_key_wrap; + bool dea_key_wrap; + bool pv; + uint8_t loadparm[8]; +}; + +struct S390CcwMachineClass { + /*< private >*/ + MachineClass parent_class; + + /*< public >*/ + bool ri_allowed; + bool cpu_model_allowed; + bool css_migration_enabled; + bool hpage_1m_allowed; +}; + +/* 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 + * is enabled, false if it is disabled. + */ +bool css_migration_enabled(void); + +#endif diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h new file mode 100644 index 000000000..3907a13d0 --- /dev/null +++ b/include/hw/s390x/s390_flic.h @@ -0,0 +1,142 @@ +/* + * QEMU S390x floating interrupt controller (flic) + * + * Copyright 2014 IBM Corp. + * Author(s): Jens Freimann <jfrei@linux.vnet.ibm.com> + * Cornelia Huck <cornelia.huck@de.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef HW_S390_FLIC_H +#define HW_S390_FLIC_H + +#include "hw/sysbus.h" +#include "hw/s390x/adapter.h" +#include "hw/virtio/virtio.h" +#include "qemu/queue.h" +#include "qom/object.h" + +/* + * Reserve enough gsis to accommodate all virtio devices. + * If any other user of adapter routes needs more of these, + * we need to bump the value; but virtio looks like the + * maximum right now. + */ +#define ADAPTER_ROUTES_MAX_GSI VIRTIO_QUEUE_MAX + +typedef struct AdapterRoutes { + AdapterInfo adapter; + int num_routes; + int gsi[ADAPTER_ROUTES_MAX_GSI]; +} AdapterRoutes; + +extern const VMStateDescription vmstate_adapter_routes; + +#define VMSTATE_ADAPTER_ROUTES(_f, _s) \ + VMSTATE_STRUCT(_f, _s, 1, vmstate_adapter_routes, AdapterRoutes) + +#define TYPE_S390_FLIC_COMMON "s390-flic" +OBJECT_DECLARE_TYPE(S390FLICState, S390FLICStateClass, + S390_FLIC_COMMON) + +struct S390FLICState { + SysBusDevice parent_obj; + /* to limit AdapterRoutes.num_routes for compat */ + uint32_t adapter_routes_max_batch; + bool ais_supported; +}; + + +struct S390FLICStateClass { + DeviceClass parent_class; + + int (*register_io_adapter)(S390FLICState *fs, uint32_t id, uint8_t isc, + bool swap, bool maskable, uint8_t flags); + int (*io_adapter_map)(S390FLICState *fs, uint32_t id, uint64_t map_addr, + bool do_map); + int (*add_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes); + void (*release_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes); + int (*clear_io_irq)(S390FLICState *fs, uint16_t subchannel_id, + uint16_t subchannel_nr); + int (*modify_ais_mode)(S390FLICState *fs, uint8_t isc, uint16_t mode); + int (*inject_airq)(S390FLICState *fs, uint8_t type, uint8_t isc, + uint8_t flags); + void (*inject_service)(S390FLICState *fs, uint32_t parm); + void (*inject_io)(S390FLICState *fs, uint16_t subchannel_id, + uint16_t subchannel_nr, uint32_t io_int_parm, + uint32_t io_int_word); + void (*inject_crw_mchk)(S390FLICState *fs); +}; + +#define TYPE_KVM_S390_FLIC "s390-flic-kvm" +typedef struct KVMS390FLICState KVMS390FLICState; +DECLARE_INSTANCE_CHECKER(KVMS390FLICState, KVM_S390_FLIC, + TYPE_KVM_S390_FLIC) + +#define TYPE_QEMU_S390_FLIC "s390-flic-qemu" +OBJECT_DECLARE_SIMPLE_TYPE(QEMUS390FLICState, QEMU_S390_FLIC) + +#define SIC_IRQ_MODE_ALL 0 +#define SIC_IRQ_MODE_SINGLE 1 +#define AIS_MODE_MASK(isc) (0x80 >> isc) + +#define ISC_TO_PENDING_IO(_isc) (0x80 >> (_isc)) +#define CR6_TO_PENDING_IO(_cr6) (((_cr6) >> 24) & 0xff) + +/* organize the ISC bits so that the macros above work */ +#define FLIC_PENDING_IO_ISC7 (1 << 0) +#define FLIC_PENDING_IO_ISC6 (1 << 1) +#define FLIC_PENDING_IO_ISC5 (1 << 2) +#define FLIC_PENDING_IO_ISC4 (1 << 3) +#define FLIC_PENDING_IO_ISC3 (1 << 4) +#define FLIC_PENDING_IO_ISC2 (1 << 5) +#define FLIC_PENDING_IO_ISC1 (1 << 6) +#define FLIC_PENDING_IO_ISC0 (1 << 7) +#define FLIC_PENDING_SERVICE (1 << 8) +#define FLIC_PENDING_MCHK_CR (1 << 9) + +#define FLIC_PENDING_IO (FLIC_PENDING_IO_ISC0 | FLIC_PENDING_IO_ISC1 | \ + FLIC_PENDING_IO_ISC2 | FLIC_PENDING_IO_ISC3 | \ + FLIC_PENDING_IO_ISC4 | FLIC_PENDING_IO_ISC5 | \ + FLIC_PENDING_IO_ISC6 | FLIC_PENDING_IO_ISC7) + +typedef struct QEMUS390FlicIO { + uint16_t id; + uint16_t nr; + uint32_t parm; + uint32_t word; + QLIST_ENTRY(QEMUS390FlicIO) next; +} QEMUS390FlicIO; + +struct QEMUS390FLICState { + S390FLICState parent_obj; + uint32_t pending; + uint32_t service_param; + uint8_t simm; + uint8_t nimm; + QLIST_HEAD(, QEMUS390FlicIO) io[8]; +}; + +uint32_t qemu_s390_flic_dequeue_service(QEMUS390FLICState *flic); +QEMUS390FlicIO *qemu_s390_flic_dequeue_io(QEMUS390FLICState *flic, + uint64_t cr6); +void qemu_s390_flic_dequeue_crw_mchk(QEMUS390FLICState *flic); +bool qemu_s390_flic_has_service(QEMUS390FLICState *flic); +bool qemu_s390_flic_has_io(QEMUS390FLICState *fs, uint64_t cr6); +bool qemu_s390_flic_has_crw_mchk(QEMUS390FLICState *flic); +bool qemu_s390_flic_has_any(QEMUS390FLICState *flic); + +void s390_flic_init(void); + +S390FLICState *s390_get_flic(void); +QEMUS390FLICState *s390_get_qemu_flic(S390FLICState *fs); +S390FLICStateClass *s390_get_flic_class(S390FLICState *fs); +void s390_crw_mchk(void); +void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, + uint32_t io_int_parm, uint32_t io_int_word); +bool ais_needed(void *opaque); + +#endif /* HW_S390_FLIC_H */ diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h new file mode 100644 index 000000000..d3ade40a5 --- /dev/null +++ b/include/hw/s390x/sclp.h @@ -0,0 +1,232 @@ +/* + * SCLP Support + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Christian Borntraeger <borntraeger@de.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at your + * option) any later version. See the COPYING file in the top-level directory. + * + */ + +#ifndef HW_S390_SCLP_H +#define HW_S390_SCLP_H + +#include "hw/sysbus.h" +#include "target/s390x/cpu-qom.h" +#include "qom/object.h" + +#define SCLP_CMD_CODE_MASK 0xffff00ff + +/* SCLP command codes */ +#define SCLP_CMDW_READ_SCP_INFO 0x00020001 +#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001 +#define SCLP_READ_STORAGE_ELEMENT_INFO 0x00040001 +#define SCLP_ATTACH_STORAGE_ELEMENT 0x00080001 +#define SCLP_ASSIGN_STORAGE 0x000D0001 +#define SCLP_UNASSIGN_STORAGE 0x000C0001 +#define SCLP_CMD_READ_EVENT_DATA 0x00770005 +#define SCLP_CMD_WRITE_EVENT_DATA 0x00760005 +#define SCLP_CMD_WRITE_EVENT_MASK 0x00780005 + +/* SCLP Memory hotplug codes */ +#define SCLP_FC_ASSIGN_ATTACH_READ_STOR 0xE00000000000ULL +#define SCLP_STARTING_SUBINCREMENT_ID 0x10001 +#define SCLP_INCREMENT_UNIT 0x10000 +#define MAX_STORAGE_INCREMENTS 1020 + +/* CPU hotplug SCLP codes */ +#define SCLP_HAS_CPU_INFO 0x0C00000000000000ULL +#define SCLP_CMDW_READ_CPU_INFO 0x00010001 +#define SCLP_CMDW_CONFIGURE_CPU 0x00110001 +#define SCLP_CMDW_DECONFIGURE_CPU 0x00100001 + +/* SCLP PCI codes */ +#define SCLP_HAS_IOA_RECONFIG 0x0000000040000000ULL +#define SCLP_CMDW_CONFIGURE_IOA 0x001a0001 +#define SCLP_CMDW_DECONFIGURE_IOA 0x001b0001 +#define SCLP_RECONFIG_PCI_ATYPE 2 + +/* SCLP response codes */ +#define SCLP_RC_NORMAL_READ_COMPLETION 0x0010 +#define SCLP_RC_NORMAL_COMPLETION 0x0020 +#define SCLP_RC_SCCB_BOUNDARY_VIOLATION 0x0100 +#define SCLP_RC_NO_ACTION_REQUIRED 0x0120 +#define SCLP_RC_INVALID_SCLP_COMMAND 0x01f0 +#define SCLP_RC_CONTAINED_EQUIPMENT_CHECK 0x0340 +#define SCLP_RC_INSUFFICIENT_SCCB_LENGTH 0x0300 +#define SCLP_RC_STANDBY_READ_COMPLETION 0x0410 +#define SCLP_RC_ADAPTER_IN_RESERVED_STATE 0x05f0 +#define SCLP_RC_ADAPTER_TYPE_NOT_RECOGNIZED 0x06f0 +#define SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED 0x09f0 +#define SCLP_RC_INVALID_FUNCTION 0x40f0 +#define SCLP_RC_NO_EVENT_BUFFERS_STORED 0x60f0 +#define SCLP_RC_INVALID_SELECTION_MASK 0x70f0 +#define SCLP_RC_INCONSISTENT_LENGTHS 0x72f0 +#define SCLP_RC_EVENT_BUFFER_SYNTAX_ERROR 0x73f0 +#define SCLP_RC_INVALID_MASK_LENGTH 0x74f0 + + +/* Service Call Control Block (SCCB) and its elements */ + +#define SCCB_SIZE 4096 + +#define SCLP_VARIABLE_LENGTH_RESPONSE 0x80 +#define SCLP_EVENT_BUFFER_ACCEPTED 0x80 + +#define SCLP_FC_NORMAL_WRITE 0 + +/* + * Normally packed structures are not the right thing to do, since all code + * must take care of endianness. We cannot use ldl_phys and friends for two + * reasons, though: + * - some of the embedded structures below the SCCB can appear multiple times + * at different locations, so there is no fixed offset + * - we work on a private copy of the SCCB, since there are several length + * fields, that would cause a security nightmare if we allow the guest to + * alter the structure while we parse it. We cannot use ldl_p and friends + * either without doing pointer arithmetics + * So we have to double check that all users of sclp data structures use the + * right endianness wrappers. + */ +typedef struct SCCBHeader { + uint16_t length; + uint8_t function_code; + uint8_t control_mask[3]; + uint16_t response_code; +} QEMU_PACKED SCCBHeader; + +#define SCCB_DATA_LEN (SCCB_SIZE - sizeof(SCCBHeader)) +#define SCCB_CPU_FEATURE_LEN 6 + +/* CPU information */ +typedef struct CPUEntry { + uint8_t address; + uint8_t reserved0; + uint8_t features[SCCB_CPU_FEATURE_LEN]; + uint8_t reserved2[6]; + uint8_t type; + uint8_t reserved1; +} QEMU_PACKED CPUEntry; + +#define SCLP_READ_SCP_INFO_FIXED_CPU_OFFSET 128 +typedef struct ReadInfo { + SCCBHeader h; + uint16_t rnmax; + uint8_t rnsize; + uint8_t _reserved1[16 - 11]; /* 11-15 */ + uint16_t entries_cpu; /* 16-17 */ + uint16_t offset_cpu; /* 18-19 */ + uint8_t _reserved2[24 - 20]; /* 20-23 */ + uint8_t loadparm[8]; /* 24-31 */ + uint8_t _reserved3[48 - 32]; /* 32-47 */ + uint64_t facilities; /* 48-55 */ + uint8_t _reserved0[76 - 56]; /* 56-75 */ + uint32_t ibc_val; + uint8_t conf_char[99 - 80]; /* 80-98 */ + uint8_t mha_pow; + uint32_t rnsize2; + uint64_t rnmax2; + uint8_t _reserved6[116 - 112]; /* 112-115 */ + uint8_t conf_char_ext[120 - 116]; /* 116-119 */ + uint16_t highest_cpu; + uint8_t _reserved5[124 - 122]; /* 122-123 */ + uint32_t hmfai; + uint8_t _reserved7[134 - 128]; /* 128-133 */ + uint8_t fac134; + uint8_t _reserved8[144 - 135]; /* 135-143 */ + 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; + +typedef struct ReadCpuInfo { + SCCBHeader h; + uint16_t nr_configured; /* 8-9 */ + uint16_t offset_configured; /* 10-11 */ + uint16_t nr_standby; /* 12-13 */ + uint16_t offset_standby; /* 14-15 */ + uint8_t reserved0[24-16]; /* 16-23 */ + struct CPUEntry entries[]; +} QEMU_PACKED ReadCpuInfo; + +typedef struct ReadStorageElementInfo { + SCCBHeader h; + uint16_t max_id; + uint16_t assigned; + uint16_t standby; + uint8_t _reserved0[16 - 14]; /* 14-15 */ + uint32_t entries[]; +} QEMU_PACKED ReadStorageElementInfo; + +typedef struct AttachStorageElement { + SCCBHeader h; + uint8_t _reserved0[10 - 8]; /* 8-9 */ + uint16_t assigned; + uint8_t _reserved1[16 - 12]; /* 12-15 */ + uint32_t entries[]; +} QEMU_PACKED AttachStorageElement; + +typedef struct AssignStorage { + SCCBHeader h; + uint16_t rn; +} QEMU_PACKED AssignStorage; + +typedef struct IoaCfgSccb { + SCCBHeader header; + uint8_t atype; + uint8_t reserved1; + uint16_t reserved2; + uint32_t aid; +} QEMU_PACKED IoaCfgSccb; + +typedef struct SCCB { + SCCBHeader h; + char data[]; + } QEMU_PACKED SCCB; + +#define TYPE_SCLP "sclp" +OBJECT_DECLARE_TYPE(SCLPDevice, SCLPDeviceClass, + SCLP) + +struct SCLPEventFacility; + +struct SCLPDevice { + /* private */ + DeviceState parent_obj; + struct SCLPEventFacility *event_facility; + int increment_size; + + /* public */ +}; + +struct SCLPDeviceClass { + /* private */ + DeviceClass parent_class; + void (*read_SCP_info)(SCLPDevice *sclp, SCCB *sccb); + void (*read_cpu_info)(SCLPDevice *sclp, SCCB *sccb); + + /* public */ + void (*execute)(SCLPDevice *sclp, SCCB *sccb, uint32_t code); + void (*service_interrupt)(SCLPDevice *sclp, uint32_t sccb); +}; + +static inline int sccb_data_len(SCCB *sccb) +{ + return be16_to_cpu(sccb->h.length) - sizeof(sccb->h); +} + + +void s390_sclp_init(void); +void sclp_service_interrupt(uint32_t sccb); +void raise_irq_cpu_hotplug(void); +int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code); +int sclp_service_call_protected(CPUS390XState *env, uint64_t sccb, + uint32_t code); + +#endif diff --git a/include/hw/s390x/storage-attributes.h b/include/hw/s390x/storage-attributes.h new file mode 100644 index 000000000..5239eb538 --- /dev/null +++ b/include/hw/s390x/storage-attributes.h @@ -0,0 +1,79 @@ +/* + * s390 storage attributes device + * + * Copyright 2016 IBM Corp. + * Author(s): Claudio Imbrenda <imbrenda@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef S390_STORAGE_ATTRIBUTES_H +#define S390_STORAGE_ATTRIBUTES_H + +#include "hw/qdev-core.h" +#include "monitor/monitor.h" +#include "qom/object.h" + +#define TYPE_S390_STATTRIB "s390-storage_attributes" +#define TYPE_QEMU_S390_STATTRIB "s390-storage_attributes-qemu" +#define TYPE_KVM_S390_STATTRIB "s390-storage_attributes-kvm" + +OBJECT_DECLARE_TYPE(S390StAttribState, S390StAttribClass, S390_STATTRIB) + +struct S390StAttribState { + DeviceState parent_obj; + uint64_t migration_cur_gfn; + bool migration_enabled; +}; + + +struct S390StAttribClass { + DeviceClass parent_class; + /* Return value: < 0 on error, or new count */ + int (*get_stattr)(S390StAttribState *sa, uint64_t *start_gfn, + uint32_t count, uint8_t *values); + int (*peek_stattr)(S390StAttribState *sa, uint64_t start_gfn, + uint32_t count, uint8_t *values); + int (*set_stattr)(S390StAttribState *sa, uint64_t start_gfn, + uint32_t count, uint8_t *values); + void (*synchronize)(S390StAttribState *sa); + int (*set_migrationmode)(S390StAttribState *sa, bool value); + int (*get_active)(S390StAttribState *sa); + long long (*get_dirtycount)(S390StAttribState *sa); +}; + +typedef struct QEMUS390StAttribState QEMUS390StAttribState; +DECLARE_INSTANCE_CHECKER(QEMUS390StAttribState, QEMU_S390_STATTRIB, + TYPE_QEMU_S390_STATTRIB) + +struct QEMUS390StAttribState { + S390StAttribState parent_obj; +}; + +typedef struct KVMS390StAttribState KVMS390StAttribState; +DECLARE_INSTANCE_CHECKER(KVMS390StAttribState, KVM_S390_STATTRIB, + TYPE_KVM_S390_STATTRIB) + +struct KVMS390StAttribState { + S390StAttribState parent_obj; + uint64_t still_dirty; + uint8_t *incoming_buffer; +}; + +void s390_stattrib_init(void); + +#ifdef CONFIG_KVM +Object *kvm_s390_stattrib_create(void); +#else +static inline Object *kvm_s390_stattrib_create(void) +{ + return NULL; +} +#endif + +void hmp_info_cmma(Monitor *mon, const QDict *qdict); +void hmp_migrationmode(Monitor *mon, const QDict *qdict); + +#endif /* S390_STORAGE_ATTRIBUTES_H */ diff --git a/include/hw/s390x/storage-keys.h b/include/hw/s390x/storage-keys.h new file mode 100644 index 000000000..aa2ec2aae --- /dev/null +++ b/include/hw/s390x/storage-keys.h @@ -0,0 +1,120 @@ +/* + * s390 storage key device + * + * Copyright 2015 IBM Corp. + * Author(s): Jason J. Herne <jjherne@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef S390_STORAGE_KEYS_H +#define S390_STORAGE_KEYS_H + +#include "hw/qdev-core.h" +#include "monitor/monitor.h" +#include "qom/object.h" + +#define TYPE_S390_SKEYS "s390-skeys" +OBJECT_DECLARE_TYPE(S390SKeysState, S390SKeysClass, S390_SKEYS) + +struct S390SKeysState { + DeviceState parent_obj; + bool migration_enabled; + +}; + + +struct S390SKeysClass { + DeviceClass parent_class; + + /** + * @skeys_are_enabled: + * + * Check whether storage keys are enabled. If not enabled, they were not + * enabled lazily either by the guest via a storage key instruction or + * by the host during migration. + * + * If disabled, everything not explicitly triggered by the guest, + * such as outgoing migration or dirty/change tracking, should not touch + * storage keys and should not lazily enable it. + * + * @ks: the #S390SKeysState + * + * Returns false if not enabled and true if enabled. + */ + bool (*skeys_are_enabled)(S390SKeysState *ks); + + /** + * @enable_skeys: + * + * Lazily enable storage keys. If this function is not implemented, + * setting a storage key will lazily enable storage keys implicitly + * instead. TCG guests have to make sure to flush the TLB of all CPUs + * if storage keys were not enabled before this call. + * + * @ks: the #S390SKeysState + * + * Returns false if not enabled before this call, and true if already + * enabled. + */ + bool (*enable_skeys)(S390SKeysState *ks); + + /** + * @get_skeys: + * + * Get storage keys for the given PFN range. This call will fail if + * storage keys have not been lazily enabled yet. + * + * Callers have to validate that a GFN is valid before this call. + * + * @ks: the #S390SKeysState + * @start_gfn: the start GFN to get storage keys for + * @count: the number of storage keys to get + * @keys: the byte array where storage keys will be stored to + * + * Returns 0 on success, returns an error if getting a storage key failed. + */ + int (*get_skeys)(S390SKeysState *ks, uint64_t start_gfn, uint64_t count, + uint8_t *keys); + /** + * @set_skeys: + * + * Set storage keys for the given PFN range. This call will fail if + * storage keys have not been lazily enabled yet and implicit + * enablement is not supported. + * + * Callers have to validate that a GFN is valid before this call. + * + * @ks: the #S390SKeysState + * @start_gfn: the start GFN to set storage keys for + * @count: the number of storage keys to set + * @keys: the byte array where storage keys will be read from + * + * Returns 0 on success, returns an error if setting a storage key failed. + */ + int (*set_skeys)(S390SKeysState *ks, uint64_t start_gfn, uint64_t count, + uint8_t *keys); +}; + +#define TYPE_KVM_S390_SKEYS "s390-skeys-kvm" +#define TYPE_QEMU_S390_SKEYS "s390-skeys-qemu" +typedef struct QEMUS390SKeysState QEMUS390SKeysState; +DECLARE_INSTANCE_CHECKER(QEMUS390SKeysState, QEMU_S390_SKEYS, + TYPE_QEMU_S390_SKEYS) + +struct QEMUS390SKeysState { + S390SKeysState parent_obj; + uint8_t *keydata; + uint32_t key_count; +}; + +void s390_skeys_init(void); + +S390SKeysState *s390_get_skeys_device(void); + +void hmp_dump_skeys(Monitor *mon, const QDict *qdict); +void hmp_info_skeys(Monitor *mon, const QDict *qdict); + +#endif /* S390_STORAGE_KEYS_H */ diff --git a/include/hw/s390x/tod.h b/include/hw/s390x/tod.h new file mode 100644 index 000000000..0935e8508 --- /dev/null +++ b/include/hw/s390x/tod.h @@ -0,0 +1,54 @@ +/* + * TOD (Time Of Day) clock + * + * Copyright 2018 Red Hat, Inc. + * Author(s): David Hildenbrand <david@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_S390_TOD_H +#define HW_S390_TOD_H + +#include "hw/qdev-core.h" +#include "tcg/s390-tod.h" +#include "qom/object.h" + +typedef struct S390TOD { + uint8_t high; + uint64_t low; +} S390TOD; + +#define TYPE_S390_TOD "s390-tod" +OBJECT_DECLARE_TYPE(S390TODState, S390TODClass, S390_TOD) +#define TYPE_KVM_S390_TOD TYPE_S390_TOD "-kvm" +#define TYPE_QEMU_S390_TOD TYPE_S390_TOD "-qemu" + +struct S390TODState { + /* private */ + DeviceState parent_obj; + + /* + * Used by TCG to remember the time base. Used by KVM to backup the TOD + * while the TOD is stopped. + */ + S390TOD base; + /* Used by KVM to remember if the TOD is stopped and base is valid. */ + bool stopped; +}; + +struct S390TODClass { + /* private */ + DeviceClass parent_class; + void (*parent_realize)(DeviceState *dev, Error **errp); + + /* public */ + void (*get)(const S390TODState *td, S390TOD *tod, Error **errp); + void (*set)(S390TODState *td, const S390TOD *tod, Error **errp); +}; + +void s390_init_tod(void); +S390TODState *s390_get_todstate(void); + +#endif diff --git a/include/hw/s390x/vfio-ccw.h b/include/hw/s390x/vfio-ccw.h new file mode 100644 index 000000000..63a909eb7 --- /dev/null +++ b/include/hw/s390x/vfio-ccw.h @@ -0,0 +1,27 @@ +/* + * vfio based subchannel assignment support + * + * Copyright 2017, 2019 IBM Corp. + * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com> + * Xiao Feng Ren <renxiaof@linux.vnet.ibm.com> + * Pierre Morel <pmorel@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef HW_VFIO_CCW_H +#define HW_VFIO_CCW_H + +#include "hw/vfio/vfio-common.h" +#include "hw/s390x/s390-ccw.h" +#include "hw/s390x/ccw-device.h" +#include "qom/object.h" + +#define TYPE_VFIO_CCW "vfio-ccw" +OBJECT_DECLARE_SIMPLE_TYPE(VFIOCCWDevice, VFIO_CCW) + +#define TYPE_VFIO_CCW "vfio-ccw" + +#endif |