mirror of
https://github.com/xemu-project/xemu.git
synced 2024-12-04 01:21:54 +00:00
First batch of s390x patches for 2.7:
- The new machine for 2.7 - Make use of the runtime instrumentation support introduced in the kernel - Enhance our ipl (boot) process: We can now start from devices in subchannel sets > 0 as well. As a bonus, the conversion to diag308 in the bios allows us to get rid of the gr7 hack. - Xiaoqiang Zhao's SCLP qomification patches - Several fixes in the s390x pci implementation -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJXOyw0AAoJEN7Pa5PG8C+v2fkQAI+woDEWJ9a1DtOw/sdIicX2 wlXdzadtGM1/g0HWvmF1smMLCUcNtEA77+R5o0yE5cPnOBWI0WzuNPZmiMbkMROm gCC9OU9WOVDTPrrxfOGp4yhZkbZdz/K7TQUUB0bRRC+RTBJFNOqHSKrIDl+4AgkS v83hwYHcGEku53++BOrstlMcVY9gzGnL3E2KH6m1Rvhtac8bkjps5qzgmmQVCmL9 EZCFZn0rH0LYq6Sdq3Fa6x89tdKsZ4ktnT76UJvJ4XGagHvOq9yojJixYQQnvfK4 m5OlHadJdA/op4JxXxCM4TZbdxDQWo/r+pivULOmEA/cvwbQo+Ap1pDnp7BzByR+ xjSzak7vSvfF+p8L7va/J9IZqSsMmTcrpBoRrhP6vGgDUZz53XzsZIOd/Q7haNFW 5JeL3Qr7YqCi7//SQJAX0y1Q0JpyzZrZvwewAN1qyNeMSbW8lZOuj9Do2dHBvfkG l3C99V42idycu4DAVlmyULpirURg43XUjvztOjwEn9yXrnp3g+tThmwIdecDY4zQ IvTgIs5HEKFqy/HODZj7sCzY8YIJHhbGLmAzwqhtzemiH2ozsQFoN3tOITyMRL7F 5T/l2C4COZJBevGtQyd/uAGrrVU/57Ro9Ly7qchHINpWYFbnE5YkKTA3IyUIWQdz 9i36Szd8WGXgngh1z0Mz =bYQm -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20160517' into staging First batch of s390x patches for 2.7: - The new machine for 2.7 - Make use of the runtime instrumentation support introduced in the kernel - Enhance our ipl (boot) process: We can now start from devices in subchannel sets > 0 as well. As a bonus, the conversion to diag308 in the bios allows us to get rid of the gr7 hack. - Xiaoqiang Zhao's SCLP qomification patches - Several fixes in the s390x pci implementation # gpg: Signature made Tue 17 May 2016 15:35:32 BST using RSA key ID C6F02FAF # gpg: Good signature from "Cornelia Huck <huckc@linux.vnet.ibm.com>" # gpg: aka "Cornelia Huck <cornelia.huck@de.ibm.com>" * remotes/cohuck/tags/s390x-20160517: s390x/pci: remove whitespace s390x/pci: add length checking for pci sclp handlers s390x/pci: enhance mpcifc_service_call s390x/pci: fix s390_pci_sclp_deconfigure s390x/pci: introduce S390PCIBusDevice.iommu_enabled s390x/pci: export pci_dereg_ioat and pci_dereg_irqs s390x/pci: separate s390_pcihost_iommu_configure function s390x/pci: separate s390_sclp_configure function s390x/pci: fix reg_irqs() hw/char: QOM'ify sclpconsole.c hw/char: QOM'ify sclpconsole-lm.c s390x/ipl: Remove redundant usage of gr7 s390-ccw.img: rebuild image pc-bios/s390-ccw: Get device address via diag 308/6 s390x/ipl: Add ssid field to IplParameterBlock s390x/ipl: Provide ipl parameter block s390x/ipl: Add type and length checks for IplParameterBlock values s390x/ipl: Extend the IplParameterBlock struct s390x: enable runtime instrumentation s390x: add compat machine for 2.7 Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
a257c74149
@ -44,6 +44,10 @@ typedef struct SCLPConsoleLM {
|
||||
uint8_t buf[SIZE_CONSOLE_BUFFER];
|
||||
} SCLPConsoleLM;
|
||||
|
||||
#define TYPE_SCLPLM_CONSOLE "sclplmconsole"
|
||||
#define SCLPLM_CONSOLE(obj) \
|
||||
OBJECT_CHECK(SCLPConsoleLM, (obj), TYPE_SCLPLM_CONSOLE)
|
||||
|
||||
/*
|
||||
* Character layer call-back functions
|
||||
*
|
||||
@ -116,7 +120,7 @@ static int get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size,
|
||||
{
|
||||
int len;
|
||||
|
||||
SCLPConsoleLM *cons = DO_UPCAST(SCLPConsoleLM, event, event);
|
||||
SCLPConsoleLM *cons = SCLPLM_CONSOLE(event);
|
||||
|
||||
len = cons->length;
|
||||
/* data need to fit into provided SCLP buffer */
|
||||
@ -190,7 +194,7 @@ static int write_console_data(SCLPEvent *event, const uint8_t *buf, int len)
|
||||
int ret = 0;
|
||||
const uint8_t *buf_offset;
|
||||
|
||||
SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event);
|
||||
SCLPConsoleLM *scon = SCLPLM_CONSOLE(event);
|
||||
|
||||
if (!scon->chr) {
|
||||
/* If there's no backend, we can just say we consumed all data. */
|
||||
@ -244,7 +248,7 @@ static int write_event_data(SCLPEvent *event, EventBufferHeader *ebh)
|
||||
int errors = 0;
|
||||
MDBO *mdbo;
|
||||
SclpMsg *data = (SclpMsg *) ebh;
|
||||
SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event);
|
||||
SCLPConsoleLM *scon = SCLPLM_CONSOLE(event);
|
||||
|
||||
len = be16_to_cpu(data->mdb.header.length);
|
||||
if (len < sizeof(data->mdb.header)) {
|
||||
@ -313,7 +317,7 @@ static int console_init(SCLPEvent *event)
|
||||
{
|
||||
static bool console_available;
|
||||
|
||||
SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event);
|
||||
SCLPConsoleLM *scon = SCLPLM_CONSOLE(event);
|
||||
|
||||
if (console_available) {
|
||||
error_report("Multiple line-mode operator consoles are not supported");
|
||||
@ -336,7 +340,7 @@ static int console_exit(SCLPEvent *event)
|
||||
static void console_reset(DeviceState *dev)
|
||||
{
|
||||
SCLPEvent *event = SCLP_EVENT(dev);
|
||||
SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event);
|
||||
SCLPConsoleLM *scon = SCLPLM_CONSOLE(event);
|
||||
|
||||
event->event_pending = false;
|
||||
scon->length = 0;
|
||||
|
@ -40,6 +40,10 @@ typedef struct SCLPConsole {
|
||||
bool notify; /* qemu_notify_event() req'd if true */
|
||||
} SCLPConsole;
|
||||
|
||||
#define TYPE_SCLP_CONSOLE "sclpconsole"
|
||||
#define SCLP_CONSOLE(obj) \
|
||||
OBJECT_CHECK(SCLPConsole, (obj), TYPE_SCLP_CONSOLE)
|
||||
|
||||
/* character layer call-back functions */
|
||||
|
||||
/* Return number of bytes that fit into iov buffer */
|
||||
@ -95,7 +99,7 @@ static unsigned int receive_mask(void)
|
||||
static void get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size,
|
||||
int avail)
|
||||
{
|
||||
SCLPConsole *cons = DO_UPCAST(SCLPConsole, event, event);
|
||||
SCLPConsole *cons = SCLP_CONSOLE(event);
|
||||
|
||||
/* first byte is hex 0 saying an ascii string follows */
|
||||
*buf++ = '\0';
|
||||
@ -157,7 +161,7 @@ static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr,
|
||||
static ssize_t write_console_data(SCLPEvent *event, const uint8_t *buf,
|
||||
size_t len)
|
||||
{
|
||||
SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event);
|
||||
SCLPConsole *scon = SCLP_CONSOLE(event);
|
||||
|
||||
if (!scon->chr) {
|
||||
/* If there's no backend, we can just say we consumed all data. */
|
||||
@ -214,7 +218,7 @@ static int console_init(SCLPEvent *event)
|
||||
{
|
||||
static bool console_available;
|
||||
|
||||
SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event);
|
||||
SCLPConsole *scon = SCLP_CONSOLE(event);
|
||||
|
||||
if (console_available) {
|
||||
error_report("Multiple VT220 operator consoles are not supported");
|
||||
@ -232,7 +236,7 @@ static int console_init(SCLPEvent *event)
|
||||
static void console_reset(DeviceState *dev)
|
||||
{
|
||||
SCLPEvent *event = SCLP_EVENT(dev);
|
||||
SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event);
|
||||
SCLPConsole *scon = SCLP_CONSOLE(event);
|
||||
|
||||
event->event_pending = false;
|
||||
scon->iov_sclp = 0;
|
||||
|
@ -30,6 +30,24 @@
|
||||
#define ZIPL_IMAGE_START 0x009000UL
|
||||
#define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64)
|
||||
|
||||
static bool iplb_extended_needed(void *opaque)
|
||||
{
|
||||
S390IPLState *ipl = S390_IPL(object_resolve_path(TYPE_S390_IPL, NULL));
|
||||
|
||||
return ipl->iplbext_migration;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_iplb_extended = {
|
||||
.name = "ipl/iplb_extended",
|
||||
.version_id = 0,
|
||||
.minimum_version_id = 0,
|
||||
.needed = iplb_extended_needed,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT8_ARRAY(reserved_ext, IplParameterBlock, 4096 - 200),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_iplb = {
|
||||
.name = "ipl/iplb",
|
||||
.version_id = 0,
|
||||
@ -39,6 +57,10 @@ static const VMStateDescription vmstate_iplb = {
|
||||
VMSTATE_UINT16(devno, IplParameterBlock),
|
||||
VMSTATE_UINT8_ARRAY(reserved2, IplParameterBlock, 88),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
.subsections = (const VMStateDescription*[]) {
|
||||
&vmstate_iplb_extended,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
@ -181,46 +203,32 @@ static Property s390_ipl_properties[] = {
|
||||
DEFINE_PROP_STRING("cmdline", S390IPLState, cmdline),
|
||||
DEFINE_PROP_STRING("firmware", S390IPLState, firmware),
|
||||
DEFINE_PROP_BOOL("enforce_bios", S390IPLState, enforce_bios, false),
|
||||
DEFINE_PROP_BOOL("iplbext_migration", S390IPLState, iplbext_migration,
|
||||
true),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
/*
|
||||
* In addition to updating the iplstate, this function returns:
|
||||
* - 0 if system was ipled with external kernel
|
||||
* - -1 if no valid boot device was found
|
||||
* - ccw id of the boot device otherwise
|
||||
*/
|
||||
static uint64_t s390_update_iplstate(S390IPLState *ipl)
|
||||
static bool s390_gen_initial_iplb(S390IPLState *ipl)
|
||||
{
|
||||
DeviceState *dev_st;
|
||||
|
||||
if (ipl->iplb_valid) {
|
||||
ipl->cssid = 0;
|
||||
ipl->ssid = 0;
|
||||
ipl->devno = ipl->iplb.devno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ipl->kernel) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_st = get_boot_device(0);
|
||||
if (dev_st) {
|
||||
VirtioCcwDevice *ccw_dev = (VirtioCcwDevice *) object_dynamic_cast(
|
||||
OBJECT(qdev_get_parent_bus(dev_st)->parent),
|
||||
TYPE_VIRTIO_CCW_DEVICE);
|
||||
if (ccw_dev) {
|
||||
ipl->cssid = ccw_dev->sch->cssid;
|
||||
ipl->ssid = ccw_dev->sch->ssid;
|
||||
ipl->devno = ccw_dev->sch->devno;
|
||||
goto out;
|
||||
ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
|
||||
ipl->iplb.blk0_len =
|
||||
cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN);
|
||||
ipl->iplb.pbt = S390_IPL_TYPE_CCW;
|
||||
ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
|
||||
ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
out:
|
||||
return (uint32_t) (ipl->cssid << 24 | ipl->ssid << 16 | ipl->devno);
|
||||
return false;
|
||||
}
|
||||
|
||||
void s390_ipl_update_diag308(IplParameterBlock *iplb)
|
||||
@ -258,7 +266,9 @@ void s390_ipl_prepare_cpu(S390CPU *cpu)
|
||||
|
||||
if (!ipl->kernel || ipl->iplb_valid) {
|
||||
cpu->env.psw.addr = ipl->bios_start_addr;
|
||||
cpu->env.regs[7] = s390_update_iplstate(ipl);
|
||||
if (!ipl->iplb_valid) {
|
||||
ipl->iplb_valid = s390_gen_initial_iplb(ipl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,6 +278,7 @@ static void s390_ipl_reset(DeviceState *dev)
|
||||
|
||||
if (!ipl->reipl_requested) {
|
||||
ipl->iplb_valid = false;
|
||||
memset(&ipl->iplb, 0, sizeof(IplParameterBlock));
|
||||
}
|
||||
ipl->reipl_requested = false;
|
||||
}
|
||||
|
@ -15,11 +15,60 @@
|
||||
#include "hw/qdev.h"
|
||||
#include "cpu.h"
|
||||
|
||||
typedef struct IplParameterBlock {
|
||||
uint8_t reserved1[110];
|
||||
uint16_t devno;
|
||||
uint8_t reserved2[88];
|
||||
} IplParameterBlock;
|
||||
struct IplBlockCcw {
|
||||
uint8_t reserved0[85];
|
||||
uint8_t ssid;
|
||||
uint16_t devno;
|
||||
uint8_t vm_flags;
|
||||
uint8_t reserved3[3];
|
||||
uint32_t vm_parm_len;
|
||||
uint8_t nss_name[8];
|
||||
uint8_t vm_parm[64];
|
||||
uint8_t reserved4[8];
|
||||
} QEMU_PACKED;
|
||||
typedef struct IplBlockCcw IplBlockCcw;
|
||||
|
||||
struct IplBlockFcp {
|
||||
uint8_t reserved1[305 - 1];
|
||||
uint8_t opt;
|
||||
uint8_t reserved2[3];
|
||||
uint16_t reserved3;
|
||||
uint16_t devno;
|
||||
uint8_t reserved4[4];
|
||||
uint64_t wwpn;
|
||||
uint64_t lun;
|
||||
uint32_t bootprog;
|
||||
uint8_t reserved5[12];
|
||||
uint64_t br_lba;
|
||||
uint32_t scp_data_len;
|
||||
uint8_t reserved6[260];
|
||||
uint8_t scp_data[];
|
||||
} QEMU_PACKED;
|
||||
typedef struct IplBlockFcp IplBlockFcp;
|
||||
|
||||
union IplParameterBlock {
|
||||
struct {
|
||||
uint32_t len;
|
||||
uint8_t reserved0[3];
|
||||
uint8_t version;
|
||||
uint32_t blk0_len;
|
||||
uint8_t pbt;
|
||||
uint8_t flags;
|
||||
uint16_t reserved01;
|
||||
uint8_t loadparm[8];
|
||||
union {
|
||||
IplBlockCcw ccw;
|
||||
IplBlockFcp fcp;
|
||||
};
|
||||
} QEMU_PACKED;
|
||||
struct {
|
||||
uint8_t reserved1[110];
|
||||
uint16_t devno;
|
||||
uint8_t reserved2[88];
|
||||
uint8_t reserved_ext[4096 - 200];
|
||||
} QEMU_PACKED;
|
||||
} QEMU_PACKED;
|
||||
typedef union IplParameterBlock IplParameterBlock;
|
||||
|
||||
void s390_ipl_update_diag308(IplParameterBlock *iplb);
|
||||
void s390_ipl_prepare_cpu(S390CPU *cpu);
|
||||
@ -47,7 +96,32 @@ struct S390IPLState {
|
||||
uint8_t cssid;
|
||||
uint8_t ssid;
|
||||
uint16_t devno;
|
||||
bool iplbext_migration;
|
||||
};
|
||||
typedef struct S390IPLState S390IPLState;
|
||||
|
||||
#define S390_IPL_TYPE_FCP 0x00
|
||||
#define S390_IPL_TYPE_CCW 0x02
|
||||
|
||||
#define S390_IPLB_HEADER_LEN 8
|
||||
#define S390_IPLB_MIN_CCW_LEN 200
|
||||
#define S390_IPLB_MIN_FCP_LEN 384
|
||||
|
||||
static inline bool iplb_valid_len(IplParameterBlock *iplb)
|
||||
{
|
||||
return be32_to_cpu(iplb->len) <= sizeof(IplParameterBlock);
|
||||
}
|
||||
|
||||
static inline bool iplb_valid_ccw(IplParameterBlock *iplb)
|
||||
{
|
||||
return be32_to_cpu(iplb->len) >= S390_IPLB_MIN_CCW_LEN &&
|
||||
iplb->pbt == S390_IPL_TYPE_CCW;
|
||||
}
|
||||
|
||||
static inline bool iplb_valid_fcp(IplParameterBlock *iplb)
|
||||
{
|
||||
return be32_to_cpu(iplb->len) >= S390_IPLB_MIN_FCP_LEN &&
|
||||
iplb->pbt == S390_IPL_TYPE_FCP;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "s390-pci-bus.h"
|
||||
#include "s390-pci-inst.h"
|
||||
#include <hw/pci/pci_bus.h>
|
||||
#include <hw/pci/msi.h>
|
||||
#include <qemu/error-report.h>
|
||||
@ -106,25 +107,61 @@ S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void s390_pci_sclp_configure(int configure, SCCB *sccb)
|
||||
void s390_pci_sclp_configure(SCCB *sccb)
|
||||
{
|
||||
PciCfgSccb *psccb = (PciCfgSccb *)sccb;
|
||||
S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(be32_to_cpu(psccb->aid));
|
||||
uint16_t rc;
|
||||
|
||||
if (be16_to_cpu(sccb->h.length) < 16) {
|
||||
rc = SCLP_RC_INSUFFICIENT_SCCB_LENGTH;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (pbdev) {
|
||||
if ((configure == 1 && pbdev->configured == true) ||
|
||||
(configure == 0 && pbdev->configured == false)) {
|
||||
if (pbdev->configured) {
|
||||
rc = SCLP_RC_NO_ACTION_REQUIRED;
|
||||
} else {
|
||||
pbdev->configured = !pbdev->configured;
|
||||
pbdev->configured = true;
|
||||
rc = SCLP_RC_NORMAL_COMPLETION;
|
||||
}
|
||||
} else {
|
||||
DPRINTF("sclp config %d no dev found\n", configure);
|
||||
DPRINTF("sclp config no dev found\n");
|
||||
rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED;
|
||||
}
|
||||
out:
|
||||
psccb->header.response_code = cpu_to_be16(rc);
|
||||
}
|
||||
|
||||
void s390_pci_sclp_deconfigure(SCCB *sccb)
|
||||
{
|
||||
PciCfgSccb *psccb = (PciCfgSccb *)sccb;
|
||||
S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(be32_to_cpu(psccb->aid));
|
||||
uint16_t rc;
|
||||
|
||||
if (be16_to_cpu(sccb->h.length) < 16) {
|
||||
rc = SCLP_RC_INSUFFICIENT_SCCB_LENGTH;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (pbdev) {
|
||||
if (!pbdev->configured) {
|
||||
rc = SCLP_RC_NO_ACTION_REQUIRED;
|
||||
} else {
|
||||
if (pbdev->summary_ind) {
|
||||
pci_dereg_irqs(pbdev);
|
||||
}
|
||||
if (pbdev->iommu_enabled) {
|
||||
pci_dereg_ioat(pbdev);
|
||||
}
|
||||
pbdev->configured = false;
|
||||
rc = SCLP_RC_NORMAL_COMPLETION;
|
||||
}
|
||||
} else {
|
||||
DPRINTF("sclp deconfig no dev found\n");
|
||||
rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED;
|
||||
}
|
||||
out:
|
||||
psccb->header.response_code = cpu_to_be16(rc);
|
||||
}
|
||||
|
||||
@ -320,7 +357,8 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr,
|
||||
.perm = IOMMU_NONE,
|
||||
};
|
||||
|
||||
if (!pbdev->configured || !pbdev->pdev || !(pbdev->fh & FH_ENABLED)) {
|
||||
if (!pbdev->configured || !pbdev->pdev ||
|
||||
!(pbdev->fh & FH_ENABLED) || !pbdev->iommu_enabled) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -458,20 +496,21 @@ static const MemoryRegionOps s390_msi_ctrl_ops = {
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
void s390_pcihost_iommu_configure(S390PCIBusDevice *pbdev, bool enable)
|
||||
void s390_pci_iommu_enable(S390PCIBusDevice *pbdev)
|
||||
{
|
||||
pbdev->configured = false;
|
||||
uint64_t size = pbdev->pal - pbdev->pba + 1;
|
||||
|
||||
if (enable) {
|
||||
uint64_t size = pbdev->pal - pbdev->pba + 1;
|
||||
memory_region_init_iommu(&pbdev->iommu_mr, OBJECT(&pbdev->mr),
|
||||
&s390_iommu_ops, "iommu-s390", size);
|
||||
memory_region_add_subregion(&pbdev->mr, pbdev->pba, &pbdev->iommu_mr);
|
||||
} else {
|
||||
memory_region_del_subregion(&pbdev->mr, &pbdev->iommu_mr);
|
||||
}
|
||||
memory_region_init_iommu(&pbdev->iommu_mr, OBJECT(&pbdev->mr),
|
||||
&s390_iommu_ops, "iommu-s390", size);
|
||||
memory_region_add_subregion(&pbdev->mr, pbdev->pba, &pbdev->iommu_mr);
|
||||
pbdev->iommu_enabled = true;
|
||||
}
|
||||
|
||||
pbdev->configured = true;
|
||||
void s390_pci_iommu_disable(S390PCIBusDevice *pbdev)
|
||||
{
|
||||
memory_region_del_subregion(&pbdev->mr, &pbdev->iommu_mr);
|
||||
object_unparent(OBJECT(&pbdev->iommu_mr));
|
||||
pbdev->iommu_enabled = false;
|
||||
}
|
||||
|
||||
static void s390_pcihost_init_as(S390pciState *s)
|
||||
|
@ -198,11 +198,11 @@ typedef struct ChscSeiNt2Res {
|
||||
} QEMU_PACKED ChscSeiNt2Res;
|
||||
|
||||
typedef struct PciCfgSccb {
|
||||
SCCBHeader header;
|
||||
uint8_t atype;
|
||||
uint8_t reserved1;
|
||||
uint16_t reserved2;
|
||||
uint32_t aid;
|
||||
SCCBHeader header;
|
||||
uint8_t atype;
|
||||
uint8_t reserved1;
|
||||
uint16_t reserved2;
|
||||
uint32_t aid;
|
||||
} QEMU_PACKED PciCfgSccb;
|
||||
|
||||
typedef struct S390MsixInfo {
|
||||
@ -219,6 +219,7 @@ typedef struct S390PCIBusDevice {
|
||||
bool configured;
|
||||
bool error_state;
|
||||
bool lgstg_blocked;
|
||||
bool iommu_enabled;
|
||||
uint32_t fh;
|
||||
uint32_t fid;
|
||||
uint64_t g_iota;
|
||||
@ -247,8 +248,10 @@ typedef struct S390pciState {
|
||||
|
||||
int chsc_sei_nt2_get_event(void *res);
|
||||
int chsc_sei_nt2_have_event(void);
|
||||
void s390_pci_sclp_configure(int configure, SCCB *sccb);
|
||||
void s390_pcihost_iommu_configure(S390PCIBusDevice *pbdev, bool enable);
|
||||
void s390_pci_sclp_configure(SCCB *sccb);
|
||||
void s390_pci_sclp_deconfigure(SCCB *sccb);
|
||||
void s390_pci_iommu_enable(S390PCIBusDevice *pbdev);
|
||||
void s390_pci_iommu_disable(S390PCIBusDevice *pbdev);
|
||||
S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx);
|
||||
S390PCIBusDevice *s390_pci_find_dev_by_fh(uint32_t fh);
|
||||
S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid);
|
||||
|
@ -634,8 +634,15 @@ static int reg_irqs(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
|
||||
len = BITS_TO_LONGS(FIB_DATA_NOI(ldl_p(&fib.data))) * sizeof(unsigned long);
|
||||
pbdev->indicator = get_indicator(ldq_p(&fib.aibv), len);
|
||||
|
||||
map_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
|
||||
map_indicator(&pbdev->routes.adapter, pbdev->indicator);
|
||||
ret = map_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
|
||||
if (ret) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = map_indicator(&pbdev->routes.adapter, pbdev->indicator);
|
||||
if (ret) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
pbdev->routes.adapter.summary_addr = ldq_p(&fib.aisb);
|
||||
pbdev->routes.adapter.summary_offset = FIB_DATA_AISBO(ldl_p(&fib.data));
|
||||
@ -647,9 +654,15 @@ static int reg_irqs(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
|
||||
|
||||
DPRINTF("reg_irqs adapter id %d\n", pbdev->routes.adapter.adapter_id);
|
||||
return 0;
|
||||
out:
|
||||
release_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
|
||||
release_indicator(&pbdev->routes.adapter, pbdev->indicator);
|
||||
pbdev->summary_ind = NULL;
|
||||
pbdev->indicator = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dereg_irqs(S390PCIBusDevice *pbdev)
|
||||
int pci_dereg_irqs(S390PCIBusDevice *pbdev)
|
||||
{
|
||||
release_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
|
||||
release_indicator(&pbdev->routes.adapter, pbdev->indicator);
|
||||
@ -692,24 +705,23 @@ static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
|
||||
pbdev->pal = pal;
|
||||
pbdev->g_iota = g_iota;
|
||||
|
||||
s390_pcihost_iommu_configure(pbdev, true);
|
||||
s390_pci_iommu_enable(pbdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dereg_ioat(S390PCIBusDevice *pbdev)
|
||||
void pci_dereg_ioat(S390PCIBusDevice *pbdev)
|
||||
{
|
||||
s390_pci_iommu_disable(pbdev);
|
||||
pbdev->pba = 0;
|
||||
pbdev->pal = 0;
|
||||
pbdev->g_iota = 0;
|
||||
|
||||
s390_pcihost_iommu_configure(pbdev, false);
|
||||
}
|
||||
|
||||
int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
|
||||
{
|
||||
CPUS390XState *env = &cpu->env;
|
||||
uint8_t oc;
|
||||
uint8_t oc, dmaas;
|
||||
uint32_t fh;
|
||||
ZpciFib fib;
|
||||
S390PCIBusDevice *pbdev;
|
||||
@ -721,6 +733,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
|
||||
}
|
||||
|
||||
oc = env->regs[r1] & 0xff;
|
||||
dmaas = (env->regs[r1] >> 16) & 0xff;
|
||||
fh = env->regs[r1] >> 32;
|
||||
|
||||
if (fiba & 0x7) {
|
||||
@ -739,27 +752,65 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fib.fmt != 0) {
|
||||
program_interrupt(env, PGM_OPERAND, 6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (oc) {
|
||||
case ZPCI_MOD_FC_REG_INT:
|
||||
if (reg_irqs(env, pbdev, fib)) {
|
||||
if (pbdev->summary_ind) {
|
||||
cc = ZPCI_PCI_LS_ERR;
|
||||
s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
|
||||
} else if (reg_irqs(env, pbdev, fib)) {
|
||||
cc = ZPCI_PCI_LS_ERR;
|
||||
s390_set_status_code(env, r1, ZPCI_MOD_ST_RES_NOT_AVAIL);
|
||||
}
|
||||
break;
|
||||
case ZPCI_MOD_FC_DEREG_INT:
|
||||
dereg_irqs(pbdev);
|
||||
if (!pbdev->summary_ind) {
|
||||
cc = ZPCI_PCI_LS_ERR;
|
||||
s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
|
||||
} else {
|
||||
pci_dereg_irqs(pbdev);
|
||||
}
|
||||
break;
|
||||
case ZPCI_MOD_FC_REG_IOAT:
|
||||
if (reg_ioat(env, pbdev, fib)) {
|
||||
if (dmaas != 0) {
|
||||
cc = ZPCI_PCI_LS_ERR;
|
||||
s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
|
||||
} else if (pbdev->iommu_enabled) {
|
||||
cc = ZPCI_PCI_LS_ERR;
|
||||
s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
|
||||
} else if (reg_ioat(env, pbdev, fib)) {
|
||||
cc = ZPCI_PCI_LS_ERR;
|
||||
s390_set_status_code(env, r1, ZPCI_MOD_ST_INSUF_RES);
|
||||
}
|
||||
break;
|
||||
case ZPCI_MOD_FC_DEREG_IOAT:
|
||||
dereg_ioat(pbdev);
|
||||
if (dmaas != 0) {
|
||||
cc = ZPCI_PCI_LS_ERR;
|
||||
s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
|
||||
} else if (!pbdev->iommu_enabled) {
|
||||
cc = ZPCI_PCI_LS_ERR;
|
||||
s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
|
||||
} else {
|
||||
pci_dereg_ioat(pbdev);
|
||||
}
|
||||
break;
|
||||
case ZPCI_MOD_FC_REREG_IOAT:
|
||||
dereg_ioat(pbdev);
|
||||
if (reg_ioat(env, pbdev, fib)) {
|
||||
if (dmaas != 0) {
|
||||
cc = ZPCI_PCI_LS_ERR;
|
||||
s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
|
||||
} else if (!pbdev->iommu_enabled) {
|
||||
cc = ZPCI_PCI_LS_ERR;
|
||||
s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
|
||||
} else {
|
||||
pci_dereg_ioat(pbdev);
|
||||
if (reg_ioat(env, pbdev, fib)) {
|
||||
cc = ZPCI_PCI_LS_ERR;
|
||||
s390_set_status_code(env, r1, ZPCI_MOD_ST_INSUF_RES);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZPCI_MOD_FC_RESET_ERROR:
|
||||
|
@ -14,6 +14,7 @@
|
||||
#ifndef HW_S390_PCI_INST_H
|
||||
#define HW_S390_PCI_INST_H
|
||||
|
||||
#include "s390-pci-bus.h"
|
||||
#include <sysemu/dma.h>
|
||||
|
||||
/* CLP common request & response block size */
|
||||
@ -230,6 +231,14 @@ typedef struct ClpReqRspQueryPciGrp {
|
||||
#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
|
||||
@ -277,6 +286,8 @@ typedef struct ZpciFib {
|
||||
uint32_t gd;
|
||||
} QEMU_PACKED ZpciFib;
|
||||
|
||||
int pci_dereg_irqs(S390PCIBusDevice *pbdev);
|
||||
void pci_dereg_ioat(S390PCIBusDevice *pbdev);
|
||||
int clp_service_call(S390CPU *cpu, uint8_t r2);
|
||||
int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2);
|
||||
int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2);
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "s390-pci-bus.h"
|
||||
#include "hw/s390x/storage-keys.h"
|
||||
#include "hw/compat.h"
|
||||
#include "ipl.h"
|
||||
#include "hw/s390x/s390-virtio-ccw.h"
|
||||
|
||||
static const char *const reset_dev_types[] = {
|
||||
@ -190,7 +191,9 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data)
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
NMIClass *nc = NMI_CLASS(oc);
|
||||
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
|
||||
S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
|
||||
|
||||
s390mc->ri_allowed = true;
|
||||
mc->init = ccw_init;
|
||||
mc->reset = s390_machine_reset;
|
||||
mc->hot_add_cpu = s390_hot_add_cpu;
|
||||
@ -237,6 +240,20 @@ static inline void machine_set_dea_key_wrap(Object *obj, bool value,
|
||||
ms->dea_key_wrap = value;
|
||||
}
|
||||
|
||||
bool ri_allowed(void)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
|
||||
if (object_class_dynamic_cast(OBJECT_CLASS(mc),
|
||||
TYPE_S390_CCW_MACHINE)) {
|
||||
S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
|
||||
|
||||
return s390mc->ri_allowed;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void s390_machine_initfn(Object *obj)
|
||||
{
|
||||
object_property_add_bool(obj, "aes-key-wrap",
|
||||
@ -262,6 +279,7 @@ static const TypeInfo ccw_machine_info = {
|
||||
.abstract = true,
|
||||
.instance_size = sizeof(S390CcwMachineState),
|
||||
.instance_init = s390_machine_initfn,
|
||||
.class_size = sizeof(S390CcwMachineClass),
|
||||
.class_init = ccw_machine_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ TYPE_NMI },
|
||||
@ -299,7 +317,16 @@ static const TypeInfo ccw_machine_info = {
|
||||
} \
|
||||
type_init(ccw_machine_register_##suffix)
|
||||
|
||||
#define CCW_COMPAT_2_6 \
|
||||
HW_COMPAT_2_6 \
|
||||
{\
|
||||
.driver = TYPE_S390_IPL,\
|
||||
.property = "iplbext_migration",\
|
||||
.value = "off",\
|
||||
},
|
||||
|
||||
#define CCW_COMPAT_2_5 \
|
||||
CCW_COMPAT_2_6 \
|
||||
HW_COMPAT_2_5
|
||||
|
||||
#define CCW_COMPAT_2_4 \
|
||||
@ -343,21 +370,38 @@ static const TypeInfo ccw_machine_info = {
|
||||
.value = "0",\
|
||||
},
|
||||
|
||||
static void ccw_machine_2_7_instance_options(MachineState *machine)
|
||||
{
|
||||
}
|
||||
|
||||
static void ccw_machine_2_7_class_options(MachineClass *mc)
|
||||
{
|
||||
}
|
||||
DEFINE_CCW_MACHINE(2_7, "2.7", true);
|
||||
|
||||
static void ccw_machine_2_6_instance_options(MachineState *machine)
|
||||
{
|
||||
ccw_machine_2_7_instance_options(machine);
|
||||
}
|
||||
|
||||
static void ccw_machine_2_6_class_options(MachineClass *mc)
|
||||
{
|
||||
S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
|
||||
|
||||
s390mc->ri_allowed = false;
|
||||
ccw_machine_2_7_class_options(mc);
|
||||
SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_6);
|
||||
}
|
||||
DEFINE_CCW_MACHINE(2_6, "2.6", true);
|
||||
DEFINE_CCW_MACHINE(2_6, "2.6", false);
|
||||
|
||||
static void ccw_machine_2_5_instance_options(MachineState *machine)
|
||||
{
|
||||
ccw_machine_2_6_instance_options(machine);
|
||||
}
|
||||
|
||||
static void ccw_machine_2_5_class_options(MachineClass *mc)
|
||||
{
|
||||
ccw_machine_2_6_class_options(mc);
|
||||
SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_5);
|
||||
}
|
||||
DEFINE_CCW_MACHINE(2_5, "2.5", false);
|
||||
@ -369,6 +413,7 @@ static void ccw_machine_2_4_instance_options(MachineState *machine)
|
||||
|
||||
static void ccw_machine_2_4_class_options(MachineClass *mc)
|
||||
{
|
||||
ccw_machine_2_5_class_options(mc);
|
||||
SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_4);
|
||||
}
|
||||
DEFINE_CCW_MACHINE(2_4, "2.4", false);
|
||||
|
@ -357,10 +357,10 @@ static void sclp_execute(SCLPDevice *sclp, SCCB *sccb, uint32_t code)
|
||||
sclp_c->unassign_storage(sclp, sccb);
|
||||
break;
|
||||
case SCLP_CMDW_CONFIGURE_PCI:
|
||||
s390_pci_sclp_configure(1, sccb);
|
||||
s390_pci_sclp_configure(sccb);
|
||||
break;
|
||||
case SCLP_CMDW_DECONFIGURE_PCI:
|
||||
s390_pci_sclp_configure(0, sccb);
|
||||
s390_pci_sclp_deconfigure(sccb);
|
||||
break;
|
||||
default:
|
||||
efc->command_handler(ef, sccb, code);
|
||||
|
@ -1,6 +1,9 @@
|
||||
#ifndef HW_COMPAT_H
|
||||
#define HW_COMPAT_H
|
||||
|
||||
#define HW_COMPAT_2_6 \
|
||||
/* empty */
|
||||
|
||||
#define HW_COMPAT_2_5 \
|
||||
{\
|
||||
.driver = "isa-fdc",\
|
||||
|
@ -35,6 +35,10 @@ typedef struct S390CcwMachineClass {
|
||||
MachineClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
bool ri_allowed;
|
||||
} S390CcwMachineClass;
|
||||
|
||||
/* runtime-instrumentation allowed by the machine */
|
||||
bool ri_allowed(void);
|
||||
|
||||
#endif
|
||||
|
Binary file not shown.
79
pc-bios/s390-ccw/iplb.h
Normal file
79
pc-bios/s390-ccw/iplb.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* QEMU S390 IPL Block
|
||||
*
|
||||
* Copyright 2015 IBM Corp.
|
||||
* Author(s): Alexander Yarygin <yarygin@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 IPLB_H
|
||||
#define IPLB_H
|
||||
|
||||
struct IplBlockCcw {
|
||||
uint8_t reserved0[85];
|
||||
uint8_t ssid;
|
||||
uint16_t devno;
|
||||
uint8_t vm_flags;
|
||||
uint8_t reserved3[3];
|
||||
uint32_t vm_parm_len;
|
||||
uint8_t nss_name[8];
|
||||
uint8_t vm_parm[64];
|
||||
uint8_t reserved4[8];
|
||||
} __attribute__ ((packed));
|
||||
typedef struct IplBlockCcw IplBlockCcw;
|
||||
|
||||
struct IplBlockFcp {
|
||||
uint8_t reserved1[305 - 1];
|
||||
uint8_t opt;
|
||||
uint8_t reserved2[3];
|
||||
uint16_t reserved3;
|
||||
uint16_t devno;
|
||||
uint8_t reserved4[4];
|
||||
uint64_t wwpn;
|
||||
uint64_t lun;
|
||||
uint32_t bootprog;
|
||||
uint8_t reserved5[12];
|
||||
uint64_t br_lba;
|
||||
uint32_t scp_data_len;
|
||||
uint8_t reserved6[260];
|
||||
uint8_t scp_data[];
|
||||
} __attribute__ ((packed));
|
||||
typedef struct IplBlockFcp IplBlockFcp;
|
||||
|
||||
struct IplParameterBlock {
|
||||
uint32_t len;
|
||||
uint8_t reserved0[3];
|
||||
uint8_t version;
|
||||
uint32_t blk0_len;
|
||||
uint8_t pbt;
|
||||
uint8_t flags;
|
||||
uint16_t reserved01;
|
||||
uint8_t loadparm[8];
|
||||
union {
|
||||
IplBlockCcw ccw;
|
||||
IplBlockFcp fcp;
|
||||
};
|
||||
} __attribute__ ((packed));
|
||||
typedef struct IplParameterBlock IplParameterBlock;
|
||||
|
||||
extern IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
|
||||
|
||||
#define S390_IPL_TYPE_FCP 0x00
|
||||
#define S390_IPL_TYPE_CCW 0x02
|
||||
|
||||
static inline bool store_iplb(IplParameterBlock *iplb)
|
||||
{
|
||||
register unsigned long addr asm("0") = (unsigned long) iplb;
|
||||
register unsigned long rc asm("1") = 0;
|
||||
|
||||
asm volatile ("diag %0,%2,0x308\n"
|
||||
: "+d" (addr), "+d" (rc)
|
||||
: "d" (6)
|
||||
: "memory", "cc");
|
||||
return rc == 0x01;
|
||||
}
|
||||
|
||||
#endif /* IPLB_H */
|
@ -12,8 +12,8 @@
|
||||
#include "virtio.h"
|
||||
|
||||
char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
|
||||
uint64_t boot_value;
|
||||
static SubChannelId blk_schid = { .one = 1 };
|
||||
IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
|
||||
|
||||
/*
|
||||
* Priniciples of Operations (SA22-7832-09) chapter 17 requires that
|
||||
@ -61,7 +61,7 @@ static bool find_dev(Schib *schib, int dev_no)
|
||||
return false;
|
||||
}
|
||||
|
||||
static void virtio_setup(uint64_t dev_info)
|
||||
static void virtio_setup(void)
|
||||
{
|
||||
Schib schib;
|
||||
int ssid;
|
||||
@ -75,12 +75,18 @@ static void virtio_setup(uint64_t dev_info)
|
||||
*/
|
||||
enable_mss_facility();
|
||||
|
||||
if (dev_info != -1) {
|
||||
dev_no = dev_info & 0xffff;
|
||||
debug_print_int("device no. ", dev_no);
|
||||
blk_schid.ssid = (dev_info >> 16) & 0x3;
|
||||
debug_print_int("ssid ", blk_schid.ssid);
|
||||
found = find_dev(&schib, dev_no);
|
||||
if (store_iplb(&iplb)) {
|
||||
switch (iplb.pbt) {
|
||||
case S390_IPL_TYPE_CCW:
|
||||
dev_no = iplb.ccw.devno;
|
||||
debug_print_int("device no. ", dev_no);
|
||||
blk_schid.ssid = iplb.ccw.ssid & 0x3;
|
||||
debug_print_int("ssid ", blk_schid.ssid);
|
||||
found = find_dev(&schib, dev_no);
|
||||
break;
|
||||
default:
|
||||
panic("List-directed IPL not supported yet!\n");
|
||||
}
|
||||
} else {
|
||||
for (ssid = 0; ssid < 0x3; ssid++) {
|
||||
blk_schid.ssid = ssid;
|
||||
@ -101,8 +107,7 @@ static void virtio_setup(uint64_t dev_info)
|
||||
int main(void)
|
||||
{
|
||||
sclp_setup();
|
||||
debug_print_int("boot reg[7] ", boot_value);
|
||||
virtio_setup(boot_value);
|
||||
virtio_setup();
|
||||
|
||||
zipl_load(); /* no return */
|
||||
|
||||
|
@ -44,6 +44,7 @@ typedef unsigned long long __u64;
|
||||
#endif
|
||||
|
||||
#include "cio.h"
|
||||
#include "iplb.h"
|
||||
|
||||
typedef struct irb Irb;
|
||||
typedef struct ccw1 Ccw1;
|
||||
@ -61,7 +62,6 @@ void consume_sclp_int(void);
|
||||
void panic(const char *string);
|
||||
void write_subsystem_identification(void);
|
||||
extern char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
|
||||
extern uint64_t boot_value;
|
||||
|
||||
/* sclp-ascii.c */
|
||||
void sclp_print(const char *string);
|
||||
|
@ -14,8 +14,6 @@
|
||||
_start:
|
||||
|
||||
larl %r15, stack + 0x8000 /* Set up stack */
|
||||
larl %r6, boot_value
|
||||
stg %r7, 0(%r6) /* save the boot_value before any function calls */
|
||||
j main /* And call C */
|
||||
|
||||
/*
|
||||
|
@ -135,6 +135,8 @@ typedef struct CPUS390XState {
|
||||
uint64_t gbea;
|
||||
uint64_t pp;
|
||||
|
||||
uint8_t riccb[64];
|
||||
|
||||
CPU_COMMON
|
||||
|
||||
/* reset does memset(0) up to here */
|
||||
@ -1159,6 +1161,7 @@ void kvm_s390_reset_vcpu(S390CPU *cpu);
|
||||
int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, uint64_t *hw_limit);
|
||||
void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu);
|
||||
int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu);
|
||||
int kvm_s390_get_ri(void);
|
||||
void kvm_s390_crypto_reset(void);
|
||||
#else
|
||||
static inline void kvm_s390_io_interrupt(uint16_t subchannel_id,
|
||||
@ -1209,6 +1212,10 @@ static inline int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int kvm_s390_get_ri(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void kvm_s390_crypto_reset(void)
|
||||
{
|
||||
}
|
||||
@ -1272,11 +1279,22 @@ static inline bool vregs_needed(void *opaque)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static inline bool riccb_needed(void *opaque)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
return kvm_s390_get_ri();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline bool vregs_needed(void *opaque)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline bool riccb_needed(void *opaque)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* machine check interruption code */
|
||||
|
@ -509,6 +509,7 @@ static void ioinst_handle_chsc_scsc(ChscReq *req, ChscResp *res)
|
||||
|
||||
general_chars[0] = cpu_to_be32(0x03000000);
|
||||
general_chars[1] = cpu_to_be32(0x00059000);
|
||||
general_chars[3] = cpu_to_be32(0x00080000);
|
||||
|
||||
chsc_chars[0] = cpu_to_be32(0x40000000);
|
||||
chsc_chars[3] = cpu_to_be32(0x00040000);
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "hw/s390x/ipl.h"
|
||||
#include "hw/s390x/ebcdic.h"
|
||||
#include "exec/memattrs.h"
|
||||
#include "hw/s390x/s390-virtio-ccw.h"
|
||||
|
||||
/* #define DEBUG_KVM */
|
||||
|
||||
@ -135,6 +136,7 @@ static int cap_sync_regs;
|
||||
static int cap_async_pf;
|
||||
static int cap_mem_op;
|
||||
static int cap_s390_irq;
|
||||
static int cap_ri;
|
||||
|
||||
static void *legacy_s390_alloc(size_t size, uint64_t *align);
|
||||
|
||||
@ -270,6 +272,11 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
kvm_vm_enable_cap(s, KVM_CAP_S390_USER_SIGP, 0);
|
||||
kvm_vm_enable_cap(s, KVM_CAP_S390_VECTOR_REGISTERS, 0);
|
||||
kvm_vm_enable_cap(s, KVM_CAP_S390_USER_STSI, 0);
|
||||
if (ri_allowed()) {
|
||||
if (kvm_vm_enable_cap(s, KVM_CAP_S390_RI, 0) == 0) {
|
||||
cap_ri = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -386,6 +393,11 @@ int kvm_arch_put_registers(CPUState *cs, int level)
|
||||
kvm_set_one_reg(cs, KVM_REG_S390_PP, &env->pp);
|
||||
}
|
||||
|
||||
if (can_sync_regs(cs, KVM_SYNC_RICCB)) {
|
||||
memcpy(cs->kvm_run->s.regs.riccb, env->riccb, 64);
|
||||
cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_RICCB;
|
||||
}
|
||||
|
||||
/* pfault parameters */
|
||||
if (can_sync_regs(cs, KVM_SYNC_PFAULT)) {
|
||||
cs->kvm_run->s.regs.pft = env->pfault_token;
|
||||
@ -528,6 +540,10 @@ int kvm_arch_get_registers(CPUState *cs)
|
||||
kvm_get_one_reg(cs, KVM_REG_S390_PP, &env->pp);
|
||||
}
|
||||
|
||||
if (can_sync_regs(cs, KVM_SYNC_RICCB)) {
|
||||
memcpy(env->riccb, cs->kvm_run->s.regs.riccb, 64);
|
||||
}
|
||||
|
||||
/* pfault parameters */
|
||||
if (can_sync_regs(cs, KVM_SYNC_PFAULT)) {
|
||||
env->pfault_token = cs->kvm_run->s.regs.pft;
|
||||
@ -2136,6 +2152,11 @@ int kvm_s390_get_memslot_count(KVMState *s)
|
||||
return kvm_check_extension(s, KVM_CAP_NR_MEMSLOTS);
|
||||
}
|
||||
|
||||
int kvm_s390_get_ri(void)
|
||||
{
|
||||
return cap_ri;
|
||||
}
|
||||
|
||||
int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state)
|
||||
{
|
||||
struct kvm_mp_state mp_state = {};
|
||||
|
@ -135,6 +135,17 @@ static const VMStateDescription vmstate_vregs = {
|
||||
}
|
||||
};
|
||||
|
||||
const VMStateDescription vmstate_riccb = {
|
||||
.name = "cpu/riccb",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = riccb_needed,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT8_ARRAY(env.riccb, S390CPU, 64),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
const VMStateDescription vmstate_s390_cpu = {
|
||||
.name = "cpu",
|
||||
.post_load = cpu_post_load,
|
||||
@ -166,6 +177,7 @@ const VMStateDescription vmstate_s390_cpu = {
|
||||
.subsections = (const VMStateDescription*[]) {
|
||||
&vmstate_fpu,
|
||||
&vmstate_vregs,
|
||||
&vmstate_riccb,
|
||||
NULL
|
||||
},
|
||||
};
|
||||
|
@ -232,10 +232,23 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3)
|
||||
program_interrupt(env, PGM_ADDRESSING, ILEN_LATER_INC);
|
||||
return;
|
||||
}
|
||||
iplb = g_malloc0(sizeof(struct IplParameterBlock));
|
||||
cpu_physical_memory_read(addr, iplb, sizeof(struct IplParameterBlock));
|
||||
iplb = g_malloc0(sizeof(IplParameterBlock));
|
||||
cpu_physical_memory_read(addr, iplb, sizeof(iplb->len));
|
||||
if (!iplb_valid_len(iplb)) {
|
||||
env->regs[r1 + 1] = DIAG_308_RC_INVALID;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cpu_physical_memory_read(addr, iplb, be32_to_cpu(iplb->len));
|
||||
|
||||
if (!iplb_valid_ccw(iplb) && !iplb_valid_fcp(iplb)) {
|
||||
env->regs[r1 + 1] = DIAG_308_RC_INVALID;
|
||||
goto out;
|
||||
}
|
||||
|
||||
s390_ipl_update_diag308(iplb);
|
||||
env->regs[r1 + 1] = DIAG_308_RC_OK;
|
||||
out:
|
||||
g_free(iplb);
|
||||
return;
|
||||
case 6:
|
||||
@ -250,8 +263,7 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3)
|
||||
}
|
||||
iplb = s390_ipl_get_iplb();
|
||||
if (iplb) {
|
||||
cpu_physical_memory_write(addr, iplb,
|
||||
sizeof(struct IplParameterBlock));
|
||||
cpu_physical_memory_write(addr, iplb, be32_to_cpu(iplb->len));
|
||||
env->regs[r1 + 1] = DIAG_308_RC_OK;
|
||||
} else {
|
||||
env->regs[r1 + 1] = DIAG_308_RC_NO_CONF;
|
||||
|
Loading…
Reference in New Issue
Block a user