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:
Peter Maydell 2017-08-31 11:29:41 +01:00
commit 1415e8ea1f
62 changed files with 1257 additions and 853 deletions

View File

@ -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
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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/

View File

@ -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"

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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 = {

View File

@ -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;

View File

@ -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);

View File

@ -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
View 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;
}

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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)
{

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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",\

View File

@ -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))

View File

@ -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);

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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)/

View File

@ -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 {

View File

@ -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"

View File

@ -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)

View File

@ -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

View File

@ -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,

View File

@ -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);

View File

@ -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)
{

View File

@ -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"

View File

@ -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"

View File

@ -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];
}

View File

@ -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
View 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 */

View File

@ -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"

View File

@ -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
View 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)
{
}

View File

@ -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
View 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 */

View File

@ -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)

View File

@ -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)
{

View File

@ -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)) {

View File

@ -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"

View File

@ -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"

View File

@ -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)

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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)

View File

@ -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;
}