First pile of s390x patches for 2.4, including:
- some cleanup patches - sort most of the s390x devices into categories - support for the new STSI post handler, used to insert vm name and friends - support for the new MEM_OP ioctl (including access register mode) for accessing guest memory -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJVQhiKAAoJEN7Pa5PG8C+v9fQQAJh+vHKZF1soi7u8Em1RZAKV TiuvGwTfEF1ajSpPxRd6JQjKAIAoCJ7yuDJUzJbQOg1fo1EOJHAJHpBz10Cuk0FD 8ves9+ZirOjAwPNGjC697mqKWzaoxeDFxHyf1HUlstpiYkRR1iaAMUWAdWIz2WE7 6mvwFV/gNGulyFKjKT47vaela4DTVyymsp8yu37/njNav0bEIF+7zBDiXi1z05lE LlzjoDJcRUhk5mnbEnxSszZ2ndSdKSY/xsk+/Ykofapz00F+Bpg85m/+9TNNjSBm RfgsmFTD5Qyp0UehawbINejOhTjuIRO5AZVyq3upc5TJy7oGTP/ueFad0HHsM7Nk 1RrFr7pEVOKVY6a1VMqX2O8w28PTKUzHi5SCmJTyr5ryBGGW3SqeA0742uwQDCDU ejm3F97jKgLvpX135zoBUtfu4KbeARmrCiL2x1OPCP7XDEWkz/k2UfP1iR+11BFR GQ3cfid3JXKS/5qGfFwJVWPJbMyZbxRn6qCh4ywUMVcKr22KOM653pCfJ65IYbJO O0ZMuddHMoOt6TlTlIJ4/V13ZtoPhmGVnfP43I3V4Y4ByFQacDB+JL9n2fxWq/Yk loSd/5lhH+HJCWjg6psm9oT1vVd1AgL9GqltFXHTaG8hJHQqwzBUrKNW8DpS/PIj ViR0oEPmV+dZQxYM22tR =z0Lu -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20150430' into staging First pile of s390x patches for 2.4, including: - some cleanup patches - sort most of the s390x devices into categories - support for the new STSI post handler, used to insert vm name and friends - support for the new MEM_OP ioctl (including access register mode) for accessing guest memory # gpg: Signature made Thu Apr 30 12:56:58 2015 BST using RSA key ID C6F02FAF # gpg: Good signature from "Cornelia Huck <huckc@linux.vnet.ibm.com>" # gpg: aka "Cornelia Huck <cornelia.huck@de.ibm.com>" * remotes/cohuck/tags/s390x-20150430: kvm: better advice for failed s390x startup s390x/kvm: Support access register mode for KVM_S390_MEM_OP ioctl s390x/mmu: Use ioctl for reading and writing from/to guest memory s390x/kvm: Put vm name, extended name and UUID into STSI322 SYSIB linux-headers: update s390x/mmu: Use access type definitions instead of magic values s390x/ipl: sort into categories sclp: sort into categories s390-virtio: sort into categories virtio-ccw: sort into categories Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
498147529d
@ -364,6 +364,7 @@ static void console_class_init(ObjectClass *klass, void *data)
|
||||
ec->can_handle_event = can_handle_event;
|
||||
ec->read_event_data = read_event_data;
|
||||
ec->write_event_data = write_event_data;
|
||||
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo sclp_console_info = {
|
||||
|
@ -266,6 +266,7 @@ static void console_class_init(ObjectClass *klass, void *data)
|
||||
ec->can_handle_event = can_handle_event;
|
||||
ec->read_event_data = read_event_data;
|
||||
ec->write_event_data = write_event_data;
|
||||
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo sclp_console_info = {
|
||||
|
@ -362,6 +362,7 @@ static void init_event_facility_class(ObjectClass *klass, void *data)
|
||||
|
||||
dc->reset = reset_event_facility;
|
||||
dc->vmsd = &vmstate_event_facility;
|
||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
k->init = init_event_facility;
|
||||
k->command_handler = command_handler;
|
||||
k->event_pending = event_pending;
|
||||
|
@ -315,6 +315,7 @@ static void s390_ipl_class_init(ObjectClass *klass, void *data)
|
||||
dc->props = s390_ipl_properties;
|
||||
dc->reset = s390_ipl_reset;
|
||||
dc->vmsd = &vmstate_ipl;
|
||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo s390_ipl_info = {
|
||||
|
@ -155,7 +155,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s390_cpu_virt_mem_read(cpu, env->regs[r2], buffer, sizeof(*reqh))) {
|
||||
if (s390_cpu_virt_mem_read(cpu, env->regs[r2], r2, buffer, sizeof(*reqh))) {
|
||||
return 0;
|
||||
}
|
||||
reqh = (ClpReqHdr *)buffer;
|
||||
@ -165,7 +165,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s390_cpu_virt_mem_read(cpu, env->regs[r2], buffer,
|
||||
if (s390_cpu_virt_mem_read(cpu, env->regs[r2], r2, buffer,
|
||||
req_len + sizeof(*resh))) {
|
||||
return 0;
|
||||
}
|
||||
@ -180,7 +180,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s390_cpu_virt_mem_read(cpu, env->regs[r2], buffer,
|
||||
if (s390_cpu_virt_mem_read(cpu, env->regs[r2], r2, buffer,
|
||||
req_len + res_len)) {
|
||||
return 0;
|
||||
}
|
||||
@ -277,7 +277,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
|
||||
}
|
||||
|
||||
out:
|
||||
if (s390_cpu_virt_mem_write(cpu, env->regs[r2], buffer,
|
||||
if (s390_cpu_virt_mem_write(cpu, env->regs[r2], r2, buffer,
|
||||
req_len + res_len)) {
|
||||
return 0;
|
||||
}
|
||||
@ -546,7 +546,8 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr)
|
||||
int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
|
||||
uint8_t ar)
|
||||
{
|
||||
CPUS390XState *env = &cpu->env;
|
||||
S390PCIBusDevice *pbdev;
|
||||
@ -603,7 +604,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s390_cpu_virt_mem_read(cpu, gaddr, buffer, len)) {
|
||||
if (s390_cpu_virt_mem_read(cpu, gaddr, ar, buffer, len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -698,7 +699,7 @@ static void dereg_ioat(S390PCIBusDevice *pbdev)
|
||||
pbdev->g_iota = 0;
|
||||
}
|
||||
|
||||
int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba)
|
||||
int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
|
||||
{
|
||||
CPUS390XState *env = &cpu->env;
|
||||
uint8_t oc;
|
||||
@ -727,7 +728,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s390_cpu_virt_mem_read(cpu, fiba, (uint8_t *)&fib, sizeof(fib))) {
|
||||
if (s390_cpu_virt_mem_read(cpu, fiba, ar, (uint8_t *)&fib, sizeof(fib))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -773,7 +774,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba)
|
||||
int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
|
||||
{
|
||||
CPUS390XState *env = &cpu->env;
|
||||
uint32_t fh;
|
||||
@ -829,7 +830,7 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba)
|
||||
fib.fc |= 0x10;
|
||||
}
|
||||
|
||||
if (s390_cpu_virt_mem_write(cpu, fiba, (uint8_t *)&fib, sizeof(fib))) {
|
||||
if (s390_cpu_virt_mem_write(cpu, fiba, ar, (uint8_t *)&fib, sizeof(fib))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -281,8 +281,9 @@ int clp_service_call(S390CPU *cpu, uint8_t r2);
|
||||
int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2);
|
||||
int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2);
|
||||
int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2);
|
||||
int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr);
|
||||
int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba);
|
||||
int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba);
|
||||
int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
|
||||
uint8_t ar);
|
||||
int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar);
|
||||
int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar);
|
||||
|
||||
#endif
|
||||
|
@ -542,6 +542,7 @@ static void s390_virtio_net_class_init(ObjectClass *klass, void *data)
|
||||
|
||||
k->realize = s390_virtio_net_realize;
|
||||
dc->props = s390_virtio_net_properties;
|
||||
set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo s390_virtio_net = {
|
||||
@ -555,8 +556,10 @@ static const TypeInfo s390_virtio_net = {
|
||||
static void s390_virtio_blk_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
k->realize = s390_virtio_blk_realize;
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo s390_virtio_blk = {
|
||||
@ -578,6 +581,7 @@ static void s390_virtio_serial_class_init(ObjectClass *klass, void *data)
|
||||
|
||||
k->realize = s390_virtio_serial_realize;
|
||||
dc->props = s390_virtio_serial_properties;
|
||||
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo s390_virtio_serial = {
|
||||
@ -600,6 +604,7 @@ static void s390_virtio_rng_class_init(ObjectClass *klass, void *data)
|
||||
|
||||
k->realize = s390_virtio_rng_realize;
|
||||
dc->props = s390_virtio_rng_properties;
|
||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo s390_virtio_rng = {
|
||||
@ -658,6 +663,7 @@ static void s390_virtio_scsi_class_init(ObjectClass *klass, void *data)
|
||||
|
||||
k->realize = s390_virtio_scsi_realize;
|
||||
dc->props = s390_virtio_scsi_properties;
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo s390_virtio_scsi = {
|
||||
@ -681,6 +687,7 @@ static void s390_vhost_scsi_class_init(ObjectClass *klass, void *data)
|
||||
|
||||
k->realize = s390_vhost_scsi_realize;
|
||||
dc->props = s390_vhost_scsi_properties;
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo s390_vhost_scsi = {
|
||||
@ -704,8 +711,10 @@ static int s390_virtio_bridge_init(SysBusDevice *dev)
|
||||
static void s390_virtio_bridge_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
k->init = s390_virtio_bridge_init;
|
||||
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo s390_virtio_bridge_info = {
|
||||
|
@ -457,10 +457,19 @@ sclpMemoryHotplugDev *get_sclp_memory_hotplug_dev(void)
|
||||
TYPE_SCLP_MEMORY_HOTPLUG_DEV, NULL));
|
||||
}
|
||||
|
||||
static void sclp_memory_hotplug_dev_class_init(ObjectClass *klass,
|
||||
void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
}
|
||||
|
||||
static TypeInfo sclp_memory_hotplug_dev_info = {
|
||||
.name = TYPE_SCLP_MEMORY_HOTPLUG_DEV,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(sclpMemoryHotplugDev),
|
||||
.class_init = sclp_memory_hotplug_dev_class_init,
|
||||
};
|
||||
|
||||
static void register_types(void)
|
||||
|
@ -88,12 +88,14 @@ static int irq_cpu_hotplug_init(SCLPEvent *event)
|
||||
static void cpu_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
SCLPEventClass *k = SCLP_EVENT_CLASS(oc);
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
k->init = irq_cpu_hotplug_init;
|
||||
k->get_send_mask = send_mask;
|
||||
k->get_receive_mask = receive_mask;
|
||||
k->read_event_data = read_event_data;
|
||||
k->write_event_data = NULL;
|
||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo sclp_cpu_info = {
|
||||
|
@ -116,6 +116,7 @@ static void quiesce_class_init(ObjectClass *klass, void *data)
|
||||
|
||||
dc->reset = quiesce_reset;
|
||||
dc->vmsd = &vmstate_sclpquiesce;
|
||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
k->init = quiesce_init;
|
||||
|
||||
k->get_send_mask = send_mask;
|
||||
|
@ -1453,6 +1453,7 @@ static void virtio_ccw_net_class_init(ObjectClass *klass, void *data)
|
||||
k->exit = virtio_ccw_exit;
|
||||
dc->reset = virtio_ccw_reset;
|
||||
dc->props = virtio_ccw_net_properties;
|
||||
set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo virtio_ccw_net = {
|
||||
@ -1479,6 +1480,7 @@ static void virtio_ccw_blk_class_init(ObjectClass *klass, void *data)
|
||||
k->exit = virtio_ccw_exit;
|
||||
dc->reset = virtio_ccw_reset;
|
||||
dc->props = virtio_ccw_blk_properties;
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo virtio_ccw_blk = {
|
||||
@ -1505,6 +1507,7 @@ static void virtio_ccw_serial_class_init(ObjectClass *klass, void *data)
|
||||
k->exit = virtio_ccw_exit;
|
||||
dc->reset = virtio_ccw_reset;
|
||||
dc->props = virtio_ccw_serial_properties;
|
||||
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo virtio_ccw_serial = {
|
||||
@ -1531,6 +1534,7 @@ static void virtio_ccw_balloon_class_init(ObjectClass *klass, void *data)
|
||||
k->exit = virtio_ccw_exit;
|
||||
dc->reset = virtio_ccw_reset;
|
||||
dc->props = virtio_ccw_balloon_properties;
|
||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo virtio_ccw_balloon = {
|
||||
@ -1558,6 +1562,7 @@ static void virtio_ccw_scsi_class_init(ObjectClass *klass, void *data)
|
||||
k->exit = virtio_ccw_exit;
|
||||
dc->reset = virtio_ccw_reset;
|
||||
dc->props = virtio_ccw_scsi_properties;
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo virtio_ccw_scsi = {
|
||||
@ -1583,6 +1588,7 @@ static void vhost_ccw_scsi_class_init(ObjectClass *klass, void *data)
|
||||
k->exit = virtio_ccw_exit;
|
||||
dc->reset = virtio_ccw_reset;
|
||||
dc->props = vhost_ccw_scsi_properties;
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo vhost_ccw_scsi = {
|
||||
@ -1620,6 +1626,7 @@ static void virtio_ccw_rng_class_init(ObjectClass *klass, void *data)
|
||||
k->exit = virtio_ccw_exit;
|
||||
dc->reset = virtio_ccw_reset;
|
||||
dc->props = virtio_ccw_rng_properties;
|
||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo virtio_ccw_rng = {
|
||||
@ -1706,9 +1713,11 @@ static void virtual_css_bridge_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
|
||||
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
k->init = virtual_css_bridge_init;
|
||||
hc->unplug = virtio_ccw_busdev_unplug;
|
||||
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo virtual_css_bridge_info = {
|
||||
|
@ -25,6 +25,7 @@
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE. */
|
||||
#include "standard-headers/linux/types.h"
|
||||
#include "standard-headers/linux/virtio_ids.h"
|
||||
#include "standard-headers/linux/virtio_config.h"
|
||||
|
||||
@ -51,9 +52,32 @@ struct virtio_balloon_config {
|
||||
#define VIRTIO_BALLOON_S_MEMTOT 5 /* Total amount of memory */
|
||||
#define VIRTIO_BALLOON_S_NR 6
|
||||
|
||||
/*
|
||||
* Memory statistics structure.
|
||||
* Driver fills an array of these structures and passes to device.
|
||||
*
|
||||
* NOTE: fields are laid out in a way that would make compiler add padding
|
||||
* between and after fields, so we have to use compiler-specific attributes to
|
||||
* pack it, to disable this padding. This also often causes compiler to
|
||||
* generate suboptimal code.
|
||||
*
|
||||
* We maintain this statistics structure format for backwards compatibility,
|
||||
* but don't follow this example.
|
||||
*
|
||||
* If implementing a similar structure, do something like the below instead:
|
||||
* struct virtio_balloon_stat {
|
||||
* __virtio16 tag;
|
||||
* uint8_t reserved[6];
|
||||
* __virtio64 val;
|
||||
* };
|
||||
*
|
||||
* In other words, add explicit reserved fields to align field and
|
||||
* structure boundaries at field size, avoiding compiler padding
|
||||
* without the packed attribute.
|
||||
*/
|
||||
struct virtio_balloon_stat {
|
||||
uint16_t tag;
|
||||
uint64_t val;
|
||||
__virtio16 tag;
|
||||
__virtio64 val;
|
||||
} QEMU_PACKED;
|
||||
|
||||
#endif /* _LINUX_VIRTIO_BALLOON_H */
|
||||
|
@ -39,5 +39,6 @@
|
||||
#define VIRTIO_ID_9P 9 /* 9p virtio console */
|
||||
#define VIRTIO_ID_RPROC_SERIAL 11 /* virtio remoteproc serial link */
|
||||
#define VIRTIO_ID_CAIF 12 /* Virtio caif */
|
||||
#define VIRTIO_ID_INPUT 18 /* virtio input */
|
||||
|
||||
#endif /* _LINUX_VIRTIO_IDS_H */
|
||||
|
76
include/standard-headers/linux/virtio_input.h
Normal file
76
include/standard-headers/linux/virtio_input.h
Normal file
@ -0,0 +1,76 @@
|
||||
#ifndef _LINUX_VIRTIO_INPUT_H
|
||||
#define _LINUX_VIRTIO_INPUT_H
|
||||
/* This header is BSD licensed so anyone can use the definitions to implement
|
||||
* compatible drivers/servers.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of IBM nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IBM OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE. */
|
||||
|
||||
#include "standard-headers/linux/types.h"
|
||||
|
||||
enum virtio_input_config_select {
|
||||
VIRTIO_INPUT_CFG_UNSET = 0x00,
|
||||
VIRTIO_INPUT_CFG_ID_NAME = 0x01,
|
||||
VIRTIO_INPUT_CFG_ID_SERIAL = 0x02,
|
||||
VIRTIO_INPUT_CFG_ID_DEVIDS = 0x03,
|
||||
VIRTIO_INPUT_CFG_PROP_BITS = 0x10,
|
||||
VIRTIO_INPUT_CFG_EV_BITS = 0x11,
|
||||
VIRTIO_INPUT_CFG_ABS_INFO = 0x12,
|
||||
};
|
||||
|
||||
struct virtio_input_absinfo {
|
||||
uint32_t min;
|
||||
uint32_t max;
|
||||
uint32_t fuzz;
|
||||
uint32_t flat;
|
||||
uint32_t res;
|
||||
};
|
||||
|
||||
struct virtio_input_devids {
|
||||
uint16_t bustype;
|
||||
uint16_t vendor;
|
||||
uint16_t product;
|
||||
uint16_t version;
|
||||
};
|
||||
|
||||
struct virtio_input_config {
|
||||
uint8_t select;
|
||||
uint8_t subsel;
|
||||
uint8_t size;
|
||||
uint8_t reserved[5];
|
||||
union {
|
||||
char string[128];
|
||||
uint8_t bitmap[128];
|
||||
struct virtio_input_absinfo abs;
|
||||
struct virtio_input_devids ids;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct virtio_input_event {
|
||||
uint16_t type;
|
||||
uint16_t code;
|
||||
uint32_t value;
|
||||
};
|
||||
|
||||
#endif /* _LINUX_VIRTIO_INPUT_H */
|
13
kvm-all.c
13
kvm-all.c
@ -1544,8 +1544,17 @@ static int kvm_init(MachineState *ms)
|
||||
strerror(-ret));
|
||||
|
||||
#ifdef TARGET_S390X
|
||||
fprintf(stderr, "Please add the 'switch_amode' kernel parameter to "
|
||||
"your host kernel command line\n");
|
||||
if (ret == -EINVAL) {
|
||||
fprintf(stderr,
|
||||
"Host kernel setup problem detected. Please verify:\n");
|
||||
fprintf(stderr, "- for kernels supporting the switch_amode or"
|
||||
" user_mode parameters, whether\n");
|
||||
fprintf(stderr,
|
||||
" user space is running in primary address space\n");
|
||||
fprintf(stderr,
|
||||
"- for kernels supporting the vm.allocate_pgste sysctl, "
|
||||
"whether it is enabled\n");
|
||||
}
|
||||
#endif
|
||||
goto err;
|
||||
}
|
||||
|
@ -195,9 +195,16 @@ struct kvm_arch_memory_slot {
|
||||
#define KVM_ARM_IRQ_CPU_IRQ 0
|
||||
#define KVM_ARM_IRQ_CPU_FIQ 1
|
||||
|
||||
/* Highest supported SPI, from VGIC_NR_IRQS */
|
||||
/*
|
||||
* This used to hold the highest supported SPI, but it is now obsolete
|
||||
* and only here to provide source code level compatibility with older
|
||||
* userland. The highest SPI number can be set via KVM_DEV_ARM_VGIC_GRP_NR_IRQS.
|
||||
*/
|
||||
#define KVM_ARM_IRQ_GIC_MAX 127
|
||||
|
||||
/* One single KVM irqchip, ie. the VGIC */
|
||||
#define KVM_NR_IRQCHIPS 1
|
||||
|
||||
/* PSCI interface */
|
||||
#define KVM_PSCI_FN_BASE 0x95c1ba5e
|
||||
#define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
|
||||
|
@ -188,9 +188,16 @@ struct kvm_arch_memory_slot {
|
||||
#define KVM_ARM_IRQ_CPU_IRQ 0
|
||||
#define KVM_ARM_IRQ_CPU_FIQ 1
|
||||
|
||||
/* Highest supported SPI, from VGIC_NR_IRQS */
|
||||
/*
|
||||
* This used to hold the highest supported SPI, but it is now obsolete
|
||||
* and only here to provide source code level compatibility with older
|
||||
* userland. The highest SPI number can be set via KVM_DEV_ARM_VGIC_GRP_NR_IRQS.
|
||||
*/
|
||||
#define KVM_ARM_IRQ_GIC_MAX 127
|
||||
|
||||
/* One single KVM irqchip, ie. the VGIC */
|
||||
#define KVM_NR_IRQCHIPS 1
|
||||
|
||||
/* PSCI interface */
|
||||
#define KVM_PSCI_FN_BASE 0x95c1ba5e
|
||||
#define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
|
||||
|
@ -36,77 +36,85 @@ struct kvm_regs {
|
||||
|
||||
/*
|
||||
* for KVM_GET_FPU and KVM_SET_FPU
|
||||
*
|
||||
* If Status[FR] is zero (32-bit FPU), the upper 32-bits of the FPRs
|
||||
* are zero filled.
|
||||
*/
|
||||
struct kvm_fpu {
|
||||
__u64 fpr[32];
|
||||
__u32 fir;
|
||||
__u32 fccr;
|
||||
__u32 fexr;
|
||||
__u32 fenr;
|
||||
__u32 fcsr;
|
||||
__u32 pad;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* For MIPS, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access CP0
|
||||
* For MIPS, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access various
|
||||
* registers. The id field is broken down as follows:
|
||||
*
|
||||
* bits[2..0] - Register 'sel' index.
|
||||
* bits[7..3] - Register 'rd' index.
|
||||
* bits[15..8] - Must be zero.
|
||||
* bits[31..16] - 1 -> CP0 registers.
|
||||
* bits[51..32] - Must be zero.
|
||||
* bits[63..52] - As per linux/kvm.h
|
||||
* bits[51..32] - Must be zero.
|
||||
* bits[31..16] - Register set.
|
||||
*
|
||||
* Register set = 0: GP registers from kvm_regs (see definitions below).
|
||||
*
|
||||
* Register set = 1: CP0 registers.
|
||||
* bits[15..8] - Must be zero.
|
||||
* bits[7..3] - Register 'rd' index.
|
||||
* bits[2..0] - Register 'sel' index.
|
||||
*
|
||||
* Register set = 2: KVM specific registers (see definitions below).
|
||||
*
|
||||
* Register set = 3: FPU / MSA registers (see definitions below).
|
||||
*
|
||||
* Other sets registers may be added in the future. Each set would
|
||||
* have its own identifier in bits[31..16].
|
||||
*
|
||||
* The registers defined in struct kvm_regs are also accessible, the
|
||||
* id values for these are below.
|
||||
*/
|
||||
|
||||
#define KVM_REG_MIPS_R0 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 0)
|
||||
#define KVM_REG_MIPS_R1 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 1)
|
||||
#define KVM_REG_MIPS_R2 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 2)
|
||||
#define KVM_REG_MIPS_R3 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 3)
|
||||
#define KVM_REG_MIPS_R4 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 4)
|
||||
#define KVM_REG_MIPS_R5 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 5)
|
||||
#define KVM_REG_MIPS_R6 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 6)
|
||||
#define KVM_REG_MIPS_R7 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 7)
|
||||
#define KVM_REG_MIPS_R8 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 8)
|
||||
#define KVM_REG_MIPS_R9 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 9)
|
||||
#define KVM_REG_MIPS_R10 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 10)
|
||||
#define KVM_REG_MIPS_R11 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 11)
|
||||
#define KVM_REG_MIPS_R12 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 12)
|
||||
#define KVM_REG_MIPS_R13 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 13)
|
||||
#define KVM_REG_MIPS_R14 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 14)
|
||||
#define KVM_REG_MIPS_R15 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 15)
|
||||
#define KVM_REG_MIPS_R16 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 16)
|
||||
#define KVM_REG_MIPS_R17 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 17)
|
||||
#define KVM_REG_MIPS_R18 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 18)
|
||||
#define KVM_REG_MIPS_R19 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 19)
|
||||
#define KVM_REG_MIPS_R20 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 20)
|
||||
#define KVM_REG_MIPS_R21 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 21)
|
||||
#define KVM_REG_MIPS_R22 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 22)
|
||||
#define KVM_REG_MIPS_R23 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 23)
|
||||
#define KVM_REG_MIPS_R24 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 24)
|
||||
#define KVM_REG_MIPS_R25 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 25)
|
||||
#define KVM_REG_MIPS_R26 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 26)
|
||||
#define KVM_REG_MIPS_R27 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 27)
|
||||
#define KVM_REG_MIPS_R28 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 28)
|
||||
#define KVM_REG_MIPS_R29 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 29)
|
||||
#define KVM_REG_MIPS_R30 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 30)
|
||||
#define KVM_REG_MIPS_R31 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 31)
|
||||
#define KVM_REG_MIPS_GP (KVM_REG_MIPS | 0x0000000000000000ULL)
|
||||
#define KVM_REG_MIPS_CP0 (KVM_REG_MIPS | 0x0000000000010000ULL)
|
||||
#define KVM_REG_MIPS_KVM (KVM_REG_MIPS | 0x0000000000020000ULL)
|
||||
#define KVM_REG_MIPS_FPU (KVM_REG_MIPS | 0x0000000000030000ULL)
|
||||
|
||||
#define KVM_REG_MIPS_HI (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 32)
|
||||
#define KVM_REG_MIPS_LO (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 33)
|
||||
#define KVM_REG_MIPS_PC (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 34)
|
||||
|
||||
/* KVM specific control registers */
|
||||
/*
|
||||
* KVM_REG_MIPS_GP - General purpose registers from kvm_regs.
|
||||
*/
|
||||
|
||||
#define KVM_REG_MIPS_R0 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 0)
|
||||
#define KVM_REG_MIPS_R1 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 1)
|
||||
#define KVM_REG_MIPS_R2 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 2)
|
||||
#define KVM_REG_MIPS_R3 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 3)
|
||||
#define KVM_REG_MIPS_R4 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 4)
|
||||
#define KVM_REG_MIPS_R5 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 5)
|
||||
#define KVM_REG_MIPS_R6 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 6)
|
||||
#define KVM_REG_MIPS_R7 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 7)
|
||||
#define KVM_REG_MIPS_R8 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 8)
|
||||
#define KVM_REG_MIPS_R9 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 9)
|
||||
#define KVM_REG_MIPS_R10 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 10)
|
||||
#define KVM_REG_MIPS_R11 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 11)
|
||||
#define KVM_REG_MIPS_R12 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 12)
|
||||
#define KVM_REG_MIPS_R13 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 13)
|
||||
#define KVM_REG_MIPS_R14 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 14)
|
||||
#define KVM_REG_MIPS_R15 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 15)
|
||||
#define KVM_REG_MIPS_R16 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 16)
|
||||
#define KVM_REG_MIPS_R17 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 17)
|
||||
#define KVM_REG_MIPS_R18 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 18)
|
||||
#define KVM_REG_MIPS_R19 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 19)
|
||||
#define KVM_REG_MIPS_R20 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 20)
|
||||
#define KVM_REG_MIPS_R21 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 21)
|
||||
#define KVM_REG_MIPS_R22 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 22)
|
||||
#define KVM_REG_MIPS_R23 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 23)
|
||||
#define KVM_REG_MIPS_R24 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 24)
|
||||
#define KVM_REG_MIPS_R25 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 25)
|
||||
#define KVM_REG_MIPS_R26 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 26)
|
||||
#define KVM_REG_MIPS_R27 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 27)
|
||||
#define KVM_REG_MIPS_R28 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 28)
|
||||
#define KVM_REG_MIPS_R29 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 29)
|
||||
#define KVM_REG_MIPS_R30 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 30)
|
||||
#define KVM_REG_MIPS_R31 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 31)
|
||||
|
||||
#define KVM_REG_MIPS_HI (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 32)
|
||||
#define KVM_REG_MIPS_LO (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 33)
|
||||
#define KVM_REG_MIPS_PC (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 34)
|
||||
|
||||
|
||||
/*
|
||||
* KVM_REG_MIPS_KVM - KVM specific control registers.
|
||||
*/
|
||||
|
||||
/*
|
||||
* CP0_Count control
|
||||
@ -118,8 +126,7 @@ struct kvm_fpu {
|
||||
* safely without losing time or guest timer interrupts.
|
||||
* Other: Reserved, do not change.
|
||||
*/
|
||||
#define KVM_REG_MIPS_COUNT_CTL (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \
|
||||
0x20000 | 0)
|
||||
#define KVM_REG_MIPS_COUNT_CTL (KVM_REG_MIPS_KVM | KVM_REG_SIZE_U64 | 0)
|
||||
#define KVM_REG_MIPS_COUNT_CTL_DC 0x00000001
|
||||
|
||||
/*
|
||||
@ -131,15 +138,46 @@ struct kvm_fpu {
|
||||
* emulated.
|
||||
* Modifications to times in the future are rejected.
|
||||
*/
|
||||
#define KVM_REG_MIPS_COUNT_RESUME (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \
|
||||
0x20000 | 1)
|
||||
#define KVM_REG_MIPS_COUNT_RESUME (KVM_REG_MIPS_KVM | KVM_REG_SIZE_U64 | 1)
|
||||
/*
|
||||
* CP0_Count rate in Hz
|
||||
* Specifies the rate of the CP0_Count timer in Hz. Modifications occur without
|
||||
* discontinuities in CP0_Count.
|
||||
*/
|
||||
#define KVM_REG_MIPS_COUNT_HZ (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \
|
||||
0x20000 | 2)
|
||||
#define KVM_REG_MIPS_COUNT_HZ (KVM_REG_MIPS_KVM | KVM_REG_SIZE_U64 | 2)
|
||||
|
||||
|
||||
/*
|
||||
* KVM_REG_MIPS_FPU - Floating Point and MIPS SIMD Architecture (MSA) registers.
|
||||
*
|
||||
* bits[15..8] - Register subset (see definitions below).
|
||||
* bits[7..5] - Must be zero.
|
||||
* bits[4..0] - Register number within register subset.
|
||||
*/
|
||||
|
||||
#define KVM_REG_MIPS_FPR (KVM_REG_MIPS_FPU | 0x0000000000000000ULL)
|
||||
#define KVM_REG_MIPS_FCR (KVM_REG_MIPS_FPU | 0x0000000000000100ULL)
|
||||
#define KVM_REG_MIPS_MSACR (KVM_REG_MIPS_FPU | 0x0000000000000200ULL)
|
||||
|
||||
/*
|
||||
* KVM_REG_MIPS_FPR - Floating point / Vector registers.
|
||||
*/
|
||||
#define KVM_REG_MIPS_FPR_32(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U32 | (n))
|
||||
#define KVM_REG_MIPS_FPR_64(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U64 | (n))
|
||||
#define KVM_REG_MIPS_VEC_128(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U128 | (n))
|
||||
|
||||
/*
|
||||
* KVM_REG_MIPS_FCR - Floating point control registers.
|
||||
*/
|
||||
#define KVM_REG_MIPS_FCR_IR (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 | 0)
|
||||
#define KVM_REG_MIPS_FCR_CSR (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 | 31)
|
||||
|
||||
/*
|
||||
* KVM_REG_MIPS_MSACR - MIPS SIMD Architecture (MSA) control registers.
|
||||
*/
|
||||
#define KVM_REG_MIPS_MSA_IR (KVM_REG_MIPS_MSACR | KVM_REG_SIZE_U32 | 0)
|
||||
#define KVM_REG_MIPS_MSA_CSR (KVM_REG_MIPS_MSACR | KVM_REG_SIZE_U32 | 1)
|
||||
|
||||
|
||||
/*
|
||||
* KVM MIPS specific structures and definitions
|
||||
|
@ -150,6 +150,7 @@ struct kvm_guest_debug_arch {
|
||||
#define KVM_SYNC_CRS (1UL << 3)
|
||||
#define KVM_SYNC_ARCH0 (1UL << 4)
|
||||
#define KVM_SYNC_PFAULT (1UL << 5)
|
||||
#define KVM_SYNC_VRS (1UL << 6)
|
||||
/* definition of registers in kvm_run */
|
||||
struct kvm_sync_regs {
|
||||
__u64 prefix; /* prefix register */
|
||||
@ -164,6 +165,9 @@ struct kvm_sync_regs {
|
||||
__u64 pft; /* pfault token [PFAULT] */
|
||||
__u64 pfs; /* pfault select [PFAULT] */
|
||||
__u64 pfc; /* pfault compare [PFAULT] */
|
||||
__u64 vrs[32][2]; /* vector registers */
|
||||
__u8 reserved[512]; /* for future vector expansion */
|
||||
__u32 fpc; /* only valid with vector registers */
|
||||
};
|
||||
|
||||
#define KVM_REG_S390_TODPR (KVM_REG_S390 | KVM_REG_SIZE_U32 | 0x1)
|
||||
|
@ -225,6 +225,8 @@
|
||||
#define HV_STATUS_INVALID_HYPERCALL_CODE 2
|
||||
#define HV_STATUS_INVALID_HYPERCALL_INPUT 3
|
||||
#define HV_STATUS_INVALID_ALIGNMENT 4
|
||||
#define HV_STATUS_INSUFFICIENT_MEMORY 11
|
||||
#define HV_STATUS_INVALID_CONNECTION_ID 18
|
||||
#define HV_STATUS_INSUFFICIENT_BUFFERS 19
|
||||
|
||||
typedef struct _HV_REFERENCE_TSC_PAGE {
|
||||
|
@ -147,6 +147,16 @@ struct kvm_pit_config {
|
||||
|
||||
#define KVM_PIT_SPEAKER_DUMMY 1
|
||||
|
||||
struct kvm_s390_skeys {
|
||||
__u64 start_gfn;
|
||||
__u64 count;
|
||||
__u64 skeydata_addr;
|
||||
__u32 flags;
|
||||
__u32 reserved[9];
|
||||
};
|
||||
#define KVM_S390_GET_SKEYS_NONE 1
|
||||
#define KVM_S390_SKEYS_MAX 1048576
|
||||
|
||||
#define KVM_EXIT_UNKNOWN 0
|
||||
#define KVM_EXIT_EXCEPTION 1
|
||||
#define KVM_EXIT_IO 2
|
||||
@ -172,6 +182,7 @@ struct kvm_pit_config {
|
||||
#define KVM_EXIT_S390_TSCH 22
|
||||
#define KVM_EXIT_EPR 23
|
||||
#define KVM_EXIT_SYSTEM_EVENT 24
|
||||
#define KVM_EXIT_S390_STSI 25
|
||||
|
||||
/* For KVM_EXIT_INTERNAL_ERROR */
|
||||
/* Emulate instruction failed. */
|
||||
@ -309,6 +320,15 @@ struct kvm_run {
|
||||
__u32 type;
|
||||
__u64 flags;
|
||||
} system_event;
|
||||
/* KVM_EXIT_S390_STSI */
|
||||
struct {
|
||||
__u64 addr;
|
||||
__u8 ar;
|
||||
__u8 reserved;
|
||||
__u8 fc;
|
||||
__u8 sel1;
|
||||
__u16 sel2;
|
||||
} s390_stsi;
|
||||
/* Fix the size of the union. */
|
||||
char padding[256];
|
||||
};
|
||||
@ -324,7 +344,7 @@ struct kvm_run {
|
||||
__u64 kvm_dirty_regs;
|
||||
union {
|
||||
struct kvm_sync_regs regs;
|
||||
char padding[1024];
|
||||
char padding[2048];
|
||||
} s;
|
||||
};
|
||||
|
||||
@ -365,6 +385,24 @@ struct kvm_translation {
|
||||
__u8 pad[5];
|
||||
};
|
||||
|
||||
/* for KVM_S390_MEM_OP */
|
||||
struct kvm_s390_mem_op {
|
||||
/* in */
|
||||
__u64 gaddr; /* the guest address */
|
||||
__u64 flags; /* flags */
|
||||
__u32 size; /* amount of bytes */
|
||||
__u32 op; /* type of operation */
|
||||
__u64 buf; /* buffer in userspace */
|
||||
__u8 ar; /* the access register number */
|
||||
__u8 reserved[31]; /* should be set to 0 */
|
||||
};
|
||||
/* types for kvm_s390_mem_op->op */
|
||||
#define KVM_S390_MEMOP_LOGICAL_READ 0
|
||||
#define KVM_S390_MEMOP_LOGICAL_WRITE 1
|
||||
/* flags for kvm_s390_mem_op->flags */
|
||||
#define KVM_S390_MEMOP_F_CHECK_ONLY (1ULL << 0)
|
||||
#define KVM_S390_MEMOP_F_INJECT_EXCEPTION (1ULL << 1)
|
||||
|
||||
/* for KVM_INTERRUPT */
|
||||
struct kvm_interrupt {
|
||||
/* in */
|
||||
@ -520,6 +558,13 @@ struct kvm_s390_irq {
|
||||
} u;
|
||||
};
|
||||
|
||||
struct kvm_s390_irq_state {
|
||||
__u64 buf;
|
||||
__u32 flags;
|
||||
__u32 len;
|
||||
__u32 reserved[4];
|
||||
};
|
||||
|
||||
/* for KVM_SET_GUEST_DEBUG */
|
||||
|
||||
#define KVM_GUESTDBG_ENABLE 0x00000001
|
||||
@ -760,6 +805,15 @@ struct kvm_ppc_smmu_info {
|
||||
#define KVM_CAP_PPC_ENABLE_HCALL 104
|
||||
#define KVM_CAP_CHECK_EXTENSION_VM 105
|
||||
#define KVM_CAP_S390_USER_SIGP 106
|
||||
#define KVM_CAP_S390_VECTOR_REGISTERS 107
|
||||
#define KVM_CAP_S390_MEM_OP 108
|
||||
#define KVM_CAP_S390_USER_STSI 109
|
||||
#define KVM_CAP_S390_SKEYS 110
|
||||
#define KVM_CAP_MIPS_FPU 111
|
||||
#define KVM_CAP_MIPS_MSA 112
|
||||
#define KVM_CAP_S390_INJECT_IRQ 113
|
||||
#define KVM_CAP_S390_IRQ_STATE 114
|
||||
#define KVM_CAP_PPC_HWRNG 115
|
||||
|
||||
#ifdef KVM_CAP_IRQ_ROUTING
|
||||
|
||||
@ -1135,6 +1189,16 @@ struct kvm_s390_ucas_mapping {
|
||||
#define KVM_ARM_VCPU_INIT _IOW(KVMIO, 0xae, struct kvm_vcpu_init)
|
||||
#define KVM_ARM_PREFERRED_TARGET _IOR(KVMIO, 0xaf, struct kvm_vcpu_init)
|
||||
#define KVM_GET_REG_LIST _IOWR(KVMIO, 0xb0, struct kvm_reg_list)
|
||||
/* Available with KVM_CAP_S390_MEM_OP */
|
||||
#define KVM_S390_MEM_OP _IOW(KVMIO, 0xb1, struct kvm_s390_mem_op)
|
||||
/* Available with KVM_CAP_S390_SKEYS */
|
||||
#define KVM_S390_GET_SKEYS _IOW(KVMIO, 0xb2, struct kvm_s390_skeys)
|
||||
#define KVM_S390_SET_SKEYS _IOW(KVMIO, 0xb3, struct kvm_s390_skeys)
|
||||
/* Available with KVM_CAP_S390_INJECT_IRQ */
|
||||
#define KVM_S390_IRQ _IOW(KVMIO, 0xb4, struct kvm_s390_irq)
|
||||
/* Available with KVM_CAP_S390_IRQ_STATE */
|
||||
#define KVM_S390_SET_IRQ_STATE _IOW(KVMIO, 0xb5, struct kvm_s390_irq_state)
|
||||
#define KVM_S390_GET_IRQ_STATE _IOW(KVMIO, 0xb6, struct kvm_s390_irq_state)
|
||||
|
||||
#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
|
||||
#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
|
||||
|
@ -160,6 +160,8 @@ struct vfio_device_info {
|
||||
__u32 flags;
|
||||
#define VFIO_DEVICE_FLAGS_RESET (1 << 0) /* Device supports reset */
|
||||
#define VFIO_DEVICE_FLAGS_PCI (1 << 1) /* vfio-pci device */
|
||||
#define VFIO_DEVICE_FLAGS_PLATFORM (1 << 2) /* vfio-platform device */
|
||||
#define VFIO_DEVICE_FLAGS_AMBA (1 << 3) /* vfio-amba device */
|
||||
__u32 num_regions; /* Max region index + 1 */
|
||||
__u32 num_irqs; /* Max IRQ index + 1 */
|
||||
};
|
||||
|
@ -356,7 +356,8 @@ int s390_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
void do_restart_interrupt(CPUS390XState *env);
|
||||
|
||||
static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb)
|
||||
static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb,
|
||||
uint8_t *ar)
|
||||
{
|
||||
hwaddr addr = 0;
|
||||
uint8_t reg;
|
||||
@ -366,6 +367,9 @@ static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb)
|
||||
addr = env->regs[reg];
|
||||
}
|
||||
addr += (ipb >> 16) & 0xfff;
|
||||
if (ar) {
|
||||
*ar = reg;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
@ -401,6 +405,8 @@ 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
|
||||
@ -418,6 +424,11 @@ 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)
|
||||
{
|
||||
@ -865,9 +876,13 @@ struct sysib_322 {
|
||||
uint8_t name[8];
|
||||
uint32_t caf;
|
||||
uint8_t cpi[16];
|
||||
uint8_t res3[24];
|
||||
uint8_t res5[3];
|
||||
uint8_t ext_name_encoding;
|
||||
uint32_t res3;
|
||||
uint8_t uuid[16];
|
||||
} vm[8];
|
||||
uint8_t res4[3552];
|
||||
uint8_t res4[1504];
|
||||
uint8_t ext_names[8][256];
|
||||
};
|
||||
|
||||
/* MMU defines */
|
||||
@ -952,15 +967,15 @@ 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);
|
||||
|
||||
int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, void *hostbuf, int len,
|
||||
bool is_write);
|
||||
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, dest, len) \
|
||||
s390_cpu_virt_mem_rw(cpu, laddr, dest, len, false)
|
||||
#define s390_cpu_virt_mem_write(cpu, laddr, dest, len) \
|
||||
s390_cpu_virt_mem_rw(cpu, laddr, dest, len, true)
|
||||
#define s390_cpu_virt_mem_check_write(cpu, laddr, len) \
|
||||
s390_cpu_virt_mem_rw(cpu, laddr, NULL, len, true)
|
||||
#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
|
||||
|
@ -162,7 +162,7 @@ hwaddr s390_cpu_get_phys_page_debug(CPUState *cs, vaddr vaddr)
|
||||
vaddr &= 0x7fffffff;
|
||||
}
|
||||
|
||||
mmu_translate(env, vaddr, 2, asc, &raddr, &prot, false);
|
||||
mmu_translate(env, vaddr, MMU_INST_FETCH, asc, &raddr, &prot, false);
|
||||
|
||||
return raddr;
|
||||
}
|
||||
|
@ -149,13 +149,14 @@ void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
|
||||
int ret = -ENODEV;
|
||||
int cc;
|
||||
CPUS390XState *env = &cpu->env;
|
||||
uint8_t ar;
|
||||
|
||||
addr = decode_basedisp_s(env, ipb);
|
||||
addr = decode_basedisp_s(env, ipb, &ar);
|
||||
if (addr & 3) {
|
||||
program_interrupt(env, PGM_SPECIFICATION, 2);
|
||||
return;
|
||||
}
|
||||
if (s390_cpu_virt_mem_read(cpu, addr, &schib, sizeof(schib))) {
|
||||
if (s390_cpu_virt_mem_read(cpu, addr, ar, &schib, sizeof(schib))) {
|
||||
return;
|
||||
}
|
||||
if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) ||
|
||||
@ -215,13 +216,14 @@ void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
|
||||
int ret = -ENODEV;
|
||||
int cc;
|
||||
CPUS390XState *env = &cpu->env;
|
||||
uint8_t ar;
|
||||
|
||||
addr = decode_basedisp_s(env, ipb);
|
||||
addr = decode_basedisp_s(env, ipb, &ar);
|
||||
if (addr & 3) {
|
||||
program_interrupt(env, PGM_SPECIFICATION, 2);
|
||||
return;
|
||||
}
|
||||
if (s390_cpu_virt_mem_read(cpu, addr, &orig_orb, sizeof(orb))) {
|
||||
if (s390_cpu_virt_mem_read(cpu, addr, ar, &orig_orb, sizeof(orb))) {
|
||||
return;
|
||||
}
|
||||
copy_orb_from_guest(&orb, &orig_orb);
|
||||
@ -258,8 +260,9 @@ void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb)
|
||||
uint64_t addr;
|
||||
int cc;
|
||||
CPUS390XState *env = &cpu->env;
|
||||
uint8_t ar;
|
||||
|
||||
addr = decode_basedisp_s(env, ipb);
|
||||
addr = decode_basedisp_s(env, ipb, &ar);
|
||||
if (addr & 3) {
|
||||
program_interrupt(env, PGM_SPECIFICATION, 2);
|
||||
return;
|
||||
@ -268,7 +271,7 @@ void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb)
|
||||
cc = css_do_stcrw(&crw);
|
||||
/* 0 - crw stored, 1 - zeroes stored */
|
||||
|
||||
if (s390_cpu_virt_mem_write(cpu, addr, &crw, sizeof(crw)) == 0) {
|
||||
if (s390_cpu_virt_mem_write(cpu, addr, ar, &crw, sizeof(crw)) == 0) {
|
||||
setcc(cpu, cc);
|
||||
} else if (cc == 0) {
|
||||
/* Write failed: requeue CRW since STCRW is a suppressing instruction */
|
||||
@ -284,8 +287,9 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
|
||||
int cc;
|
||||
SCHIB schib;
|
||||
CPUS390XState *env = &cpu->env;
|
||||
uint8_t ar;
|
||||
|
||||
addr = decode_basedisp_s(env, ipb);
|
||||
addr = decode_basedisp_s(env, ipb, &ar);
|
||||
if (addr & 3) {
|
||||
program_interrupt(env, PGM_SPECIFICATION, 2);
|
||||
return;
|
||||
@ -297,7 +301,7 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
|
||||
* we check whether the memory area is writeable (injecting the
|
||||
* access execption if it is not) first.
|
||||
*/
|
||||
if (!s390_cpu_virt_mem_check_write(cpu, addr, sizeof(schib))) {
|
||||
if (!s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib))) {
|
||||
program_interrupt(env, PGM_OPERAND, 2);
|
||||
}
|
||||
return;
|
||||
@ -322,12 +326,13 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
|
||||
}
|
||||
}
|
||||
if (cc != 3) {
|
||||
if (s390_cpu_virt_mem_write(cpu, addr, &schib, sizeof(schib)) != 0) {
|
||||
if (s390_cpu_virt_mem_write(cpu, addr, ar, &schib,
|
||||
sizeof(schib)) != 0) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* Access exceptions have a higher priority than cc3 */
|
||||
if (s390_cpu_virt_mem_check_write(cpu, addr, sizeof(schib)) != 0) {
|
||||
if (s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib)) != 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -342,13 +347,14 @@ int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
|
||||
IRB irb;
|
||||
uint64_t addr;
|
||||
int cc, irb_len;
|
||||
uint8_t ar;
|
||||
|
||||
if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
|
||||
program_interrupt(env, PGM_OPERAND, 2);
|
||||
return -EIO;
|
||||
}
|
||||
trace_ioinst_sch_id("tsch", cssid, ssid, schid);
|
||||
addr = decode_basedisp_s(env, ipb);
|
||||
addr = decode_basedisp_s(env, ipb, &ar);
|
||||
if (addr & 3) {
|
||||
program_interrupt(env, PGM_SPECIFICATION, 2);
|
||||
return -EIO;
|
||||
@ -362,14 +368,14 @@ int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
|
||||
}
|
||||
/* 0 - status pending, 1 - not status pending, 3 - not operational */
|
||||
if (cc != 3) {
|
||||
if (s390_cpu_virt_mem_write(cpu, addr, &irb, irb_len) != 0) {
|
||||
if (s390_cpu_virt_mem_write(cpu, addr, ar, &irb, irb_len) != 0) {
|
||||
return -EFAULT;
|
||||
}
|
||||
css_do_tsch_update_subch(sch);
|
||||
} else {
|
||||
irb_len = sizeof(irb) - sizeof(irb.emw);
|
||||
/* Access exceptions have a higher priority than cc3 */
|
||||
if (s390_cpu_virt_mem_check_write(cpu, addr, irb_len) != 0) {
|
||||
if (s390_cpu_virt_mem_check_write(cpu, addr, ar, irb_len) != 0) {
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
@ -645,7 +651,7 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb)
|
||||
* present CHSC sub-handlers ... if we ever need more, we should take
|
||||
* care of req->len here first.
|
||||
*/
|
||||
if (s390_cpu_virt_mem_read(cpu, addr, buf, sizeof(ChscReq))) {
|
||||
if (s390_cpu_virt_mem_read(cpu, addr, reg, buf, sizeof(ChscReq))) {
|
||||
return;
|
||||
}
|
||||
req = (ChscReq *)buf;
|
||||
@ -677,7 +683,8 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!s390_cpu_virt_mem_write(cpu, addr + len, res, be16_to_cpu(res->len))) {
|
||||
if (!s390_cpu_virt_mem_write(cpu, addr + len, reg, res,
|
||||
be16_to_cpu(res->len))) {
|
||||
setcc(cpu, 0); /* Command execution complete */
|
||||
}
|
||||
}
|
||||
@ -690,9 +697,10 @@ int ioinst_handle_tpi(S390CPU *cpu, uint32_t ipb)
|
||||
IOIntCode int_code;
|
||||
hwaddr len;
|
||||
int ret;
|
||||
uint8_t ar;
|
||||
|
||||
trace_ioinst("tpi");
|
||||
addr = decode_basedisp_s(env, ipb);
|
||||
addr = decode_basedisp_s(env, ipb, &ar);
|
||||
if (addr & 3) {
|
||||
program_interrupt(env, PGM_SPECIFICATION, 2);
|
||||
return -EIO;
|
||||
@ -702,7 +710,7 @@ int ioinst_handle_tpi(S390CPU *cpu, uint32_t ipb)
|
||||
len = lowcore ? 8 /* two words */ : 12 /* three words */;
|
||||
ret = css_do_tpi(&int_code, lowcore);
|
||||
if (ret == 1) {
|
||||
s390_cpu_virt_mem_write(cpu, lowcore ? 184 : addr, &int_code, len);
|
||||
s390_cpu_virt_mem_write(cpu, lowcore ? 184 : addr, ar, &int_code, len);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "hw/s390x/s390-pci-inst.h"
|
||||
#include "hw/s390x/s390-pci-bus.h"
|
||||
#include "hw/s390x/ipl.h"
|
||||
#include "hw/s390x/ebcdic.h"
|
||||
|
||||
/* #define DEBUG_KVM */
|
||||
|
||||
@ -122,6 +123,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
|
||||
|
||||
static int cap_sync_regs;
|
||||
static int cap_async_pf;
|
||||
static int cap_mem_op;
|
||||
|
||||
static void *legacy_s390_alloc(size_t size, uint64_t *align);
|
||||
|
||||
@ -246,6 +248,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
{
|
||||
cap_sync_regs = kvm_check_extension(s, KVM_CAP_SYNC_REGS);
|
||||
cap_async_pf = kvm_check_extension(s, KVM_CAP_ASYNC_PF);
|
||||
cap_mem_op = kvm_check_extension(s, KVM_CAP_S390_MEM_OP);
|
||||
|
||||
kvm_s390_enable_cmma(s);
|
||||
|
||||
@ -255,6 +258,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
}
|
||||
|
||||
kvm_vm_enable_cap(s, KVM_CAP_S390_USER_SIGP, 0);
|
||||
kvm_vm_enable_cap(s, KVM_CAP_S390_USER_STSI, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -548,6 +552,46 @@ int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
|
||||
return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* kvm_s390_mem_op:
|
||||
* @addr: the logical start address in guest memory
|
||||
* @ar: the access register number
|
||||
* @hostbuf: buffer in host memory. NULL = do only checks w/o copying
|
||||
* @len: length that should be transfered
|
||||
* @is_write: true = write, false = read
|
||||
* Returns: 0 on success, non-zero if an exception or error occured
|
||||
*
|
||||
* Use KVM ioctl to read/write from/to guest memory. An access exception
|
||||
* is injected into the vCPU in case of translation errors.
|
||||
*/
|
||||
int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf,
|
||||
int len, bool is_write)
|
||||
{
|
||||
struct kvm_s390_mem_op mem_op = {
|
||||
.gaddr = addr,
|
||||
.flags = KVM_S390_MEMOP_F_INJECT_EXCEPTION,
|
||||
.size = len,
|
||||
.op = is_write ? KVM_S390_MEMOP_LOGICAL_WRITE
|
||||
: KVM_S390_MEMOP_LOGICAL_READ,
|
||||
.buf = (uint64_t)hostbuf,
|
||||
.ar = ar,
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (!cap_mem_op) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
if (!hostbuf) {
|
||||
mem_op.flags |= KVM_S390_MEMOP_F_CHECK_ONLY;
|
||||
}
|
||||
|
||||
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_S390_MEM_OP, &mem_op);
|
||||
if (ret < 0) {
|
||||
error_printf("KVM_S390_MEM_OP failed: %s\n", strerror(-ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Legacy layout for s390:
|
||||
* Older S390 KVM requires the topmost vma of the RAM to be
|
||||
@ -975,7 +1019,8 @@ static int handle_b2(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static uint64_t get_base_disp_rxy(S390CPU *cpu, struct kvm_run *run)
|
||||
static uint64_t get_base_disp_rxy(S390CPU *cpu, struct kvm_run *run,
|
||||
uint8_t *ar)
|
||||
{
|
||||
CPUS390XState *env = &cpu->env;
|
||||
uint32_t x2 = (run->s390_sieic.ipa & 0x000f);
|
||||
@ -986,12 +1031,16 @@ static uint64_t get_base_disp_rxy(S390CPU *cpu, struct kvm_run *run)
|
||||
if (disp2 & 0x80000) {
|
||||
disp2 += 0xfff00000;
|
||||
}
|
||||
if (ar) {
|
||||
*ar = base2;
|
||||
}
|
||||
|
||||
return (base2 ? env->regs[base2] : 0) +
|
||||
(x2 ? env->regs[x2] : 0) + (long)(int)disp2;
|
||||
}
|
||||
|
||||
static uint64_t get_base_disp_rsy(S390CPU *cpu, struct kvm_run *run)
|
||||
static uint64_t get_base_disp_rsy(S390CPU *cpu, struct kvm_run *run,
|
||||
uint8_t *ar)
|
||||
{
|
||||
CPUS390XState *env = &cpu->env;
|
||||
uint32_t base2 = run->s390_sieic.ipb >> 28;
|
||||
@ -1001,6 +1050,9 @@ static uint64_t get_base_disp_rsy(S390CPU *cpu, struct kvm_run *run)
|
||||
if (disp2 & 0x80000) {
|
||||
disp2 += 0xfff00000;
|
||||
}
|
||||
if (ar) {
|
||||
*ar = base2;
|
||||
}
|
||||
|
||||
return (base2 ? env->regs[base2] : 0) + (long)(int)disp2;
|
||||
}
|
||||
@ -1032,11 +1084,12 @@ static int kvm_stpcifc_service_call(S390CPU *cpu, struct kvm_run *run)
|
||||
{
|
||||
uint8_t r1 = (run->s390_sieic.ipa & 0x00f0) >> 4;
|
||||
uint64_t fiba;
|
||||
uint8_t ar;
|
||||
|
||||
cpu_synchronize_state(CPU(cpu));
|
||||
fiba = get_base_disp_rxy(cpu, run);
|
||||
fiba = get_base_disp_rxy(cpu, run, &ar);
|
||||
|
||||
return stpcifc_service_call(cpu, r1, fiba);
|
||||
return stpcifc_service_call(cpu, r1, fiba, ar);
|
||||
}
|
||||
|
||||
static int kvm_sic_service_call(S390CPU *cpu, struct kvm_run *run)
|
||||
@ -1058,22 +1111,24 @@ static int kvm_pcistb_service_call(S390CPU *cpu, struct kvm_run *run)
|
||||
uint8_t r1 = (run->s390_sieic.ipa & 0x00f0) >> 4;
|
||||
uint8_t r3 = run->s390_sieic.ipa & 0x000f;
|
||||
uint64_t gaddr;
|
||||
uint8_t ar;
|
||||
|
||||
cpu_synchronize_state(CPU(cpu));
|
||||
gaddr = get_base_disp_rsy(cpu, run);
|
||||
gaddr = get_base_disp_rsy(cpu, run, &ar);
|
||||
|
||||
return pcistb_service_call(cpu, r1, r3, gaddr);
|
||||
return pcistb_service_call(cpu, r1, r3, gaddr, ar);
|
||||
}
|
||||
|
||||
static int kvm_mpcifc_service_call(S390CPU *cpu, struct kvm_run *run)
|
||||
{
|
||||
uint8_t r1 = (run->s390_sieic.ipa & 0x00f0) >> 4;
|
||||
uint64_t fiba;
|
||||
uint8_t ar;
|
||||
|
||||
cpu_synchronize_state(CPU(cpu));
|
||||
fiba = get_base_disp_rxy(cpu, run);
|
||||
fiba = get_base_disp_rxy(cpu, run, &ar);
|
||||
|
||||
return mpcifc_service_call(cpu, r1, fiba);
|
||||
return mpcifc_service_call(cpu, r1, fiba, ar);
|
||||
}
|
||||
|
||||
static int handle_b9(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
|
||||
@ -1202,7 +1257,7 @@ static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb)
|
||||
* For any diagnose call we support, bits 48-63 of the resulting
|
||||
* address specify the function code; the remainder is ignored.
|
||||
*/
|
||||
func_code = decode_basedisp_rs(&cpu->env, ipb) & DIAG_KVM_CODE_MASK;
|
||||
func_code = decode_basedisp_rs(&cpu->env, ipb, NULL) & DIAG_KVM_CODE_MASK;
|
||||
switch (func_code) {
|
||||
case DIAG_IPL:
|
||||
kvm_handle_diag_308(cpu, run);
|
||||
@ -1549,7 +1604,8 @@ static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
|
||||
cpu_synchronize_state(CPU(cpu));
|
||||
|
||||
/* get order code */
|
||||
order = decode_basedisp_rs(env, run->s390_sieic.ipb) & SIGP_ORDER_MASK;
|
||||
order = decode_basedisp_rs(env, run->s390_sieic.ipb, NULL)
|
||||
& SIGP_ORDER_MASK;
|
||||
status_reg = &env->regs[r1];
|
||||
param = (r1 % 2) ? env->regs[r1] : env->regs[r1 + 1];
|
||||
|
||||
@ -1723,6 +1779,72 @@ static int handle_tsch(S390CPU *cpu)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void insert_stsi_3_2_2(S390CPU *cpu, __u64 addr, uint8_t ar)
|
||||
{
|
||||
struct sysib_322 sysib;
|
||||
int del;
|
||||
|
||||
if (s390_cpu_virt_mem_read(cpu, addr, ar, &sysib, sizeof(sysib))) {
|
||||
return;
|
||||
}
|
||||
/* Shift the stack of Extended Names to prepare for our own data */
|
||||
memmove(&sysib.ext_names[1], &sysib.ext_names[0],
|
||||
sizeof(sysib.ext_names[0]) * (sysib.count - 1));
|
||||
/* First virt level, that doesn't provide Ext Names delimits stack. It is
|
||||
* assumed it's not capable of managing Extended Names for lower levels.
|
||||
*/
|
||||
for (del = 1; del < sysib.count; del++) {
|
||||
if (!sysib.vm[del].ext_name_encoding || !sysib.ext_names[del][0]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (del < sysib.count) {
|
||||
memset(sysib.ext_names[del], 0,
|
||||
sizeof(sysib.ext_names[0]) * (sysib.count - del));
|
||||
}
|
||||
/* Insert short machine name in EBCDIC, padded with blanks */
|
||||
if (qemu_name) {
|
||||
memset(sysib.vm[0].name, 0x40, sizeof(sysib.vm[0].name));
|
||||
ebcdic_put(sysib.vm[0].name, qemu_name, MIN(sizeof(sysib.vm[0].name),
|
||||
strlen(qemu_name)));
|
||||
}
|
||||
sysib.vm[0].ext_name_encoding = 2; /* 2 = UTF-8 */
|
||||
memset(sysib.ext_names[0], 0, sizeof(sysib.ext_names[0]));
|
||||
/* If hypervisor specifies zero Extended Name in STSI322 SYSIB, it's
|
||||
* considered by s390 as not capable of providing any Extended Name.
|
||||
* Therefore if no name was specified on qemu invocation, we go with the
|
||||
* same "KVMguest" default, which KVM has filled into short name field.
|
||||
*/
|
||||
if (qemu_name) {
|
||||
strncpy((char *)sysib.ext_names[0], qemu_name,
|
||||
sizeof(sysib.ext_names[0]));
|
||||
} else {
|
||||
strcpy((char *)sysib.ext_names[0], "KVMguest");
|
||||
}
|
||||
/* Insert UUID */
|
||||
memcpy(sysib.vm[0].uuid, qemu_uuid, sizeof(sysib.vm[0].uuid));
|
||||
|
||||
s390_cpu_virt_mem_write(cpu, addr, ar, &sysib, sizeof(sysib));
|
||||
}
|
||||
|
||||
static int handle_stsi(S390CPU *cpu)
|
||||
{
|
||||
CPUState *cs = CPU(cpu);
|
||||
struct kvm_run *run = cs->kvm_run;
|
||||
|
||||
switch (run->s390_stsi.fc) {
|
||||
case 3:
|
||||
if (run->s390_stsi.sel1 != 2 || run->s390_stsi.sel2 != 2) {
|
||||
return 0;
|
||||
}
|
||||
/* Only sysib 3.2.2 needs post-handling for now. */
|
||||
insert_stsi_3_2_2(cpu, run->s390_stsi.addr, run->s390_stsi.ar);
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int kvm_arch_handle_debug_exit(S390CPU *cpu)
|
||||
{
|
||||
CPUState *cs = CPU(cpu);
|
||||
@ -1772,6 +1894,9 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||
case KVM_EXIT_S390_TSCH:
|
||||
ret = handle_tsch(cpu);
|
||||
break;
|
||||
case KVM_EXIT_S390_STSI:
|
||||
ret = handle_stsi(cpu);
|
||||
break;
|
||||
case KVM_EXIT_DEBUG:
|
||||
ret = kvm_arch_handle_debug_exit(cpu);
|
||||
break;
|
||||
|
@ -68,7 +68,7 @@ static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr,
|
||||
{
|
||||
uint64_t tec;
|
||||
|
||||
tec = vaddr | (rw == 1 ? FS_WRITE : FS_READ) | 4 | asc >> 46;
|
||||
tec = vaddr | (rw == MMU_DATA_STORE ? FS_WRITE : FS_READ) | 4 | asc >> 46;
|
||||
|
||||
DPRINTF("%s: trans_exc_code=%016" PRIx64 "\n", __func__, tec);
|
||||
|
||||
@ -85,7 +85,7 @@ static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
|
||||
int ilen = ILEN_LATER;
|
||||
uint64_t tec;
|
||||
|
||||
tec = vaddr | (rw == 1 ? FS_WRITE : FS_READ) | asc >> 46;
|
||||
tec = vaddr | (rw == MMU_DATA_STORE ? FS_WRITE : FS_READ) | asc >> 46;
|
||||
|
||||
DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
|
||||
|
||||
@ -94,7 +94,7 @@ static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
|
||||
}
|
||||
|
||||
/* Code accesses have an undefined ilc. */
|
||||
if (rw == 2) {
|
||||
if (rw == MMU_INST_FETCH) {
|
||||
ilen = 2;
|
||||
}
|
||||
|
||||
@ -288,7 +288,7 @@ static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,
|
||||
|
||||
r = mmu_translate_region(env, vaddr, asc, asce, level, raddr, flags, rw,
|
||||
exc);
|
||||
if ((rw == 1) && !(*flags & PAGE_WRITE)) {
|
||||
if (rw == MMU_DATA_STORE && !(*flags & PAGE_WRITE)) {
|
||||
trigger_prot_fault(env, vaddr, asc, rw, exc);
|
||||
return -1;
|
||||
}
|
||||
@ -338,7 +338,7 @@ int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
|
||||
* Instruction: Primary
|
||||
* Data: Secondary
|
||||
*/
|
||||
if (rw == 2) {
|
||||
if (rw == MMU_INST_FETCH) {
|
||||
r = mmu_translate_asce(env, vaddr, PSW_ASC_PRIMARY, env->cregs[1],
|
||||
raddr, flags, rw, exc);
|
||||
*flags &= ~(PAGE_READ | PAGE_WRITE);
|
||||
@ -435,6 +435,7 @@ static int translate_pages(S390CPU *cpu, vaddr addr, int nr_pages,
|
||||
/**
|
||||
* s390_cpu_virt_mem_rw:
|
||||
* @laddr: the logical start address
|
||||
* @ar: the access register number
|
||||
* @hostbuf: buffer in host memory. NULL = do only checks w/o copying
|
||||
* @len: length that should be transfered
|
||||
* @is_write: true = write, false = read
|
||||
@ -443,13 +444,20 @@ static int translate_pages(S390CPU *cpu, vaddr addr, int nr_pages,
|
||||
* Copy from/to guest memory using logical addresses. Note that we inject a
|
||||
* program interrupt in case there is an error while accessing the memory.
|
||||
*/
|
||||
int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, void *hostbuf,
|
||||
int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, uint8_t ar, void *hostbuf,
|
||||
int len, bool is_write)
|
||||
{
|
||||
int currlen, nr_pages, i;
|
||||
target_ulong *pages;
|
||||
int ret;
|
||||
|
||||
if (kvm_enabled()) {
|
||||
ret = kvm_s390_mem_op(cpu, laddr, ar, hostbuf, len, is_write);
|
||||
if (ret >= 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
nr_pages = (((laddr & ~TARGET_PAGE_MASK) + len - 1) >> TARGET_PAGE_BITS)
|
||||
+ 1;
|
||||
pages = g_malloc(nr_pages * sizeof(*pages));
|
||||
|
Loading…
Reference in New Issue
Block a user