mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-10 11:04:58 -06:00
Hi,
"Host Memory Backends" and "Memory devices" queue ("mem"): - Fixup handling of virtio-mem unplug during system resets, as preparation for s390x support (especially kdump in the Linux guest) - virtio-mem support for s390x -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEEG9nKrXNcTDpGDfzKTd4Q9wD/g1oFAmdnFD4RHGRhdmlkQHJl ZGhhdC5jb20ACgkQTd4Q9wD/g1rWBBAAp7WkYaNAjRy1PgpjNZ3z1gUJc/vk+skJ xVgGodA8txrJOFpNrbTyfhrdLs2TV4oWDvB/zrZRRtuxvur3O1EhFd9k6EqXuydr 0FunvLvVJwRHfEZycjN4aacQMRH3CJw07OaTzexeSl5UR/6w5PRofwUK4HX7W/Ka arqomGa3OJrs1+WgkV0Qcn4vh9HLRVv3iNC2Xo4W1wOCr1Du9zSPn9oC7zOQ0EO4 ZC//7QsdkNRjUX/yMXMkhlSXx3b/RmRg2DBrxo7BZXg27VwGu4uHxL4LRBZiB2A7 V9MqFOcVKzPMkXKTRjrgZ0vXQx1MPJ6WprEihMzMpYU6DrpA7KN/l8Ca8H24B2ln h7+bmkDsHVVcWovE9ii/9cMRfws6uWXXg3KoA8RQ8IbX1tU02lblw2uHhXEzcoge npqp/Z5LAiKVMetEnNnLH5thjut5PAEjuqD00cmZAMy4DNngLX2bGSdzMeVBkDMa 78ehLGRplm3t7ibUfaZaMKe6UD9tFrcD6XKsvUTXXHNbYO8ynbx58WOxSZmY98zU n3JNQRqtXYjBVlH3Dqm47vOTZHgOzFv3raa8BmSLpcBDeTXCTcUIl20s77dGw/vT r5YNCMN7O4YPFKUoRK9604QTgw6qlYaRTQlJD09usprGqVylb6gQtfZZuZkYDMp8 sEI77QHsePA= =HDxr -----END PGP SIGNATURE----- Merge tag 'mem-2024-12-21' of https://github.com/davidhildenbrand/qemu into staging Hi, "Host Memory Backends" and "Memory devices" queue ("mem"): - Fixup handling of virtio-mem unplug during system resets, as preparation for s390x support (especially kdump in the Linux guest) - virtio-mem support for s390x # -----BEGIN PGP SIGNATURE----- # # iQJFBAABCAAvFiEEG9nKrXNcTDpGDfzKTd4Q9wD/g1oFAmdnFD4RHGRhdmlkQHJl # ZGhhdC5jb20ACgkQTd4Q9wD/g1rWBBAAp7WkYaNAjRy1PgpjNZ3z1gUJc/vk+skJ # xVgGodA8txrJOFpNrbTyfhrdLs2TV4oWDvB/zrZRRtuxvur3O1EhFd9k6EqXuydr # 0FunvLvVJwRHfEZycjN4aacQMRH3CJw07OaTzexeSl5UR/6w5PRofwUK4HX7W/Ka # arqomGa3OJrs1+WgkV0Qcn4vh9HLRVv3iNC2Xo4W1wOCr1Du9zSPn9oC7zOQ0EO4 # ZC//7QsdkNRjUX/yMXMkhlSXx3b/RmRg2DBrxo7BZXg27VwGu4uHxL4LRBZiB2A7 # V9MqFOcVKzPMkXKTRjrgZ0vXQx1MPJ6WprEihMzMpYU6DrpA7KN/l8Ca8H24B2ln # h7+bmkDsHVVcWovE9ii/9cMRfws6uWXXg3KoA8RQ8IbX1tU02lblw2uHhXEzcoge # npqp/Z5LAiKVMetEnNnLH5thjut5PAEjuqD00cmZAMy4DNngLX2bGSdzMeVBkDMa # 78ehLGRplm3t7ibUfaZaMKe6UD9tFrcD6XKsvUTXXHNbYO8ynbx58WOxSZmY98zU # n3JNQRqtXYjBVlH3Dqm47vOTZHgOzFv3raa8BmSLpcBDeTXCTcUIl20s77dGw/vT # r5YNCMN7O4YPFKUoRK9604QTgw6qlYaRTQlJD09usprGqVylb6gQtfZZuZkYDMp8 # sEI77QHsePA= # =HDxr # -----END PGP SIGNATURE----- # gpg: Signature made Sat 21 Dec 2024 14:17:18 EST # gpg: using RSA key 1BD9CAAD735C4C3A460DFCCA4DDE10F700FF835A # gpg: issuer "david@redhat.com" # gpg: Good signature from "David Hildenbrand <david@redhat.com>" [unknown] # gpg: aka "David Hildenbrand <davidhildenbrand@gmail.com>" [full] # gpg: aka "David Hildenbrand <hildenbr@in.tum.de>" [unknown] # gpg: WARNING: The key's User ID is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 1BD9 CAAD 735C 4C3A 460D FCCA 4DDE 10F7 00FF 835A * tag 'mem-2024-12-21' of https://github.com/davidhildenbrand/qemu: s390x: virtio-mem support s390x/virtio-ccw: add support for virtio based memory devices s390x: remember the maximum page size s390x/pv: prepare for memory devices s390x/s390-virtio-ccw: prepare for memory devices s390x/s390-skeys: prepare for memory devices s390x/s390-stattrib-kvm: prepare for memory devices and sparse memory layouts s390x/s390-hypercall: introduce DIAG500 STORAGE_LIMIT s390x: introduce s390_get_memory_limit() s390x/s390-virtio-ccw: move setting the maximum guest size from sclp to machine code s390x: rename s390-virtio-hcall* to s390-hypercall* s390x/s390-virtio-hcall: prepare for more diag500 hypercalls s390x/s390-virtio-hcall: remove hypercall registration mechanism s390x/s390-virtio-ccw: don't crash on weird RAM sizes virtio-mem: unplug memory only during system resets, not device resets Conflicts: - hw/s390x/s390-stattrib-kvm.c sysemu/ -> system/ header rename conflict. - hw/s390x/virtio-ccw-mem.c Make Property array const and removed DEFINE_PROP_END_OF_LIST() to conform to the latest conventions. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
aa3a285b5b
25 changed files with 879 additions and 235 deletions
|
@ -2384,6 +2384,9 @@ F: include/hw/virtio/virtio-crypto.h
|
||||||
virtio based memory device
|
virtio based memory device
|
||||||
M: David Hildenbrand <david@redhat.com>
|
M: David Hildenbrand <david@redhat.com>
|
||||||
S: Supported
|
S: Supported
|
||||||
|
F: hw/s390x/virtio-ccw-md.c
|
||||||
|
F: hw/s390x/virtio-ccw-md.h
|
||||||
|
F: hw/s390x/virtio-ccw-md-stubs.c
|
||||||
F: hw/virtio/virtio-md-pci.c
|
F: hw/virtio/virtio-md-pci.c
|
||||||
F: include/hw/virtio/virtio-md-pci.h
|
F: include/hw/virtio/virtio-md-pci.h
|
||||||
F: stubs/virtio-md-pci.c
|
F: stubs/virtio-md-pci.c
|
||||||
|
@ -2395,6 +2398,8 @@ W: https://virtio-mem.gitlab.io/
|
||||||
F: hw/virtio/virtio-mem.c
|
F: hw/virtio/virtio-mem.c
|
||||||
F: hw/virtio/virtio-mem-pci.h
|
F: hw/virtio/virtio-mem-pci.h
|
||||||
F: hw/virtio/virtio-mem-pci.c
|
F: hw/virtio/virtio-mem-pci.c
|
||||||
|
F: hw/s390x/virtio-ccw-mem.c
|
||||||
|
F: hw/s390x/virtio-ccw-mem.h
|
||||||
F: include/hw/virtio/virtio-mem.h
|
F: include/hw/virtio/virtio-mem.h
|
||||||
|
|
||||||
virtio-snd
|
virtio-snd
|
||||||
|
|
|
@ -16,3 +16,4 @@ config S390_CCW_VIRTIO
|
||||||
select SCLPCONSOLE
|
select SCLPCONSOLE
|
||||||
select VIRTIO_CCW
|
select VIRTIO_CCW
|
||||||
select MSI_NONBROKEN
|
select MSI_NONBROKEN
|
||||||
|
select VIRTIO_MEM_SUPPORTED
|
||||||
|
|
|
@ -12,7 +12,6 @@ s390x_ss.add(files(
|
||||||
's390-pci-inst.c',
|
's390-pci-inst.c',
|
||||||
's390-skeys.c',
|
's390-skeys.c',
|
||||||
's390-stattrib.c',
|
's390-stattrib.c',
|
||||||
's390-virtio-hcall.c',
|
|
||||||
'sclp.c',
|
'sclp.c',
|
||||||
'sclpcpu.c',
|
'sclpcpu.c',
|
||||||
'sclpquiesce.c',
|
'sclpquiesce.c',
|
||||||
|
@ -28,7 +27,10 @@ s390x_ss.add(when: 'CONFIG_KVM', if_true: files(
|
||||||
s390x_ss.add(when: 'CONFIG_TCG', if_true: files(
|
s390x_ss.add(when: 'CONFIG_TCG', if_true: files(
|
||||||
'tod-tcg.c',
|
'tod-tcg.c',
|
||||||
))
|
))
|
||||||
s390x_ss.add(when: 'CONFIG_S390_CCW_VIRTIO', if_true: files('s390-virtio-ccw.c'))
|
s390x_ss.add(when: 'CONFIG_S390_CCW_VIRTIO', if_true: files(
|
||||||
|
's390-virtio-ccw.c',
|
||||||
|
's390-hypercall.c',
|
||||||
|
))
|
||||||
s390x_ss.add(when: 'CONFIG_TERMINAL3270', if_true: files('3270-ccw.c'))
|
s390x_ss.add(when: 'CONFIG_TERMINAL3270', if_true: files('3270-ccw.c'))
|
||||||
s390x_ss.add(when: 'CONFIG_VFIO', if_true: files('s390-pci-vfio.c'))
|
s390x_ss.add(when: 'CONFIG_VFIO', if_true: files('s390-pci-vfio.c'))
|
||||||
|
|
||||||
|
@ -48,8 +50,12 @@ endif
|
||||||
virtio_ss.add(when: 'CONFIG_VHOST_SCSI', if_true: files('vhost-scsi-ccw.c'))
|
virtio_ss.add(when: 'CONFIG_VHOST_SCSI', if_true: files('vhost-scsi-ccw.c'))
|
||||||
virtio_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock-ccw.c'))
|
virtio_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock-ccw.c'))
|
||||||
virtio_ss.add(when: 'CONFIG_VHOST_USER_FS', if_true: files('vhost-user-fs-ccw.c'))
|
virtio_ss.add(when: 'CONFIG_VHOST_USER_FS', if_true: files('vhost-user-fs-ccw.c'))
|
||||||
|
virtio_ss.add(when: 'CONFIG_VIRTIO_MD', if_true: files('virtio-ccw-md.c'))
|
||||||
|
virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-ccw-mem.c'))
|
||||||
s390x_ss.add_all(when: 'CONFIG_VIRTIO_CCW', if_true: virtio_ss)
|
s390x_ss.add_all(when: 'CONFIG_VIRTIO_CCW', if_true: virtio_ss)
|
||||||
|
|
||||||
|
s390x_ss.add(when: 'CONFIG_VIRTIO_MD', if_false: files('virtio-ccw-md-stubs.c'))
|
||||||
|
|
||||||
hw_arch += {'s390x': s390x_ss}
|
hw_arch += {'s390x': s390x_ss}
|
||||||
|
|
||||||
hw_s390x_modules = {}
|
hw_s390x_modules = {}
|
||||||
|
|
85
hw/s390x/s390-hypercall.c
Normal file
85
hw/s390x/s390-hypercall.c
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Support for QEMU/KVM hypercalls on s390
|
||||||
|
*
|
||||||
|
* Copyright 2012 IBM Corp.
|
||||||
|
* Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or (at
|
||||||
|
* your option) any later version. See the COPYING file in the top-level
|
||||||
|
* directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "hw/s390x/s390-virtio-ccw.h"
|
||||||
|
#include "hw/s390x/s390-hypercall.h"
|
||||||
|
#include "hw/s390x/ioinst.h"
|
||||||
|
#include "hw/s390x/css.h"
|
||||||
|
#include "virtio-ccw.h"
|
||||||
|
|
||||||
|
static int handle_virtio_notify(uint64_t mem)
|
||||||
|
{
|
||||||
|
MachineState *ms = MACHINE(qdev_get_machine());
|
||||||
|
|
||||||
|
if (mem < ms->ram_size) {
|
||||||
|
/* Early printk */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int handle_virtio_ccw_notify(uint64_t subch_id, uint64_t data)
|
||||||
|
{
|
||||||
|
SubchDev *sch;
|
||||||
|
VirtIODevice *vdev;
|
||||||
|
int cssid, ssid, schid, m;
|
||||||
|
uint16_t vq_idx = data;
|
||||||
|
|
||||||
|
if (ioinst_disassemble_sch_ident(subch_id, &m, &cssid, &ssid, &schid)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
sch = css_find_subch(m, cssid, ssid, schid);
|
||||||
|
if (!sch || !css_subch_visible(sch)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
vdev = virtio_ccw_get_vdev(sch);
|
||||||
|
if (vq_idx >= VIRTIO_QUEUE_MAX || !virtio_queue_get_num(vdev, vq_idx)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virtio_vdev_has_feature(vdev, VIRTIO_F_NOTIFICATION_DATA)) {
|
||||||
|
virtio_queue_set_shadow_avail_idx(virtio_get_queue(vdev, vq_idx),
|
||||||
|
(data >> 16) & 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtio_queue_notify(vdev, vq_idx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t handle_storage_limit(void)
|
||||||
|
{
|
||||||
|
S390CcwMachineState *s390ms = S390_CCW_MACHINE(qdev_get_machine());
|
||||||
|
|
||||||
|
return s390_get_memory_limit(s390ms) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_diag_500(S390CPU *cpu, uintptr_t ra)
|
||||||
|
{
|
||||||
|
CPUS390XState *env = &cpu->env;
|
||||||
|
const uint64_t subcode = env->regs[1];
|
||||||
|
|
||||||
|
switch (subcode) {
|
||||||
|
case DIAG500_VIRTIO_NOTIFY:
|
||||||
|
env->regs[2] = handle_virtio_notify(env->regs[2]);
|
||||||
|
break;
|
||||||
|
case DIAG500_VIRTIO_CCW_NOTIFY:
|
||||||
|
env->regs[2] = handle_virtio_ccw_notify(env->regs[2], env->regs[3]);
|
||||||
|
break;
|
||||||
|
case DIAG500_STORAGE_LIMIT:
|
||||||
|
env->regs[2] = handle_storage_limit();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
s390_program_interrupt(env, PGM_SPECIFICATION, ra);
|
||||||
|
}
|
||||||
|
}
|
25
hw/s390x/s390-hypercall.h
Normal file
25
hw/s390x/s390-hypercall.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Support for QEMU/KVM hypercalls on s390x
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2012, 2017
|
||||||
|
* Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or (at
|
||||||
|
* your option) any later version. See the COPYING file in the top-level
|
||||||
|
* directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HW_S390_HYPERCALL_H
|
||||||
|
#define HW_S390_HYPERCALL_H
|
||||||
|
|
||||||
|
#include "cpu.h"
|
||||||
|
|
||||||
|
#define DIAG500_VIRTIO_NOTIFY 0 /* legacy, implemented as a NOP */
|
||||||
|
#define DIAG500_VIRTIO_RESET 1 /* legacy */
|
||||||
|
#define DIAG500_VIRTIO_SET_STATUS 2 /* legacy */
|
||||||
|
#define DIAG500_VIRTIO_CCW_NOTIFY 3 /* KVM_S390_VIRTIO_CCW_NOTIFY */
|
||||||
|
#define DIAG500_STORAGE_LIMIT 4
|
||||||
|
|
||||||
|
void handle_diag_500(S390CPU *cpu, uintptr_t ra);
|
||||||
|
|
||||||
|
#endif /* HW_S390_HYPERCALL_H */
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu/units.h"
|
#include "qemu/units.h"
|
||||||
#include "hw/boards.h"
|
#include "hw/s390x/s390-virtio-ccw.h"
|
||||||
#include "hw/qdev-properties.h"
|
#include "hw/qdev-properties.h"
|
||||||
#include "hw/s390x/storage-keys.h"
|
#include "hw/s390x/storage-keys.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
|
@ -251,9 +251,9 @@ static bool qemu_s390_enable_skeys(S390SKeysState *ss)
|
||||||
* g_once_init_enter() is good enough.
|
* g_once_init_enter() is good enough.
|
||||||
*/
|
*/
|
||||||
if (g_once_init_enter(&initialized)) {
|
if (g_once_init_enter(&initialized)) {
|
||||||
MachineState *machine = MACHINE(qdev_get_machine());
|
S390CcwMachineState *s390ms = S390_CCW_MACHINE(qdev_get_machine());
|
||||||
|
|
||||||
skeys->key_count = machine->ram_size / TARGET_PAGE_SIZE;
|
skeys->key_count = s390_get_memory_limit(s390ms) / TARGET_PAGE_SIZE;
|
||||||
skeys->keydata = g_malloc0(skeys->key_count);
|
skeys->keydata = g_malloc0(skeys->key_count);
|
||||||
g_once_init_leave(&initialized, 1);
|
g_once_init_leave(&initialized, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "hw/boards.h"
|
#include "hw/s390x/s390-virtio-ccw.h"
|
||||||
#include "migration/qemu-file.h"
|
#include "migration/qemu-file.h"
|
||||||
#include "hw/s390x/storage-attributes.h"
|
#include "hw/s390x/storage-attributes.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "system/kvm.h"
|
#include "system/kvm.h"
|
||||||
|
#include "system/memory_mapping.h"
|
||||||
#include "exec/ram_addr.h"
|
#include "exec/ram_addr.h"
|
||||||
#include "kvm/kvm_s390x.h"
|
#include "kvm/kvm_s390x.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
|
@ -84,8 +85,8 @@ static int kvm_s390_stattrib_set_stattr(S390StAttribState *sa,
|
||||||
uint8_t *values)
|
uint8_t *values)
|
||||||
{
|
{
|
||||||
KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa);
|
KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa);
|
||||||
MachineState *machine = MACHINE(qdev_get_machine());
|
S390CcwMachineState *s390ms = S390_CCW_MACHINE(qdev_get_machine());
|
||||||
unsigned long max = machine->ram_size / TARGET_PAGE_SIZE;
|
unsigned long max = s390_get_memory_limit(s390ms) / TARGET_PAGE_SIZE;
|
||||||
|
|
||||||
if (start_gfn + count > max) {
|
if (start_gfn + count > max) {
|
||||||
error_report("Out of memory bounds when setting storage attributes");
|
error_report("Out of memory bounds when setting storage attributes");
|
||||||
|
@ -103,39 +104,57 @@ static int kvm_s390_stattrib_set_stattr(S390StAttribState *sa,
|
||||||
static void kvm_s390_stattrib_synchronize(S390StAttribState *sa)
|
static void kvm_s390_stattrib_synchronize(S390StAttribState *sa)
|
||||||
{
|
{
|
||||||
KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa);
|
KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa);
|
||||||
MachineState *machine = MACHINE(qdev_get_machine());
|
S390CcwMachineState *s390ms = S390_CCW_MACHINE(qdev_get_machine());
|
||||||
unsigned long max = machine->ram_size / TARGET_PAGE_SIZE;
|
unsigned long max = s390_get_memory_limit(s390ms) / TARGET_PAGE_SIZE;
|
||||||
/* We do not need to reach the maximum buffer size allowed */
|
unsigned long start_gfn, end_gfn, pages;
|
||||||
unsigned long cx, len = KVM_S390_SKEYS_MAX / 2;
|
GuestPhysBlockList guest_phys_blocks;
|
||||||
|
GuestPhysBlock *block;
|
||||||
int r;
|
int r;
|
||||||
struct kvm_s390_cmma_log clog = {
|
struct kvm_s390_cmma_log clog = {
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.mask = ~0ULL,
|
.mask = ~0ULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (sas->incoming_buffer) {
|
if (!sas->incoming_buffer) {
|
||||||
for (cx = 0; cx + len <= max; cx += len) {
|
return;
|
||||||
clog.start_gfn = cx;
|
|
||||||
clog.count = len;
|
|
||||||
clog.values = (uint64_t)(sas->incoming_buffer + cx);
|
|
||||||
r = kvm_vm_ioctl(kvm_state, KVM_S390_SET_CMMA_BITS, &clog);
|
|
||||||
if (r) {
|
|
||||||
error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cx < max) {
|
|
||||||
clog.start_gfn = cx;
|
|
||||||
clog.count = max - cx;
|
|
||||||
clog.values = (uint64_t)(sas->incoming_buffer + cx);
|
|
||||||
r = kvm_vm_ioctl(kvm_state, KVM_S390_SET_CMMA_BITS, &clog);
|
|
||||||
if (r) {
|
|
||||||
error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_free(sas->incoming_buffer);
|
|
||||||
sas->incoming_buffer = NULL;
|
|
||||||
}
|
}
|
||||||
|
guest_phys_blocks_init(&guest_phys_blocks);
|
||||||
|
guest_phys_blocks_append(&guest_phys_blocks);
|
||||||
|
|
||||||
|
QTAILQ_FOREACH(block, &guest_phys_blocks.head, next) {
|
||||||
|
assert(QEMU_IS_ALIGNED(block->target_start, TARGET_PAGE_SIZE));
|
||||||
|
assert(QEMU_IS_ALIGNED(block->target_end, TARGET_PAGE_SIZE));
|
||||||
|
|
||||||
|
start_gfn = block->target_start / TARGET_PAGE_SIZE;
|
||||||
|
end_gfn = block->target_end / TARGET_PAGE_SIZE;
|
||||||
|
|
||||||
|
while (start_gfn < end_gfn) {
|
||||||
|
/* Don't exceed the maximum buffer size. */
|
||||||
|
pages = MIN(end_gfn - start_gfn, KVM_S390_SKEYS_MAX / 2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we ever get guest physical memory beyond the configured
|
||||||
|
* memory limit, something went very wrong.
|
||||||
|
*/
|
||||||
|
assert(start_gfn + pages <= max);
|
||||||
|
|
||||||
|
clog.start_gfn = start_gfn;
|
||||||
|
clog.count = pages;
|
||||||
|
clog.values = (uint64_t)(sas->incoming_buffer + start_gfn);
|
||||||
|
r = kvm_vm_ioctl(kvm_state, KVM_S390_SET_CMMA_BITS, &clog);
|
||||||
|
if (r) {
|
||||||
|
error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_gfn += pages;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
guest_phys_blocks_free(&guest_phys_blocks);
|
||||||
|
g_free(sas->incoming_buffer);
|
||||||
|
sas->incoming_buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kvm_s390_stattrib_set_migrationmode(S390StAttribState *sa, bool val,
|
static int kvm_s390_stattrib_set_migrationmode(S390StAttribState *sa, bool val,
|
||||||
|
|
|
@ -16,11 +16,8 @@
|
||||||
#include "exec/ram_addr.h"
|
#include "exec/ram_addr.h"
|
||||||
#include "system/confidential-guest-support.h"
|
#include "system/confidential-guest-support.h"
|
||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
#include "hw/s390x/s390-virtio-hcall.h"
|
|
||||||
#include "hw/s390x/sclp.h"
|
#include "hw/s390x/sclp.h"
|
||||||
#include "hw/s390x/s390_flic.h"
|
#include "hw/s390x/s390_flic.h"
|
||||||
#include "hw/s390x/ioinst.h"
|
|
||||||
#include "hw/s390x/css.h"
|
|
||||||
#include "virtio-ccw.h"
|
#include "virtio-ccw.h"
|
||||||
#include "qemu/config-file.h"
|
#include "qemu/config-file.h"
|
||||||
#include "qemu/ctype.h"
|
#include "qemu/ctype.h"
|
||||||
|
@ -48,6 +45,9 @@
|
||||||
#include "migration/blocker.h"
|
#include "migration/blocker.h"
|
||||||
#include "qapi/visitor.h"
|
#include "qapi/visitor.h"
|
||||||
#include "hw/s390x/cpu-topology.h"
|
#include "hw/s390x/cpu-topology.h"
|
||||||
|
#include "kvm/kvm_s390x.h"
|
||||||
|
#include "hw/virtio/virtio-md-pci.h"
|
||||||
|
#include "hw/s390x/virtio-ccw-md.h"
|
||||||
#include CONFIG_DEVICES
|
#include CONFIG_DEVICES
|
||||||
|
|
||||||
static Error *pv_mig_blocker;
|
static Error *pv_mig_blocker;
|
||||||
|
@ -124,70 +124,86 @@ static void subsystem_reset(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int virtio_ccw_hcall_notify(const uint64_t *args)
|
static void s390_set_memory_limit(S390CcwMachineState *s390ms,
|
||||||
|
uint64_t new_limit)
|
||||||
{
|
{
|
||||||
uint64_t subch_id = args[0];
|
uint64_t hw_limit = 0;
|
||||||
uint64_t data = args[1];
|
int ret = 0;
|
||||||
SubchDev *sch;
|
|
||||||
VirtIODevice *vdev;
|
|
||||||
int cssid, ssid, schid, m;
|
|
||||||
uint16_t vq_idx = data;
|
|
||||||
|
|
||||||
if (ioinst_disassemble_sch_ident(subch_id, &m, &cssid, &ssid, &schid)) {
|
assert(!s390ms->memory_limit && new_limit);
|
||||||
return -EINVAL;
|
if (kvm_enabled()) {
|
||||||
|
ret = kvm_s390_set_mem_limit(new_limit, &hw_limit);
|
||||||
}
|
}
|
||||||
sch = css_find_subch(m, cssid, ssid, schid);
|
if (ret == -E2BIG) {
|
||||||
if (!sch || !css_subch_visible(sch)) {
|
error_report("host supports a maximum of %" PRIu64 " GB",
|
||||||
return -EINVAL;
|
hw_limit / GiB);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
} else if (ret) {
|
||||||
|
error_report("setting the guest size failed");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
s390ms->memory_limit = new_limit;
|
||||||
vdev = virtio_ccw_get_vdev(sch);
|
|
||||||
if (vq_idx >= VIRTIO_QUEUE_MAX || !virtio_queue_get_num(vdev, vq_idx)) {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virtio_vdev_has_feature(vdev, VIRTIO_F_NOTIFICATION_DATA)) {
|
|
||||||
virtio_queue_set_shadow_avail_idx(virtio_get_queue(vdev, vq_idx),
|
|
||||||
(data >> 16) & 0xFFFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtio_queue_notify(vdev, vq_idx);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int virtio_ccw_hcall_early_printk(const uint64_t *args)
|
static void s390_set_max_pagesize(S390CcwMachineState *s390ms,
|
||||||
|
uint64_t pagesize)
|
||||||
{
|
{
|
||||||
uint64_t mem = args[0];
|
assert(!s390ms->max_pagesize && pagesize);
|
||||||
MachineState *ms = MACHINE(qdev_get_machine());
|
if (kvm_enabled()) {
|
||||||
|
kvm_s390_set_max_pagesize(pagesize, &error_fatal);
|
||||||
if (mem < ms->ram_size) {
|
|
||||||
/* Early printk */
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return -EINVAL;
|
s390ms->max_pagesize = pagesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_ccw_register_hcalls(void)
|
static void s390_memory_init(MachineState *machine)
|
||||||
{
|
|
||||||
s390_register_virtio_hypercall(KVM_S390_VIRTIO_CCW_NOTIFY,
|
|
||||||
virtio_ccw_hcall_notify);
|
|
||||||
/* Tolerate early printk. */
|
|
||||||
s390_register_virtio_hypercall(KVM_S390_VIRTIO_NOTIFY,
|
|
||||||
virtio_ccw_hcall_early_printk);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void s390_memory_init(MemoryRegion *ram)
|
|
||||||
{
|
{
|
||||||
|
S390CcwMachineState *s390ms = S390_CCW_MACHINE(machine);
|
||||||
MemoryRegion *sysmem = get_system_memory();
|
MemoryRegion *sysmem = get_system_memory();
|
||||||
|
MemoryRegion *ram = machine->ram;
|
||||||
|
uint64_t ram_size = memory_region_size(ram);
|
||||||
|
uint64_t devmem_base, devmem_size;
|
||||||
|
|
||||||
/* allocate RAM for core */
|
if (!QEMU_IS_ALIGNED(ram_size, 1 * MiB)) {
|
||||||
|
/*
|
||||||
|
* SCLP cannot possibly expose smaller granularity right now and KVM
|
||||||
|
* cannot handle smaller granularity. As we don't support NUMA, the
|
||||||
|
* region size directly corresponds to machine->ram_size, and the region
|
||||||
|
* is a single RAM memory region.
|
||||||
|
*/
|
||||||
|
error_report("ram size must be multiples of 1 MiB");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
devmem_size = 0;
|
||||||
|
devmem_base = ram_size;
|
||||||
|
#ifdef CONFIG_MEM_DEVICE
|
||||||
|
if (machine->ram_size < machine->maxram_size) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure memory devices have a sane default alignment, even
|
||||||
|
* when weird initial memory sizes are specified.
|
||||||
|
*/
|
||||||
|
devmem_base = QEMU_ALIGN_UP(devmem_base, 1 * GiB);
|
||||||
|
devmem_size = machine->maxram_size - machine->ram_size;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
s390_set_memory_limit(s390ms, devmem_base + devmem_size);
|
||||||
|
|
||||||
|
/* Map the initial memory. Must happen after setting the memory limit. */
|
||||||
memory_region_add_subregion(sysmem, 0, ram);
|
memory_region_add_subregion(sysmem, 0, ram);
|
||||||
|
|
||||||
|
/* Initialize address space for memory devices. */
|
||||||
|
#ifdef CONFIG_MEM_DEVICE
|
||||||
|
if (devmem_size) {
|
||||||
|
machine_memory_devices_init(machine, devmem_base, devmem_size);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_MEM_DEVICE */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configure the maximum page size. As no memory devices were created
|
* Configure the maximum page size. As no memory devices were created
|
||||||
* yet, this is the page size of initial memory only.
|
* yet, this is the page size of initial memory only.
|
||||||
*/
|
*/
|
||||||
s390_set_max_pagesize(qemu_maxrampagesize(), &error_fatal);
|
s390_set_max_pagesize(s390ms, qemu_maxrampagesize());
|
||||||
/* Initialize storage key device */
|
/* Initialize storage key device */
|
||||||
s390_skeys_init();
|
s390_skeys_init();
|
||||||
/* Initialize storage attributes device */
|
/* Initialize storage attributes device */
|
||||||
|
@ -255,7 +271,7 @@ static void ccw_init(MachineState *machine)
|
||||||
qdev_realize_and_unref(DEVICE(ms->sclp), NULL, &error_fatal);
|
qdev_realize_and_unref(DEVICE(ms->sclp), NULL, &error_fatal);
|
||||||
|
|
||||||
/* init memory + setup max page size. Required for the CPU model */
|
/* init memory + setup max page size. Required for the CPU model */
|
||||||
s390_memory_init(machine->ram);
|
s390_memory_init(machine);
|
||||||
|
|
||||||
/* init CPUs (incl. CPU model) early so s390_has_feature() works */
|
/* init CPUs (incl. CPU model) early so s390_has_feature() works */
|
||||||
s390_init_cpus(machine);
|
s390_init_cpus(machine);
|
||||||
|
@ -285,9 +301,6 @@ static void ccw_init(MachineState *machine)
|
||||||
OBJECT(dev));
|
OBJECT(dev));
|
||||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||||
|
|
||||||
/* register hypercalls */
|
|
||||||
virtio_ccw_register_hcalls();
|
|
||||||
|
|
||||||
s390_enable_css_support(s390_cpu_addr2state(0));
|
s390_enable_css_support(s390_cpu_addr2state(0));
|
||||||
|
|
||||||
ret = css_create_css_image(VIRTUAL_CSSID, true);
|
ret = css_create_css_image(VIRTUAL_CSSID, true);
|
||||||
|
@ -535,11 +548,39 @@ static void s390_machine_reset(MachineState *machine, ResetType type)
|
||||||
s390_ipl_clear_reset_request();
|
s390_ipl_clear_reset_request();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void s390_machine_device_pre_plug(HotplugHandler *hotplug_dev,
|
||||||
|
DeviceState *dev, Error **errp)
|
||||||
|
{
|
||||||
|
if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_CCW)) {
|
||||||
|
virtio_ccw_md_pre_plug(VIRTIO_MD_CCW(dev), MACHINE(hotplug_dev), errp);
|
||||||
|
} else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) {
|
||||||
|
error_setg(errp,
|
||||||
|
"PCI-attached virtio based memory devices not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void s390_machine_device_plug(HotplugHandler *hotplug_dev,
|
static void s390_machine_device_plug(HotplugHandler *hotplug_dev,
|
||||||
DeviceState *dev, Error **errp)
|
DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
|
S390CcwMachineState *s390ms = S390_CCW_MACHINE(hotplug_dev);
|
||||||
|
|
||||||
if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
||||||
s390_cpu_plug(hotplug_dev, dev, errp);
|
s390_cpu_plug(hotplug_dev, dev, errp);
|
||||||
|
} else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_CCW)) {
|
||||||
|
/*
|
||||||
|
* At this point, the device is realized and set all memdevs mapped, so
|
||||||
|
* qemu_maxrampagesize() will pick up the page sizes of these memdevs
|
||||||
|
* as well. Before we plug the device and expose any RAM memory regions
|
||||||
|
* to the system, make sure we don't exceed the previously set max page
|
||||||
|
* size. While only relevant for KVM, there is not really any use case
|
||||||
|
* for this with TCG, so we'll unconditionally reject it.
|
||||||
|
*/
|
||||||
|
if (qemu_maxrampagesize() != s390ms->max_pagesize) {
|
||||||
|
error_setg(errp, "Memory device uses a bigger page size than"
|
||||||
|
" initial memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
virtio_ccw_md_plug(VIRTIO_MD_CCW(dev), MACHINE(hotplug_dev), errp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,9 +590,20 @@ static void s390_machine_device_unplug_request(HotplugHandler *hotplug_dev,
|
||||||
if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
||||||
error_setg(errp, "CPU hot unplug not supported on this machine");
|
error_setg(errp, "CPU hot unplug not supported on this machine");
|
||||||
return;
|
return;
|
||||||
|
} else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_CCW)) {
|
||||||
|
virtio_ccw_md_unplug_request(VIRTIO_MD_CCW(dev), MACHINE(hotplug_dev),
|
||||||
|
errp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void s390_machine_device_unplug(HotplugHandler *hotplug_dev,
|
||||||
|
DeviceState *dev, Error **errp)
|
||||||
|
{
|
||||||
|
if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_CCW)) {
|
||||||
|
virtio_ccw_md_unplug(VIRTIO_MD_CCW(dev), MACHINE(hotplug_dev), errp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static CpuInstanceProperties s390_cpu_index_to_props(MachineState *ms,
|
static CpuInstanceProperties s390_cpu_index_to_props(MachineState *ms,
|
||||||
unsigned cpu_index)
|
unsigned cpu_index)
|
||||||
{
|
{
|
||||||
|
@ -598,7 +650,9 @@ static const CPUArchIdList *s390_possible_cpu_arch_ids(MachineState *ms)
|
||||||
static HotplugHandler *s390_get_hotplug_handler(MachineState *machine,
|
static HotplugHandler *s390_get_hotplug_handler(MachineState *machine,
|
||||||
DeviceState *dev)
|
DeviceState *dev)
|
||||||
{
|
{
|
||||||
if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
if (object_dynamic_cast(OBJECT(dev), TYPE_CPU) ||
|
||||||
|
object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_CCW) ||
|
||||||
|
object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) {
|
||||||
return HOTPLUG_HANDLER(machine);
|
return HOTPLUG_HANDLER(machine);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -758,8 +812,10 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data)
|
||||||
mc->possible_cpu_arch_ids = s390_possible_cpu_arch_ids;
|
mc->possible_cpu_arch_ids = s390_possible_cpu_arch_ids;
|
||||||
/* it is overridden with 'host' cpu *in kvm_arch_init* */
|
/* it is overridden with 'host' cpu *in kvm_arch_init* */
|
||||||
mc->default_cpu_type = S390_CPU_TYPE_NAME("qemu");
|
mc->default_cpu_type = S390_CPU_TYPE_NAME("qemu");
|
||||||
|
hc->pre_plug = s390_machine_device_pre_plug;
|
||||||
hc->plug = s390_machine_device_plug;
|
hc->plug = s390_machine_device_plug;
|
||||||
hc->unplug_request = s390_machine_device_unplug_request;
|
hc->unplug_request = s390_machine_device_unplug_request;
|
||||||
|
hc->unplug = s390_machine_device_unplug;
|
||||||
nc->nmi_monitor_handler = s390_nmi;
|
nc->nmi_monitor_handler = s390_nmi;
|
||||||
mc->default_ram_id = "s390.ram";
|
mc->default_ram_id = "s390.ram";
|
||||||
mc->default_nic = "virtio-net-ccw";
|
mc->default_nic = "virtio-net-ccw";
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* Support for virtio hypercalls on s390
|
|
||||||
*
|
|
||||||
* Copyright 2012 IBM Corp.
|
|
||||||
* Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
|
|
||||||
*
|
|
||||||
* This work is licensed under the terms of the GNU GPL, version 2 or (at
|
|
||||||
* your option) any later version. See the COPYING file in the top-level
|
|
||||||
* directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
|
||||||
#include "cpu.h"
|
|
||||||
#include "hw/s390x/s390-virtio-hcall.h"
|
|
||||||
|
|
||||||
#define MAX_DIAG_SUBCODES 255
|
|
||||||
|
|
||||||
static s390_virtio_fn s390_diag500_table[MAX_DIAG_SUBCODES];
|
|
||||||
|
|
||||||
void s390_register_virtio_hypercall(uint64_t code, s390_virtio_fn fn)
|
|
||||||
{
|
|
||||||
assert(code < MAX_DIAG_SUBCODES);
|
|
||||||
assert(!s390_diag500_table[code]);
|
|
||||||
|
|
||||||
s390_diag500_table[code] = fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
int s390_virtio_hypercall(CPUS390XState *env)
|
|
||||||
{
|
|
||||||
s390_virtio_fn fn;
|
|
||||||
|
|
||||||
if (env->regs[1] < MAX_DIAG_SUBCODES) {
|
|
||||||
fn = s390_diag500_table[env->regs[1]];
|
|
||||||
if (fn) {
|
|
||||||
env->regs[2] = fn(&env->regs[2]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
/*
|
|
||||||
* Support for virtio hypercalls on s390x
|
|
||||||
*
|
|
||||||
* Copyright IBM Corp. 2012, 2017
|
|
||||||
* Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
|
|
||||||
*
|
|
||||||
* This work is licensed under the terms of the GNU GPL, version 2 or (at
|
|
||||||
* your option) any later version. See the COPYING file in the top-level
|
|
||||||
* directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HW_S390_VIRTIO_HCALL_H
|
|
||||||
#define HW_S390_VIRTIO_HCALL_H
|
|
||||||
|
|
||||||
#include "standard-headers/asm-s390/virtio-ccw.h"
|
|
||||||
#include "cpu.h"
|
|
||||||
|
|
||||||
/* The only thing that we need from the old kvm_virtio.h file */
|
|
||||||
#define KVM_S390_VIRTIO_NOTIFY 0
|
|
||||||
|
|
||||||
typedef int (*s390_virtio_fn)(const uint64_t *args);
|
|
||||||
void s390_register_virtio_hypercall(uint64_t code, s390_virtio_fn fn);
|
|
||||||
int s390_virtio_hypercall(CPUS390XState *env);
|
|
||||||
|
|
||||||
#endif /* HW_S390_VIRTIO_HCALL_H */
|
|
|
@ -161,7 +161,11 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
|
||||||
read_info->rnsize2 = cpu_to_be32(rnsize);
|
read_info->rnsize2 = cpu_to_be32(rnsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we don't support standby memory, maxram_size is never exposed */
|
/*
|
||||||
|
* We don't support standby memory. maxram_size is used for sizing the
|
||||||
|
* memory device region, which is not exposed through SCLP but through
|
||||||
|
* diag500.
|
||||||
|
*/
|
||||||
rnmax = machine->ram_size >> sclp->increment_size;
|
rnmax = machine->ram_size >> sclp->increment_size;
|
||||||
if (rnmax < 0x10000) {
|
if (rnmax < 0x10000) {
|
||||||
read_info->rnmax = cpu_to_be16(rnmax);
|
read_info->rnmax = cpu_to_be16(rnmax);
|
||||||
|
@ -376,10 +380,7 @@ void sclp_service_interrupt(uint32_t sccb)
|
||||||
/* qemu object creation and initialization functions */
|
/* qemu object creation and initialization functions */
|
||||||
static void sclp_realize(DeviceState *dev, Error **errp)
|
static void sclp_realize(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
MachineState *machine = MACHINE(qdev_get_machine());
|
|
||||||
SCLPDevice *sclp = SCLP(dev);
|
SCLPDevice *sclp = SCLP(dev);
|
||||||
uint64_t hw_limit;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* qdev_device_add searches the sysbus for TYPE_SCLP_EVENTS_BUS. As long
|
* qdev_device_add searches the sysbus for TYPE_SCLP_EVENTS_BUS. As long
|
||||||
|
@ -389,14 +390,6 @@ static void sclp_realize(DeviceState *dev, Error **errp)
|
||||||
if (!sysbus_realize(SYS_BUS_DEVICE(sclp->event_facility), errp)) {
|
if (!sysbus_realize(SYS_BUS_DEVICE(sclp->event_facility), errp)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = s390_set_memory_limit(machine->maxram_size, &hw_limit);
|
|
||||||
if (ret == -E2BIG) {
|
|
||||||
error_setg(errp, "host supports a maximum of %" PRIu64 " GB",
|
|
||||||
hw_limit / GiB);
|
|
||||||
} else if (ret) {
|
|
||||||
error_setg(errp, "setting the guest size failed");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sclp_memory_init(SCLPDevice *sclp)
|
static void sclp_memory_init(SCLPDevice *sclp)
|
||||||
|
|
24
hw/s390x/virtio-ccw-md-stubs.c
Normal file
24
hw/s390x/virtio-ccw-md-stubs.c
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "hw/s390x/virtio-ccw-md.h"
|
||||||
|
|
||||||
|
void virtio_ccw_md_pre_plug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp)
|
||||||
|
{
|
||||||
|
error_setg(errp, "virtio based memory devices not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
void virtio_ccw_md_plug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp)
|
||||||
|
{
|
||||||
|
error_setg(errp, "virtio based memory devices not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
void virtio_ccw_md_unplug_request(VirtIOMDCcw *vmd, MachineState *ms,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
error_setg(errp, "virtio based memory devices not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
void virtio_ccw_md_unplug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp)
|
||||||
|
{
|
||||||
|
error_setg(errp, "virtio based memory devices not supported");
|
||||||
|
}
|
153
hw/s390x/virtio-ccw-md.c
Normal file
153
hw/s390x/virtio-ccw-md.c
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
/*
|
||||||
|
* Virtio CCW support for abstract virtio based memory device
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* David Hildenbrand <david@redhat.com>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "hw/s390x/virtio-ccw-md.h"
|
||||||
|
#include "hw/mem/memory-device.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
|
|
||||||
|
void virtio_ccw_md_pre_plug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp)
|
||||||
|
{
|
||||||
|
DeviceState *dev = DEVICE(vmd);
|
||||||
|
HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
|
||||||
|
MemoryDeviceState *md = MEMORY_DEVICE(vmd);
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
if (!bus_handler && dev->hotplugged) {
|
||||||
|
/*
|
||||||
|
* Without a bus hotplug handler, we cannot control the plug/unplug
|
||||||
|
* order. We should never reach this point when hotplugging, but
|
||||||
|
* better add a safety net.
|
||||||
|
*/
|
||||||
|
error_setg(errp, "hotplug of virtio based memory devices not supported"
|
||||||
|
" on this bus.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First, see if we can plug this memory device at all. If that
|
||||||
|
* succeeds, branch of to the actual hotplug handler.
|
||||||
|
*/
|
||||||
|
memory_device_pre_plug(md, ms, &local_err);
|
||||||
|
if (!local_err && bus_handler) {
|
||||||
|
hotplug_handler_pre_plug(bus_handler, dev, &local_err);
|
||||||
|
}
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
}
|
||||||
|
|
||||||
|
void virtio_ccw_md_plug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp)
|
||||||
|
{
|
||||||
|
DeviceState *dev = DEVICE(vmd);
|
||||||
|
HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
|
||||||
|
MemoryDeviceState *md = MEMORY_DEVICE(vmd);
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Plug the memory device first and then branch off to the actual
|
||||||
|
* hotplug handler. If that one fails, we can easily undo the memory
|
||||||
|
* device bits.
|
||||||
|
*/
|
||||||
|
memory_device_plug(md, ms);
|
||||||
|
if (bus_handler) {
|
||||||
|
hotplug_handler_plug(bus_handler, dev, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
memory_device_unplug(md, ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
}
|
||||||
|
|
||||||
|
void virtio_ccw_md_unplug_request(VirtIOMDCcw *vmd, MachineState *ms,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
VirtIOMDCcwClass *vmdc = VIRTIO_MD_CCW_GET_CLASS(vmd);
|
||||||
|
DeviceState *dev = DEVICE(vmd);
|
||||||
|
HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
|
||||||
|
HotplugHandlerClass *hdc;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
if (!vmdc->unplug_request_check) {
|
||||||
|
error_setg(errp,
|
||||||
|
"this virtio based memory devices cannot be unplugged");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bus_handler) {
|
||||||
|
error_setg(errp, "hotunplug of virtio based memory devices not"
|
||||||
|
"supported on this bus");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vmdc->unplug_request_check(vmd, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Forward the async request or turn it into a sync request (handling it
|
||||||
|
* like qdev_unplug()).
|
||||||
|
*/
|
||||||
|
hdc = HOTPLUG_HANDLER_GET_CLASS(bus_handler);
|
||||||
|
if (hdc->unplug_request) {
|
||||||
|
hotplug_handler_unplug_request(bus_handler, dev, &local_err);
|
||||||
|
} else {
|
||||||
|
virtio_ccw_md_unplug(vmd, ms, &local_err);
|
||||||
|
if (!local_err) {
|
||||||
|
object_unparent(OBJECT(dev));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void virtio_ccw_md_unplug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp)
|
||||||
|
{
|
||||||
|
DeviceState *dev = DEVICE(vmd);
|
||||||
|
HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
|
||||||
|
MemoryDeviceState *md = MEMORY_DEVICE(vmd);
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
/* Unplug the memory device while it is still realized. */
|
||||||
|
memory_device_unplug(md, ms);
|
||||||
|
|
||||||
|
if (bus_handler) {
|
||||||
|
hotplug_handler_unplug(bus_handler, dev, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
/* Not expected to fail ... but still try to recover. */
|
||||||
|
memory_device_plug(md, ms);
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Very unexpected, but let's just try to do the right thing. */
|
||||||
|
warn_report("Unexpected unplug of virtio based memory device");
|
||||||
|
qdev_unrealize(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TypeInfo virtio_ccw_md_info = {
|
||||||
|
.name = TYPE_VIRTIO_MD_CCW,
|
||||||
|
.parent = TYPE_VIRTIO_CCW_DEVICE,
|
||||||
|
.instance_size = sizeof(VirtIOMDCcw),
|
||||||
|
.class_size = sizeof(VirtIOMDCcwClass),
|
||||||
|
.abstract = true,
|
||||||
|
.interfaces = (InterfaceInfo[]) {
|
||||||
|
{ TYPE_MEMORY_DEVICE },
|
||||||
|
{ }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void virtio_ccw_md_register(void)
|
||||||
|
{
|
||||||
|
type_register_static(&virtio_ccw_md_info);
|
||||||
|
}
|
||||||
|
type_init(virtio_ccw_md_register)
|
44
hw/s390x/virtio-ccw-md.h
Normal file
44
hw/s390x/virtio-ccw-md.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Virtio CCW support for abstract virtio based memory device
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* David Hildenbrand <david@redhat.com>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HW_S390X_VIRTIO_CCW_MD_H
|
||||||
|
#define HW_S390X_VIRTIO_CCW_MD_H
|
||||||
|
|
||||||
|
#include "virtio-ccw.h"
|
||||||
|
#include "qom/object.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* virtio-md-ccw: This extends VirtioCcwDevice.
|
||||||
|
*/
|
||||||
|
#define TYPE_VIRTIO_MD_CCW "virtio-md-ccw"
|
||||||
|
|
||||||
|
OBJECT_DECLARE_TYPE(VirtIOMDCcw, VirtIOMDCcwClass, VIRTIO_MD_CCW)
|
||||||
|
|
||||||
|
struct VirtIOMDCcwClass {
|
||||||
|
/* private */
|
||||||
|
VirtIOCCWDeviceClass parent;
|
||||||
|
|
||||||
|
/* public */
|
||||||
|
void (*unplug_request_check)(VirtIOMDCcw *vmd, Error **errp);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VirtIOMDCcw {
|
||||||
|
VirtioCcwDevice parent_obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
void virtio_ccw_md_pre_plug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp);
|
||||||
|
void virtio_ccw_md_plug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp);
|
||||||
|
void virtio_ccw_md_unplug_request(VirtIOMDCcw *vmd, MachineState *ms,
|
||||||
|
Error **errp);
|
||||||
|
void virtio_ccw_md_unplug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp);
|
||||||
|
|
||||||
|
#endif /* HW_S390X_VIRTIO_CCW_MD_H */
|
225
hw/s390x/virtio-ccw-mem.c
Normal file
225
hw/s390x/virtio-ccw-mem.c
Normal file
|
@ -0,0 +1,225 @@
|
||||||
|
/*
|
||||||
|
* virtio-mem CCW implementation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* David Hildenbrand <david@redhat.com>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "hw/qdev-properties.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "qemu/module.h"
|
||||||
|
#include "virtio-ccw-mem.h"
|
||||||
|
#include "hw/mem/memory-device.h"
|
||||||
|
#include "qapi/qapi-events-machine.h"
|
||||||
|
#include "qapi/qapi-events-misc.h"
|
||||||
|
|
||||||
|
static void virtio_ccw_mem_realize(VirtioCcwDevice *ccw_dev, Error **errp)
|
||||||
|
{
|
||||||
|
VirtIOMEMCcw *dev = VIRTIO_MEM_CCW(ccw_dev);
|
||||||
|
DeviceState *vdev = DEVICE(&dev->vdev);
|
||||||
|
|
||||||
|
qdev_realize(vdev, BUS(&ccw_dev->bus), errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_ccw_mem_set_addr(MemoryDeviceState *md, uint64_t addr,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
object_property_set_uint(OBJECT(md), VIRTIO_MEM_ADDR_PROP, addr, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t virtio_ccw_mem_get_addr(const MemoryDeviceState *md)
|
||||||
|
{
|
||||||
|
return object_property_get_uint(OBJECT(md), VIRTIO_MEM_ADDR_PROP,
|
||||||
|
&error_abort);
|
||||||
|
}
|
||||||
|
|
||||||
|
static MemoryRegion *virtio_ccw_mem_get_memory_region(MemoryDeviceState *md,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
VirtIOMEMCcw *dev = VIRTIO_MEM_CCW(md);
|
||||||
|
VirtIOMEM *vmem = &dev->vdev;
|
||||||
|
VirtIOMEMClass *vmc = VIRTIO_MEM_GET_CLASS(vmem);
|
||||||
|
|
||||||
|
return vmc->get_memory_region(vmem, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_ccw_mem_decide_memslots(MemoryDeviceState *md,
|
||||||
|
unsigned int limit)
|
||||||
|
{
|
||||||
|
VirtIOMEMCcw *dev = VIRTIO_MEM_CCW(md);
|
||||||
|
VirtIOMEM *vmem = VIRTIO_MEM(&dev->vdev);
|
||||||
|
VirtIOMEMClass *vmc = VIRTIO_MEM_GET_CLASS(vmem);
|
||||||
|
|
||||||
|
vmc->decide_memslots(vmem, limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int virtio_ccw_mem_get_memslots(MemoryDeviceState *md)
|
||||||
|
{
|
||||||
|
VirtIOMEMCcw *dev = VIRTIO_MEM_CCW(md);
|
||||||
|
VirtIOMEM *vmem = VIRTIO_MEM(&dev->vdev);
|
||||||
|
VirtIOMEMClass *vmc = VIRTIO_MEM_GET_CLASS(vmem);
|
||||||
|
|
||||||
|
return vmc->get_memslots(vmem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t virtio_ccw_mem_get_plugged_size(const MemoryDeviceState *md,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
return object_property_get_uint(OBJECT(md), VIRTIO_MEM_SIZE_PROP,
|
||||||
|
errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_ccw_mem_fill_device_info(const MemoryDeviceState *md,
|
||||||
|
MemoryDeviceInfo *info)
|
||||||
|
{
|
||||||
|
VirtioMEMDeviceInfo *vi = g_new0(VirtioMEMDeviceInfo, 1);
|
||||||
|
VirtIOMEMCcw *dev = VIRTIO_MEM_CCW(md);
|
||||||
|
VirtIOMEM *vmem = &dev->vdev;
|
||||||
|
VirtIOMEMClass *vpc = VIRTIO_MEM_GET_CLASS(vmem);
|
||||||
|
DeviceState *vdev = DEVICE(md);
|
||||||
|
|
||||||
|
if (vdev->id) {
|
||||||
|
vi->id = g_strdup(vdev->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* let the real device handle everything else */
|
||||||
|
vpc->fill_device_info(vmem, vi);
|
||||||
|
|
||||||
|
info->u.virtio_mem.data = vi;
|
||||||
|
info->type = MEMORY_DEVICE_INFO_KIND_VIRTIO_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t virtio_ccw_mem_get_min_alignment(const MemoryDeviceState *md)
|
||||||
|
{
|
||||||
|
return object_property_get_uint(OBJECT(md), VIRTIO_MEM_BLOCK_SIZE_PROP,
|
||||||
|
&error_abort);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_ccw_mem_size_change_notify(Notifier *notifier, void *data)
|
||||||
|
{
|
||||||
|
VirtIOMEMCcw *dev = container_of(notifier, VirtIOMEMCcw,
|
||||||
|
size_change_notifier);
|
||||||
|
DeviceState *vdev = DEVICE(dev);
|
||||||
|
char *qom_path = object_get_canonical_path(OBJECT(dev));
|
||||||
|
const uint64_t * const size_p = data;
|
||||||
|
|
||||||
|
qapi_event_send_memory_device_size_change(vdev->id, *size_p, qom_path);
|
||||||
|
g_free(qom_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_ccw_mem_unplug_request_check(VirtIOMDCcw *vmd, Error **errp)
|
||||||
|
{
|
||||||
|
VirtIOMEMCcw *dev = VIRTIO_MEM_CCW(vmd);
|
||||||
|
VirtIOMEM *vmem = &dev->vdev;
|
||||||
|
VirtIOMEMClass *vpc = VIRTIO_MEM_GET_CLASS(vmem);
|
||||||
|
|
||||||
|
vpc->unplug_request_check(vmem, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_ccw_mem_get_requested_size(Object *obj, Visitor *v,
|
||||||
|
const char *name, void *opaque,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
VirtIOMEMCcw *dev = VIRTIO_MEM_CCW(obj);
|
||||||
|
|
||||||
|
object_property_get(OBJECT(&dev->vdev), name, v, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_ccw_mem_set_requested_size(Object *obj, Visitor *v,
|
||||||
|
const char *name, void *opaque,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
VirtIOMEMCcw *dev = VIRTIO_MEM_CCW(obj);
|
||||||
|
DeviceState *vdev = DEVICE(obj);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we passed virtio_ccw_mem_unplug_request_check(), making sure that
|
||||||
|
* the requested size is 0, don't allow modifying the requested size
|
||||||
|
* anymore, otherwise the VM might end up hotplugging memory before
|
||||||
|
* handling the unplug request.
|
||||||
|
*/
|
||||||
|
if (vdev->pending_deleted_event) {
|
||||||
|
error_setg(errp, "'%s' cannot be changed if the device is in the"
|
||||||
|
" process of unplug", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
object_property_set(OBJECT(&dev->vdev), name, v, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Property virtio_ccw_mem_properties[] = {
|
||||||
|
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
||||||
|
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
||||||
|
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
|
||||||
|
VIRTIO_CCW_MAX_REV),
|
||||||
|
};
|
||||||
|
|
||||||
|
static void virtio_ccw_mem_class_init(ObjectClass *klass, void *data)
|
||||||
|
{
|
||||||
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
|
||||||
|
MemoryDeviceClass *mdc = MEMORY_DEVICE_CLASS(klass);
|
||||||
|
VirtIOMDCcwClass *vmdc = VIRTIO_MD_CCW_CLASS(klass);
|
||||||
|
|
||||||
|
k->realize = virtio_ccw_mem_realize;
|
||||||
|
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||||
|
device_class_set_props(dc, virtio_ccw_mem_properties);
|
||||||
|
|
||||||
|
mdc->get_addr = virtio_ccw_mem_get_addr;
|
||||||
|
mdc->set_addr = virtio_ccw_mem_set_addr;
|
||||||
|
mdc->get_plugged_size = virtio_ccw_mem_get_plugged_size;
|
||||||
|
mdc->get_memory_region = virtio_ccw_mem_get_memory_region;
|
||||||
|
mdc->decide_memslots = virtio_ccw_mem_decide_memslots;
|
||||||
|
mdc->get_memslots = virtio_ccw_mem_get_memslots;
|
||||||
|
mdc->fill_device_info = virtio_ccw_mem_fill_device_info;
|
||||||
|
mdc->get_min_alignment = virtio_ccw_mem_get_min_alignment;
|
||||||
|
|
||||||
|
vmdc->unplug_request_check = virtio_ccw_mem_unplug_request_check;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_ccw_mem_instance_init(Object *obj)
|
||||||
|
{
|
||||||
|
VirtIOMEMCcw *dev = VIRTIO_MEM_CCW(obj);
|
||||||
|
VirtIOMEMClass *vmc;
|
||||||
|
VirtIOMEM *vmem;
|
||||||
|
|
||||||
|
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||||
|
TYPE_VIRTIO_MEM);
|
||||||
|
|
||||||
|
dev->size_change_notifier.notify = virtio_ccw_mem_size_change_notify;
|
||||||
|
vmem = &dev->vdev;
|
||||||
|
vmc = VIRTIO_MEM_GET_CLASS(vmem);
|
||||||
|
/*
|
||||||
|
* We never remove the notifier again, as we expect both devices to
|
||||||
|
* disappear at the same time.
|
||||||
|
*/
|
||||||
|
vmc->add_size_change_notifier(vmem, &dev->size_change_notifier);
|
||||||
|
|
||||||
|
object_property_add_alias(obj, VIRTIO_MEM_BLOCK_SIZE_PROP,
|
||||||
|
OBJECT(&dev->vdev), VIRTIO_MEM_BLOCK_SIZE_PROP);
|
||||||
|
object_property_add_alias(obj, VIRTIO_MEM_SIZE_PROP, OBJECT(&dev->vdev),
|
||||||
|
VIRTIO_MEM_SIZE_PROP);
|
||||||
|
object_property_add(obj, VIRTIO_MEM_REQUESTED_SIZE_PROP, "size",
|
||||||
|
virtio_ccw_mem_get_requested_size,
|
||||||
|
virtio_ccw_mem_set_requested_size, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TypeInfo virtio_ccw_mem = {
|
||||||
|
.name = TYPE_VIRTIO_MEM_CCW,
|
||||||
|
.parent = TYPE_VIRTIO_MD_CCW,
|
||||||
|
.instance_size = sizeof(VirtIOMEMCcw),
|
||||||
|
.instance_init = virtio_ccw_mem_instance_init,
|
||||||
|
.class_init = virtio_ccw_mem_class_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void virtio_ccw_mem_register_types(void)
|
||||||
|
{
|
||||||
|
type_register_static(&virtio_ccw_mem);
|
||||||
|
}
|
||||||
|
type_init(virtio_ccw_mem_register_types)
|
34
hw/s390x/virtio-ccw-mem.h
Normal file
34
hw/s390x/virtio-ccw-mem.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Virtio MEM CCW device
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* David Hildenbrand <david@redhat.com>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HW_S390X_VIRTIO_CCW_MEM_H
|
||||||
|
#define HW_S390X_VIRTIO_CCW_MEM_H
|
||||||
|
|
||||||
|
#include "virtio-ccw-md.h"
|
||||||
|
#include "hw/virtio/virtio-mem.h"
|
||||||
|
#include "qom/object.h"
|
||||||
|
|
||||||
|
typedef struct VirtIOMEMCcw VirtIOMEMCcw;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* virtio-mem-ccw: This extends VirtIOMDCcw
|
||||||
|
*/
|
||||||
|
#define TYPE_VIRTIO_MEM_CCW "virtio-mem-ccw"
|
||||||
|
DECLARE_INSTANCE_CHECKER(VirtIOMEMCcw, VIRTIO_MEM_CCW, TYPE_VIRTIO_MEM_CCW)
|
||||||
|
|
||||||
|
struct VirtIOMEMCcw {
|
||||||
|
VirtIOMDCcw parent_obj;
|
||||||
|
VirtIOMEM vdev;
|
||||||
|
Notifier size_change_notifier;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* HW_S390X_VIRTIO_CCW_MEM_H */
|
|
@ -29,6 +29,7 @@ config VIRTIO_MMIO
|
||||||
config VIRTIO_CCW
|
config VIRTIO_CCW
|
||||||
bool
|
bool
|
||||||
select VIRTIO
|
select VIRTIO
|
||||||
|
select VIRTIO_MD_SUPPORTED
|
||||||
|
|
||||||
config VIRTIO_BALLOON
|
config VIRTIO_BALLOON
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -61,6 +61,8 @@ static uint32_t virtio_mem_default_thp_size(void)
|
||||||
} else if (qemu_real_host_page_size() == 64 * KiB) {
|
} else if (qemu_real_host_page_size() == 64 * KiB) {
|
||||||
default_thp_size = 512 * MiB;
|
default_thp_size = 512 * MiB;
|
||||||
}
|
}
|
||||||
|
#elif defined(__s390x__)
|
||||||
|
default_thp_size = 1 * MiB;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return default_thp_size;
|
return default_thp_size;
|
||||||
|
@ -168,7 +170,7 @@ static bool virtio_mem_has_shared_zeropage(RAMBlock *rb)
|
||||||
* necessary (as the section size can change). But it's more likely that the
|
* necessary (as the section size can change). But it's more likely that the
|
||||||
* section size will rather get smaller and not bigger over time.
|
* section size will rather get smaller and not bigger over time.
|
||||||
*/
|
*/
|
||||||
#if defined(TARGET_X86_64) || defined(TARGET_I386)
|
#if defined(TARGET_X86_64) || defined(TARGET_I386) || defined(TARGET_S390X)
|
||||||
#define VIRTIO_MEM_USABLE_EXTENT (2 * (128 * MiB))
|
#define VIRTIO_MEM_USABLE_EXTENT (2 * (128 * MiB))
|
||||||
#elif defined(TARGET_ARM)
|
#elif defined(TARGET_ARM)
|
||||||
#define VIRTIO_MEM_USABLE_EXTENT (2 * (512 * MiB))
|
#define VIRTIO_MEM_USABLE_EXTENT (2 * (512 * MiB))
|
||||||
|
@ -956,6 +958,7 @@ static void virtio_mem_device_realize(DeviceState *dev, Error **errp)
|
||||||
VirtIOMEM *vmem = VIRTIO_MEM(dev);
|
VirtIOMEM *vmem = VIRTIO_MEM(dev);
|
||||||
uint64_t page_size;
|
uint64_t page_size;
|
||||||
RAMBlock *rb;
|
RAMBlock *rb;
|
||||||
|
Object *obj;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!vmem->memdev) {
|
if (!vmem->memdev) {
|
||||||
|
@ -1121,7 +1124,28 @@ static void virtio_mem_device_realize(DeviceState *dev, Error **errp)
|
||||||
vmstate_register_any(VMSTATE_IF(vmem),
|
vmstate_register_any(VMSTATE_IF(vmem),
|
||||||
&vmstate_virtio_mem_device_early, vmem);
|
&vmstate_virtio_mem_device_early, vmem);
|
||||||
}
|
}
|
||||||
qemu_register_resettable(OBJECT(vmem));
|
|
||||||
|
/*
|
||||||
|
* We only want to unplug all memory to start with a clean slate when
|
||||||
|
* it is safe for the guest -- during system resets that call
|
||||||
|
* qemu_devices_reset().
|
||||||
|
*
|
||||||
|
* We'll filter out selected qemu_devices_reset() calls used for other
|
||||||
|
* purposes, like resetting all devices during wakeup from suspend on
|
||||||
|
* x86 based on the reset type passed to qemu_devices_reset().
|
||||||
|
*
|
||||||
|
* Unplugging all memory during simple device resets can result in the VM
|
||||||
|
* unexpectedly losing RAM, corrupting VM state.
|
||||||
|
*
|
||||||
|
* Simple device resets (or resets triggered by getting a parent device
|
||||||
|
* reset) must not change the state of plugged memory blocks. Therefore,
|
||||||
|
* we need a dedicated reset object that only gets called during
|
||||||
|
* qemu_devices_reset().
|
||||||
|
*/
|
||||||
|
obj = object_new(TYPE_VIRTIO_MEM_SYSTEM_RESET);
|
||||||
|
vmem->system_reset = VIRTIO_MEM_SYSTEM_RESET(obj);
|
||||||
|
vmem->system_reset->vmem = vmem;
|
||||||
|
qemu_register_resettable(obj);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set ourselves as RamDiscardManager before the plug handler maps the
|
* Set ourselves as RamDiscardManager before the plug handler maps the
|
||||||
|
@ -1141,7 +1165,10 @@ static void virtio_mem_device_unrealize(DeviceState *dev)
|
||||||
* found via an address space anymore. Unset ourselves.
|
* found via an address space anymore. Unset ourselves.
|
||||||
*/
|
*/
|
||||||
memory_region_set_ram_discard_manager(&vmem->memdev->mr, NULL);
|
memory_region_set_ram_discard_manager(&vmem->memdev->mr, NULL);
|
||||||
qemu_unregister_resettable(OBJECT(vmem));
|
|
||||||
|
qemu_unregister_resettable(OBJECT(vmem->system_reset));
|
||||||
|
object_unref(OBJECT(vmem->system_reset));
|
||||||
|
|
||||||
if (vmem->early_migration) {
|
if (vmem->early_migration) {
|
||||||
vmstate_unregister(VMSTATE_IF(vmem), &vmstate_virtio_mem_device_early,
|
vmstate_unregister(VMSTATE_IF(vmem), &vmstate_virtio_mem_device_early,
|
||||||
vmem);
|
vmem);
|
||||||
|
@ -1840,38 +1867,12 @@ static void virtio_mem_unplug_request_check(VirtIOMEM *vmem, Error **errp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static ResettableState *virtio_mem_get_reset_state(Object *obj)
|
|
||||||
{
|
|
||||||
VirtIOMEM *vmem = VIRTIO_MEM(obj);
|
|
||||||
return &vmem->reset_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void virtio_mem_system_reset_hold(Object *obj, ResetType type)
|
|
||||||
{
|
|
||||||
VirtIOMEM *vmem = VIRTIO_MEM(obj);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When waking up from standby/suspend-to-ram, do not unplug any memory.
|
|
||||||
*/
|
|
||||||
if (type == RESET_TYPE_WAKEUP) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* During usual resets, we will unplug all memory and shrink the usable
|
|
||||||
* region size. This is, however, not possible in all scenarios. Then,
|
|
||||||
* the guest has to deal with this manually (VIRTIO_MEM_REQ_UNPLUG_ALL).
|
|
||||||
*/
|
|
||||||
virtio_mem_unplug_all(vmem);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void virtio_mem_class_init(ObjectClass *klass, void *data)
|
static void virtio_mem_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
|
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
|
||||||
VirtIOMEMClass *vmc = VIRTIO_MEM_CLASS(klass);
|
VirtIOMEMClass *vmc = VIRTIO_MEM_CLASS(klass);
|
||||||
RamDiscardManagerClass *rdmc = RAM_DISCARD_MANAGER_CLASS(klass);
|
RamDiscardManagerClass *rdmc = RAM_DISCARD_MANAGER_CLASS(klass);
|
||||||
ResettableClass *rc = RESETTABLE_CLASS(klass);
|
|
||||||
|
|
||||||
device_class_set_props(dc, virtio_mem_properties);
|
device_class_set_props(dc, virtio_mem_properties);
|
||||||
dc->vmsd = &vmstate_virtio_mem;
|
dc->vmsd = &vmstate_virtio_mem;
|
||||||
|
@ -1898,9 +1899,6 @@ static void virtio_mem_class_init(ObjectClass *klass, void *data)
|
||||||
rdmc->replay_discarded = virtio_mem_rdm_replay_discarded;
|
rdmc->replay_discarded = virtio_mem_rdm_replay_discarded;
|
||||||
rdmc->register_listener = virtio_mem_rdm_register_listener;
|
rdmc->register_listener = virtio_mem_rdm_register_listener;
|
||||||
rdmc->unregister_listener = virtio_mem_rdm_unregister_listener;
|
rdmc->unregister_listener = virtio_mem_rdm_unregister_listener;
|
||||||
|
|
||||||
rc->get_state = virtio_mem_get_reset_state;
|
|
||||||
rc->phases.hold = virtio_mem_system_reset_hold;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo virtio_mem_info = {
|
static const TypeInfo virtio_mem_info = {
|
||||||
|
@ -1923,3 +1921,48 @@ static void virtio_register_types(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
type_init(virtio_register_types)
|
type_init(virtio_register_types)
|
||||||
|
|
||||||
|
OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(VirtioMemSystemReset, virtio_mem_system_reset, VIRTIO_MEM_SYSTEM_RESET, OBJECT, { TYPE_RESETTABLE_INTERFACE }, { })
|
||||||
|
|
||||||
|
static void virtio_mem_system_reset_init(Object *obj)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_mem_system_reset_finalize(Object *obj)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static ResettableState *virtio_mem_system_reset_get_state(Object *obj)
|
||||||
|
{
|
||||||
|
VirtioMemSystemReset *vmem_reset = VIRTIO_MEM_SYSTEM_RESET(obj);
|
||||||
|
|
||||||
|
return &vmem_reset->reset_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_mem_system_reset_hold(Object *obj, ResetType type)
|
||||||
|
{
|
||||||
|
VirtioMemSystemReset *vmem_reset = VIRTIO_MEM_SYSTEM_RESET(obj);
|
||||||
|
VirtIOMEM *vmem = vmem_reset->vmem;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When waking up from standby/suspend-to-ram, do not unplug any memory.
|
||||||
|
*/
|
||||||
|
if (type == RESET_TYPE_WAKEUP) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* During usual resets, we will unplug all memory and shrink the usable
|
||||||
|
* region size. This is, however, not possible in all scenarios. Then,
|
||||||
|
* the guest has to deal with this manually (VIRTIO_MEM_REQ_UNPLUG_ALL).
|
||||||
|
*/
|
||||||
|
virtio_mem_unplug_all(vmem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_mem_system_reset_class_init(ObjectClass *klass, void *data)
|
||||||
|
{
|
||||||
|
ResettableClass *rc = RESETTABLE_CLASS(klass);
|
||||||
|
|
||||||
|
rc->get_state = virtio_mem_system_reset_get_state;
|
||||||
|
rc->phases.hold = virtio_mem_system_reset_hold;
|
||||||
|
}
|
||||||
|
|
|
@ -29,10 +29,19 @@ struct S390CcwMachineState {
|
||||||
bool dea_key_wrap;
|
bool dea_key_wrap;
|
||||||
bool pv;
|
bool pv;
|
||||||
uint8_t loadparm[8];
|
uint8_t loadparm[8];
|
||||||
|
uint64_t memory_limit;
|
||||||
|
uint64_t max_pagesize;
|
||||||
|
|
||||||
SCLPDevice *sclp;
|
SCLPDevice *sclp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline uint64_t s390_get_memory_limit(S390CcwMachineState *s390ms)
|
||||||
|
{
|
||||||
|
/* We expect to be called only after the limit was set. */
|
||||||
|
assert(s390ms->memory_limit);
|
||||||
|
return s390ms->memory_limit;
|
||||||
|
}
|
||||||
|
|
||||||
#define S390_PTF_REASON_NONE (0x00 << 8)
|
#define S390_PTF_REASON_NONE (0x00 << 8)
|
||||||
#define S390_PTF_REASON_DONE (0x01 << 8)
|
#define S390_PTF_REASON_DONE (0x01 << 8)
|
||||||
#define S390_PTF_REASON_BUSY (0x02 << 8)
|
#define S390_PTF_REASON_BUSY (0x02 << 8)
|
||||||
|
|
|
@ -25,6 +25,10 @@
|
||||||
OBJECT_DECLARE_TYPE(VirtIOMEM, VirtIOMEMClass,
|
OBJECT_DECLARE_TYPE(VirtIOMEM, VirtIOMEMClass,
|
||||||
VIRTIO_MEM)
|
VIRTIO_MEM)
|
||||||
|
|
||||||
|
#define TYPE_VIRTIO_MEM_SYSTEM_RESET "virtio-mem-system-reset"
|
||||||
|
|
||||||
|
OBJECT_DECLARE_SIMPLE_TYPE(VirtioMemSystemReset, VIRTIO_MEM_SYSTEM_RESET)
|
||||||
|
|
||||||
#define VIRTIO_MEM_MEMDEV_PROP "memdev"
|
#define VIRTIO_MEM_MEMDEV_PROP "memdev"
|
||||||
#define VIRTIO_MEM_NODE_PROP "node"
|
#define VIRTIO_MEM_NODE_PROP "node"
|
||||||
#define VIRTIO_MEM_SIZE_PROP "size"
|
#define VIRTIO_MEM_SIZE_PROP "size"
|
||||||
|
@ -117,8 +121,15 @@ struct VirtIOMEM {
|
||||||
/* listeners to notify on plug/unplug activity. */
|
/* listeners to notify on plug/unplug activity. */
|
||||||
QLIST_HEAD(, RamDiscardListener) rdl_list;
|
QLIST_HEAD(, RamDiscardListener) rdl_list;
|
||||||
|
|
||||||
/* State of the resettable container */
|
/* Catch system resets -> qemu_devices_reset() only. */
|
||||||
|
VirtioMemSystemReset *system_reset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VirtioMemSystemReset {
|
||||||
|
Object parent;
|
||||||
|
|
||||||
ResettableState reset_state;
|
ResettableState reset_state;
|
||||||
|
VirtIOMEM *vmem;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VirtIOMEMClass {
|
struct VirtIOMEMClass {
|
||||||
|
|
|
@ -255,21 +255,6 @@ unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu)
|
||||||
return s390_count_running_cpus();
|
return s390_count_running_cpus();
|
||||||
}
|
}
|
||||||
|
|
||||||
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_set_max_pagesize(uint64_t pagesize, Error **errp)
|
|
||||||
{
|
|
||||||
if (kvm_enabled()) {
|
|
||||||
kvm_s390_set_max_pagesize(pagesize, errp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void s390_cmma_reset(void)
|
void s390_cmma_reset(void)
|
||||||
{
|
{
|
||||||
if (kvm_enabled()) {
|
if (kvm_enabled()) {
|
||||||
|
|
|
@ -881,8 +881,6 @@ static inline void s390_do_cpu_load_normal(CPUState *cs, run_on_cpu_data arg)
|
||||||
|
|
||||||
/* cpu.c */
|
/* cpu.c */
|
||||||
void s390_crypto_reset(void);
|
void s390_crypto_reset(void);
|
||||||
int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit);
|
|
||||||
void s390_set_max_pagesize(uint64_t pagesize, Error **errp);
|
|
||||||
void s390_cmma_reset(void);
|
void s390_cmma_reset(void);
|
||||||
void s390_enable_css_support(S390CPU *cpu);
|
void s390_enable_css_support(S390CPU *cpu);
|
||||||
void s390_do_cpu_set_diag318(CPUState *cs, run_on_cpu_data arg);
|
void s390_do_cpu_set_diag318(CPUState *cs, run_on_cpu_data arg);
|
||||||
|
|
|
@ -49,8 +49,9 @@
|
||||||
#include "hw/s390x/ebcdic.h"
|
#include "hw/s390x/ebcdic.h"
|
||||||
#include "exec/memattrs.h"
|
#include "exec/memattrs.h"
|
||||||
#include "hw/s390x/s390-virtio-ccw.h"
|
#include "hw/s390x/s390-virtio-ccw.h"
|
||||||
#include "hw/s390x/s390-virtio-hcall.h"
|
#include "hw/s390x/s390-hypercall.h"
|
||||||
#include "target/s390x/kvm/pv.h"
|
#include "target/s390x/kvm/pv.h"
|
||||||
|
#include CONFIG_DEVICES
|
||||||
|
|
||||||
#define kvm_vm_check_mem_attr(s, attr) \
|
#define kvm_vm_check_mem_attr(s, attr) \
|
||||||
kvm_vm_check_attr(s, KVM_S390_VM_MEM_CTRL, attr)
|
kvm_vm_check_attr(s, KVM_S390_VM_MEM_CTRL, attr)
|
||||||
|
@ -1491,20 +1492,6 @@ static int handle_e3(S390CPU *cpu, struct kvm_run *run, uint8_t ipbl)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_hypercall(S390CPU *cpu, struct kvm_run *run)
|
|
||||||
{
|
|
||||||
CPUS390XState *env = &cpu->env;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = s390_virtio_hypercall(env);
|
|
||||||
if (ret == -EINVAL) {
|
|
||||||
kvm_s390_program_interrupt(cpu, PGM_SPECIFICATION);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void kvm_handle_diag_288(S390CPU *cpu, struct kvm_run *run)
|
static void kvm_handle_diag_288(S390CPU *cpu, struct kvm_run *run)
|
||||||
{
|
{
|
||||||
uint64_t r1, r3;
|
uint64_t r1, r3;
|
||||||
|
@ -1600,9 +1587,11 @@ static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb)
|
||||||
case DIAG_SET_CONTROL_PROGRAM_CODES:
|
case DIAG_SET_CONTROL_PROGRAM_CODES:
|
||||||
handle_diag_318(cpu, run);
|
handle_diag_318(cpu, run);
|
||||||
break;
|
break;
|
||||||
|
#ifdef CONFIG_S390_CCW_VIRTIO
|
||||||
case DIAG_KVM_HYPERCALL:
|
case DIAG_KVM_HYPERCALL:
|
||||||
r = handle_hypercall(cpu, run);
|
handle_diag_500(cpu, RA_IGNORED);
|
||||||
break;
|
break;
|
||||||
|
#endif /* CONFIG_S390_CCW_VIRTIO */
|
||||||
case DIAG_KVM_BREAKPOINT:
|
case DIAG_KVM_BREAKPOINT:
|
||||||
r = handle_sw_breakpoint(cpu, run);
|
r = handle_sw_breakpoint(cpu, run);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -133,7 +133,7 @@ bool s390_pv_vm_try_disable_async(S390CcwMachineState *ms)
|
||||||
* If the feature is not present or if the VM is not larger than 2 GiB,
|
* If the feature is not present or if the VM is not larger than 2 GiB,
|
||||||
* KVM_PV_ASYNC_CLEANUP_PREPARE fill fail; no point in attempting it.
|
* KVM_PV_ASYNC_CLEANUP_PREPARE fill fail; no point in attempting it.
|
||||||
*/
|
*/
|
||||||
if ((MACHINE(ms)->maxram_size <= 2 * GiB) ||
|
if (s390_get_memory_limit(ms) <= 2 * GiB ||
|
||||||
!kvm_check_extension(kvm_state, KVM_CAP_S390_PROTECTED_ASYNC_DISABLE)) {
|
!kvm_check_extension(kvm_state, KVM_CAP_S390_PROTECTED_ASYNC_DISABLE)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,13 +36,14 @@
|
||||||
#include "system/cpus.h"
|
#include "system/cpus.h"
|
||||||
#include "system/system.h"
|
#include "system/system.h"
|
||||||
#include "hw/s390x/ebcdic.h"
|
#include "hw/s390x/ebcdic.h"
|
||||||
#include "hw/s390x/s390-virtio-hcall.h"
|
#include "hw/s390x/s390-hypercall.h"
|
||||||
#include "hw/s390x/sclp.h"
|
#include "hw/s390x/sclp.h"
|
||||||
#include "hw/s390x/s390_flic.h"
|
#include "hw/s390x/s390_flic.h"
|
||||||
#include "hw/s390x/ioinst.h"
|
#include "hw/s390x/ioinst.h"
|
||||||
#include "hw/s390x/s390-pci-inst.h"
|
#include "hw/s390x/s390-pci-inst.h"
|
||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
#include "hw/s390x/tod.h"
|
#include "hw/s390x/tod.h"
|
||||||
|
#include CONFIG_DEVICES
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* #define DEBUG_HELPER */
|
/* #define DEBUG_HELPER */
|
||||||
|
@ -116,12 +117,15 @@ void HELPER(diag)(CPUS390XState *env, uint32_t r1, uint32_t r3, uint32_t num)
|
||||||
uint64_t r;
|
uint64_t r;
|
||||||
|
|
||||||
switch (num) {
|
switch (num) {
|
||||||
|
#ifdef CONFIG_S390_CCW_VIRTIO
|
||||||
case 0x500:
|
case 0x500:
|
||||||
/* KVM hypercall */
|
/* QEMU/KVM hypercall */
|
||||||
bql_lock();
|
bql_lock();
|
||||||
r = s390_virtio_hypercall(env);
|
handle_diag_500(env_archcpu(env), GETPC());
|
||||||
bql_unlock();
|
bql_unlock();
|
||||||
|
r = 0;
|
||||||
break;
|
break;
|
||||||
|
#endif /* CONFIG_S390_CCW_VIRTIO */
|
||||||
case 0x44:
|
case 0x44:
|
||||||
/* yield */
|
/* yield */
|
||||||
r = 0;
|
r = 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue