Skip to content

Commit 67db130

Browse files
davidhildenbrandhuth
authored andcommitted
hw/s390x/s390-skeys: use memory mapping to detect which storage keys to migrate
Let's use the guest_phys_blocks API to get physical memory regions that are well defined inside our physical address space and migrate the storage keys of these. This is a preparation for having memory besides initial ram defined in the guest physical address space, for example, via memory devices. We get rid of the ms->ram_size dependency. Please note that we will usually have very little (--> 1) physical ranges. With virtio-mem might have significantly more ranges in the future. If that turns out to be a problem (e.g., total memory footprint of the list), we could look into a memory mapping API that avoids creation of a list and instead triggers a callback for each range. Signed-off-by: David Hildenbrand <[email protected]> Reviewed-by: Thomas Huth <[email protected]> Message-Id: <[email protected]> Signed-off-by: Thomas Huth <[email protected]>
1 parent 380ac2b commit 67db130

File tree

1 file changed

+43
-27
lines changed

1 file changed

+43
-27
lines changed

hw/s390x/s390-skeys.c

Lines changed: 43 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "qapi/qapi-commands-misc-target.h"
1818
#include "qapi/qmp/qdict.h"
1919
#include "qemu/error-report.h"
20+
#include "sysemu/memory_mapping.h"
2021
#include "sysemu/kvm.h"
2122
#include "migration/qemu-file-types.h"
2223
#include "migration/register.h"
@@ -257,10 +258,9 @@ static void s390_storage_keys_save(QEMUFile *f, void *opaque)
257258
{
258259
S390SKeysState *ss = S390_SKEYS(opaque);
259260
S390SKeysClass *skeyclass = S390_SKEYS_GET_CLASS(ss);
260-
MachineState *ms = MACHINE(qdev_get_machine());
261-
uint64_t pages_left = ms->ram_size / TARGET_PAGE_SIZE;
262-
uint64_t read_count, eos = S390_SKEYS_SAVE_FLAG_EOS;
263-
vaddr cur_gfn = 0;
261+
GuestPhysBlockList guest_phys_blocks;
262+
GuestPhysBlock *block;
263+
uint64_t pages, gfn;
264264
int error = 0;
265265
uint8_t *buf;
266266

@@ -274,36 +274,52 @@ static void s390_storage_keys_save(QEMUFile *f, void *opaque)
274274
goto end_stream;
275275
}
276276

277-
/* We only support initial memory. Standby memory is not handled yet. */
278-
qemu_put_be64(f, (cur_gfn * TARGET_PAGE_SIZE) | S390_SKEYS_SAVE_FLAG_SKEYS);
279-
qemu_put_be64(f, pages_left);
280-
281-
while (pages_left) {
282-
read_count = MIN(pages_left, S390_SKEYS_BUFFER_SIZE);
283-
284-
if (!error) {
285-
error = skeyclass->get_skeys(ss, cur_gfn, read_count, buf);
286-
if (error) {
287-
/*
288-
* If error: we want to fill the stream with valid data instead
289-
* of stopping early so we pad the stream with 0x00 values and
290-
* use S390_SKEYS_SAVE_FLAG_ERROR to indicate failure to the
291-
* reading side.
292-
*/
293-
error_report("S390_GET_KEYS error %d", error);
294-
memset(buf, 0, S390_SKEYS_BUFFER_SIZE);
295-
eos = S390_SKEYS_SAVE_FLAG_ERROR;
277+
guest_phys_blocks_init(&guest_phys_blocks);
278+
guest_phys_blocks_append(&guest_phys_blocks);
279+
280+
/* Send each contiguous physical memory range separately. */
281+
QTAILQ_FOREACH(block, &guest_phys_blocks.head, next) {
282+
assert(QEMU_IS_ALIGNED(block->target_start, TARGET_PAGE_SIZE));
283+
assert(QEMU_IS_ALIGNED(block->target_end, TARGET_PAGE_SIZE));
284+
285+
gfn = block->target_start / TARGET_PAGE_SIZE;
286+
pages = (block->target_end - block->target_start) / TARGET_PAGE_SIZE;
287+
qemu_put_be64(f, block->target_start | S390_SKEYS_SAVE_FLAG_SKEYS);
288+
qemu_put_be64(f, pages);
289+
290+
while (pages) {
291+
const uint64_t cur_pages = MIN(pages, S390_SKEYS_BUFFER_SIZE);
292+
293+
if (!error) {
294+
error = skeyclass->get_skeys(ss, gfn, cur_pages, buf);
295+
if (error) {
296+
/*
297+
* Create a valid stream with all 0x00 and indicate
298+
* S390_SKEYS_SAVE_FLAG_ERROR to the destination.
299+
*/
300+
error_report("S390_GET_KEYS error %d", error);
301+
memset(buf, 0, S390_SKEYS_BUFFER_SIZE);
302+
}
296303
}
304+
305+
qemu_put_buffer(f, buf, cur_pages);
306+
gfn += cur_pages;
307+
pages -= cur_pages;
297308
}
298309

299-
qemu_put_buffer(f, buf, read_count);
300-
cur_gfn += read_count;
301-
pages_left -= read_count;
310+
if (error) {
311+
break;
312+
}
302313
}
303314

315+
guest_phys_blocks_free(&guest_phys_blocks);
304316
g_free(buf);
305317
end_stream:
306-
qemu_put_be64(f, eos);
318+
if (error) {
319+
qemu_put_be64(f, S390_SKEYS_SAVE_FLAG_ERROR);
320+
} else {
321+
qemu_put_be64(f, S390_SKEYS_SAVE_FLAG_EOS);
322+
}
307323
}
308324

309325
static int s390_storage_keys_load(QEMUFile *f, void *opaque, int version_id)

0 commit comments

Comments
 (0)