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