Skip to content

Commit aa3a285

Browse files
committed
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 "[email protected]" # gpg: Good signature from "David Hildenbrand <[email protected]>" [unknown] # gpg: aka "David Hildenbrand <[email protected]>" [full] # gpg: aka "David Hildenbrand <[email protected]>" [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 <[email protected]>
2 parents 65cb712 + aa910c2 commit aa3a285

25 files changed

+873
-229
lines changed

MAINTAINERS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2384,6 +2384,9 @@ F: include/hw/virtio/virtio-crypto.h
23842384
virtio based memory device
23852385
M: David Hildenbrand <[email protected]>
23862386
S: Supported
2387+
F: hw/s390x/virtio-ccw-md.c
2388+
F: hw/s390x/virtio-ccw-md.h
2389+
F: hw/s390x/virtio-ccw-md-stubs.c
23872390
F: hw/virtio/virtio-md-pci.c
23882391
F: include/hw/virtio/virtio-md-pci.h
23892392
F: stubs/virtio-md-pci.c
@@ -2395,6 +2398,8 @@ W: https://virtio-mem.gitlab.io/
23952398
F: hw/virtio/virtio-mem.c
23962399
F: hw/virtio/virtio-mem-pci.h
23972400
F: hw/virtio/virtio-mem-pci.c
2401+
F: hw/s390x/virtio-ccw-mem.c
2402+
F: hw/s390x/virtio-ccw-mem.h
23982403
F: include/hw/virtio/virtio-mem.h
23992404

24002405
virtio-snd

hw/s390x/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ config S390_CCW_VIRTIO
1616
select SCLPCONSOLE
1717
select VIRTIO_CCW
1818
select MSI_NONBROKEN
19+
select VIRTIO_MEM_SUPPORTED

hw/s390x/meson.build

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ s390x_ss.add(files(
1212
's390-pci-inst.c',
1313
's390-skeys.c',
1414
's390-stattrib.c',
15-
's390-virtio-hcall.c',
1615
'sclp.c',
1716
'sclpcpu.c',
1817
'sclpquiesce.c',
@@ -28,7 +27,10 @@ s390x_ss.add(when: 'CONFIG_KVM', if_true: files(
2827
s390x_ss.add(when: 'CONFIG_TCG', if_true: files(
2928
'tod-tcg.c',
3029
))
31-
s390x_ss.add(when: 'CONFIG_S390_CCW_VIRTIO', if_true: files('s390-virtio-ccw.c'))
30+
s390x_ss.add(when: 'CONFIG_S390_CCW_VIRTIO', if_true: files(
31+
's390-virtio-ccw.c',
32+
's390-hypercall.c',
33+
))
3234
s390x_ss.add(when: 'CONFIG_TERMINAL3270', if_true: files('3270-ccw.c'))
3335
s390x_ss.add(when: 'CONFIG_VFIO', if_true: files('s390-pci-vfio.c'))
3436

@@ -48,8 +50,12 @@ endif
4850
virtio_ss.add(when: 'CONFIG_VHOST_SCSI', if_true: files('vhost-scsi-ccw.c'))
4951
virtio_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock-ccw.c'))
5052
virtio_ss.add(when: 'CONFIG_VHOST_USER_FS', if_true: files('vhost-user-fs-ccw.c'))
53+
virtio_ss.add(when: 'CONFIG_VIRTIO_MD', if_true: files('virtio-ccw-md.c'))
54+
virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-ccw-mem.c'))
5155
s390x_ss.add_all(when: 'CONFIG_VIRTIO_CCW', if_true: virtio_ss)
5256

57+
s390x_ss.add(when: 'CONFIG_VIRTIO_MD', if_false: files('virtio-ccw-md-stubs.c'))
58+
5359
hw_arch += {'s390x': s390x_ss}
5460

5561
hw_s390x_modules = {}

hw/s390x/s390-hypercall.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Support for QEMU/KVM hypercalls on s390
3+
*
4+
* Copyright 2012 IBM Corp.
5+
* Author(s): Cornelia Huck <[email protected]>
6+
*
7+
* This work is licensed under the terms of the GNU GPL, version 2 or (at
8+
* your option) any later version. See the COPYING file in the top-level
9+
* directory.
10+
*/
11+
12+
#include "qemu/osdep.h"
13+
#include "cpu.h"
14+
#include "hw/s390x/s390-virtio-ccw.h"
15+
#include "hw/s390x/s390-hypercall.h"
16+
#include "hw/s390x/ioinst.h"
17+
#include "hw/s390x/css.h"
18+
#include "virtio-ccw.h"
19+
20+
static int handle_virtio_notify(uint64_t mem)
21+
{
22+
MachineState *ms = MACHINE(qdev_get_machine());
23+
24+
if (mem < ms->ram_size) {
25+
/* Early printk */
26+
return 0;
27+
}
28+
return -EINVAL;
29+
}
30+
31+
static int handle_virtio_ccw_notify(uint64_t subch_id, uint64_t data)
32+
{
33+
SubchDev *sch;
34+
VirtIODevice *vdev;
35+
int cssid, ssid, schid, m;
36+
uint16_t vq_idx = data;
37+
38+
if (ioinst_disassemble_sch_ident(subch_id, &m, &cssid, &ssid, &schid)) {
39+
return -EINVAL;
40+
}
41+
sch = css_find_subch(m, cssid, ssid, schid);
42+
if (!sch || !css_subch_visible(sch)) {
43+
return -EINVAL;
44+
}
45+
46+
vdev = virtio_ccw_get_vdev(sch);
47+
if (vq_idx >= VIRTIO_QUEUE_MAX || !virtio_queue_get_num(vdev, vq_idx)) {
48+
return -EINVAL;
49+
}
50+
51+
if (virtio_vdev_has_feature(vdev, VIRTIO_F_NOTIFICATION_DATA)) {
52+
virtio_queue_set_shadow_avail_idx(virtio_get_queue(vdev, vq_idx),
53+
(data >> 16) & 0xFFFF);
54+
}
55+
56+
virtio_queue_notify(vdev, vq_idx);
57+
return 0;
58+
}
59+
60+
static uint64_t handle_storage_limit(void)
61+
{
62+
S390CcwMachineState *s390ms = S390_CCW_MACHINE(qdev_get_machine());
63+
64+
return s390_get_memory_limit(s390ms) - 1;
65+
}
66+
67+
void handle_diag_500(S390CPU *cpu, uintptr_t ra)
68+
{
69+
CPUS390XState *env = &cpu->env;
70+
const uint64_t subcode = env->regs[1];
71+
72+
switch (subcode) {
73+
case DIAG500_VIRTIO_NOTIFY:
74+
env->regs[2] = handle_virtio_notify(env->regs[2]);
75+
break;
76+
case DIAG500_VIRTIO_CCW_NOTIFY:
77+
env->regs[2] = handle_virtio_ccw_notify(env->regs[2], env->regs[3]);
78+
break;
79+
case DIAG500_STORAGE_LIMIT:
80+
env->regs[2] = handle_storage_limit();
81+
break;
82+
default:
83+
s390_program_interrupt(env, PGM_SPECIFICATION, ra);
84+
}
85+
}

hw/s390x/s390-hypercall.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Support for QEMU/KVM hypercalls on s390x
3+
*
4+
* Copyright IBM Corp. 2012, 2017
5+
* Author(s): Cornelia Huck <[email protected]>
6+
*
7+
* This work is licensed under the terms of the GNU GPL, version 2 or (at
8+
* your option) any later version. See the COPYING file in the top-level
9+
* directory.
10+
*/
11+
12+
#ifndef HW_S390_HYPERCALL_H
13+
#define HW_S390_HYPERCALL_H
14+
15+
#include "cpu.h"
16+
17+
#define DIAG500_VIRTIO_NOTIFY 0 /* legacy, implemented as a NOP */
18+
#define DIAG500_VIRTIO_RESET 1 /* legacy */
19+
#define DIAG500_VIRTIO_SET_STATUS 2 /* legacy */
20+
#define DIAG500_VIRTIO_CCW_NOTIFY 3 /* KVM_S390_VIRTIO_CCW_NOTIFY */
21+
#define DIAG500_STORAGE_LIMIT 4
22+
23+
void handle_diag_500(S390CPU *cpu, uintptr_t ra);
24+
25+
#endif /* HW_S390_HYPERCALL_H */

hw/s390x/s390-skeys.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
#include "qemu/osdep.h"
1313
#include "qemu/units.h"
14-
#include "hw/boards.h"
14+
#include "hw/s390x/s390-virtio-ccw.h"
1515
#include "hw/qdev-properties.h"
1616
#include "hw/s390x/storage-keys.h"
1717
#include "qapi/error.h"
@@ -251,9 +251,9 @@ static bool qemu_s390_enable_skeys(S390SKeysState *ss)
251251
* g_once_init_enter() is good enough.
252252
*/
253253
if (g_once_init_enter(&initialized)) {
254-
MachineState *machine = MACHINE(qdev_get_machine());
254+
S390CcwMachineState *s390ms = S390_CCW_MACHINE(qdev_get_machine());
255255

256-
skeys->key_count = machine->ram_size / TARGET_PAGE_SIZE;
256+
skeys->key_count = s390_get_memory_limit(s390ms) / TARGET_PAGE_SIZE;
257257
skeys->keydata = g_malloc0(skeys->key_count);
258258
g_once_init_leave(&initialized, 1);
259259
}

hw/s390x/s390-stattrib-kvm.c

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010
*/
1111

1212
#include "qemu/osdep.h"
13-
#include "hw/boards.h"
13+
#include "hw/s390x/s390-virtio-ccw.h"
1414
#include "migration/qemu-file.h"
1515
#include "hw/s390x/storage-attributes.h"
1616
#include "qemu/error-report.h"
1717
#include "system/kvm.h"
18+
#include "system/memory_mapping.h"
1819
#include "exec/ram_addr.h"
1920
#include "kvm/kvm_s390x.h"
2021
#include "qapi/error.h"
@@ -84,8 +85,8 @@ static int kvm_s390_stattrib_set_stattr(S390StAttribState *sa,
8485
uint8_t *values)
8586
{
8687
KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa);
87-
MachineState *machine = MACHINE(qdev_get_machine());
88-
unsigned long max = machine->ram_size / TARGET_PAGE_SIZE;
88+
S390CcwMachineState *s390ms = S390_CCW_MACHINE(qdev_get_machine());
89+
unsigned long max = s390_get_memory_limit(s390ms) / TARGET_PAGE_SIZE;
8990

9091
if (start_gfn + count > max) {
9192
error_report("Out of memory bounds when setting storage attributes");
@@ -103,39 +104,57 @@ static int kvm_s390_stattrib_set_stattr(S390StAttribState *sa,
103104
static void kvm_s390_stattrib_synchronize(S390StAttribState *sa)
104105
{
105106
KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa);
106-
MachineState *machine = MACHINE(qdev_get_machine());
107-
unsigned long max = machine->ram_size / TARGET_PAGE_SIZE;
108-
/* We do not need to reach the maximum buffer size allowed */
109-
unsigned long cx, len = KVM_S390_SKEYS_MAX / 2;
107+
S390CcwMachineState *s390ms = S390_CCW_MACHINE(qdev_get_machine());
108+
unsigned long max = s390_get_memory_limit(s390ms) / TARGET_PAGE_SIZE;
109+
unsigned long start_gfn, end_gfn, pages;
110+
GuestPhysBlockList guest_phys_blocks;
111+
GuestPhysBlock *block;
110112
int r;
111113
struct kvm_s390_cmma_log clog = {
112114
.flags = 0,
113115
.mask = ~0ULL,
114116
};
115117

116-
if (sas->incoming_buffer) {
117-
for (cx = 0; cx + len <= max; cx += len) {
118-
clog.start_gfn = cx;
119-
clog.count = len;
120-
clog.values = (uint64_t)(sas->incoming_buffer + cx);
121-
r = kvm_vm_ioctl(kvm_state, KVM_S390_SET_CMMA_BITS, &clog);
122-
if (r) {
123-
error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r));
124-
return;
125-
}
126-
}
127-
if (cx < max) {
128-
clog.start_gfn = cx;
129-
clog.count = max - cx;
130-
clog.values = (uint64_t)(sas->incoming_buffer + cx);
118+
if (!sas->incoming_buffer) {
119+
return;
120+
}
121+
guest_phys_blocks_init(&guest_phys_blocks);
122+
guest_phys_blocks_append(&guest_phys_blocks);
123+
124+
QTAILQ_FOREACH(block, &guest_phys_blocks.head, next) {
125+
assert(QEMU_IS_ALIGNED(block->target_start, TARGET_PAGE_SIZE));
126+
assert(QEMU_IS_ALIGNED(block->target_end, TARGET_PAGE_SIZE));
127+
128+
start_gfn = block->target_start / TARGET_PAGE_SIZE;
129+
end_gfn = block->target_end / TARGET_PAGE_SIZE;
130+
131+
while (start_gfn < end_gfn) {
132+
/* Don't exceed the maximum buffer size. */
133+
pages = MIN(end_gfn - start_gfn, KVM_S390_SKEYS_MAX / 2);
134+
135+
/*
136+
* If we ever get guest physical memory beyond the configured
137+
* memory limit, something went very wrong.
138+
*/
139+
assert(start_gfn + pages <= max);
140+
141+
clog.start_gfn = start_gfn;
142+
clog.count = pages;
143+
clog.values = (uint64_t)(sas->incoming_buffer + start_gfn);
131144
r = kvm_vm_ioctl(kvm_state, KVM_S390_SET_CMMA_BITS, &clog);
132145
if (r) {
133146
error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r));
147+
goto out;
134148
}
149+
150+
start_gfn += pages;
135151
}
136-
g_free(sas->incoming_buffer);
137-
sas->incoming_buffer = NULL;
138152
}
153+
154+
out:
155+
guest_phys_blocks_free(&guest_phys_blocks);
156+
g_free(sas->incoming_buffer);
157+
sas->incoming_buffer = NULL;
139158
}
140159

141160
static int kvm_s390_stattrib_set_migrationmode(S390StAttribState *sa, bool val,

0 commit comments

Comments
 (0)