First batch of s390x patches:
- 2.11 compat machine - support the new --s390-pgste linker option, making it possible to avoid enabling the global vm.allocate_pgste systl if all pieces are in place - correctly identify some devices as not hotpluggable - clean up some tests and enable them for s390x - wire up the diag288 watchdog in tcg - clean up dependencies on CONFIG_PCI, making it possible to disable it by hand - lots of cleanup in target/s390x/ - fix alignment of the ccw1 structure in the s390-ccw bios - and some more bugfixes -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJZpuqCAAoJEN7Pa5PG8C+vGCUP/39T8NxUtnz+ZU28F7t2ON+b L8ASoxit4mQ5DkB8aKqm5UofwF3KGfAOeLWOxGNOsXtRUD0F6hmv7ep3brIIv8nf HJ7JlbZxrqL6ExVJrRcNcshu5LqJ/AWCdmRnIG5OP0DGBQ12HXTcvZ7tktNimqpg kJ6hfwxQaj3j79i2DsopsuEi800NXdyp9QKSj5jGNcVB23zEkpp6jLb3Jzbts9Wv SZwCQeJSI1tGN6nOcMmDHEQtYdGvz3gdf86AVuR3Vlhv0bElRcBeqKau4Jky2Xow wcy5B2wVuNqpa2SvE1MFI6zmDRIH2x1NcJ+n4AmbpnxmDT2LhfFIeR2Ieqfy5qHC uiKVaLUVKaAC02APyRUGApiPetPv6jm2U7BKZvpmqlPqLjEExAiZmLpK1cp8dkY+ oU9Z0ce7u+NWTdziEFzRdmrJMO0DNd9dhKHWOZOU+ksL374dgMLOPzmRWKkopKuE nrtEf1IxmH6WirMsCUsrWrlwQb7SHJfWYQR5IyVhCfQ5zWzY3o0JtyqP/BDCBU8R Yv2bmR1krqfc7B1YqT3nGIeq6IGw80OTtgoxerqxcyvwAp+NVE4vb1mtqh/J7Kq3 3aM6tq5Pju32lYdFL443AtsRXlEtPDyGuU1VrnuMmmy11gk6Mq7B8/yWCLrPai1n lFQyvYfrMoW6vGN/juiL =WxdK -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20170830' into staging First batch of s390x patches: - 2.11 compat machine - support the new --s390-pgste linker option, making it possible to avoid enabling the global vm.allocate_pgste systl if all pieces are in place - correctly identify some devices as not hotpluggable - clean up some tests and enable them for s390x - wire up the diag288 watchdog in tcg - clean up dependencies on CONFIG_PCI, making it possible to disable it by hand - lots of cleanup in target/s390x/ - fix alignment of the ccw1 structure in the s390-ccw bios - and some more bugfixes # gpg: Signature made Wed 30 Aug 2017 17:40:34 BST # gpg: using RSA key 0xDECF6B93C6F02FAF # gpg: Good signature from "Cornelia Huck <conny@cornelia-huck.de>" # gpg: aka "Cornelia Huck <huckc@linux.vnet.ibm.com>" # gpg: aka "Cornelia Huck <cornelia.huck@de.ibm.com>" # gpg: aka "Cornelia Huck <cohuck@kernel.org>" # gpg: aka "Cornelia Huck <cohuck@redhat.com>" # Primary key fingerprint: C3D0 D66D C362 4FF6 A8C0 18CE DECF 6B93 C6F0 2FAF * remotes/cohuck/tags/s390x-20170830: (44 commits) s390x/pci: fixup trap_msix() pc-bios/s390-ccw.img: update image s390-ccw: Fix alignment for CCW1 s390x/s390-stattrib: Mark the storage attribute as not user_creatable target/s390x: cleanup cpu.h s390x/kvm: move KVM declarations and stubs to separate files s390x: avoid calling kvm_ functions outside of target/s390x/ target/s390x: move a couple of functions to cpu.c target/s390x: introduce internal.h target/s390x: move get_per_in_range() to misc_helper.c target/s390x: move s390_do_cpu_reset() to diag.c target/s390x: move psw_key_valid() to mem_helper.c target/s390x: move cpu_mmu_idx_to_asc() to excp_helper.c target/s390x: move cc_name() to helper.c target/s390x: move gtod_*() declarations to s390-virtio.h s390x: drop inclusion of sysemu/kvm.h from some files s390x/cpumodel: factor out determination of default model name target/s390x: no need to pass kvm_state to savevm_gtod handlers target/s390x: simplify gs_allowed() target/s390x: simplify ri_allowed() ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
1415e8ea1f
@ -1248,7 +1248,7 @@ int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev)
|
||||
int virq;
|
||||
MSIMessage msg = {0, 0};
|
||||
|
||||
if (dev) {
|
||||
if (pci_available && dev) {
|
||||
msg = pci_get_msi_message(dev, vector);
|
||||
}
|
||||
|
||||
@ -1271,7 +1271,7 @@ int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev)
|
||||
kroute.u.msi.address_lo = (uint32_t)msg.address;
|
||||
kroute.u.msi.address_hi = msg.address >> 32;
|
||||
kroute.u.msi.data = le32_to_cpu(msg.data);
|
||||
if (kvm_msi_devid_required()) {
|
||||
if (pci_available && kvm_msi_devid_required()) {
|
||||
kroute.flags = KVM_MSI_VALID_DEVID;
|
||||
kroute.u.msi.devid = pci_requester_id(dev);
|
||||
}
|
||||
@ -1309,7 +1309,7 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg,
|
||||
kroute.u.msi.address_lo = (uint32_t)msg.address;
|
||||
kroute.u.msi.address_hi = msg.address >> 32;
|
||||
kroute.u.msi.data = le32_to_cpu(msg.data);
|
||||
if (kvm_msi_devid_required()) {
|
||||
if (pci_available && kvm_msi_devid_required()) {
|
||||
kroute.flags = KVM_MSI_VALID_DEVID;
|
||||
kroute.u.msi.devid = pci_requester_id(dev);
|
||||
}
|
||||
|
21
configure
vendored
21
configure
vendored
@ -240,6 +240,11 @@ supported_target() {
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
ld_has() {
|
||||
$ld --help 2>/dev/null | grep ".$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# default parameters
|
||||
source_path=$(dirname "$0")
|
||||
cpu=""
|
||||
@ -5043,7 +5048,7 @@ fi
|
||||
# Use ASLR, no-SEH and DEP if available
|
||||
if test "$mingw32" = "yes" ; then
|
||||
for flag in --dynamicbase --no-seh --nxcompat; do
|
||||
if $ld --help 2>/dev/null | grep ".$flag" >/dev/null 2>/dev/null ; then
|
||||
if ld_has $flag ; then
|
||||
LDFLAGS="-Wl,$flag $LDFLAGS"
|
||||
fi
|
||||
done
|
||||
@ -6522,6 +6527,20 @@ if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then
|
||||
ldflags="$ldflags $textseg_ldflags"
|
||||
fi
|
||||
|
||||
# Newer kernels on s390 check for an S390_PGSTE program header and
|
||||
# enable the pgste page table extensions in that case. This makes
|
||||
# the vm.allocate_pgste sysctl unnecessary. We enable this program
|
||||
# header if
|
||||
# - we build on s390x
|
||||
# - we build the system emulation for s390x (qemu-system-s390x)
|
||||
# - KVM is enabled
|
||||
# - the linker supports --s390-pgste
|
||||
if test "$TARGET_ARCH" = "s390x" -a "$target_softmmu" = "yes" -a "$ARCH" = "s390x" -a "$kvm" = "yes"; then
|
||||
if ld_has --s390-pgste ; then
|
||||
ldflags="-Wl,--s390-pgste $ldflags"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "LDFLAGS+=$ldflags" >> $config_target_mak
|
||||
echo "QEMU_CFLAGS+=$cflags" >> $config_target_mak
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
CONFIG_PCI=y
|
||||
CONFIG_VIRTIO_PCI=y
|
||||
CONFIG_VIRTIO_PCI=$(CONFIG_PCI)
|
||||
CONFIG_VHOST_USER_SCSI=$(and $(CONFIG_VHOST_USER),$(CONFIG_LINUX))
|
||||
CONFIG_VIRTIO=y
|
||||
CONFIG_SCLPCONSOLE=y
|
||||
|
@ -1,10 +1,7 @@
|
||||
ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
|
||||
# Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
|
||||
# only pull in the actual virtio-9p device if we also enabled virtio.
|
||||
common-obj-y = qemu-fsdev.o 9p-marshal.o 9p-iov-marshal.o
|
||||
else
|
||||
common-obj-y = qemu-fsdev-dummy.o
|
||||
endif
|
||||
# only pull in the actual 9p backend if we also enabled virtio or xen.
|
||||
common-obj-$(call land,$(CONFIG_VIRTFS),$(call lor,$(CONFIG_VIRTIO),$(CONFIG_XEN))) = qemu-fsdev.o 9p-marshal.o 9p-iov-marshal.o
|
||||
common-obj-$(call lnot,$(call land,$(CONFIG_VIRTFS),$(call lor,$(CONFIG_VIRTIO),$(CONFIG_XEN)))) = qemu-fsdev-dummy.o
|
||||
common-obj-y += qemu-fsdev-opts.o qemu-fsdev-throttle.o
|
||||
|
||||
# Toplevel always builds this; targets without virtio will put it in
|
||||
|
@ -7,4 +7,4 @@ common-obj-$(CONFIG_OPEN_BY_HANDLE) += 9p-handle.o
|
||||
common-obj-y += 9p-proxy.o
|
||||
common-obj-$(CONFIG_XEN) += xen-9p-backend.o
|
||||
|
||||
obj-y += virtio-9p-device.o
|
||||
obj-$(CONFIG_VIRTIO) += virtio-9p-device.o
|
||||
|
@ -1,4 +1,4 @@
|
||||
devices-dirs-$(call land, $(CONFIG_VIRTIO),$(call land,$(CONFIG_VIRTFS),$(CONFIG_PCI))) += 9pfs/
|
||||
devices-dirs-$(call land,$(CONFIG_VIRTFS),$(call lor,$(CONFIG_VIRTIO),$(CONFIG_XEN))) += 9pfs/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += acpi/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += adc/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += audio/
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "kvm_s390x.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include "qemu/error-report.h"
|
||||
#include "qapi/error.h"
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "hw/pci/msi.h"
|
||||
|
||||
bool msi_nonbroken;
|
||||
bool pci_available;
|
||||
|
||||
PciInfoList *qmp_query_pci(Error **errp)
|
||||
{
|
||||
@ -38,3 +39,16 @@ void hmp_pcie_aer_inject_error(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
monitor_printf(mon, "PCI devices not supported\n");
|
||||
}
|
||||
|
||||
/* kvm-all wants this */
|
||||
MSIMessage pci_get_msi_message(PCIDevice *dev, int vector)
|
||||
{
|
||||
g_assert(false);
|
||||
return (MSIMessage){};
|
||||
}
|
||||
|
||||
uint16_t pci_requester_id(PCIDevice *dev)
|
||||
{
|
||||
g_assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
@ -49,6 +49,8 @@
|
||||
# define PCI_DPRINTF(format, ...) do { } while (0)
|
||||
#endif
|
||||
|
||||
bool pci_available = true;
|
||||
|
||||
static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent);
|
||||
static char *pcibus_get_dev_path(DeviceState *dev);
|
||||
static char *pcibus_get_fw_dev_path(DeviceState *dev);
|
||||
|
@ -11,7 +11,8 @@ obj-y += 3270-ccw.o
|
||||
obj-y += virtio-ccw.o
|
||||
obj-y += css-bridge.o
|
||||
obj-y += ccw-device.o
|
||||
obj-y += s390-pci-bus.o s390-pci-inst.o
|
||||
obj-$(CONFIG_PCI) += s390-pci-bus.o s390-pci-inst.o
|
||||
obj-$(call lnot,$(CONFIG_PCI)) += s390-pci-stub.o
|
||||
obj-y += s390-skeys.o
|
||||
obj-y += s390-stattrib.o
|
||||
obj-$(CONFIG_KVM) += s390-skeys-kvm.o
|
||||
|
@ -1750,10 +1750,10 @@ int css_do_rchp(uint8_t cssid, uint8_t chpid)
|
||||
}
|
||||
|
||||
/* We don't really use a channel path, so we're done here. */
|
||||
css_queue_crw(CRW_RSC_CHP, CRW_ERC_INIT,
|
||||
css_queue_crw(CRW_RSC_CHP, CRW_ERC_INIT, 1,
|
||||
channel_subsys.max_cssid > 0 ? 1 : 0, chpid);
|
||||
if (channel_subsys.max_cssid > 0) {
|
||||
css_queue_crw(CRW_RSC_CHP, CRW_ERC_INIT, 0, real_cssid << 8);
|
||||
css_queue_crw(CRW_RSC_CHP, CRW_ERC_INIT, 1, 0, real_cssid << 8);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -2033,7 +2033,8 @@ void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid,
|
||||
}
|
||||
}
|
||||
|
||||
void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid)
|
||||
void css_queue_crw(uint8_t rsc, uint8_t erc, int solicited,
|
||||
int chain, uint16_t rsid)
|
||||
{
|
||||
CrwContainer *crw_cont;
|
||||
|
||||
@ -2045,6 +2046,9 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid)
|
||||
return;
|
||||
}
|
||||
crw_cont->crw.flags = (rsc << 8) | erc;
|
||||
if (solicited) {
|
||||
crw_cont->crw.flags |= CRW_FLAGS_MASK_S;
|
||||
}
|
||||
if (chain) {
|
||||
crw_cont->crw.flags |= CRW_FLAGS_MASK_C;
|
||||
}
|
||||
@ -2091,9 +2095,9 @@ void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid,
|
||||
}
|
||||
chain_crw = (channel_subsys.max_ssid > 0) ||
|
||||
(channel_subsys.max_cssid > 0);
|
||||
css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, chain_crw ? 1 : 0, schid);
|
||||
css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, 0, chain_crw ? 1 : 0, schid);
|
||||
if (chain_crw) {
|
||||
css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, 0,
|
||||
css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, 0, 0,
|
||||
(guest_cssid << 8) | (ssid << 4));
|
||||
}
|
||||
/* RW_ERC_IPI --> clear pending interrupts */
|
||||
@ -2108,7 +2112,7 @@ void css_generate_chp_crws(uint8_t cssid, uint8_t chpid)
|
||||
void css_generate_css_crws(uint8_t cssid)
|
||||
{
|
||||
if (!channel_subsys.sei_pending) {
|
||||
css_queue_crw(CRW_RSC_CSS, 0, 0, cssid);
|
||||
css_queue_crw(CRW_RSC_CSS, CRW_ERC_EVENT, 0, 0, cssid);
|
||||
}
|
||||
channel_subsys.sei_pending = true;
|
||||
}
|
||||
|
@ -442,6 +442,8 @@ static void s390_ipl_class_init(ObjectClass *klass, void *data)
|
||||
dc->reset = s390_ipl_reset;
|
||||
dc->vmsd = &vmstate_ipl;
|
||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
/* Reason: Loads the ROMs and thus can only be used one time - internally */
|
||||
dc->user_creatable = false;
|
||||
}
|
||||
|
||||
static const TypeInfo s390_ipl_info = {
|
||||
|
@ -47,7 +47,7 @@ S390pciState *s390_get_phb(void)
|
||||
return phb;
|
||||
}
|
||||
|
||||
int chsc_sei_nt2_get_event(void *res)
|
||||
int pci_chsc_sei_nt2_get_event(void *res)
|
||||
{
|
||||
ChscSeiNt2Res *nt2_res = (ChscSeiNt2Res *)res;
|
||||
PciCcdfAvail *accdf;
|
||||
@ -87,7 +87,7 @@ int chsc_sei_nt2_get_event(void *res)
|
||||
return rc;
|
||||
}
|
||||
|
||||
int chsc_sei_nt2_have_event(void)
|
||||
int pci_chsc_sei_nt2_have_event(void)
|
||||
{
|
||||
S390pciState *s = s390_get_phb();
|
||||
|
||||
@ -122,16 +122,11 @@ S390PCIBusDevice *s390_pci_find_dev_by_fid(S390pciState *s, uint32_t fid)
|
||||
|
||||
void s390_pci_sclp_configure(SCCB *sccb)
|
||||
{
|
||||
PciCfgSccb *psccb = (PciCfgSccb *)sccb;
|
||||
IoaCfgSccb *psccb = (IoaCfgSccb *)sccb;
|
||||
S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(s390_get_phb(),
|
||||
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) {
|
||||
DPRINTF("sclp config no dev found\n");
|
||||
rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED;
|
||||
@ -155,16 +150,11 @@ out:
|
||||
|
||||
void s390_pci_sclp_deconfigure(SCCB *sccb)
|
||||
{
|
||||
PciCfgSccb *psccb = (PciCfgSccb *)sccb;
|
||||
IoaCfgSccb *psccb = (IoaCfgSccb *)sccb;
|
||||
S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(s390_get_phb(),
|
||||
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) {
|
||||
DPRINTF("sclp deconfig no dev found\n");
|
||||
rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED;
|
||||
|
@ -244,14 +244,6 @@ typedef struct ChscSeiNt2Res {
|
||||
uint8_t ccdf[4016];
|
||||
} QEMU_PACKED ChscSeiNt2Res;
|
||||
|
||||
typedef struct PciCfgSccb {
|
||||
SCCBHeader header;
|
||||
uint8_t atype;
|
||||
uint8_t reserved1;
|
||||
uint16_t reserved2;
|
||||
uint32_t aid;
|
||||
} QEMU_PACKED PciCfgSccb;
|
||||
|
||||
typedef struct S390MsixInfo {
|
||||
bool available;
|
||||
uint8_t table_bar;
|
||||
@ -319,8 +311,8 @@ typedef struct S390pciState {
|
||||
} S390pciState;
|
||||
|
||||
S390pciState *s390_get_phb(void);
|
||||
int chsc_sei_nt2_get_event(void *res);
|
||||
int chsc_sei_nt2_have_event(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);
|
||||
|
@ -440,8 +440,8 @@ static int trap_msix(S390PCIBusDevice *pbdev, uint64_t offset, uint8_t pcias)
|
||||
{
|
||||
if (pbdev->msix.available && pbdev->msix.table_bar == pcias &&
|
||||
offset >= pbdev->msix.table_offset &&
|
||||
offset <= pbdev->msix.table_offset +
|
||||
(pbdev->msix.entries - 1) * PCI_MSIX_ENTRY_SIZE) {
|
||||
offset < (pbdev->msix.table_offset +
|
||||
pbdev->msix.entries * PCI_MSIX_ENTRY_SIZE)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
|
76
hw/s390x/s390-pci-stub.c
Normal file
76
hw/s390x/s390-pci-stub.c
Normal file
@ -0,0 +1,76 @@
|
||||
/* stubs for non-pci builds */
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "s390-pci-inst.h"
|
||||
#include "s390-pci-bus.h"
|
||||
|
||||
/* target/s390x/ioinst.c */
|
||||
int pci_chsc_sei_nt2_get_event(void *res)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pci_chsc_sei_nt2_have_event(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* hw/s390x/sclp.c */
|
||||
void s390_pci_sclp_configure(SCCB *sccb)
|
||||
{
|
||||
sccb->h.response_code = cpu_to_be16(SCLP_RC_ADAPTER_TYPE_NOT_RECOGNIZED);
|
||||
}
|
||||
|
||||
void s390_pci_sclp_deconfigure(SCCB *sccb)
|
||||
{
|
||||
sccb->h.response_code = cpu_to_be16(SCLP_RC_ADAPTER_TYPE_NOT_RECOGNIZED);
|
||||
}
|
||||
|
||||
/* target/s390x/kvm.c */
|
||||
int clp_service_call(S390CPU *cpu, uint8_t r2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
|
||||
uint8_t ar)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
S390pciState *s390_get_phb(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
S390PCIBusDevice *s390_pci_find_dev_by_idx(S390pciState *s, uint32_t idx)
|
||||
{
|
||||
return NULL;
|
||||
}
|
@ -54,10 +54,14 @@ static int kvm_s390_skeys_set(S390SKeysState *ss, uint64_t start_gfn,
|
||||
static void kvm_s390_skeys_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
S390SKeysClass *skeyclass = S390_SKEYS_CLASS(oc);
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
skeyclass->skeys_enabled = kvm_s390_skeys_enabled;
|
||||
skeyclass->get_skeys = kvm_s390_skeys_get;
|
||||
skeyclass->set_skeys = kvm_s390_skeys_set;
|
||||
|
||||
/* Reason: Internal device (only one skeys device for the whole memory) */
|
||||
dc->user_creatable = false;
|
||||
}
|
||||
|
||||
static const TypeInfo kvm_s390_skeys_info = {
|
||||
|
@ -229,10 +229,14 @@ static int qemu_s390_skeys_get(S390SKeysState *ss, uint64_t start_gfn,
|
||||
static void qemu_s390_skeys_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
S390SKeysClass *skeyclass = S390_SKEYS_CLASS(oc);
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
skeyclass->skeys_enabled = qemu_s390_skeys_enabled;
|
||||
skeyclass->get_skeys = qemu_s390_skeys_get;
|
||||
skeyclass->set_skeys = qemu_s390_skeys_set;
|
||||
|
||||
/* Reason: Internal device (only one skeys device for the whole memory) */
|
||||
dc->user_creatable = false;
|
||||
}
|
||||
|
||||
static const TypeInfo qemu_s390_skeys_info = {
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "sysemu/kvm.h"
|
||||
#include "exec/ram_addr.h"
|
||||
#include "cpu.h"
|
||||
#include "kvm_s390x.h"
|
||||
|
||||
Object *kvm_s390_stattrib_create(void)
|
||||
{
|
||||
@ -163,6 +164,7 @@ static int kvm_s390_stattrib_get_active(S390StAttribState *sa)
|
||||
static void kvm_s390_stattrib_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
S390StAttribClass *sac = S390_STATTRIB_CLASS(oc);
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
sac->get_stattr = kvm_s390_stattrib_get_stattr;
|
||||
sac->peek_stattr = kvm_s390_stattrib_peek_stattr;
|
||||
@ -171,6 +173,9 @@ static void kvm_s390_stattrib_class_init(ObjectClass *oc, void *data)
|
||||
sac->get_dirtycount = kvm_s390_stattrib_get_dirtycount;
|
||||
sac->synchronize = kvm_s390_stattrib_synchronize;
|
||||
sac->get_active = kvm_s390_stattrib_get_active;
|
||||
|
||||
/* Reason: Can only be instantiated one time (internally) */
|
||||
dc->user_creatable = false;
|
||||
}
|
||||
|
||||
static const TypeInfo kvm_s390_stattrib_info = {
|
||||
|
@ -11,12 +11,12 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/boards.h"
|
||||
#include "cpu.h"
|
||||
#include "qmp-commands.h"
|
||||
#include "migration/qemu-file.h"
|
||||
#include "migration/register.h"
|
||||
#include "hw/s390x/storage-attributes.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "exec/ram_addr.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
@ -306,6 +306,7 @@ static int qemu_s390_get_active(S390StAttribState *sa)
|
||||
static void qemu_s390_stattrib_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
S390StAttribClass *sa_cl = S390_STATTRIB_CLASS(oc);
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
sa_cl->synchronize = qemu_s390_synchronize_stub;
|
||||
sa_cl->get_stattr = qemu_s390_get_stattr_stub;
|
||||
@ -314,6 +315,9 @@ static void qemu_s390_stattrib_class_init(ObjectClass *oc, void *data)
|
||||
sa_cl->set_migrationmode = qemu_s390_set_migrationmode_stub;
|
||||
sa_cl->get_dirtycount = qemu_s390_get_dirtycount_stub;
|
||||
sa_cl->get_active = qemu_s390_get_active;
|
||||
|
||||
/* Reason: Can only be instantiated one time (internally) */
|
||||
dc->user_creatable = false;
|
||||
}
|
||||
|
||||
static const TypeInfo qemu_s390_stattrib_info = {
|
||||
|
@ -118,12 +118,11 @@ static void ccw_init(MachineState *machine)
|
||||
{
|
||||
int ret;
|
||||
VirtualCssBus *css_bus;
|
||||
DeviceState *dev;
|
||||
|
||||
s390_sclp_init();
|
||||
s390_memory_init(machine->ram_size);
|
||||
|
||||
/* init CPUs */
|
||||
/* init CPUs (incl. CPU model) early so s390_has_feature() works */
|
||||
s390_init_cpus(machine);
|
||||
|
||||
s390_flic_init();
|
||||
@ -134,17 +133,18 @@ static void ccw_init(MachineState *machine)
|
||||
machine->initrd_filename, "s390-ccw.img",
|
||||
"s390-netboot.img", true);
|
||||
|
||||
dev = qdev_create(NULL, TYPE_S390_PCI_HOST_BRIDGE);
|
||||
object_property_add_child(qdev_get_machine(), TYPE_S390_PCI_HOST_BRIDGE,
|
||||
OBJECT(dev), NULL);
|
||||
qdev_init_nofail(dev);
|
||||
if (s390_has_feat(S390_FEAT_ZPCI)) {
|
||||
DeviceState *dev = qdev_create(NULL, TYPE_S390_PCI_HOST_BRIDGE);
|
||||
object_property_add_child(qdev_get_machine(),
|
||||
TYPE_S390_PCI_HOST_BRIDGE,
|
||||
OBJECT(dev), NULL);
|
||||
qdev_init_nofail(dev);
|
||||
}
|
||||
|
||||
/* register hypercalls */
|
||||
virtio_ccw_register_hcalls();
|
||||
|
||||
if (kvm_enabled()) {
|
||||
kvm_s390_enable_css_support(s390_cpu_addr2state(0));
|
||||
}
|
||||
s390_enable_css_support(s390_cpu_addr2state(0));
|
||||
/*
|
||||
* Non mcss-e enabled guests only see the devices from the default
|
||||
* css, which is determined by the value of the squash_mcss property.
|
||||
@ -161,7 +161,7 @@ static void ccw_init(MachineState *machine)
|
||||
s390_create_virtio_net(BUS(css_bus), "virtio-net-ccw");
|
||||
|
||||
/* Register savevm handler for guest TOD clock */
|
||||
register_savevm_live(NULL, "todclock", 0, 1, &savevm_gtod, kvm_state);
|
||||
register_savevm_live(NULL, "todclock", 0, 1, &savevm_gtod, NULL);
|
||||
}
|
||||
|
||||
static void s390_cpu_plug(HotplugHandler *hotplug_dev,
|
||||
@ -276,9 +276,6 @@ static S390CcwMachineClass *get_machine_class(void)
|
||||
|
||||
bool ri_allowed(void)
|
||||
{
|
||||
if (!kvm_enabled()) {
|
||||
return false;
|
||||
}
|
||||
/* for "none" machine this results in true */
|
||||
return get_machine_class()->ri_allowed;
|
||||
}
|
||||
@ -291,18 +288,8 @@ bool cpu_model_allowed(void)
|
||||
|
||||
bool gs_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->gs_allowed;
|
||||
}
|
||||
/* Make sure the "none" machine can have gs */
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
/* for "none" machine this results in true */
|
||||
return get_machine_class()->gs_allowed;
|
||||
}
|
||||
|
||||
static char *machine_get_loadparm(Object *obj, Error **errp)
|
||||
@ -432,6 +419,9 @@ bool css_migration_enabled(void)
|
||||
} \
|
||||
type_init(ccw_machine_register_##suffix)
|
||||
|
||||
#define CCW_COMPAT_2_10 \
|
||||
HW_COMPAT_2_10
|
||||
|
||||
#define CCW_COMPAT_2_9 \
|
||||
HW_COMPAT_2_9 \
|
||||
{\
|
||||
@ -506,8 +496,18 @@ bool css_migration_enabled(void)
|
||||
.value = "0",\
|
||||
},
|
||||
|
||||
static void ccw_machine_2_11_instance_options(MachineState *machine)
|
||||
{
|
||||
}
|
||||
|
||||
static void ccw_machine_2_11_class_options(MachineClass *mc)
|
||||
{
|
||||
}
|
||||
DEFINE_CCW_MACHINE(2_11, "2.11", true);
|
||||
|
||||
static void ccw_machine_2_10_instance_options(MachineState *machine)
|
||||
{
|
||||
ccw_machine_2_11_instance_options(machine);
|
||||
if (css_migration_enabled()) {
|
||||
css_register_vmstate();
|
||||
}
|
||||
@ -515,8 +515,10 @@ static void ccw_machine_2_10_instance_options(MachineState *machine)
|
||||
|
||||
static void ccw_machine_2_10_class_options(MachineClass *mc)
|
||||
{
|
||||
ccw_machine_2_11_class_options(mc);
|
||||
SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_10);
|
||||
}
|
||||
DEFINE_CCW_MACHINE(2_10, "2.10", true);
|
||||
DEFINE_CCW_MACHINE(2_10, "2.10", false);
|
||||
|
||||
static void ccw_machine_2_9_instance_options(MachineState *machine)
|
||||
{
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include "hw/boards.h"
|
||||
#include "hw/loader.h"
|
||||
#include "hw/virtio/virtio.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "sysemu/qtest.h"
|
||||
|
||||
@ -93,11 +92,7 @@ void s390_init_cpus(MachineState *machine)
|
||||
gchar *name;
|
||||
|
||||
if (machine->cpu_model == NULL) {
|
||||
if (kvm_enabled()) {
|
||||
machine->cpu_model = "host";
|
||||
} else {
|
||||
machine->cpu_model = "qemu";
|
||||
}
|
||||
machine->cpu_model = s390_default_cpu_model_name();
|
||||
}
|
||||
|
||||
cpu_states = g_new0(S390CPU *, max_cpus);
|
||||
|
@ -30,4 +30,6 @@ void s390_create_virtio_net(BusState *bus, const char *name);
|
||||
void s390_nmi(NMIState *n, int cpu_index, Error **errp);
|
||||
void s390_machine_reset(void);
|
||||
void s390_memory_init(ram_addr_t mem_size);
|
||||
void gtod_save(QEMUFile *f, void *opaque);
|
||||
int gtod_load(QEMUFile *f, void *opaque, int version_id);
|
||||
#endif
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "cpu.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "exec/memory.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "exec/address-spaces.h"
|
||||
@ -57,7 +56,7 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
|
||||
CPUState *cpu;
|
||||
int cpu_count = 0;
|
||||
int rnsize, rnmax;
|
||||
int slots = MIN(machine->ram_slots, s390_get_memslot_count(kvm_state));
|
||||
int slots = MIN(machine->ram_slots, s390_get_memslot_count());
|
||||
IplParameterBlock *ipib = s390_ipl_get_iplb();
|
||||
|
||||
CPU_FOREACH(cpu) {
|
||||
@ -80,7 +79,7 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
|
||||
prepare_cpu_entries(sclp, read_info->entries, cpu_count);
|
||||
|
||||
read_info->facilities = cpu_to_be64(SCLP_HAS_CPU_INFO |
|
||||
SCLP_HAS_PCI_RECONFIG);
|
||||
SCLP_HAS_IOA_RECONFIG);
|
||||
|
||||
/* Memory Hotplug is only supported for the ccw machine type */
|
||||
if (mhd) {
|
||||
@ -354,6 +353,35 @@ static void sclp_read_cpu_info(SCLPDevice *sclp, SCCB *sccb)
|
||||
sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
|
||||
}
|
||||
|
||||
static void sclp_configure_io_adapter(SCLPDevice *sclp, SCCB *sccb,
|
||||
bool configure)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (be16_to_cpu(sccb->h.length) < 16) {
|
||||
rc = SCLP_RC_INSUFFICIENT_SCCB_LENGTH;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
switch (((IoaCfgSccb *)sccb)->atype) {
|
||||
case SCLP_RECONFIG_PCI_ATYPE:
|
||||
if (s390_has_feat(S390_FEAT_ZPCI)) {
|
||||
if (configure) {
|
||||
s390_pci_sclp_configure(sccb);
|
||||
} else {
|
||||
s390_pci_sclp_deconfigure(sccb);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* fallthrough */
|
||||
default:
|
||||
rc = SCLP_RC_ADAPTER_TYPE_NOT_RECOGNIZED;
|
||||
}
|
||||
|
||||
out_err:
|
||||
sccb->h.response_code = cpu_to_be16(rc);
|
||||
}
|
||||
|
||||
static void sclp_execute(SCLPDevice *sclp, SCCB *sccb, uint32_t code)
|
||||
{
|
||||
SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
|
||||
@ -384,11 +412,11 @@ static void sclp_execute(SCLPDevice *sclp, SCCB *sccb, uint32_t code)
|
||||
case SCLP_UNASSIGN_STORAGE:
|
||||
sclp_c->unassign_storage(sclp, sccb);
|
||||
break;
|
||||
case SCLP_CMDW_CONFIGURE_PCI:
|
||||
s390_pci_sclp_configure(sccb);
|
||||
case SCLP_CMDW_CONFIGURE_IOA:
|
||||
sclp_configure_io_adapter(sclp, sccb, true);
|
||||
break;
|
||||
case SCLP_CMDW_DECONFIGURE_PCI:
|
||||
s390_pci_sclp_deconfigure(sccb);
|
||||
case SCLP_CMDW_DECONFIGURE_IOA:
|
||||
sclp_configure_io_adapter(sclp, sccb, false);
|
||||
break;
|
||||
default:
|
||||
efc->command_handler(ef, sccb, code);
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "hw/s390x/event-facility.h"
|
||||
#include "cpu.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
typedef struct ConfigMgtData {
|
||||
EventBufferHeader ebh;
|
||||
|
@ -121,6 +121,7 @@ static void wdt_diag288_class_init(ObjectClass *klass, void *data)
|
||||
dc->realize = wdt_diag288_realize;
|
||||
dc->unrealize = wdt_diag288_unrealize;
|
||||
dc->reset = wdt_diag288_reset;
|
||||
dc->hotpluggable = false;
|
||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
dc->vmsd = &vmstate_diag288;
|
||||
diag288->handle_timer = wdt_diag288_handle_timer;
|
||||
|
@ -1,6 +1,9 @@
|
||||
#ifndef HW_COMPAT_H
|
||||
#define HW_COMPAT_H
|
||||
|
||||
#define HW_COMPAT_2_10 \
|
||||
/* empty */
|
||||
|
||||
#define HW_COMPAT_2_9 \
|
||||
{\
|
||||
.driver = "pci-bridge",\
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include "hw/pci/pcie.h"
|
||||
|
||||
extern bool pci_available;
|
||||
|
||||
/* PCI bus */
|
||||
|
||||
#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "hw/s390x/adapter.h"
|
||||
#include "hw/s390x/s390_flic.h"
|
||||
#include "hw/s390x/ioinst.h"
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
/* Channel subsystem constants. */
|
||||
#define MAX_DEVNO 65535
|
||||
@ -150,7 +151,8 @@ void copy_scsw_to_guest(SCSW *dest, const SCSW *src);
|
||||
void css_inject_io_interrupt(SubchDev *sch);
|
||||
void css_reset(void);
|
||||
void css_reset_sch(SubchDev *sch);
|
||||
void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid);
|
||||
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);
|
||||
|
@ -201,8 +201,16 @@ typedef struct CRW {
|
||||
#define CRW_FLAGS_MASK_A 0x0080
|
||||
#define CRW_FLAGS_MASK_ERC 0x003f
|
||||
|
||||
#define CRW_ERC_INIT 0x02
|
||||
#define CRW_ERC_IPI 0x04
|
||||
#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
|
||||
|
@ -44,10 +44,10 @@
|
||||
#define SCLP_CMDW_DECONFIGURE_CPU 0x00100001
|
||||
|
||||
/* SCLP PCI codes */
|
||||
#define SCLP_HAS_PCI_RECONFIG 0x0000000040000000ULL
|
||||
#define SCLP_CMDW_CONFIGURE_PCI 0x001a0001
|
||||
#define SCLP_CMDW_DECONFIGURE_PCI 0x001b0001
|
||||
#define SCLP_RECONFIG_PCI_ATPYE 2
|
||||
#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
|
||||
@ -59,6 +59,7 @@
|
||||
#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
|
||||
@ -167,6 +168,14 @@ typedef struct AssignStorage {
|
||||
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[SCCB_DATA_LEN];
|
||||
|
Binary file not shown.
@ -133,7 +133,7 @@ struct ccw1 {
|
||||
__u8 flags;
|
||||
__u16 count;
|
||||
__u32 cda;
|
||||
} __attribute__ ((packed));
|
||||
} __attribute__ ((packed, aligned(8)));
|
||||
|
||||
#define CCW_FLAG_DC 0x80
|
||||
#define CCW_FLAG_CC 0x40
|
||||
|
@ -3,6 +3,7 @@ obj-$(CONFIG_TCG) += translate.o cc_helper.o excp_helper.o fpu_helper.o
|
||||
obj-$(CONFIG_TCG) += int_helper.o mem_helper.o misc_helper.o
|
||||
obj-$(CONFIG_SOFTMMU) += machine.o ioinst.o arch_dump.o mmu_helper.o diag.o
|
||||
obj-$(CONFIG_KVM) += kvm.o
|
||||
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
|
||||
|
||||
# build and run feature list generator
|
||||
feat-src = $(SRC_PATH)/target/$(TARGET_BASE_ARCH)/
|
||||
|
@ -13,10 +13,10 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "elf.h"
|
||||
#include "exec/cpu-all.h"
|
||||
#include "sysemu/dump.h"
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
|
||||
struct S390xUserRegsStruct {
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "qemu/host-utils.h"
|
||||
|
@ -26,6 +26,9 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "kvm_s390x.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/timer.h"
|
||||
@ -391,6 +394,92 @@ unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu)
|
||||
|
||||
return s390_count_running_cpus();
|
||||
}
|
||||
|
||||
int s390_get_clock(uint8_t *tod_high, uint64_t *tod_low)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
return kvm_s390_get_clock(tod_high, tod_low);
|
||||
}
|
||||
/* Fixme TCG */
|
||||
*tod_high = 0;
|
||||
*tod_low = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
return kvm_s390_set_clock(tod_high, tod_low);
|
||||
}
|
||||
/* Fixme TCG */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
return kvm_s390_set_mem_limit(new_limit, hw_limit);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void s390_cmma_reset(void)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
kvm_s390_cmma_reset();
|
||||
}
|
||||
}
|
||||
|
||||
int s390_cpu_restart(S390CPU *cpu)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
return kvm_s390_cpu_restart(cpu);
|
||||
}
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int s390_get_memslot_count(void)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
return kvm_s390_get_memslot_count();
|
||||
} else {
|
||||
return MAX_AVAIL_SLOTS;
|
||||
}
|
||||
}
|
||||
|
||||
int s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch_id,
|
||||
int vq, bool assign)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
return kvm_s390_assign_subch_ioeventfd(notifier, sch_id, vq, assign);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void s390_crypto_reset(void)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
kvm_s390_crypto_reset();
|
||||
}
|
||||
}
|
||||
|
||||
bool s390_get_squash_mcss(void)
|
||||
{
|
||||
if (object_property_get_bool(OBJECT(qdev_get_machine()), "s390-squash-mcss",
|
||||
NULL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void s390_enable_css_support(S390CPU *cpu)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
kvm_s390_enable_css_support(cpu);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static gchar *s390_gdb_arch_name(CPUState *cs)
|
||||
|
@ -213,22 +213,6 @@ static inline S390CPU *s390_env_get_cpu(CPUS390XState *env)
|
||||
extern const struct VMStateDescription vmstate_s390_cpu;
|
||||
#endif
|
||||
|
||||
void s390_cpu_do_interrupt(CPUState *cpu);
|
||||
bool s390_cpu_exec_interrupt(CPUState *cpu, int int_req);
|
||||
void s390_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
|
||||
int flags);
|
||||
int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||
int cpuid, void *opaque);
|
||||
|
||||
hwaddr s390_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
|
||||
hwaddr s390_cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr);
|
||||
int s390_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
int s390_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
void s390_cpu_gdb_init(CPUState *cs);
|
||||
void s390x_cpu_debug_excp_handler(CPUState *cs);
|
||||
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
/* distinguish between 24 bit and 31 bit addressing */
|
||||
#define HIGH_ORDER_BIT 0x80000000
|
||||
|
||||
@ -366,17 +350,6 @@ void s390x_cpu_debug_excp_handler(CPUState *cs);
|
||||
#define MMU_SECONDARY_IDX 1
|
||||
#define MMU_HOME_IDX 2
|
||||
|
||||
static inline bool psw_key_valid(CPUS390XState *env, uint8_t psw_key)
|
||||
{
|
||||
uint16_t pkm = env->cregs[3] >> 16;
|
||||
|
||||
if (env->psw.mask & PSW_MASK_PSTATE) {
|
||||
/* PSW key has range 0..15, it is valid if the bit is 1 in the PKM */
|
||||
return pkm & (0x80 >> psw_key);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline int cpu_mmu_index(CPUS390XState *env, bool ifetch)
|
||||
{
|
||||
switch (env->psw.mask & PSW_MASK_ASC) {
|
||||
@ -393,20 +366,6 @@ static inline int cpu_mmu_index(CPUS390XState *env, bool ifetch)
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint64_t cpu_mmu_idx_to_asc(int mmu_idx)
|
||||
{
|
||||
switch (mmu_idx) {
|
||||
case MMU_PRIMARY_IDX:
|
||||
return PSW_ASC_PRIMARY;
|
||||
case MMU_SECONDARY_IDX:
|
||||
return PSW_ASC_SECONDARY;
|
||||
case MMU_HOME_IDX:
|
||||
return PSW_ASC_HOME;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc,
|
||||
target_ulong *cs_base, uint32_t *flags)
|
||||
{
|
||||
@ -415,26 +374,6 @@ static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc,
|
||||
*flags = (env->psw.mask >> FLAG_MASK_PSW_SHIFT) & FLAG_MASK_PSW;
|
||||
}
|
||||
|
||||
#define MAX_ILEN 6
|
||||
|
||||
/* While the PoO talks about ILC (a number between 1-3) what is actually
|
||||
stored in LowCore is shifted left one bit (an even between 2-6). As
|
||||
this is the actual length of the insn and therefore more useful, that
|
||||
is what we want to pass around and manipulate. To make sure that we
|
||||
have applied this distinction universally, rename the "ILC" to "ILEN". */
|
||||
static inline int get_ilen(uint8_t opc)
|
||||
{
|
||||
switch (opc >> 6) {
|
||||
case 0:
|
||||
return 2;
|
||||
case 1:
|
||||
case 2:
|
||||
return 4;
|
||||
default:
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
/* PER bits from control register 9 */
|
||||
#define PER_CR9_EVENT_BRANCH 0x80000000
|
||||
#define PER_CR9_EVENT_IFETCH 0x40000000
|
||||
@ -451,203 +390,6 @@ static inline int get_ilen(uint8_t opc)
|
||||
#define PER_CODE_EVENT_STORE_REAL 0x0800
|
||||
#define PER_CODE_EVENT_NULLIFICATION 0x0100
|
||||
|
||||
/* Compute the ATMID field that is stored in the per_perc_atmid lowcore
|
||||
entry when a PER exception is triggered. */
|
||||
static inline uint8_t get_per_atmid(CPUS390XState *env)
|
||||
{
|
||||
return ((env->psw.mask & PSW_MASK_64) ? (1 << 7) : 0) |
|
||||
( (1 << 6) ) |
|
||||
((env->psw.mask & PSW_MASK_32) ? (1 << 5) : 0) |
|
||||
((env->psw.mask & PSW_MASK_DAT)? (1 << 4) : 0) |
|
||||
((env->psw.mask & PSW_ASC_SECONDARY)? (1 << 3) : 0) |
|
||||
((env->psw.mask & PSW_ASC_ACCREG)? (1 << 2) : 0);
|
||||
}
|
||||
|
||||
/* Check if an address is within the PER starting address and the PER
|
||||
ending address. The address range might loop. */
|
||||
static inline bool get_per_in_range(CPUS390XState *env, uint64_t addr)
|
||||
{
|
||||
if (env->cregs[10] <= env->cregs[11]) {
|
||||
return env->cregs[10] <= addr && addr <= env->cregs[11];
|
||||
} else {
|
||||
return env->cregs[10] <= addr || addr <= env->cregs[11];
|
||||
}
|
||||
}
|
||||
|
||||
S390CPU *cpu_s390x_init(const char *cpu_model);
|
||||
S390CPU *s390x_new_cpu(const char *cpu_model, int64_t id, Error **errp);
|
||||
S390CPU *cpu_s390x_create(const char *cpu_model, Error **errp);
|
||||
void s390x_translate_init(void);
|
||||
|
||||
/* you can call this signal handler from your SIGBUS and SIGSEGV
|
||||
signal handlers to inform the virtual CPU of exceptions. non zero
|
||||
is returned if the signal was handled by the virtual CPU. */
|
||||
int cpu_s390x_signal_handler(int host_signum, void *pinfo,
|
||||
void *puc);
|
||||
int s390_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
|
||||
int mmu_idx);
|
||||
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
void do_restart_interrupt(CPUS390XState *env);
|
||||
void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
|
||||
MMUAccessType access_type,
|
||||
int mmu_idx, uintptr_t retaddr);
|
||||
|
||||
static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb,
|
||||
uint8_t *ar)
|
||||
{
|
||||
hwaddr addr = 0;
|
||||
uint8_t reg;
|
||||
|
||||
reg = ipb >> 28;
|
||||
if (reg > 0) {
|
||||
addr = env->regs[reg];
|
||||
}
|
||||
addr += (ipb >> 16) & 0xfff;
|
||||
if (ar) {
|
||||
*ar = reg;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* Base/displacement are at the same locations. */
|
||||
#define decode_basedisp_rs decode_basedisp_s
|
||||
|
||||
/* helper functions for run_on_cpu() */
|
||||
static inline void s390_do_cpu_reset(CPUState *cs, run_on_cpu_data arg)
|
||||
{
|
||||
S390CPUClass *scc = S390_CPU_GET_CLASS(cs);
|
||||
|
||||
scc->cpu_reset(cs);
|
||||
}
|
||||
static inline void s390_do_cpu_full_reset(CPUState *cs, run_on_cpu_data arg)
|
||||
{
|
||||
cpu_reset(cs);
|
||||
}
|
||||
|
||||
void s390x_tod_timer(void *opaque);
|
||||
void s390x_cpu_timer(void *opaque);
|
||||
|
||||
int s390_virtio_hypercall(CPUS390XState *env);
|
||||
|
||||
#ifdef CONFIG_KVM
|
||||
void kvm_s390_service_interrupt(uint32_t parm);
|
||||
void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq);
|
||||
void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq);
|
||||
int kvm_s390_inject_flic(struct kvm_s390_irq *irq);
|
||||
void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code);
|
||||
int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf,
|
||||
int len, bool is_write);
|
||||
int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock);
|
||||
int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_clock);
|
||||
#else
|
||||
static inline void kvm_s390_service_interrupt(uint32_t parm)
|
||||
{
|
||||
}
|
||||
static inline int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_low)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar,
|
||||
void *hostbuf, int len, bool is_write)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline void kvm_s390_access_exception(S390CPU *cpu, uint16_t code,
|
||||
uint64_t te_code)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int s390_get_clock(uint8_t *tod_high, uint64_t *tod_low)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
return kvm_s390_get_clock(tod_high, tod_low);
|
||||
}
|
||||
/* Fixme TCG */
|
||||
*tod_high = 0;
|
||||
*tod_low = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
return kvm_s390_set_clock(tod_high, tod_low);
|
||||
}
|
||||
/* Fixme TCG */
|
||||
return 0;
|
||||
}
|
||||
|
||||
S390CPU *s390_cpu_addr2state(uint16_t cpu_addr);
|
||||
unsigned int s390_cpu_halt(S390CPU *cpu);
|
||||
void s390_cpu_unhalt(S390CPU *cpu);
|
||||
unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu);
|
||||
static inline uint8_t s390_cpu_get_state(S390CPU *cpu)
|
||||
{
|
||||
return cpu->env.cpu_state;
|
||||
}
|
||||
|
||||
void gtod_save(QEMUFile *f, void *opaque);
|
||||
int gtod_load(QEMUFile *f, void *opaque, int version_id);
|
||||
|
||||
void cpu_inject_ext(S390CPU *cpu, uint32_t code, uint32_t param,
|
||||
uint64_t param64);
|
||||
|
||||
/* ioinst.c */
|
||||
void ioinst_handle_xsch(S390CPU *cpu, uint64_t reg1);
|
||||
void ioinst_handle_csch(S390CPU *cpu, uint64_t reg1);
|
||||
void ioinst_handle_hsch(S390CPU *cpu, uint64_t reg1);
|
||||
void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
|
||||
void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
|
||||
void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb);
|
||||
void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
|
||||
int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
|
||||
void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb);
|
||||
int ioinst_handle_tpi(S390CPU *cpu, uint32_t ipb);
|
||||
void ioinst_handle_schm(S390CPU *cpu, uint64_t reg1, uint64_t reg2,
|
||||
uint32_t ipb);
|
||||
void ioinst_handle_rsch(S390CPU *cpu, uint64_t reg1);
|
||||
void ioinst_handle_rchp(S390CPU *cpu, uint64_t reg1);
|
||||
void ioinst_handle_sal(S390CPU *cpu, uint64_t reg1);
|
||||
|
||||
/* service interrupts are floating therefore we must not pass an cpustate */
|
||||
void s390_sclp_extint(uint32_t parm);
|
||||
|
||||
#else
|
||||
static inline unsigned int s390_cpu_halt(S390CPU *cpu)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void s390_cpu_unhalt(S390CPU *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
static inline unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern void subsystem_reset(void);
|
||||
|
||||
#define cpu_init(model) CPU(cpu_s390x_init(model))
|
||||
#define cpu_signal_handler cpu_s390x_signal_handler
|
||||
|
||||
void s390_cpu_list(FILE *f, fprintf_function cpu_fprintf);
|
||||
#define cpu_list s390_cpu_list
|
||||
void s390_cpu_model_register_props(Object *obj);
|
||||
void s390_cpu_model_class_register_props(ObjectClass *oc);
|
||||
void s390_realize_cpu_model(CPUState *cs, Error **errp);
|
||||
ObjectClass *s390_cpu_class_by_name(const char *name);
|
||||
|
||||
#define EXCP_EXT 1 /* external interrupt */
|
||||
#define EXCP_SVC 2 /* supervisor call (syscall) */
|
||||
#define EXCP_PGM 3 /* program interruption */
|
||||
@ -683,115 +425,6 @@ ObjectClass *s390_cpu_class_by_name(const char *name);
|
||||
/* Total Core Registers. */
|
||||
#define S390_NUM_CORE_REGS 18
|
||||
|
||||
/* CC optimization */
|
||||
|
||||
/* Instead of computing the condition codes after each x86 instruction,
|
||||
* QEMU just stores the result (called CC_DST), the type of operation
|
||||
* (called CC_OP) and whatever operands are needed (CC_SRC and possibly
|
||||
* CC_VR). When the condition codes are needed, the condition codes can
|
||||
* be calculated using this information. Condition codes are not generated
|
||||
* if they are only needed for conditional branches.
|
||||
*/
|
||||
enum cc_op {
|
||||
CC_OP_CONST0 = 0, /* CC is 0 */
|
||||
CC_OP_CONST1, /* CC is 1 */
|
||||
CC_OP_CONST2, /* CC is 2 */
|
||||
CC_OP_CONST3, /* CC is 3 */
|
||||
|
||||
CC_OP_DYNAMIC, /* CC calculation defined by env->cc_op */
|
||||
CC_OP_STATIC, /* CC value is env->cc_op */
|
||||
|
||||
CC_OP_NZ, /* env->cc_dst != 0 */
|
||||
CC_OP_LTGT_32, /* signed less/greater than (32bit) */
|
||||
CC_OP_LTGT_64, /* signed less/greater than (64bit) */
|
||||
CC_OP_LTUGTU_32, /* unsigned less/greater than (32bit) */
|
||||
CC_OP_LTUGTU_64, /* unsigned less/greater than (64bit) */
|
||||
CC_OP_LTGT0_32, /* signed less/greater than 0 (32bit) */
|
||||
CC_OP_LTGT0_64, /* signed less/greater than 0 (64bit) */
|
||||
|
||||
CC_OP_ADD_64, /* overflow on add (64bit) */
|
||||
CC_OP_ADDU_64, /* overflow on unsigned add (64bit) */
|
||||
CC_OP_ADDC_64, /* overflow on unsigned add-carry (64bit) */
|
||||
CC_OP_SUB_64, /* overflow on subtraction (64bit) */
|
||||
CC_OP_SUBU_64, /* overflow on unsigned subtraction (64bit) */
|
||||
CC_OP_SUBB_64, /* overflow on unsigned sub-borrow (64bit) */
|
||||
CC_OP_ABS_64, /* sign eval on abs (64bit) */
|
||||
CC_OP_NABS_64, /* sign eval on nabs (64bit) */
|
||||
|
||||
CC_OP_ADD_32, /* overflow on add (32bit) */
|
||||
CC_OP_ADDU_32, /* overflow on unsigned add (32bit) */
|
||||
CC_OP_ADDC_32, /* overflow on unsigned add-carry (32bit) */
|
||||
CC_OP_SUB_32, /* overflow on subtraction (32bit) */
|
||||
CC_OP_SUBU_32, /* overflow on unsigned subtraction (32bit) */
|
||||
CC_OP_SUBB_32, /* overflow on unsigned sub-borrow (32bit) */
|
||||
CC_OP_ABS_32, /* sign eval on abs (64bit) */
|
||||
CC_OP_NABS_32, /* sign eval on nabs (64bit) */
|
||||
|
||||
CC_OP_COMP_32, /* complement */
|
||||
CC_OP_COMP_64, /* complement */
|
||||
|
||||
CC_OP_TM_32, /* test under mask (32bit) */
|
||||
CC_OP_TM_64, /* test under mask (64bit) */
|
||||
|
||||
CC_OP_NZ_F32, /* FP dst != 0 (32bit) */
|
||||
CC_OP_NZ_F64, /* FP dst != 0 (64bit) */
|
||||
CC_OP_NZ_F128, /* FP dst != 0 (128bit) */
|
||||
|
||||
CC_OP_ICM, /* insert characters under mask */
|
||||
CC_OP_SLA_32, /* Calculate shift left signed (32bit) */
|
||||
CC_OP_SLA_64, /* Calculate shift left signed (64bit) */
|
||||
CC_OP_FLOGR, /* find leftmost one */
|
||||
CC_OP_MAX
|
||||
};
|
||||
|
||||
static const char *cc_names[] = {
|
||||
[CC_OP_CONST0] = "CC_OP_CONST0",
|
||||
[CC_OP_CONST1] = "CC_OP_CONST1",
|
||||
[CC_OP_CONST2] = "CC_OP_CONST2",
|
||||
[CC_OP_CONST3] = "CC_OP_CONST3",
|
||||
[CC_OP_DYNAMIC] = "CC_OP_DYNAMIC",
|
||||
[CC_OP_STATIC] = "CC_OP_STATIC",
|
||||
[CC_OP_NZ] = "CC_OP_NZ",
|
||||
[CC_OP_LTGT_32] = "CC_OP_LTGT_32",
|
||||
[CC_OP_LTGT_64] = "CC_OP_LTGT_64",
|
||||
[CC_OP_LTUGTU_32] = "CC_OP_LTUGTU_32",
|
||||
[CC_OP_LTUGTU_64] = "CC_OP_LTUGTU_64",
|
||||
[CC_OP_LTGT0_32] = "CC_OP_LTGT0_32",
|
||||
[CC_OP_LTGT0_64] = "CC_OP_LTGT0_64",
|
||||
[CC_OP_ADD_64] = "CC_OP_ADD_64",
|
||||
[CC_OP_ADDU_64] = "CC_OP_ADDU_64",
|
||||
[CC_OP_ADDC_64] = "CC_OP_ADDC_64",
|
||||
[CC_OP_SUB_64] = "CC_OP_SUB_64",
|
||||
[CC_OP_SUBU_64] = "CC_OP_SUBU_64",
|
||||
[CC_OP_SUBB_64] = "CC_OP_SUBB_64",
|
||||
[CC_OP_ABS_64] = "CC_OP_ABS_64",
|
||||
[CC_OP_NABS_64] = "CC_OP_NABS_64",
|
||||
[CC_OP_ADD_32] = "CC_OP_ADD_32",
|
||||
[CC_OP_ADDU_32] = "CC_OP_ADDU_32",
|
||||
[CC_OP_ADDC_32] = "CC_OP_ADDC_32",
|
||||
[CC_OP_SUB_32] = "CC_OP_SUB_32",
|
||||
[CC_OP_SUBU_32] = "CC_OP_SUBU_32",
|
||||
[CC_OP_SUBB_32] = "CC_OP_SUBB_32",
|
||||
[CC_OP_ABS_32] = "CC_OP_ABS_32",
|
||||
[CC_OP_NABS_32] = "CC_OP_NABS_32",
|
||||
[CC_OP_COMP_32] = "CC_OP_COMP_32",
|
||||
[CC_OP_COMP_64] = "CC_OP_COMP_64",
|
||||
[CC_OP_TM_32] = "CC_OP_TM_32",
|
||||
[CC_OP_TM_64] = "CC_OP_TM_64",
|
||||
[CC_OP_NZ_F32] = "CC_OP_NZ_F32",
|
||||
[CC_OP_NZ_F64] = "CC_OP_NZ_F64",
|
||||
[CC_OP_NZ_F128] = "CC_OP_NZ_F128",
|
||||
[CC_OP_ICM] = "CC_OP_ICM",
|
||||
[CC_OP_SLA_32] = "CC_OP_SLA_32",
|
||||
[CC_OP_SLA_64] = "CC_OP_SLA_64",
|
||||
[CC_OP_FLOGR] = "CC_OP_FLOGR",
|
||||
};
|
||||
|
||||
static inline const char *cc_name(int cc_op)
|
||||
{
|
||||
return cc_names[cc_op];
|
||||
}
|
||||
|
||||
static inline void setcc(S390CPU *cpu, uint64_t cc)
|
||||
{
|
||||
CPUS390XState *env = &cpu->env;
|
||||
@ -801,130 +434,6 @@ static inline void setcc(S390CPU *cpu, uint64_t cc)
|
||||
env->cc_op = cc;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
typedef struct LowCore
|
||||
{
|
||||
/* prefix area: defined by architecture */
|
||||
uint32_t ccw1[2]; /* 0x000 */
|
||||
uint32_t ccw2[4]; /* 0x008 */
|
||||
uint8_t pad1[0x80-0x18]; /* 0x018 */
|
||||
uint32_t ext_params; /* 0x080 */
|
||||
uint16_t cpu_addr; /* 0x084 */
|
||||
uint16_t ext_int_code; /* 0x086 */
|
||||
uint16_t svc_ilen; /* 0x088 */
|
||||
uint16_t svc_code; /* 0x08a */
|
||||
uint16_t pgm_ilen; /* 0x08c */
|
||||
uint16_t pgm_code; /* 0x08e */
|
||||
uint32_t data_exc_code; /* 0x090 */
|
||||
uint16_t mon_class_num; /* 0x094 */
|
||||
uint16_t per_perc_atmid; /* 0x096 */
|
||||
uint64_t per_address; /* 0x098 */
|
||||
uint8_t exc_access_id; /* 0x0a0 */
|
||||
uint8_t per_access_id; /* 0x0a1 */
|
||||
uint8_t op_access_id; /* 0x0a2 */
|
||||
uint8_t ar_access_id; /* 0x0a3 */
|
||||
uint8_t pad2[0xA8-0xA4]; /* 0x0a4 */
|
||||
uint64_t trans_exc_code; /* 0x0a8 */
|
||||
uint64_t monitor_code; /* 0x0b0 */
|
||||
uint16_t subchannel_id; /* 0x0b8 */
|
||||
uint16_t subchannel_nr; /* 0x0ba */
|
||||
uint32_t io_int_parm; /* 0x0bc */
|
||||
uint32_t io_int_word; /* 0x0c0 */
|
||||
uint8_t pad3[0xc8-0xc4]; /* 0x0c4 */
|
||||
uint32_t stfl_fac_list; /* 0x0c8 */
|
||||
uint8_t pad4[0xe8-0xcc]; /* 0x0cc */
|
||||
uint32_t mcck_interruption_code[2]; /* 0x0e8 */
|
||||
uint8_t pad5[0xf4-0xf0]; /* 0x0f0 */
|
||||
uint32_t external_damage_code; /* 0x0f4 */
|
||||
uint64_t failing_storage_address; /* 0x0f8 */
|
||||
uint8_t pad6[0x110-0x100]; /* 0x100 */
|
||||
uint64_t per_breaking_event_addr; /* 0x110 */
|
||||
uint8_t pad7[0x120-0x118]; /* 0x118 */
|
||||
PSW restart_old_psw; /* 0x120 */
|
||||
PSW external_old_psw; /* 0x130 */
|
||||
PSW svc_old_psw; /* 0x140 */
|
||||
PSW program_old_psw; /* 0x150 */
|
||||
PSW mcck_old_psw; /* 0x160 */
|
||||
PSW io_old_psw; /* 0x170 */
|
||||
uint8_t pad8[0x1a0-0x180]; /* 0x180 */
|
||||
PSW restart_new_psw; /* 0x1a0 */
|
||||
PSW external_new_psw; /* 0x1b0 */
|
||||
PSW svc_new_psw; /* 0x1c0 */
|
||||
PSW program_new_psw; /* 0x1d0 */
|
||||
PSW mcck_new_psw; /* 0x1e0 */
|
||||
PSW io_new_psw; /* 0x1f0 */
|
||||
PSW return_psw; /* 0x200 */
|
||||
uint8_t irb[64]; /* 0x210 */
|
||||
uint64_t sync_enter_timer; /* 0x250 */
|
||||
uint64_t async_enter_timer; /* 0x258 */
|
||||
uint64_t exit_timer; /* 0x260 */
|
||||
uint64_t last_update_timer; /* 0x268 */
|
||||
uint64_t user_timer; /* 0x270 */
|
||||
uint64_t system_timer; /* 0x278 */
|
||||
uint64_t last_update_clock; /* 0x280 */
|
||||
uint64_t steal_clock; /* 0x288 */
|
||||
PSW return_mcck_psw; /* 0x290 */
|
||||
uint8_t pad9[0xc00-0x2a0]; /* 0x2a0 */
|
||||
/* System info area */
|
||||
uint64_t save_area[16]; /* 0xc00 */
|
||||
uint8_t pad10[0xd40-0xc80]; /* 0xc80 */
|
||||
uint64_t kernel_stack; /* 0xd40 */
|
||||
uint64_t thread_info; /* 0xd48 */
|
||||
uint64_t async_stack; /* 0xd50 */
|
||||
uint64_t kernel_asce; /* 0xd58 */
|
||||
uint64_t user_asce; /* 0xd60 */
|
||||
uint64_t panic_stack; /* 0xd68 */
|
||||
uint64_t user_exec_asce; /* 0xd70 */
|
||||
uint8_t pad11[0xdc0-0xd78]; /* 0xd78 */
|
||||
|
||||
/* SMP info area: defined by DJB */
|
||||
uint64_t clock_comparator; /* 0xdc0 */
|
||||
uint64_t ext_call_fast; /* 0xdc8 */
|
||||
uint64_t percpu_offset; /* 0xdd0 */
|
||||
uint64_t current_task; /* 0xdd8 */
|
||||
uint32_t softirq_pending; /* 0xde0 */
|
||||
uint32_t pad_0x0de4; /* 0xde4 */
|
||||
uint64_t int_clock; /* 0xde8 */
|
||||
uint8_t pad12[0xe00-0xdf0]; /* 0xdf0 */
|
||||
|
||||
/* 0xe00 is used as indicator for dump tools */
|
||||
/* whether the kernel died with panic() or not */
|
||||
uint32_t panic_magic; /* 0xe00 */
|
||||
|
||||
uint8_t pad13[0x11b8-0xe04]; /* 0xe04 */
|
||||
|
||||
/* 64 bit extparam used for pfault, diag 250 etc */
|
||||
uint64_t ext_params2; /* 0x11B8 */
|
||||
|
||||
uint8_t pad14[0x1200-0x11C0]; /* 0x11C0 */
|
||||
|
||||
/* System info area */
|
||||
|
||||
uint64_t floating_pt_save_area[16]; /* 0x1200 */
|
||||
uint64_t gpregs_save_area[16]; /* 0x1280 */
|
||||
uint32_t st_status_fixed_logout[4]; /* 0x1300 */
|
||||
uint8_t pad15[0x1318-0x1310]; /* 0x1310 */
|
||||
uint32_t prefixreg_save_area; /* 0x1318 */
|
||||
uint32_t fpt_creg_save_area; /* 0x131c */
|
||||
uint8_t pad16[0x1324-0x1320]; /* 0x1320 */
|
||||
uint32_t tod_progreg_save_area; /* 0x1324 */
|
||||
uint32_t cpu_timer_save_area[2]; /* 0x1328 */
|
||||
uint32_t clock_comp_save_area[2]; /* 0x1330 */
|
||||
uint8_t pad17[0x1340-0x1338]; /* 0x1338 */
|
||||
uint32_t access_regs_save_area[16]; /* 0x1340 */
|
||||
uint64_t cregs_save_area[16]; /* 0x1380 */
|
||||
|
||||
/* align to the top of the prefix area */
|
||||
|
||||
uint8_t pad18[0x2000-0x1400]; /* 0x1400 */
|
||||
} QEMU_PACKED LowCore;
|
||||
|
||||
LowCore *cpu_map_lowcore(CPUS390XState *env);
|
||||
void cpu_unmap_lowcore(LowCore *lowcore);
|
||||
|
||||
#endif
|
||||
|
||||
/* STSI */
|
||||
#define STSI_LEVEL_MASK 0x00000000f0000000ULL
|
||||
#define STSI_LEVEL_CURRENT 0x0000000000000000ULL
|
||||
@ -1100,210 +609,10 @@ struct sysib_322 {
|
||||
/* SIGP order code mask corresponding to bit positions 56-63 */
|
||||
#define SIGP_ORDER_MASK 0x000000ff
|
||||
|
||||
void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr);
|
||||
uint64_t get_psw_mask(CPUS390XState *env);
|
||||
target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr);
|
||||
int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
|
||||
target_ulong *raddr, int *flags, bool exc);
|
||||
int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code);
|
||||
uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
|
||||
uint64_t vr);
|
||||
void s390_cpu_recompute_watchpoints(CPUState *cs);
|
||||
|
||||
int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, uint8_t ar, void *hostbuf,
|
||||
int len, bool is_write);
|
||||
|
||||
#define s390_cpu_virt_mem_read(cpu, laddr, ar, dest, len) \
|
||||
s390_cpu_virt_mem_rw(cpu, laddr, ar, dest, len, false)
|
||||
#define s390_cpu_virt_mem_write(cpu, laddr, ar, dest, len) \
|
||||
s390_cpu_virt_mem_rw(cpu, laddr, ar, dest, len, true)
|
||||
#define s390_cpu_virt_mem_check_write(cpu, laddr, ar, len) \
|
||||
s390_cpu_virt_mem_rw(cpu, laddr, ar, NULL, len, true)
|
||||
|
||||
/* The value of the TOD clock for 1.1.1970. */
|
||||
#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
|
||||
|
||||
/* Converts ns to s390's clock format */
|
||||
static inline uint64_t time2tod(uint64_t ns) {
|
||||
return (ns << 9) / 125;
|
||||
}
|
||||
|
||||
/* Converts s390's clock format to ns */
|
||||
static inline uint64_t tod2time(uint64_t t) {
|
||||
return (t * 125) >> 9;
|
||||
}
|
||||
|
||||
/* from s390-virtio-ccw */
|
||||
#define MEM_SECTION_SIZE 0x10000000UL
|
||||
#define MAX_AVAIL_SLOTS 32
|
||||
|
||||
/* fpu_helper.c */
|
||||
uint32_t set_cc_nz_f32(float32 v);
|
||||
uint32_t set_cc_nz_f64(float64 v);
|
||||
uint32_t set_cc_nz_f128(float128 v);
|
||||
|
||||
/* misc_helper.c */
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3);
|
||||
void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3);
|
||||
#endif
|
||||
/* automatically detect the instruction length */
|
||||
#define ILEN_AUTO 0xff
|
||||
void program_interrupt(CPUS390XState *env, uint32_t code, int ilen);
|
||||
void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilen);
|
||||
void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp,
|
||||
uintptr_t retaddr);
|
||||
|
||||
#ifdef CONFIG_KVM
|
||||
void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code);
|
||||
void kvm_s390_io_interrupt(uint16_t subchannel_id,
|
||||
uint16_t subchannel_nr, uint32_t io_int_parm,
|
||||
uint32_t io_int_word);
|
||||
void kvm_s390_crw_mchk(void);
|
||||
void kvm_s390_enable_css_support(S390CPU *cpu);
|
||||
int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch,
|
||||
int vq, bool assign);
|
||||
int kvm_s390_cpu_restart(S390CPU *cpu);
|
||||
int kvm_s390_get_memslot_count(KVMState *s);
|
||||
int kvm_s390_cmma_active(void);
|
||||
void kvm_s390_cmma_reset(void);
|
||||
int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state);
|
||||
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);
|
||||
int kvm_s390_get_gs(void);
|
||||
void kvm_s390_crypto_reset(void);
|
||||
#else
|
||||
static inline void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code)
|
||||
{
|
||||
}
|
||||
static inline void kvm_s390_io_interrupt(uint16_t subchannel_id,
|
||||
uint16_t subchannel_nr,
|
||||
uint32_t io_int_parm,
|
||||
uint32_t io_int_word)
|
||||
{
|
||||
}
|
||||
static inline void kvm_s390_crw_mchk(void)
|
||||
{
|
||||
}
|
||||
static inline void kvm_s390_enable_css_support(S390CPU *cpu)
|
||||
{
|
||||
}
|
||||
static inline int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier,
|
||||
uint32_t sch, int vq,
|
||||
bool assign)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline int kvm_s390_cpu_restart(S390CPU *cpu)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline void kvm_s390_cmma_reset(void)
|
||||
{
|
||||
}
|
||||
static inline int kvm_s390_get_memslot_count(KVMState *s)
|
||||
{
|
||||
return MAX_AVAIL_SLOTS;
|
||||
}
|
||||
static inline int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline void kvm_s390_reset_vcpu(S390CPU *cpu)
|
||||
{
|
||||
}
|
||||
static inline int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit,
|
||||
uint64_t *hw_limit)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu)
|
||||
{
|
||||
}
|
||||
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 int kvm_s390_get_gs(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void kvm_s390_crypto_reset(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
return kvm_s390_set_mem_limit(kvm_state, new_limit, hw_limit);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void s390_cmma_reset(void)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
kvm_s390_cmma_reset();
|
||||
}
|
||||
}
|
||||
|
||||
static inline int s390_cpu_restart(S390CPU *cpu)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
return kvm_s390_cpu_restart(cpu);
|
||||
}
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int s390_get_memslot_count(KVMState *s)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
return kvm_s390_get_memslot_count(s);
|
||||
} else {
|
||||
return MAX_AVAIL_SLOTS;
|
||||
}
|
||||
}
|
||||
|
||||
void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr,
|
||||
uint32_t io_int_parm, uint32_t io_int_word);
|
||||
void s390_crw_mchk(void);
|
||||
|
||||
static inline int s390_assign_subch_ioeventfd(EventNotifier *notifier,
|
||||
uint32_t sch_id, int vq,
|
||||
bool assign)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
return kvm_s390_assign_subch_ioeventfd(notifier, sch_id, vq, assign);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void s390_crypto_reset(void)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
kvm_s390_crypto_reset();
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool s390_get_squash_mcss(void)
|
||||
{
|
||||
if (object_property_get_bool(OBJECT(qdev_get_machine()), "s390-squash-mcss",
|
||||
NULL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* machine check interruption code */
|
||||
|
||||
/* subclasses */
|
||||
@ -1349,4 +658,72 @@ static inline bool s390_get_squash_mcss(void)
|
||||
#define MCIC_VB_CT 0x0000000000020000ULL
|
||||
#define MCIC_VB_CC 0x0000000000010000ULL
|
||||
|
||||
|
||||
/* cpu.c */
|
||||
int s390_get_clock(uint8_t *tod_high, uint64_t *tod_low);
|
||||
int s390_set_clock(uint8_t *tod_high, uint64_t *tod_low);
|
||||
void s390_crypto_reset(void);
|
||||
bool s390_get_squash_mcss(void);
|
||||
int s390_get_memslot_count(void);
|
||||
int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit);
|
||||
void s390_cmma_reset(void);
|
||||
int s390_cpu_restart(S390CPU *cpu);
|
||||
void s390_enable_css_support(S390CPU *cpu);
|
||||
int s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch_id,
|
||||
int vq, bool assign);
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu);
|
||||
#else
|
||||
static inline unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_USER_ONLY */
|
||||
|
||||
|
||||
/* cpu_models.c */
|
||||
void s390_cpu_list(FILE *f, fprintf_function cpu_fprintf);
|
||||
#define cpu_list s390_cpu_list
|
||||
const char *s390_default_cpu_model_name(void);
|
||||
|
||||
|
||||
/* helper.c */
|
||||
S390CPU *cpu_s390x_init(const char *cpu_model);
|
||||
#define cpu_init(model) CPU(cpu_s390x_init(model))
|
||||
S390CPU *s390x_new_cpu(const char *cpu_model, int64_t id, Error **errp);
|
||||
/* you can call this signal handler from your SIGBUS and SIGSEGV
|
||||
signal handlers to inform the virtual CPU of exceptions. non zero
|
||||
is returned if the signal was handled by the virtual CPU. */
|
||||
int cpu_s390x_signal_handler(int host_signum, void *pinfo, void *puc);
|
||||
#define cpu_signal_handler cpu_s390x_signal_handler
|
||||
|
||||
|
||||
/* interrupt.c */
|
||||
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);
|
||||
/* automatically detect the instruction length */
|
||||
#define ILEN_AUTO 0xff
|
||||
void program_interrupt(CPUS390XState *env, uint32_t code, int ilen);
|
||||
/* service interrupts are floating therefore we must not pass an cpustate */
|
||||
void s390_sclp_extint(uint32_t parm);
|
||||
|
||||
|
||||
/* mmu_helper.c */
|
||||
int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, uint8_t ar, void *hostbuf,
|
||||
int len, bool is_write);
|
||||
#define s390_cpu_virt_mem_read(cpu, laddr, ar, dest, len) \
|
||||
s390_cpu_virt_mem_rw(cpu, laddr, ar, dest, len, false)
|
||||
#define s390_cpu_virt_mem_write(cpu, laddr, ar, dest, len) \
|
||||
s390_cpu_virt_mem_rw(cpu, laddr, ar, dest, len, true)
|
||||
#define s390_cpu_virt_mem_check_write(cpu, laddr, ar, len) \
|
||||
s390_cpu_virt_mem_rw(cpu, laddr, ar, NULL, len, true)
|
||||
|
||||
|
||||
/* outside of target/s390x/ */
|
||||
S390CPU *s390_cpu_addr2state(uint16_t cpu_addr);
|
||||
extern void subsystem_reset(void);
|
||||
int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code);
|
||||
int s390_virtio_hypercall(CPUS390XState *env);
|
||||
|
||||
#endif
|
||||
|
@ -12,6 +12,9 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "kvm_s390x.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "gen-features.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/visitor.h"
|
||||
@ -1200,6 +1203,14 @@ ObjectClass *s390_cpu_class_by_name(const char *name)
|
||||
return oc;
|
||||
}
|
||||
|
||||
const char *s390_default_cpu_model_name(void)
|
||||
{
|
||||
if (kvm_enabled()) {
|
||||
return "host";
|
||||
}
|
||||
return "qemu";
|
||||
}
|
||||
|
||||
static const TypeInfo qemu_s390_cpu_type_info = {
|
||||
.name = S390_CPU_TYPE_NAME("qemu"),
|
||||
.parent = TYPE_S390_CPU,
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "hw/watchdog/wdt_diag288.h"
|
||||
@ -39,6 +40,13 @@ static int modified_clear_reset(S390CPU *cpu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void s390_do_cpu_reset(CPUState *cs, run_on_cpu_data arg)
|
||||
{
|
||||
S390CPUClass *scc = S390_CPU_GET_CLASS(cs);
|
||||
|
||||
scc->cpu_reset(cs);
|
||||
}
|
||||
|
||||
static int load_normal_reset(S390CPU *cpu)
|
||||
{
|
||||
S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
@ -68,6 +69,20 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
|
||||
|
||||
#else /* !CONFIG_USER_ONLY */
|
||||
|
||||
static inline uint64_t cpu_mmu_idx_to_asc(int mmu_idx)
|
||||
{
|
||||
switch (mmu_idx) {
|
||||
case MMU_PRIMARY_IDX:
|
||||
return PSW_ASC_PRIMARY;
|
||||
case MMU_SECONDARY_IDX:
|
||||
return PSW_ASC_SECONDARY;
|
||||
case MMU_HOME_IDX:
|
||||
return PSW_ASC_HOME;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr,
|
||||
int rw, int mmu_idx)
|
||||
{
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/gdbstub.h"
|
||||
#include "qemu/bitops.h"
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "exec/gdbstub.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "exec/exec-all.h"
|
||||
@ -352,3 +353,51 @@ void s390_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
|
||||
|
||||
cpu_fprintf(f, "\n");
|
||||
}
|
||||
|
||||
const char *cc_name(enum cc_op cc_op)
|
||||
{
|
||||
static const char * const cc_names[] = {
|
||||
[CC_OP_CONST0] = "CC_OP_CONST0",
|
||||
[CC_OP_CONST1] = "CC_OP_CONST1",
|
||||
[CC_OP_CONST2] = "CC_OP_CONST2",
|
||||
[CC_OP_CONST3] = "CC_OP_CONST3",
|
||||
[CC_OP_DYNAMIC] = "CC_OP_DYNAMIC",
|
||||
[CC_OP_STATIC] = "CC_OP_STATIC",
|
||||
[CC_OP_NZ] = "CC_OP_NZ",
|
||||
[CC_OP_LTGT_32] = "CC_OP_LTGT_32",
|
||||
[CC_OP_LTGT_64] = "CC_OP_LTGT_64",
|
||||
[CC_OP_LTUGTU_32] = "CC_OP_LTUGTU_32",
|
||||
[CC_OP_LTUGTU_64] = "CC_OP_LTUGTU_64",
|
||||
[CC_OP_LTGT0_32] = "CC_OP_LTGT0_32",
|
||||
[CC_OP_LTGT0_64] = "CC_OP_LTGT0_64",
|
||||
[CC_OP_ADD_64] = "CC_OP_ADD_64",
|
||||
[CC_OP_ADDU_64] = "CC_OP_ADDU_64",
|
||||
[CC_OP_ADDC_64] = "CC_OP_ADDC_64",
|
||||
[CC_OP_SUB_64] = "CC_OP_SUB_64",
|
||||
[CC_OP_SUBU_64] = "CC_OP_SUBU_64",
|
||||
[CC_OP_SUBB_64] = "CC_OP_SUBB_64",
|
||||
[CC_OP_ABS_64] = "CC_OP_ABS_64",
|
||||
[CC_OP_NABS_64] = "CC_OP_NABS_64",
|
||||
[CC_OP_ADD_32] = "CC_OP_ADD_32",
|
||||
[CC_OP_ADDU_32] = "CC_OP_ADDU_32",
|
||||
[CC_OP_ADDC_32] = "CC_OP_ADDC_32",
|
||||
[CC_OP_SUB_32] = "CC_OP_SUB_32",
|
||||
[CC_OP_SUBU_32] = "CC_OP_SUBU_32",
|
||||
[CC_OP_SUBB_32] = "CC_OP_SUBB_32",
|
||||
[CC_OP_ABS_32] = "CC_OP_ABS_32",
|
||||
[CC_OP_NABS_32] = "CC_OP_NABS_32",
|
||||
[CC_OP_COMP_32] = "CC_OP_COMP_32",
|
||||
[CC_OP_COMP_64] = "CC_OP_COMP_64",
|
||||
[CC_OP_TM_32] = "CC_OP_TM_32",
|
||||
[CC_OP_TM_64] = "CC_OP_TM_64",
|
||||
[CC_OP_NZ_F32] = "CC_OP_NZ_F32",
|
||||
[CC_OP_NZ_F64] = "CC_OP_NZ_F64",
|
||||
[CC_OP_NZ_F128] = "CC_OP_NZ_F128",
|
||||
[CC_OP_ICM] = "CC_OP_ICM",
|
||||
[CC_OP_SLA_32] = "CC_OP_SLA_32",
|
||||
[CC_OP_SLA_64] = "CC_OP_SLA_64",
|
||||
[CC_OP_FLOGR] = "CC_OP_FLOGR",
|
||||
};
|
||||
|
||||
return cc_names[cc_op];
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
391
target/s390x/internal.h
Normal file
391
target/s390x/internal.h
Normal file
@ -0,0 +1,391 @@
|
||||
/*
|
||||
* s390x internal definitions and helpers
|
||||
*
|
||||
* Copyright (c) 2009 Ulrich Hecht
|
||||
*
|
||||
* 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 S390X_INTERNAL_H
|
||||
#define S390X_INTERNAL_H
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
typedef struct LowCore {
|
||||
/* prefix area: defined by architecture */
|
||||
uint32_t ccw1[2]; /* 0x000 */
|
||||
uint32_t ccw2[4]; /* 0x008 */
|
||||
uint8_t pad1[0x80 - 0x18]; /* 0x018 */
|
||||
uint32_t ext_params; /* 0x080 */
|
||||
uint16_t cpu_addr; /* 0x084 */
|
||||
uint16_t ext_int_code; /* 0x086 */
|
||||
uint16_t svc_ilen; /* 0x088 */
|
||||
uint16_t svc_code; /* 0x08a */
|
||||
uint16_t pgm_ilen; /* 0x08c */
|
||||
uint16_t pgm_code; /* 0x08e */
|
||||
uint32_t data_exc_code; /* 0x090 */
|
||||
uint16_t mon_class_num; /* 0x094 */
|
||||
uint16_t per_perc_atmid; /* 0x096 */
|
||||
uint64_t per_address; /* 0x098 */
|
||||
uint8_t exc_access_id; /* 0x0a0 */
|
||||
uint8_t per_access_id; /* 0x0a1 */
|
||||
uint8_t op_access_id; /* 0x0a2 */
|
||||
uint8_t ar_access_id; /* 0x0a3 */
|
||||
uint8_t pad2[0xA8 - 0xA4]; /* 0x0a4 */
|
||||
uint64_t trans_exc_code; /* 0x0a8 */
|
||||
uint64_t monitor_code; /* 0x0b0 */
|
||||
uint16_t subchannel_id; /* 0x0b8 */
|
||||
uint16_t subchannel_nr; /* 0x0ba */
|
||||
uint32_t io_int_parm; /* 0x0bc */
|
||||
uint32_t io_int_word; /* 0x0c0 */
|
||||
uint8_t pad3[0xc8 - 0xc4]; /* 0x0c4 */
|
||||
uint32_t stfl_fac_list; /* 0x0c8 */
|
||||
uint8_t pad4[0xe8 - 0xcc]; /* 0x0cc */
|
||||
uint32_t mcck_interruption_code[2]; /* 0x0e8 */
|
||||
uint8_t pad5[0xf4 - 0xf0]; /* 0x0f0 */
|
||||
uint32_t external_damage_code; /* 0x0f4 */
|
||||
uint64_t failing_storage_address; /* 0x0f8 */
|
||||
uint8_t pad6[0x110 - 0x100]; /* 0x100 */
|
||||
uint64_t per_breaking_event_addr; /* 0x110 */
|
||||
uint8_t pad7[0x120 - 0x118]; /* 0x118 */
|
||||
PSW restart_old_psw; /* 0x120 */
|
||||
PSW external_old_psw; /* 0x130 */
|
||||
PSW svc_old_psw; /* 0x140 */
|
||||
PSW program_old_psw; /* 0x150 */
|
||||
PSW mcck_old_psw; /* 0x160 */
|
||||
PSW io_old_psw; /* 0x170 */
|
||||
uint8_t pad8[0x1a0 - 0x180]; /* 0x180 */
|
||||
PSW restart_new_psw; /* 0x1a0 */
|
||||
PSW external_new_psw; /* 0x1b0 */
|
||||
PSW svc_new_psw; /* 0x1c0 */
|
||||
PSW program_new_psw; /* 0x1d0 */
|
||||
PSW mcck_new_psw; /* 0x1e0 */
|
||||
PSW io_new_psw; /* 0x1f0 */
|
||||
PSW return_psw; /* 0x200 */
|
||||
uint8_t irb[64]; /* 0x210 */
|
||||
uint64_t sync_enter_timer; /* 0x250 */
|
||||
uint64_t async_enter_timer; /* 0x258 */
|
||||
uint64_t exit_timer; /* 0x260 */
|
||||
uint64_t last_update_timer; /* 0x268 */
|
||||
uint64_t user_timer; /* 0x270 */
|
||||
uint64_t system_timer; /* 0x278 */
|
||||
uint64_t last_update_clock; /* 0x280 */
|
||||
uint64_t steal_clock; /* 0x288 */
|
||||
PSW return_mcck_psw; /* 0x290 */
|
||||
uint8_t pad9[0xc00 - 0x2a0]; /* 0x2a0 */
|
||||
/* System info area */
|
||||
uint64_t save_area[16]; /* 0xc00 */
|
||||
uint8_t pad10[0xd40 - 0xc80]; /* 0xc80 */
|
||||
uint64_t kernel_stack; /* 0xd40 */
|
||||
uint64_t thread_info; /* 0xd48 */
|
||||
uint64_t async_stack; /* 0xd50 */
|
||||
uint64_t kernel_asce; /* 0xd58 */
|
||||
uint64_t user_asce; /* 0xd60 */
|
||||
uint64_t panic_stack; /* 0xd68 */
|
||||
uint64_t user_exec_asce; /* 0xd70 */
|
||||
uint8_t pad11[0xdc0 - 0xd78]; /* 0xd78 */
|
||||
|
||||
/* SMP info area: defined by DJB */
|
||||
uint64_t clock_comparator; /* 0xdc0 */
|
||||
uint64_t ext_call_fast; /* 0xdc8 */
|
||||
uint64_t percpu_offset; /* 0xdd0 */
|
||||
uint64_t current_task; /* 0xdd8 */
|
||||
uint32_t softirq_pending; /* 0xde0 */
|
||||
uint32_t pad_0x0de4; /* 0xde4 */
|
||||
uint64_t int_clock; /* 0xde8 */
|
||||
uint8_t pad12[0xe00 - 0xdf0]; /* 0xdf0 */
|
||||
|
||||
/* 0xe00 is used as indicator for dump tools */
|
||||
/* whether the kernel died with panic() or not */
|
||||
uint32_t panic_magic; /* 0xe00 */
|
||||
|
||||
uint8_t pad13[0x11b8 - 0xe04]; /* 0xe04 */
|
||||
|
||||
/* 64 bit extparam used for pfault, diag 250 etc */
|
||||
uint64_t ext_params2; /* 0x11B8 */
|
||||
|
||||
uint8_t pad14[0x1200 - 0x11C0]; /* 0x11C0 */
|
||||
|
||||
/* System info area */
|
||||
|
||||
uint64_t floating_pt_save_area[16]; /* 0x1200 */
|
||||
uint64_t gpregs_save_area[16]; /* 0x1280 */
|
||||
uint32_t st_status_fixed_logout[4]; /* 0x1300 */
|
||||
uint8_t pad15[0x1318 - 0x1310]; /* 0x1310 */
|
||||
uint32_t prefixreg_save_area; /* 0x1318 */
|
||||
uint32_t fpt_creg_save_area; /* 0x131c */
|
||||
uint8_t pad16[0x1324 - 0x1320]; /* 0x1320 */
|
||||
uint32_t tod_progreg_save_area; /* 0x1324 */
|
||||
uint32_t cpu_timer_save_area[2]; /* 0x1328 */
|
||||
uint32_t clock_comp_save_area[2]; /* 0x1330 */
|
||||
uint8_t pad17[0x1340 - 0x1338]; /* 0x1338 */
|
||||
uint32_t access_regs_save_area[16]; /* 0x1340 */
|
||||
uint64_t cregs_save_area[16]; /* 0x1380 */
|
||||
|
||||
/* align to the top of the prefix area */
|
||||
|
||||
uint8_t pad18[0x2000 - 0x1400]; /* 0x1400 */
|
||||
} QEMU_PACKED LowCore;
|
||||
#endif /* CONFIG_USER_ONLY */
|
||||
|
||||
#define MAX_ILEN 6
|
||||
|
||||
/* While the PoO talks about ILC (a number between 1-3) what is actually
|
||||
stored in LowCore is shifted left one bit (an even between 2-6). As
|
||||
this is the actual length of the insn and therefore more useful, that
|
||||
is what we want to pass around and manipulate. To make sure that we
|
||||
have applied this distinction universally, rename the "ILC" to "ILEN". */
|
||||
static inline int get_ilen(uint8_t opc)
|
||||
{
|
||||
switch (opc >> 6) {
|
||||
case 0:
|
||||
return 2;
|
||||
case 1:
|
||||
case 2:
|
||||
return 4;
|
||||
default:
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute the ATMID field that is stored in the per_perc_atmid lowcore
|
||||
entry when a PER exception is triggered. */
|
||||
static inline uint8_t get_per_atmid(CPUS390XState *env)
|
||||
{
|
||||
return ((env->psw.mask & PSW_MASK_64) ? (1 << 7) : 0) |
|
||||
(1 << 6) |
|
||||
((env->psw.mask & PSW_MASK_32) ? (1 << 5) : 0) |
|
||||
((env->psw.mask & PSW_MASK_DAT) ? (1 << 4) : 0) |
|
||||
((env->psw.mask & PSW_ASC_SECONDARY) ? (1 << 3) : 0) |
|
||||
((env->psw.mask & PSW_ASC_ACCREG) ? (1 << 2) : 0);
|
||||
}
|
||||
|
||||
/* CC optimization */
|
||||
|
||||
/* Instead of computing the condition codes after each x86 instruction,
|
||||
* QEMU just stores the result (called CC_DST), the type of operation
|
||||
* (called CC_OP) and whatever operands are needed (CC_SRC and possibly
|
||||
* CC_VR). When the condition codes are needed, the condition codes can
|
||||
* be calculated using this information. Condition codes are not generated
|
||||
* if they are only needed for conditional branches.
|
||||
*/
|
||||
enum cc_op {
|
||||
CC_OP_CONST0 = 0, /* CC is 0 */
|
||||
CC_OP_CONST1, /* CC is 1 */
|
||||
CC_OP_CONST2, /* CC is 2 */
|
||||
CC_OP_CONST3, /* CC is 3 */
|
||||
|
||||
CC_OP_DYNAMIC, /* CC calculation defined by env->cc_op */
|
||||
CC_OP_STATIC, /* CC value is env->cc_op */
|
||||
|
||||
CC_OP_NZ, /* env->cc_dst != 0 */
|
||||
CC_OP_LTGT_32, /* signed less/greater than (32bit) */
|
||||
CC_OP_LTGT_64, /* signed less/greater than (64bit) */
|
||||
CC_OP_LTUGTU_32, /* unsigned less/greater than (32bit) */
|
||||
CC_OP_LTUGTU_64, /* unsigned less/greater than (64bit) */
|
||||
CC_OP_LTGT0_32, /* signed less/greater than 0 (32bit) */
|
||||
CC_OP_LTGT0_64, /* signed less/greater than 0 (64bit) */
|
||||
|
||||
CC_OP_ADD_64, /* overflow on add (64bit) */
|
||||
CC_OP_ADDU_64, /* overflow on unsigned add (64bit) */
|
||||
CC_OP_ADDC_64, /* overflow on unsigned add-carry (64bit) */
|
||||
CC_OP_SUB_64, /* overflow on subtraction (64bit) */
|
||||
CC_OP_SUBU_64, /* overflow on unsigned subtraction (64bit) */
|
||||
CC_OP_SUBB_64, /* overflow on unsigned sub-borrow (64bit) */
|
||||
CC_OP_ABS_64, /* sign eval on abs (64bit) */
|
||||
CC_OP_NABS_64, /* sign eval on nabs (64bit) */
|
||||
|
||||
CC_OP_ADD_32, /* overflow on add (32bit) */
|
||||
CC_OP_ADDU_32, /* overflow on unsigned add (32bit) */
|
||||
CC_OP_ADDC_32, /* overflow on unsigned add-carry (32bit) */
|
||||
CC_OP_SUB_32, /* overflow on subtraction (32bit) */
|
||||
CC_OP_SUBU_32, /* overflow on unsigned subtraction (32bit) */
|
||||
CC_OP_SUBB_32, /* overflow on unsigned sub-borrow (32bit) */
|
||||
CC_OP_ABS_32, /* sign eval on abs (64bit) */
|
||||
CC_OP_NABS_32, /* sign eval on nabs (64bit) */
|
||||
|
||||
CC_OP_COMP_32, /* complement */
|
||||
CC_OP_COMP_64, /* complement */
|
||||
|
||||
CC_OP_TM_32, /* test under mask (32bit) */
|
||||
CC_OP_TM_64, /* test under mask (64bit) */
|
||||
|
||||
CC_OP_NZ_F32, /* FP dst != 0 (32bit) */
|
||||
CC_OP_NZ_F64, /* FP dst != 0 (64bit) */
|
||||
CC_OP_NZ_F128, /* FP dst != 0 (128bit) */
|
||||
|
||||
CC_OP_ICM, /* insert characters under mask */
|
||||
CC_OP_SLA_32, /* Calculate shift left signed (32bit) */
|
||||
CC_OP_SLA_64, /* Calculate shift left signed (64bit) */
|
||||
CC_OP_FLOGR, /* find leftmost one */
|
||||
CC_OP_MAX
|
||||
};
|
||||
|
||||
/* The value of the TOD clock for 1.1.1970. */
|
||||
#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
|
||||
|
||||
/* Converts ns to s390's clock format */
|
||||
static inline uint64_t time2tod(uint64_t ns)
|
||||
{
|
||||
return (ns << 9) / 125;
|
||||
}
|
||||
|
||||
/* Converts s390's clock format to ns */
|
||||
static inline uint64_t tod2time(uint64_t t)
|
||||
{
|
||||
return (t * 125) >> 9;
|
||||
}
|
||||
|
||||
static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb,
|
||||
uint8_t *ar)
|
||||
{
|
||||
hwaddr addr = 0;
|
||||
uint8_t reg;
|
||||
|
||||
reg = ipb >> 28;
|
||||
if (reg > 0) {
|
||||
addr = env->regs[reg];
|
||||
}
|
||||
addr += (ipb >> 16) & 0xfff;
|
||||
if (ar) {
|
||||
*ar = reg;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* Base/displacement are at the same locations. */
|
||||
#define decode_basedisp_rs decode_basedisp_s
|
||||
|
||||
static inline void s390_do_cpu_full_reset(CPUState *cs, run_on_cpu_data arg)
|
||||
{
|
||||
cpu_reset(cs);
|
||||
}
|
||||
|
||||
static inline uint8_t s390_cpu_get_state(S390CPU *cpu)
|
||||
{
|
||||
return cpu->env.cpu_state;
|
||||
}
|
||||
|
||||
|
||||
/* arch_dump.c */
|
||||
int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||
int cpuid, void *opaque);
|
||||
|
||||
|
||||
/* cc_helper.c */
|
||||
const char *cc_name(enum cc_op cc_op);
|
||||
void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr);
|
||||
uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
|
||||
uint64_t vr);
|
||||
|
||||
|
||||
/* cpu.c */
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
unsigned int s390_cpu_halt(S390CPU *cpu);
|
||||
void s390_cpu_unhalt(S390CPU *cpu);
|
||||
#else
|
||||
static inline unsigned int s390_cpu_halt(S390CPU *cpu)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void s390_cpu_unhalt(S390CPU *cpu)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_USER_ONLY */
|
||||
|
||||
|
||||
/* cpu_models.c */
|
||||
void s390_cpu_model_register_props(Object *obj);
|
||||
void s390_cpu_model_class_register_props(ObjectClass *oc);
|
||||
void s390_realize_cpu_model(CPUState *cs, Error **errp);
|
||||
ObjectClass *s390_cpu_class_by_name(const char *name);
|
||||
|
||||
|
||||
/* excp_helper.c */
|
||||
void s390x_cpu_debug_excp_handler(CPUState *cs);
|
||||
void s390_cpu_do_interrupt(CPUState *cpu);
|
||||
bool s390_cpu_exec_interrupt(CPUState *cpu, int int_req);
|
||||
int s390_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
|
||||
int mmu_idx);
|
||||
void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
|
||||
MMUAccessType access_type,
|
||||
int mmu_idx, uintptr_t retaddr);
|
||||
|
||||
|
||||
/* fpu_helper.c */
|
||||
uint32_t set_cc_nz_f32(float32 v);
|
||||
uint32_t set_cc_nz_f64(float64 v);
|
||||
uint32_t set_cc_nz_f128(float128 v);
|
||||
|
||||
|
||||
/* gdbstub.c */
|
||||
int s390_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
int s390_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
void s390_cpu_gdb_init(CPUState *cs);
|
||||
|
||||
|
||||
/* helper.c */
|
||||
void s390_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
|
||||
int flags);
|
||||
hwaddr s390_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
|
||||
hwaddr s390_cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr);
|
||||
uint64_t get_psw_mask(CPUS390XState *env);
|
||||
void s390_cpu_recompute_watchpoints(CPUState *cs);
|
||||
void s390x_tod_timer(void *opaque);
|
||||
void s390x_cpu_timer(void *opaque);
|
||||
S390CPU *cpu_s390x_create(const char *cpu_model, Error **errp);
|
||||
void do_restart_interrupt(CPUS390XState *env);
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
LowCore *cpu_map_lowcore(CPUS390XState *env);
|
||||
void cpu_unmap_lowcore(LowCore *lowcore);
|
||||
#endif /* CONFIG_USER_ONLY */
|
||||
|
||||
|
||||
/* interrupt.c */
|
||||
void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilen);
|
||||
void cpu_inject_ext(S390CPU *cpu, uint32_t code, uint32_t param,
|
||||
uint64_t param64);
|
||||
|
||||
|
||||
/* ioinst.c */
|
||||
void ioinst_handle_xsch(S390CPU *cpu, uint64_t reg1);
|
||||
void ioinst_handle_csch(S390CPU *cpu, uint64_t reg1);
|
||||
void ioinst_handle_hsch(S390CPU *cpu, uint64_t reg1);
|
||||
void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
|
||||
void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
|
||||
void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb);
|
||||
void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
|
||||
int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
|
||||
void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb);
|
||||
int ioinst_handle_tpi(S390CPU *cpu, uint32_t ipb);
|
||||
void ioinst_handle_schm(S390CPU *cpu, uint64_t reg1, uint64_t reg2,
|
||||
uint32_t ipb);
|
||||
void ioinst_handle_rsch(S390CPU *cpu, uint64_t reg1);
|
||||
void ioinst_handle_rchp(S390CPU *cpu, uint64_t reg1);
|
||||
void ioinst_handle_sal(S390CPU *cpu, uint64_t reg1);
|
||||
|
||||
|
||||
/* mem_helper.c */
|
||||
target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr);
|
||||
|
||||
|
||||
/* mmu_helper.c */
|
||||
int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
|
||||
target_ulong *raddr, int *flags, bool exc);
|
||||
|
||||
|
||||
/* misc_helper.c */
|
||||
void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp,
|
||||
uintptr_t retaddr);
|
||||
int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3);
|
||||
void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3);
|
||||
|
||||
|
||||
/* translate.c */
|
||||
void s390x_translate_init(void);
|
||||
|
||||
#endif /* S390X_INTERNAL_H */
|
@ -10,6 +10,8 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "cpu.h"
|
||||
#include "kvm_s390x.h"
|
||||
#include "internal.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "hw/s390x/ioinst.h"
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "hw/s390x/ioinst.h"
|
||||
#include "trace.h"
|
||||
#include "hw/s390x/s390-pci-bus.h"
|
||||
@ -599,6 +600,22 @@ static int chsc_sei_nt0_have_event(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int chsc_sei_nt2_get_event(void *res)
|
||||
{
|
||||
if (s390_has_feat(S390_FEAT_ZPCI)) {
|
||||
return pci_chsc_sei_nt2_get_event(res);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int chsc_sei_nt2_have_event(void)
|
||||
{
|
||||
if (s390_has_feat(S390_FEAT_ZPCI)) {
|
||||
return pci_chsc_sei_nt2_have_event();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CHSC_SEI_NT0 (1ULL << 63)
|
||||
#define CHSC_SEI_NT2 (1ULL << 61)
|
||||
static void ioinst_handle_chsc_sei(ChscReq *req, ChscResp *res)
|
||||
|
111
target/s390x/kvm-stub.c
Normal file
111
target/s390x/kvm-stub.c
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* QEMU KVM support -- s390x specific function stubs.
|
||||
*
|
||||
* Copyright (c) 2009 Ulrich Hecht
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "kvm_s390x.h"
|
||||
|
||||
void kvm_s390_service_interrupt(uint32_t parm)
|
||||
{
|
||||
}
|
||||
|
||||
void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code)
|
||||
{
|
||||
}
|
||||
|
||||
int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf,
|
||||
int len, bool is_write)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code)
|
||||
{
|
||||
}
|
||||
|
||||
void kvm_s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr,
|
||||
uint32_t io_int_parm, uint32_t io_int_word)
|
||||
{
|
||||
}
|
||||
|
||||
void kvm_s390_crw_mchk(void)
|
||||
{
|
||||
}
|
||||
|
||||
int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_s390_get_ri(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_s390_get_gs(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_low)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
void kvm_s390_enable_css_support(S390CPU *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch,
|
||||
int vq, bool assign)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int kvm_s390_cpu_restart(S390CPU *cpu)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
void kvm_s390_cmma_reset(void)
|
||||
{
|
||||
}
|
||||
|
||||
int kvm_s390_get_memslot_count(void)
|
||||
{
|
||||
return MAX_AVAIL_SLOTS;
|
||||
}
|
||||
|
||||
void kvm_s390_reset_vcpu(S390CPU *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
int kvm_s390_set_mem_limit(uint64_t new_limit, uint64_t *hw_limit)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kvm_s390_crypto_reset(void)
|
||||
{
|
||||
}
|
@ -29,6 +29,8 @@
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "kvm_s390x.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
@ -145,7 +147,7 @@ static int active_cmma;
|
||||
|
||||
static void *legacy_s390_alloc(size_t size, uint64_t *align);
|
||||
|
||||
static int kvm_s390_query_mem_limit(KVMState *s, uint64_t *memory_limit)
|
||||
static int kvm_s390_query_mem_limit(uint64_t *memory_limit)
|
||||
{
|
||||
struct kvm_device_attr attr = {
|
||||
.group = KVM_S390_VM_MEM_CTRL,
|
||||
@ -153,10 +155,10 @@ static int kvm_s390_query_mem_limit(KVMState *s, uint64_t *memory_limit)
|
||||
.addr = (uint64_t) memory_limit,
|
||||
};
|
||||
|
||||
return kvm_vm_ioctl(s, KVM_GET_DEVICE_ATTR, &attr);
|
||||
return kvm_vm_ioctl(kvm_state, KVM_GET_DEVICE_ATTR, &attr);
|
||||
}
|
||||
|
||||
int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, uint64_t *hw_limit)
|
||||
int kvm_s390_set_mem_limit(uint64_t new_limit, uint64_t *hw_limit)
|
||||
{
|
||||
int rc;
|
||||
|
||||
@ -166,18 +168,18 @@ int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, uint64_t *hw_limit)
|
||||
.addr = (uint64_t) &new_limit,
|
||||
};
|
||||
|
||||
if (!kvm_vm_check_mem_attr(s, KVM_S390_VM_MEM_LIMIT_SIZE)) {
|
||||
if (!kvm_vm_check_mem_attr(kvm_state, KVM_S390_VM_MEM_LIMIT_SIZE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = kvm_s390_query_mem_limit(s, hw_limit);
|
||||
rc = kvm_s390_query_mem_limit(hw_limit);
|
||||
if (rc) {
|
||||
return rc;
|
||||
} else if (*hw_limit < new_limit) {
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
return kvm_vm_ioctl(s, KVM_SET_DEVICE_ATTR, &attr);
|
||||
return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr);
|
||||
}
|
||||
|
||||
int kvm_s390_cmma_active(void)
|
||||
@ -1191,7 +1193,11 @@ static int kvm_clp_service_call(S390CPU *cpu, struct kvm_run *run)
|
||||
{
|
||||
uint8_t r2 = (run->s390_sieic.ipb & 0x000f0000) >> 16;
|
||||
|
||||
return clp_service_call(cpu, r2);
|
||||
if (s390_has_feat(S390_FEAT_ZPCI)) {
|
||||
return clp_service_call(cpu, r2);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int kvm_pcilg_service_call(S390CPU *cpu, struct kvm_run *run)
|
||||
@ -1199,7 +1205,11 @@ static int kvm_pcilg_service_call(S390CPU *cpu, struct kvm_run *run)
|
||||
uint8_t r1 = (run->s390_sieic.ipb & 0x00f00000) >> 20;
|
||||
uint8_t r2 = (run->s390_sieic.ipb & 0x000f0000) >> 16;
|
||||
|
||||
return pcilg_service_call(cpu, r1, r2);
|
||||
if (s390_has_feat(S390_FEAT_ZPCI)) {
|
||||
return pcilg_service_call(cpu, r1, r2);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int kvm_pcistg_service_call(S390CPU *cpu, struct kvm_run *run)
|
||||
@ -1207,7 +1217,11 @@ static int kvm_pcistg_service_call(S390CPU *cpu, struct kvm_run *run)
|
||||
uint8_t r1 = (run->s390_sieic.ipb & 0x00f00000) >> 20;
|
||||
uint8_t r2 = (run->s390_sieic.ipb & 0x000f0000) >> 16;
|
||||
|
||||
return pcistg_service_call(cpu, r1, r2);
|
||||
if (s390_has_feat(S390_FEAT_ZPCI)) {
|
||||
return pcistg_service_call(cpu, r1, r2);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int kvm_stpcifc_service_call(S390CPU *cpu, struct kvm_run *run)
|
||||
@ -1216,10 +1230,14 @@ static int kvm_stpcifc_service_call(S390CPU *cpu, struct kvm_run *run)
|
||||
uint64_t fiba;
|
||||
uint8_t ar;
|
||||
|
||||
cpu_synchronize_state(CPU(cpu));
|
||||
fiba = get_base_disp_rxy(cpu, run, &ar);
|
||||
if (s390_has_feat(S390_FEAT_ZPCI)) {
|
||||
cpu_synchronize_state(CPU(cpu));
|
||||
fiba = get_base_disp_rxy(cpu, run, &ar);
|
||||
|
||||
return stpcifc_service_call(cpu, r1, fiba, ar);
|
||||
return stpcifc_service_call(cpu, r1, fiba, ar);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int kvm_sic_service_call(S390CPU *cpu, struct kvm_run *run)
|
||||
@ -1247,7 +1265,11 @@ static int kvm_rpcit_service_call(S390CPU *cpu, struct kvm_run *run)
|
||||
uint8_t r1 = (run->s390_sieic.ipb & 0x00f00000) >> 20;
|
||||
uint8_t r2 = (run->s390_sieic.ipb & 0x000f0000) >> 16;
|
||||
|
||||
return rpcit_service_call(cpu, r1, r2);
|
||||
if (s390_has_feat(S390_FEAT_ZPCI)) {
|
||||
return rpcit_service_call(cpu, r1, r2);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int kvm_pcistb_service_call(S390CPU *cpu, struct kvm_run *run)
|
||||
@ -1257,10 +1279,14 @@ static int kvm_pcistb_service_call(S390CPU *cpu, struct kvm_run *run)
|
||||
uint64_t gaddr;
|
||||
uint8_t ar;
|
||||
|
||||
cpu_synchronize_state(CPU(cpu));
|
||||
gaddr = get_base_disp_rsy(cpu, run, &ar);
|
||||
if (s390_has_feat(S390_FEAT_ZPCI)) {
|
||||
cpu_synchronize_state(CPU(cpu));
|
||||
gaddr = get_base_disp_rsy(cpu, run, &ar);
|
||||
|
||||
return pcistb_service_call(cpu, r1, r3, gaddr, ar);
|
||||
return pcistb_service_call(cpu, r1, r3, gaddr, ar);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int kvm_mpcifc_service_call(S390CPU *cpu, struct kvm_run *run)
|
||||
@ -1269,10 +1295,14 @@ static int kvm_mpcifc_service_call(S390CPU *cpu, struct kvm_run *run)
|
||||
uint64_t fiba;
|
||||
uint8_t ar;
|
||||
|
||||
cpu_synchronize_state(CPU(cpu));
|
||||
fiba = get_base_disp_rxy(cpu, run, &ar);
|
||||
if (s390_has_feat(S390_FEAT_ZPCI)) {
|
||||
cpu_synchronize_state(CPU(cpu));
|
||||
fiba = get_base_disp_rxy(cpu, run, &ar);
|
||||
|
||||
return mpcifc_service_call(cpu, r1, fiba, ar);
|
||||
return mpcifc_service_call(cpu, r1, fiba, ar);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int handle_b9(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
|
||||
@ -2289,9 +2319,9 @@ int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch,
|
||||
return kvm_vm_ioctl(kvm_state, KVM_IOEVENTFD, &kick);
|
||||
}
|
||||
|
||||
int kvm_s390_get_memslot_count(KVMState *s)
|
||||
int kvm_s390_get_memslot_count(void)
|
||||
{
|
||||
return kvm_check_extension(s, KVM_CAP_NR_MEMSLOTS);
|
||||
return kvm_check_extension(kvm_state, KVM_CAP_NR_MEMSLOTS);
|
||||
}
|
||||
|
||||
int kvm_s390_get_ri(void)
|
||||
@ -2662,7 +2692,9 @@ void kvm_s390_get_host_cpu_model(S390CPUModel *model, Error **errp)
|
||||
}
|
||||
|
||||
/* We emulate a zPCI bus and AEN, therefore we don't need HW support */
|
||||
set_bit(S390_FEAT_ZPCI, model->features);
|
||||
if (pci_available) {
|
||||
set_bit(S390_FEAT_ZPCI, model->features);
|
||||
}
|
||||
set_bit(S390_FEAT_ADAPTER_EVENT_NOTIFICATION, model->features);
|
||||
|
||||
if (s390_known_cpu_type(cpu_type)) {
|
||||
|
47
target/s390x/kvm_s390x.h
Normal file
47
target/s390x/kvm_s390x.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* QEMU KVM support -- s390x specific functions.
|
||||
*
|
||||
* Copyright (c) 2009 Ulrich Hecht
|
||||
*
|
||||
* 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 KVM_S390X_H
|
||||
#define KVM_S390X_H
|
||||
|
||||
struct kvm_s390_irq;
|
||||
|
||||
void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq);
|
||||
void kvm_s390_service_interrupt(uint32_t parm);
|
||||
void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq);
|
||||
void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code);
|
||||
int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf,
|
||||
int len, bool is_write);
|
||||
void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code);
|
||||
void kvm_s390_io_interrupt(uint16_t subchannel_id,
|
||||
uint16_t subchannel_nr, uint32_t io_int_parm,
|
||||
uint32_t io_int_word);
|
||||
void kvm_s390_crw_mchk(void);
|
||||
int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state);
|
||||
void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu);
|
||||
int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu);
|
||||
int kvm_s390_get_ri(void);
|
||||
int kvm_s390_get_gs(void);
|
||||
int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock);
|
||||
int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_clock);
|
||||
void kvm_s390_enable_css_support(S390CPU *cpu);
|
||||
int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch,
|
||||
int vq, bool assign);
|
||||
int kvm_s390_cpu_restart(S390CPU *cpu);
|
||||
int kvm_s390_get_memslot_count(void);
|
||||
int kvm_s390_cmma_active(void);
|
||||
void kvm_s390_cmma_reset(void);
|
||||
void kvm_s390_reset_vcpu(S390CPU *cpu);
|
||||
int kvm_s390_set_mem_limit(uint64_t new_limit, uint64_t *hw_limit);
|
||||
void kvm_s390_crypto_reset(void);
|
||||
|
||||
/* implemented outside of target/s390x/ */
|
||||
int kvm_s390_inject_flic(struct kvm_s390_irq *irq);
|
||||
|
||||
#endif /* KVM_S390X_H */
|
@ -17,6 +17,8 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/hw.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "kvm_s390x.h"
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
static int cpu_post_load(void *opaque, int version_id)
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/exec-all.h"
|
||||
@ -56,6 +57,17 @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type,
|
||||
#define HELPER_LOG(x...)
|
||||
#endif
|
||||
|
||||
static inline bool psw_key_valid(CPUS390XState *env, uint8_t psw_key)
|
||||
{
|
||||
uint16_t pkm = env->cregs[3] >> 16;
|
||||
|
||||
if (env->psw.mask & PSW_MASK_PSTATE) {
|
||||
/* PSW key has range 0..15, it is valid if the bit is 1 in the PKM */
|
||||
return pkm & (0x80 >> psw_key);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Reduce the length so that addr + len doesn't cross a page boundary. */
|
||||
static inline uint32_t adj_len_to_page(uint32_t len, uint64_t addr)
|
||||
{
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "exec/memory.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "exec/helper-proto.h"
|
||||
@ -103,13 +104,17 @@ void HELPER(diag)(CPUS390XState *env, uint32_t r1, uint32_t r3, uint32_t num)
|
||||
handle_diag_308(env, r1, r3);
|
||||
r = 0;
|
||||
break;
|
||||
case 0x288:
|
||||
/* time bomb (watchdog) */
|
||||
r = handle_diag_288(env, r1, r3);
|
||||
break;
|
||||
default:
|
||||
r = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (r) {
|
||||
program_interrupt(env, PGM_OPERATION, ILEN_AUTO);
|
||||
program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO);
|
||||
}
|
||||
}
|
||||
|
||||
@ -451,6 +456,17 @@ void HELPER(per_check_exception)(CPUS390XState *env)
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if an address is within the PER starting address and the PER
|
||||
ending address. The address range might loop. */
|
||||
static inline bool get_per_in_range(CPUS390XState *env, uint64_t addr)
|
||||
{
|
||||
if (env->cregs[10] <= env->cregs[11]) {
|
||||
return env->cregs[10] <= addr && addr <= env->cregs[11];
|
||||
} else {
|
||||
return env->cregs[10] <= addr || addr <= env->cregs[11];
|
||||
}
|
||||
}
|
||||
|
||||
void HELPER(per_branch)(CPUS390XState *env, uint64_t from, uint64_t to)
|
||||
{
|
||||
if ((env->cregs[9] & PER_CR9_EVENT_BRANCH)) {
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include "qemu/error-report.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "kvm_s390x.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "trace.h"
|
||||
#include "hw/s390x/storage-keys.h"
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "disas/disas.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "tcg-op.h"
|
||||
|
@ -283,8 +283,8 @@ ifeq ($(CONFIG_VHOST_USER_NET_TEST_i386),)
|
||||
check-qtest-x86_64-$(CONFIG_VHOST_USER_NET_TEST_x86_64) += tests/vhost-user-test$(EXESUF)
|
||||
endif
|
||||
check-qtest-i386-$(CONFIG_SLIRP) += tests/test-netfilter$(EXESUF)
|
||||
check-qtest-i386-y += tests/test-filter-mirror$(EXESUF)
|
||||
check-qtest-i386-y += tests/test-filter-redirector$(EXESUF)
|
||||
check-qtest-i386-$(CONFIG_POSIX) += tests/test-filter-mirror$(EXESUF)
|
||||
check-qtest-i386-$(CONFIG_POSIX) += tests/test-filter-redirector$(EXESUF)
|
||||
check-qtest-i386-y += tests/postcopy-test$(EXESUF)
|
||||
check-qtest-i386-y += tests/test-x86-cpuid-compat$(EXESUF)
|
||||
check-qtest-i386-y += tests/numa-test$(EXESUF)
|
||||
@ -325,8 +325,8 @@ check-qtest-ppc64-y += tests/usb-hcd-xhci-test$(EXESUF)
|
||||
gcov-files-ppc64-y += hw/usb/hcd-xhci.c
|
||||
check-qtest-ppc64-y += $(check-qtest-virtio-y)
|
||||
check-qtest-ppc64-$(CONFIG_SLIRP) += tests/test-netfilter$(EXESUF)
|
||||
check-qtest-ppc64-y += tests/test-filter-mirror$(EXESUF)
|
||||
check-qtest-ppc64-y += tests/test-filter-redirector$(EXESUF)
|
||||
check-qtest-ppc64-$(CONFIG_POSIX) += tests/test-filter-mirror$(EXESUF)
|
||||
check-qtest-ppc64-$(CONFIG_POSIX) += tests/test-filter-redirector$(EXESUF)
|
||||
check-qtest-ppc64-y += tests/display-vga-test$(EXESUF)
|
||||
check-qtest-ppc64-y += tests/numa-test$(EXESUF)
|
||||
check-qtest-ppc64-$(CONFIG_IVSHMEM) += tests/ivshmem-test$(EXESUF)
|
||||
@ -360,6 +360,10 @@ check-qtest-microblazeel-y = $(check-qtest-microblaze-y)
|
||||
check-qtest-xtensaeb-y = $(check-qtest-xtensa-y)
|
||||
|
||||
check-qtest-s390x-y = tests/boot-serial-test$(EXESUF)
|
||||
check-qtest-s390x-$(CONFIG_SLIRP) += tests/pxe-test$(EXESUF)
|
||||
check-qtest-s390x-$(CONFIG_SLIRP) += tests/test-netfilter$(EXESUF)
|
||||
check-qtest-s390x-$(CONFIG_POSIX) += tests/test-filter-mirror$(EXESUF)
|
||||
check-qtest-s390x-$(CONFIG_POSIX) += tests/test-filter-redirector$(EXESUF)
|
||||
|
||||
check-qtest-generic-y += tests/qom-test$(EXESUF)
|
||||
check-qtest-generic-y += tests/test-hmp$(EXESUF)
|
||||
|
@ -21,13 +21,12 @@
|
||||
#define SIGNATURE 0xdead
|
||||
#define SIGNATURE_OFFSET 0x10
|
||||
#define BOOT_SECTOR_ADDRESS 0x7c00
|
||||
#define SIGNATURE_ADDR (BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET)
|
||||
|
||||
/* Boot sector code: write SIGNATURE into memory,
|
||||
/* x86 boot sector code: write SIGNATURE into memory,
|
||||
* then halt.
|
||||
* Q35 machine requires a minimum 0x7e000 bytes disk.
|
||||
* (bug or feature?)
|
||||
*/
|
||||
static uint8_t boot_sector[0x7e000] = {
|
||||
static uint8_t x86_boot_sector[512] = {
|
||||
/* The first sector will be placed at RAM address 00007C00, and
|
||||
* the BIOS transfers control to 00007C00
|
||||
*/
|
||||
@ -50,8 +49,8 @@ static uint8_t boot_sector[0x7e000] = {
|
||||
[0x07] = HIGH(SIGNATURE),
|
||||
/* 7c08: mov %ax,0x7c10 */
|
||||
[0x08] = 0xa3,
|
||||
[0x09] = LOW(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
|
||||
[0x0a] = HIGH(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
|
||||
[0x09] = LOW(SIGNATURE_ADDR),
|
||||
[0x0a] = HIGH(SIGNATURE_ADDR),
|
||||
|
||||
/* 7c0b cli */
|
||||
[0x0b] = 0xfa,
|
||||
@ -68,11 +67,28 @@ static uint8_t boot_sector[0x7e000] = {
|
||||
[0x1FF] = 0xAA,
|
||||
};
|
||||
|
||||
/* For s390x, use a mini "kernel" with the appropriate signature */
|
||||
static const uint8_t s390x_psw[] = {
|
||||
0x00, 0x08, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00
|
||||
};
|
||||
static const uint8_t s390x_code[] = {
|
||||
0xa7, 0xf4, 0x00, 0x0a, /* j 0x10010 */
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
'S', '3', '9', '0',
|
||||
'E', 'P', 0x00, 0x01,
|
||||
0xa7, 0x38, HIGH(SIGNATURE_ADDR), LOW(SIGNATURE_ADDR), /* lhi r3,0x7c10 */
|
||||
0xa7, 0x48, LOW(SIGNATURE), HIGH(SIGNATURE), /* lhi r4,0xadde */
|
||||
0x40, 0x40, 0x30, 0x00, /* sth r4,0(r3) */
|
||||
0xa7, 0xf4, 0xff, 0xfa /* j 0x10010 */
|
||||
};
|
||||
|
||||
/* Create boot disk file. */
|
||||
int boot_sector_init(char *fname)
|
||||
{
|
||||
int fd, ret;
|
||||
size_t len = sizeof boot_sector;
|
||||
size_t len;
|
||||
char *boot_code;
|
||||
const char *arch = qtest_get_arch();
|
||||
|
||||
fd = mkstemp(fname);
|
||||
if (fd < 0) {
|
||||
@ -80,16 +96,31 @@ int boot_sector_init(char *fname)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* For Open Firmware based system, we can use a Forth script instead */
|
||||
if (strcmp(qtest_get_arch(), "ppc64") == 0) {
|
||||
len = sprintf((char *)boot_sector, "\\ Bootscript\n%x %x c! %x %x c!\n",
|
||||
LOW(SIGNATURE), BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET,
|
||||
HIGH(SIGNATURE), BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET + 1);
|
||||
if (g_str_equal(arch, "i386") || g_str_equal(arch, "x86_64")) {
|
||||
/* Q35 requires a minimum 0x7e000 bytes disk (bug or feature?) */
|
||||
len = MAX(0x7e000, sizeof(x86_boot_sector));
|
||||
boot_code = g_malloc0(len);
|
||||
memcpy(boot_code, x86_boot_sector, sizeof(x86_boot_sector));
|
||||
} else if (g_str_equal(arch, "ppc64")) {
|
||||
/* For Open Firmware based system, use a Forth script */
|
||||
boot_code = g_strdup_printf("\\ Bootscript\n%x %x c! %x %x c!\n",
|
||||
LOW(SIGNATURE), SIGNATURE_ADDR,
|
||||
HIGH(SIGNATURE), SIGNATURE_ADDR + 1);
|
||||
len = strlen(boot_code);
|
||||
} else if (g_str_equal(arch, "s390x")) {
|
||||
len = 0x10000 + sizeof(s390x_code);
|
||||
boot_code = g_malloc0(len);
|
||||
memcpy(boot_code, s390x_psw, sizeof(s390x_psw));
|
||||
memcpy(&boot_code[0x10000], s390x_code, sizeof(s390x_code));
|
||||
} else {
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
ret = write(fd, boot_sector, len);
|
||||
ret = write(fd, boot_code, len);
|
||||
close(fd);
|
||||
|
||||
g_free(boot_code);
|
||||
|
||||
if (ret != len) {
|
||||
fprintf(stderr, "Could not write \"%s\"", fname);
|
||||
return 1;
|
||||
@ -115,8 +146,8 @@ void boot_sector_test(void)
|
||||
* instruction.
|
||||
*/
|
||||
for (i = 0; i < TEST_CYCLES; ++i) {
|
||||
signature_low = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET);
|
||||
signature_high = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET + 1);
|
||||
signature_low = readb(SIGNATURE_ADDR);
|
||||
signature_high = readb(SIGNATURE_ADDR + 1);
|
||||
signature = (signature_high << 8) | signature_low;
|
||||
if (signature == SIGNATURE) {
|
||||
break;
|
||||
|
@ -51,6 +51,11 @@ static void test_pxe_spapr_vlan(void)
|
||||
test_pxe_one("-device spapr-vlan,netdev=" NETNAME, true);
|
||||
}
|
||||
|
||||
static void test_pxe_virtio_ccw(void)
|
||||
{
|
||||
test_pxe_one("-device virtio-net-ccw,bootindex=1,netdev=" NETNAME, false);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ret;
|
||||
@ -68,6 +73,8 @@ int main(int argc, char *argv[])
|
||||
} else if (strcmp(arch, "ppc64") == 0) {
|
||||
qtest_add_func("pxe/virtio", test_pxe_virtio_pci);
|
||||
qtest_add_func("pxe/spapr-vlan", test_pxe_spapr_vlan);
|
||||
} else if (g_str_equal(arch, "s390x")) {
|
||||
qtest_add_func("pxe/virtio-ccw", test_pxe_virtio_ccw);
|
||||
}
|
||||
ret = g_test_run();
|
||||
boot_sector_cleanup(disk);
|
||||
|
@ -17,9 +17,6 @@
|
||||
|
||||
static void test_mirror(void)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
/* socketpair(PF_UNIX) which does not exist on windows */
|
||||
|
||||
int send_sock[2], recv_sock;
|
||||
char *cmdline;
|
||||
uint32_t ret = 0, len = 0;
|
||||
@ -28,6 +25,11 @@ static void test_mirror(void)
|
||||
char *recv_buf;
|
||||
uint32_t size = sizeof(send_buf);
|
||||
size = htonl(size);
|
||||
const char *devstr = "e1000";
|
||||
|
||||
if (g_str_equal(qtest_get_arch(), "s390x")) {
|
||||
devstr = "virtio-net-ccw";
|
||||
}
|
||||
|
||||
ret = socketpair(PF_UNIX, SOCK_STREAM, 0, send_sock);
|
||||
g_assert_cmpint(ret, !=, -1);
|
||||
@ -36,10 +38,10 @@ static void test_mirror(void)
|
||||
g_assert_cmpint(ret, !=, -1);
|
||||
|
||||
cmdline = g_strdup_printf("-netdev socket,id=qtest-bn0,fd=%d "
|
||||
"-device e1000,netdev=qtest-bn0,id=qtest-e0 "
|
||||
"-device %s,netdev=qtest-bn0,id=qtest-e0 "
|
||||
"-chardev socket,id=mirror0,path=%s,server,nowait "
|
||||
"-object filter-mirror,id=qtest-f0,netdev=qtest-bn0,queue=tx,outdev=mirror0 "
|
||||
, send_sock[1], sock_path);
|
||||
, send_sock[1], devstr, sock_path);
|
||||
qtest_start(cmdline);
|
||||
g_free(cmdline);
|
||||
|
||||
@ -74,8 +76,6 @@ static void test_mirror(void)
|
||||
g_free(recv_buf);
|
||||
close(recv_sock);
|
||||
unlink(sock_path);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
@ -57,11 +57,18 @@
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
static const char *get_devstr(void)
|
||||
{
|
||||
if (g_str_equal(qtest_get_arch(), "s390x")) {
|
||||
return "virtio-net-ccw";
|
||||
}
|
||||
|
||||
return "rtl8139";
|
||||
}
|
||||
|
||||
|
||||
static void test_redirector_tx(void)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
/* socketpair(PF_UNIX) which does not exist on windows */
|
||||
|
||||
int backend_sock[2], recv_sock;
|
||||
char *cmdline;
|
||||
uint32_t ret = 0, len = 0;
|
||||
@ -81,7 +88,7 @@ static void test_redirector_tx(void)
|
||||
g_assert_cmpint(ret, !=, -1);
|
||||
|
||||
cmdline = g_strdup_printf("-netdev socket,id=qtest-bn0,fd=%d "
|
||||
"-device rtl8139,netdev=qtest-bn0,id=qtest-e0 "
|
||||
"-device %s,netdev=qtest-bn0,id=qtest-e0 "
|
||||
"-chardev socket,id=redirector0,path=%s,server,nowait "
|
||||
"-chardev socket,id=redirector1,path=%s,server,nowait "
|
||||
"-chardev socket,id=redirector2,path=%s,nowait "
|
||||
@ -90,8 +97,8 @@ static void test_redirector_tx(void)
|
||||
"-object filter-redirector,id=qtest-f1,netdev=qtest-bn0,"
|
||||
"queue=tx,indev=redirector2 "
|
||||
"-object filter-redirector,id=qtest-f2,netdev=qtest-bn0,"
|
||||
"queue=tx,outdev=redirector1 "
|
||||
, backend_sock[1], sock_path0, sock_path1, sock_path0);
|
||||
"queue=tx,outdev=redirector1 ", backend_sock[1], get_devstr(),
|
||||
sock_path0, sock_path1, sock_path0);
|
||||
qtest_start(cmdline);
|
||||
g_free(cmdline);
|
||||
|
||||
@ -129,15 +136,10 @@ static void test_redirector_tx(void)
|
||||
unlink(sock_path0);
|
||||
unlink(sock_path1);
|
||||
qtest_end();
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_redirector_rx(void)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
/* socketpair(PF_UNIX) which does not exist on windows */
|
||||
|
||||
int backend_sock[2], send_sock;
|
||||
char *cmdline;
|
||||
uint32_t ret = 0, len = 0;
|
||||
@ -157,7 +159,7 @@ static void test_redirector_rx(void)
|
||||
g_assert_cmpint(ret, !=, -1);
|
||||
|
||||
cmdline = g_strdup_printf("-netdev socket,id=qtest-bn0,fd=%d "
|
||||
"-device rtl8139,netdev=qtest-bn0,id=qtest-e0 "
|
||||
"-device %s,netdev=qtest-bn0,id=qtest-e0 "
|
||||
"-chardev socket,id=redirector0,path=%s,server,nowait "
|
||||
"-chardev socket,id=redirector1,path=%s,server,nowait "
|
||||
"-chardev socket,id=redirector2,path=%s,nowait "
|
||||
@ -166,8 +168,8 @@ static void test_redirector_rx(void)
|
||||
"-object filter-redirector,id=qtest-f1,netdev=qtest-bn0,"
|
||||
"queue=rx,outdev=redirector2 "
|
||||
"-object filter-redirector,id=qtest-f2,netdev=qtest-bn0,"
|
||||
"queue=rx,indev=redirector1 "
|
||||
, backend_sock[1], sock_path0, sock_path1, sock_path0);
|
||||
"queue=rx,indev=redirector1 ", backend_sock[1], get_devstr(),
|
||||
sock_path0, sock_path1, sock_path0);
|
||||
qtest_start(cmdline);
|
||||
g_free(cmdline);
|
||||
|
||||
@ -203,8 +205,6 @@ static void test_redirector_rx(void)
|
||||
unlink(sock_path0);
|
||||
unlink(sock_path1);
|
||||
qtest_end();
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
@ -182,6 +182,12 @@ static void remove_netdev_with_multi_netfilter(void)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
char *args;
|
||||
const char *devstr = "e1000";
|
||||
|
||||
if (g_str_equal(qtest_get_arch(), "s390x")) {
|
||||
devstr = "virtio-net-ccw";
|
||||
}
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
qtest_add_func("/netfilter/addremove_one", add_one_netfilter);
|
||||
@ -191,10 +197,13 @@ int main(int argc, char **argv)
|
||||
qtest_add_func("/netfilter/remove_netdev_multi",
|
||||
remove_netdev_with_multi_netfilter);
|
||||
|
||||
qtest_start("-netdev user,id=qtest-bn0 -device e1000,netdev=qtest-bn0");
|
||||
args = g_strdup_printf("-netdev user,id=qtest-bn0 "
|
||||
"-device %s,netdev=qtest-bn0", devstr);
|
||||
qtest_start(args);
|
||||
ret = g_test_run();
|
||||
|
||||
qtest_end();
|
||||
g_free(args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user