Final batch of s390x enhancements/fixes for 2.3:
- handle TOD clock during migration - CPACF key wrap options - limit amount of pci device code we build - ensure big endian accesses for ccws - various fixes and cleanups -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJVBqoIAAoJEN7Pa5PG8C+v1XQP/2eZN3Ok9XjpHS/+tGSKcS7k 1UIFffWRoez5bcBez6EMaenOeI6PbBGX/6V+MRmdDCjijcvxcTYeXjbhOOLAmEaN ByKLEOVKkuYTKn3jdffWa9wU9f0tyAqeRs2wJPGFUtYEQ/mxR+A4zJAXFJPzr+ZU RoghwK7ii7CACsarVKShQSVvfj33Ick3f1t3bB031Rq4yBdPP+fubKBp4DyYgPui fU5NpkPDcblBfXTnwqOeCgxCR6JF9KuEvLsiGgb62zZrXcu/1kluROEUkgBSxdBs DLui2plFbx7RYxzJIH+wOl3ENwhbuPg54hXSd1JVFDBA4kiDepTjRzo3fcLzBHZZ PLf6Awf7xCmJluwHwlv9rkkNCJiGKabiI2vmQ+G8uIXMR23VGjuNKcOy2ugPX0RJ /dyn9to44TWpyc9uVmMTQh7qTx4wJbw8FjqJOlMObeswUwwjAWYVKa+Kwk/bur0H FFCHrqgrmPobI0x0xgYznKojJkZ/cHr7FkJTGrYxk05vu7wPV2mkBXxN9uVq9F0e byTk3/IrBtDdj1UlLHJLGfRrleLMFkRb74FqvFYAOZlg8K5z0hXIoZiV10V6QEVU dFD//CFPCO3KxeB8Mcak6osO2thEScNZurq3x5QrebeMUW7gwAwDYvzT8OPdmqR9 yLmGZ8KJ8pE5OVzW23Yq =wS11 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20150316' into staging Final batch of s390x enhancements/fixes for 2.3: - handle TOD clock during migration - CPACF key wrap options - limit amount of pci device code we build - ensure big endian accesses for ccws - various fixes and cleanups # gpg: Signature made Mon Mar 16 10:01:44 2015 GMT 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-20150316: s390x/config: Do not include full pci.mak s390x/pci: fix length in sei_nt2 event s390x/ipl: remove dead code s390x/virtio-bus: Remove unused function s390_virtio_bus_console() s390x: CPACF: Handle key wrap machine options s390x/kvm: make use of generic vm attribute check kvm: encapsulate HAS_DEVICE for vm attrs virtio-ccw: assure BE accesses s390x/kvm: Guest Migration TOD clock synchronization s390x: Replace unchecked qdev_init() by qdev_init_nofail() Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
2dfe7d07e2
@ -1,4 +1,5 @@
|
||||
include pci.mak
|
||||
CONFIG_PCI=y
|
||||
CONFIG_VIRTIO_PCI=y
|
||||
CONFIG_VIRTIO=y
|
||||
CONFIG_SCLPCONSOLE=y
|
||||
CONFIG_S390_FLIC=y
|
||||
|
@ -30,7 +30,6 @@ S390FLICState *s390_get_flic(void)
|
||||
void s390_flic_init(void)
|
||||
{
|
||||
DeviceState *dev;
|
||||
int r;
|
||||
|
||||
dev = s390_flic_kvm_create();
|
||||
if (!dev) {
|
||||
@ -38,10 +37,7 @@ void s390_flic_init(void)
|
||||
object_property_add_child(qdev_get_machine(), TYPE_QEMU_S390_FLIC,
|
||||
OBJECT(dev), NULL);
|
||||
}
|
||||
r = qdev_init(dev);
|
||||
if (r) {
|
||||
error_report("flic: couldn't create qdev");
|
||||
}
|
||||
qdev_init_nofail(dev);
|
||||
}
|
||||
|
||||
static int qemu_s390_register_io_adapter(S390FLICState *fs, uint32_t id,
|
||||
|
@ -142,9 +142,6 @@ static int s390_ipl_init(SysBusDevice *dev)
|
||||
bios_size = load_image_targphys(bios_filename, ZIPL_IMAGE_START,
|
||||
4096);
|
||||
ipl->bios_start_addr = ZIPL_IMAGE_START;
|
||||
if (bios_size > 4096) {
|
||||
hw_error("stage1 bootloader is > 4k\n");
|
||||
}
|
||||
}
|
||||
g_free(bios_filename);
|
||||
|
||||
|
@ -44,6 +44,7 @@ int chsc_sei_nt2_get_event(void *res)
|
||||
QTAILQ_REMOVE(&s->pending_sei, sei_cont, link);
|
||||
nt2_res->nt = 2;
|
||||
nt2_res->cc = sei_cont->cc;
|
||||
nt2_res->length = cpu_to_be16(sizeof(ChscSeiNt2Res));
|
||||
switch (sei_cont->cc) {
|
||||
case 1: /* error event */
|
||||
eccdf = (PciCcdfErr *)nt2_res->ccdf;
|
||||
|
@ -435,11 +435,6 @@ void s390_virtio_device_update_status(VirtIOS390Device *dev)
|
||||
virtio_set_features(vdev, features);
|
||||
}
|
||||
|
||||
VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus)
|
||||
{
|
||||
return bus->console;
|
||||
}
|
||||
|
||||
/* Find a device by vring address */
|
||||
VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus,
|
||||
ram_addr_t mem,
|
||||
|
@ -108,7 +108,6 @@ typedef struct VirtIOS390Bus {
|
||||
|
||||
void s390_virtio_device_update_status(VirtIOS390Device *dev);
|
||||
|
||||
VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus);
|
||||
VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size);
|
||||
|
||||
VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus,
|
||||
|
@ -22,6 +22,18 @@
|
||||
|
||||
#define TYPE_S390_CCW_MACHINE "s390-ccw-machine"
|
||||
|
||||
#define S390_CCW_MACHINE(obj) \
|
||||
OBJECT_CHECK(S390CcwMachineState, (obj), TYPE_S390_CCW_MACHINE)
|
||||
|
||||
typedef struct S390CcwMachineState {
|
||||
/*< private >*/
|
||||
MachineState parent_obj;
|
||||
|
||||
/*< public >*/
|
||||
bool aes_key_wrap;
|
||||
bool dea_key_wrap;
|
||||
} S390CcwMachineState;
|
||||
|
||||
void io_subsystem_reset(void)
|
||||
{
|
||||
DeviceState *css, *sclp, *flic;
|
||||
@ -181,6 +193,10 @@ static void ccw_init(MachineState *machine)
|
||||
|
||||
/* Create VirtIO network adapters */
|
||||
s390_create_virtio_net(BUS(css_bus), "virtio-net-ccw");
|
||||
|
||||
/* Register savevm handler for guest TOD clock */
|
||||
register_savevm(NULL, "todclock", 0, 1,
|
||||
gtod_save, gtod_load, kvm_state);
|
||||
}
|
||||
|
||||
static void ccw_machine_class_init(ObjectClass *oc, void *data)
|
||||
@ -203,9 +219,60 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data)
|
||||
nc->nmi_monitor_handler = s390_nmi;
|
||||
}
|
||||
|
||||
static inline bool machine_get_aes_key_wrap(Object *obj, Error **errp)
|
||||
{
|
||||
S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
|
||||
|
||||
return ms->aes_key_wrap;
|
||||
}
|
||||
|
||||
static inline void machine_set_aes_key_wrap(Object *obj, bool value,
|
||||
Error **errp)
|
||||
{
|
||||
S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
|
||||
|
||||
ms->aes_key_wrap = value;
|
||||
}
|
||||
|
||||
static inline bool machine_get_dea_key_wrap(Object *obj, Error **errp)
|
||||
{
|
||||
S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
|
||||
|
||||
return ms->dea_key_wrap;
|
||||
}
|
||||
|
||||
static inline void machine_set_dea_key_wrap(Object *obj, bool value,
|
||||
Error **errp)
|
||||
{
|
||||
S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
|
||||
|
||||
ms->dea_key_wrap = value;
|
||||
}
|
||||
|
||||
static inline void s390_machine_initfn(Object *obj)
|
||||
{
|
||||
object_property_add_bool(obj, "aes-key-wrap",
|
||||
machine_get_aes_key_wrap,
|
||||
machine_set_aes_key_wrap, NULL);
|
||||
object_property_set_description(obj, "aes-key-wrap",
|
||||
"enable/disable AES key wrapping using the CPACF wrapping key",
|
||||
NULL);
|
||||
object_property_set_bool(obj, true, "aes-key-wrap", NULL);
|
||||
|
||||
object_property_add_bool(obj, "dea-key-wrap",
|
||||
machine_get_dea_key_wrap,
|
||||
machine_set_dea_key_wrap, NULL);
|
||||
object_property_set_description(obj, "dea-key-wrap",
|
||||
"enable/disable DEA key wrapping using the CPACF wrapping key",
|
||||
NULL);
|
||||
object_property_set_bool(obj, true, "dea-key-wrap", NULL);
|
||||
}
|
||||
|
||||
static const TypeInfo ccw_machine_info = {
|
||||
.name = TYPE_S390_CCW_MACHINE,
|
||||
.parent = TYPE_MACHINE,
|
||||
.instance_size = sizeof(S390CcwMachineState),
|
||||
.instance_init = s390_machine_initfn,
|
||||
.class_init = ccw_machine_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ TYPE_NMI },
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "hw/s390x/sclp.h"
|
||||
#include "hw/s390x/s390_flic.h"
|
||||
#include "hw/s390x/s390-virtio.h"
|
||||
#include "cpu.h"
|
||||
|
||||
//#define DEBUG_S390
|
||||
|
||||
@ -53,6 +54,9 @@
|
||||
#define ZIPL_FILENAME "s390-zipl.rom"
|
||||
#define TYPE_S390_MACHINE "s390-machine"
|
||||
|
||||
#define S390_TOD_CLOCK_VALUE_MISSING 0x00
|
||||
#define S390_TOD_CLOCK_VALUE_PRESENT 0x01
|
||||
|
||||
static VirtIOS390Bus *s390_bus;
|
||||
static S390CPU **ipi_states;
|
||||
|
||||
@ -196,6 +200,51 @@ void s390_create_virtio_net(BusState *bus, const char *name)
|
||||
}
|
||||
}
|
||||
|
||||
void gtod_save(QEMUFile *f, void *opaque)
|
||||
{
|
||||
uint64_t tod_low;
|
||||
uint8_t tod_high;
|
||||
int r;
|
||||
|
||||
r = s390_get_clock(&tod_high, &tod_low);
|
||||
if (r) {
|
||||
fprintf(stderr, "WARNING: Unable to get guest clock for migration. "
|
||||
"Error code %d. Guest clock will not be migrated "
|
||||
"which could cause the guest to hang.\n", r);
|
||||
qemu_put_byte(f, S390_TOD_CLOCK_VALUE_MISSING);
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_put_byte(f, S390_TOD_CLOCK_VALUE_PRESENT);
|
||||
qemu_put_byte(f, tod_high);
|
||||
qemu_put_be64(f, tod_low);
|
||||
}
|
||||
|
||||
int gtod_load(QEMUFile *f, void *opaque, int version_id)
|
||||
{
|
||||
uint64_t tod_low;
|
||||
uint8_t tod_high;
|
||||
int r;
|
||||
|
||||
if (qemu_get_byte(f) == S390_TOD_CLOCK_VALUE_MISSING) {
|
||||
fprintf(stderr, "WARNING: Guest clock was not migrated. This could "
|
||||
"cause the guest to hang.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
tod_high = qemu_get_byte(f);
|
||||
tod_low = qemu_get_be64(f);
|
||||
|
||||
r = s390_set_clock(&tod_high, &tod_low);
|
||||
if (r) {
|
||||
fprintf(stderr, "WARNING: Unable to set guest clock value. "
|
||||
"s390_get_clock returned error %d. This could cause "
|
||||
"the guest to hang.\n", r);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* PC hardware initialisation */
|
||||
static void s390_init(MachineState *machine)
|
||||
{
|
||||
@ -253,6 +302,9 @@ static void s390_init(MachineState *machine)
|
||||
|
||||
/* Create VirtIO network adapters */
|
||||
s390_create_virtio_net((BusState *)s390_bus, "virtio-net-s390");
|
||||
|
||||
/* Register savevm handler for guest TOD clock */
|
||||
register_savevm(NULL, "todclock", 0, 1, gtod_save, gtod_load, NULL);
|
||||
}
|
||||
|
||||
void s390_nmi(NMIState *n, int cpu_index, Error **errp)
|
||||
|
@ -508,7 +508,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||
if (!ccw.cda) {
|
||||
ret = -EFAULT;
|
||||
} else {
|
||||
indicators = ldq_phys(&address_space_memory, ccw.cda);
|
||||
indicators = ldq_be_phys(&address_space_memory, ccw.cda);
|
||||
dev->indicators = get_indicator(indicators, sizeof(uint64_t));
|
||||
sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
|
||||
ret = 0;
|
||||
@ -528,7 +528,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||
if (!ccw.cda) {
|
||||
ret = -EFAULT;
|
||||
} else {
|
||||
indicators = ldq_phys(&address_space_memory, ccw.cda);
|
||||
indicators = ldq_be_phys(&address_space_memory, ccw.cda);
|
||||
dev->indicators2 = get_indicator(indicators, sizeof(uint64_t));
|
||||
sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
|
||||
ret = 0;
|
||||
@ -548,11 +548,11 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||
if (!ccw.cda) {
|
||||
ret = -EFAULT;
|
||||
} else {
|
||||
vq_config.index = lduw_phys(&address_space_memory, ccw.cda);
|
||||
vq_config.index = lduw_be_phys(&address_space_memory, ccw.cda);
|
||||
vq_config.num_max = virtio_queue_get_num(vdev,
|
||||
vq_config.index);
|
||||
stw_phys(&address_space_memory,
|
||||
ccw.cda + sizeof(vq_config.index), vq_config.num_max);
|
||||
stw_be_phys(&address_space_memory,
|
||||
ccw.cda + sizeof(vq_config.index), vq_config.num_max);
|
||||
sch->curr_status.scsw.count = ccw.count - sizeof(vq_config);
|
||||
ret = 0;
|
||||
}
|
||||
@ -580,13 +580,17 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||
if (!thinint) {
|
||||
ret = -EFAULT;
|
||||
} else {
|
||||
uint64_t ind_bit = ldq_be_p(&thinint->ind_bit);
|
||||
|
||||
len = hw_len;
|
||||
dev->summary_indicator =
|
||||
get_indicator(thinint->summary_indicator, sizeof(uint8_t));
|
||||
dev->indicators = get_indicator(thinint->device_indicator,
|
||||
thinint->ind_bit / 8 + 1);
|
||||
get_indicator(ldq_be_p(&thinint->summary_indicator),
|
||||
sizeof(uint8_t));
|
||||
dev->indicators =
|
||||
get_indicator(ldq_be_p(&thinint->device_indicator),
|
||||
ind_bit / 8 + 1);
|
||||
dev->thinint_isc = thinint->isc;
|
||||
dev->routes.adapter.ind_offset = thinint->ind_bit;
|
||||
dev->routes.adapter.ind_offset = ind_bit;
|
||||
dev->routes.adapter.summary_offset = 7;
|
||||
cpu_physical_memory_unmap(thinint, hw_len, 0, hw_len);
|
||||
ret = css_register_io_adapter(CSS_IO_ADAPTER_VIRTIO,
|
||||
|
@ -224,6 +224,18 @@ int kvm_vcpu_ioctl(CPUState *cpu, int type, ...);
|
||||
*/
|
||||
int kvm_device_ioctl(int fd, int type, ...);
|
||||
|
||||
/**
|
||||
* kvm_vm_check_attr - check for existence of a specific vm attribute
|
||||
* @s: The KVMState pointer
|
||||
* @group: the group
|
||||
* @attr: the attribute of that group to query for
|
||||
*
|
||||
* Returns: 1 if the attribute exists
|
||||
* 0 if the attribute either does not exist or if the vm device
|
||||
* interface is unavailable
|
||||
*/
|
||||
int kvm_vm_check_attr(KVMState *s, uint32_t group, uint64_t attr);
|
||||
|
||||
/**
|
||||
* kvm_create_device - create a KVM device for the device control API
|
||||
* @KVMState: The KVMState pointer
|
||||
|
21
kvm-all.c
21
kvm-all.c
@ -126,6 +126,7 @@ bool kvm_gsi_routing_allowed;
|
||||
bool kvm_gsi_direct_mapping;
|
||||
bool kvm_allowed;
|
||||
bool kvm_readonly_mem_allowed;
|
||||
bool kvm_vm_attributes_allowed;
|
||||
|
||||
static const KVMCapabilityInfo kvm_required_capabilites[] = {
|
||||
KVM_CAP_INFO(USER_MEMORY),
|
||||
@ -1598,6 +1599,9 @@ static int kvm_init(MachineState *ms)
|
||||
kvm_resamplefds_allowed =
|
||||
(kvm_check_extension(s, KVM_CAP_IRQFD_RESAMPLE) > 0);
|
||||
|
||||
kvm_vm_attributes_allowed =
|
||||
(kvm_check_extension(s, KVM_CAP_VM_ATTRIBUTES) > 0);
|
||||
|
||||
ret = kvm_arch_init(ms, s);
|
||||
if (ret < 0) {
|
||||
goto err;
|
||||
@ -1936,6 +1940,23 @@ int kvm_device_ioctl(int fd, int type, ...)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int kvm_vm_check_attr(KVMState *s, uint32_t group, uint64_t attr)
|
||||
{
|
||||
int ret;
|
||||
struct kvm_device_attr attribute = {
|
||||
.group = group,
|
||||
.attr = attr,
|
||||
};
|
||||
|
||||
if (!kvm_vm_attributes_allowed) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = kvm_vm_ioctl(s, KVM_HAS_DEVICE_ATTR, &attribute);
|
||||
/* kvm returns 0 on success for HAS_DEVICE_ATTR */
|
||||
return ret ? 0 : 1;
|
||||
}
|
||||
|
||||
int kvm_has_sync_mmu(void)
|
||||
{
|
||||
return kvm_check_extension(kvm_state, KVM_CAP_SYNC_MMU);
|
||||
|
@ -37,7 +37,9 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
|
||||
" kvm_shadow_mem=size of KVM shadow MMU\n"
|
||||
" dump-guest-core=on|off include guest memory in a core dump (default=on)\n"
|
||||
" mem-merge=on|off controls memory merge support (default: on)\n"
|
||||
" iommu=on|off controls emulated Intel IOMMU (VT-d) support (default=off)\n",
|
||||
" iommu=on|off controls emulated Intel IOMMU (VT-d) support (default=off)\n"
|
||||
" aes-key-wrap=on|off controls support for AES key wrapping (default=on)\n"
|
||||
" dea-key-wrap=on|off controls support for DEA key wrapping (default=on)\n",
|
||||
QEMU_ARCH_ALL)
|
||||
STEXI
|
||||
@item -machine [type=]@var{name}[,prop=@var{value}[,...]]
|
||||
@ -66,6 +68,14 @@ the host, de-duplicates identical memory pages among VMs instances
|
||||
(enabled by default).
|
||||
@item iommu=on|off
|
||||
Enables or disables emulated Intel IOMMU (VT-d) support. The default is off.
|
||||
@item aes-key-wrap=on|off
|
||||
Enables or disables AES key wrapping support on s390-ccw hosts. This feature
|
||||
controls whether AES wrapping keys will be created to allow
|
||||
execution of AES cryptographic functions. The default is on.
|
||||
@item dea-key-wrap=on|off
|
||||
Enables or disables DEA key wrapping support on s390-ccw hosts. This feature
|
||||
controls whether DEA wrapping keys will be created to allow
|
||||
execution of DEA cryptographic functions. The default is on.
|
||||
@end table
|
||||
ETEXI
|
||||
|
||||
|
@ -401,6 +401,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_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_virtio_irq(int config_change, uint64_t token)
|
||||
{
|
||||
@ -408,11 +410,40 @@ static inline void kvm_s390_virtio_irq(int config_change, uint64_t token)
|
||||
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 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);
|
||||
@ -422,6 +453,9 @@ 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);
|
||||
|
||||
/* service interrupts are floating therefore we must not pass an cpustate */
|
||||
void s390_sclp_extint(uint32_t parm);
|
||||
|
||||
|
@ -55,6 +55,9 @@
|
||||
do { } while (0)
|
||||
#endif
|
||||
|
||||
#define kvm_vm_check_mem_attr(s, attr) \
|
||||
kvm_vm_check_attr(s, KVM_S390_VM_MEM_CTRL, attr)
|
||||
|
||||
#define IPA0_DIAG 0x8300
|
||||
#define IPA0_SIGP 0xae00
|
||||
#define IPA0_B2 0xb200
|
||||
@ -122,16 +125,6 @@ static int cap_async_pf;
|
||||
|
||||
static void *legacy_s390_alloc(size_t size, uint64_t *align);
|
||||
|
||||
static int kvm_s390_supports_mem_limit(KVMState *s)
|
||||
{
|
||||
struct kvm_device_attr attr = {
|
||||
.group = KVM_S390_VM_MEM_CTRL,
|
||||
.attr = KVM_S390_VM_MEM_LIMIT_SIZE,
|
||||
};
|
||||
|
||||
return (kvm_vm_ioctl(s, KVM_HAS_DEVICE_ATTR, &attr) == 0);
|
||||
}
|
||||
|
||||
static int kvm_s390_query_mem_limit(KVMState *s, uint64_t *memory_limit)
|
||||
{
|
||||
struct kvm_device_attr attr = {
|
||||
@ -153,7 +146,7 @@ int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, uint64_t *hw_limit)
|
||||
.addr = (uint64_t) &new_limit,
|
||||
};
|
||||
|
||||
if (!kvm_s390_supports_mem_limit(s)) {
|
||||
if (!kvm_vm_check_mem_attr(s, KVM_S390_VM_MEM_LIMIT_SIZE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -167,26 +160,6 @@ int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, uint64_t *hw_limit)
|
||||
return kvm_vm_ioctl(s, KVM_SET_DEVICE_ATTR, &attr);
|
||||
}
|
||||
|
||||
static int kvm_s390_check_clear_cmma(KVMState *s)
|
||||
{
|
||||
struct kvm_device_attr attr = {
|
||||
.group = KVM_S390_VM_MEM_CTRL,
|
||||
.attr = KVM_S390_VM_MEM_CLR_CMMA,
|
||||
};
|
||||
|
||||
return kvm_vm_ioctl(s, KVM_HAS_DEVICE_ATTR, &attr);
|
||||
}
|
||||
|
||||
static int kvm_s390_check_enable_cmma(KVMState *s)
|
||||
{
|
||||
struct kvm_device_attr attr = {
|
||||
.group = KVM_S390_VM_MEM_CTRL,
|
||||
.attr = KVM_S390_VM_MEM_ENABLE_CMMA,
|
||||
};
|
||||
|
||||
return kvm_vm_ioctl(s, KVM_HAS_DEVICE_ATTR, &attr);
|
||||
}
|
||||
|
||||
void kvm_s390_clear_cmma_callback(void *opaque)
|
||||
{
|
||||
int rc;
|
||||
@ -208,7 +181,8 @@ static void kvm_s390_enable_cmma(KVMState *s)
|
||||
.attr = KVM_S390_VM_MEM_ENABLE_CMMA,
|
||||
};
|
||||
|
||||
if (kvm_s390_check_enable_cmma(s) || kvm_s390_check_clear_cmma(s)) {
|
||||
if (!kvm_vm_check_mem_attr(s, KVM_S390_VM_MEM_ENABLE_CMMA) ||
|
||||
!kvm_vm_check_mem_attr(s, KVM_S390_VM_MEM_CLR_CMMA)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -219,14 +193,61 @@ static void kvm_s390_enable_cmma(KVMState *s)
|
||||
trace_kvm_enable_cmma(rc);
|
||||
}
|
||||
|
||||
static void kvm_s390_set_attr(uint64_t attr)
|
||||
{
|
||||
struct kvm_device_attr attribute = {
|
||||
.group = KVM_S390_VM_CRYPTO,
|
||||
.attr = attr,
|
||||
};
|
||||
|
||||
int ret = kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attribute);
|
||||
|
||||
if (ret) {
|
||||
error_report("Failed to set crypto device attribute %lu: %s",
|
||||
attr, strerror(-ret));
|
||||
}
|
||||
}
|
||||
|
||||
static void kvm_s390_init_aes_kw(void)
|
||||
{
|
||||
uint64_t attr = KVM_S390_VM_CRYPTO_DISABLE_AES_KW;
|
||||
|
||||
if (object_property_get_bool(OBJECT(qdev_get_machine()), "aes-key-wrap",
|
||||
NULL)) {
|
||||
attr = KVM_S390_VM_CRYPTO_ENABLE_AES_KW;
|
||||
}
|
||||
|
||||
if (kvm_vm_check_attr(kvm_state, KVM_S390_VM_CRYPTO, attr)) {
|
||||
kvm_s390_set_attr(attr);
|
||||
}
|
||||
}
|
||||
|
||||
static void kvm_s390_init_dea_kw(void)
|
||||
{
|
||||
uint64_t attr = KVM_S390_VM_CRYPTO_DISABLE_DEA_KW;
|
||||
|
||||
if (object_property_get_bool(OBJECT(qdev_get_machine()), "dea-key-wrap",
|
||||
NULL)) {
|
||||
attr = KVM_S390_VM_CRYPTO_ENABLE_DEA_KW;
|
||||
}
|
||||
|
||||
if (kvm_vm_check_attr(kvm_state, KVM_S390_VM_CRYPTO, attr)) {
|
||||
kvm_s390_set_attr(attr);
|
||||
}
|
||||
}
|
||||
|
||||
static void kvm_s390_init_crypto(void)
|
||||
{
|
||||
kvm_s390_init_aes_kw();
|
||||
kvm_s390_init_dea_kw();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (kvm_check_extension(s, KVM_CAP_VM_ATTRIBUTES)) {
|
||||
kvm_s390_enable_cmma(s);
|
||||
}
|
||||
kvm_s390_enable_cmma(s);
|
||||
|
||||
if (!kvm_check_extension(s, KVM_CAP_S390_GMAP)
|
||||
|| !kvm_check_extension(s, KVM_CAP_S390_COW)) {
|
||||
@ -262,6 +283,8 @@ void kvm_s390_reset_vcpu(S390CPU *cpu)
|
||||
if (kvm_vcpu_ioctl(cs, KVM_S390_INITIAL_RESET, NULL)) {
|
||||
error_report("Initial CPU reset failed on CPU %i", cs->cpu_index);
|
||||
}
|
||||
|
||||
kvm_s390_init_crypto();
|
||||
}
|
||||
|
||||
static int can_sync_regs(CPUState *cs, int regs)
|
||||
@ -486,6 +509,45 @@ int kvm_arch_get_registers(CPUState *cs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_low)
|
||||
{
|
||||
int r;
|
||||
struct kvm_device_attr attr = {
|
||||
.group = KVM_S390_VM_TOD,
|
||||
.attr = KVM_S390_VM_TOD_LOW,
|
||||
.addr = (uint64_t)tod_low,
|
||||
};
|
||||
|
||||
r = kvm_vm_ioctl(kvm_state, KVM_GET_DEVICE_ATTR, &attr);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
attr.attr = KVM_S390_VM_TOD_HIGH;
|
||||
attr.addr = (uint64_t)tod_high;
|
||||
return kvm_vm_ioctl(kvm_state, KVM_GET_DEVICE_ATTR, &attr);
|
||||
}
|
||||
|
||||
int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
|
||||
{
|
||||
int r;
|
||||
|
||||
struct kvm_device_attr attr = {
|
||||
.group = KVM_S390_VM_TOD,
|
||||
.attr = KVM_S390_VM_TOD_LOW,
|
||||
.addr = (uint64_t)tod_low,
|
||||
};
|
||||
|
||||
r = kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
attr.attr = KVM_S390_VM_TOD_HIGH;
|
||||
attr.addr = (uint64_t)tod_high;
|
||||
return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Legacy layout for s390:
|
||||
* Older S390 KVM requires the topmost vma of the RAM to be
|
||||
|
Loading…
Reference in New Issue
Block a user