mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-27 13:30:52 +00:00
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 <david@redhat.com> Reviewed-by: Thomas Huth <thuth@redhat.com> Message-Id: <20210903155514.44772-10-david@redhat.com> Signed-off-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
parent
380ac2bcce
commit
67db1306a2
@ -17,6 +17,7 @@
|
|||||||
#include "qapi/qapi-commands-misc-target.h"
|
#include "qapi/qapi-commands-misc-target.h"
|
||||||
#include "qapi/qmp/qdict.h"
|
#include "qapi/qmp/qdict.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
|
#include "sysemu/memory_mapping.h"
|
||||||
#include "sysemu/kvm.h"
|
#include "sysemu/kvm.h"
|
||||||
#include "migration/qemu-file-types.h"
|
#include "migration/qemu-file-types.h"
|
||||||
#include "migration/register.h"
|
#include "migration/register.h"
|
||||||
@ -257,10 +258,9 @@ static void s390_storage_keys_save(QEMUFile *f, void *opaque)
|
|||||||
{
|
{
|
||||||
S390SKeysState *ss = S390_SKEYS(opaque);
|
S390SKeysState *ss = S390_SKEYS(opaque);
|
||||||
S390SKeysClass *skeyclass = S390_SKEYS_GET_CLASS(ss);
|
S390SKeysClass *skeyclass = S390_SKEYS_GET_CLASS(ss);
|
||||||
MachineState *ms = MACHINE(qdev_get_machine());
|
GuestPhysBlockList guest_phys_blocks;
|
||||||
uint64_t pages_left = ms->ram_size / TARGET_PAGE_SIZE;
|
GuestPhysBlock *block;
|
||||||
uint64_t read_count, eos = S390_SKEYS_SAVE_FLAG_EOS;
|
uint64_t pages, gfn;
|
||||||
vaddr cur_gfn = 0;
|
|
||||||
int error = 0;
|
int error = 0;
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
|
|
||||||
@ -274,36 +274,52 @@ static void s390_storage_keys_save(QEMUFile *f, void *opaque)
|
|||||||
goto end_stream;
|
goto end_stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We only support initial memory. Standby memory is not handled yet. */
|
guest_phys_blocks_init(&guest_phys_blocks);
|
||||||
qemu_put_be64(f, (cur_gfn * TARGET_PAGE_SIZE) | S390_SKEYS_SAVE_FLAG_SKEYS);
|
guest_phys_blocks_append(&guest_phys_blocks);
|
||||||
qemu_put_be64(f, pages_left);
|
|
||||||
|
|
||||||
while (pages_left) {
|
/* Send each contiguous physical memory range separately. */
|
||||||
read_count = MIN(pages_left, S390_SKEYS_BUFFER_SIZE);
|
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));
|
||||||
|
|
||||||
if (!error) {
|
gfn = block->target_start / TARGET_PAGE_SIZE;
|
||||||
error = skeyclass->get_skeys(ss, cur_gfn, read_count, buf);
|
pages = (block->target_end - block->target_start) / TARGET_PAGE_SIZE;
|
||||||
if (error) {
|
qemu_put_be64(f, block->target_start | S390_SKEYS_SAVE_FLAG_SKEYS);
|
||||||
/*
|
qemu_put_be64(f, pages);
|
||||||
* If error: we want to fill the stream with valid data instead
|
|
||||||
* of stopping early so we pad the stream with 0x00 values and
|
while (pages) {
|
||||||
* use S390_SKEYS_SAVE_FLAG_ERROR to indicate failure to the
|
const uint64_t cur_pages = MIN(pages, S390_SKEYS_BUFFER_SIZE);
|
||||||
* reading side.
|
|
||||||
*/
|
if (!error) {
|
||||||
error_report("S390_GET_KEYS error %d", error);
|
error = skeyclass->get_skeys(ss, gfn, cur_pages, buf);
|
||||||
memset(buf, 0, S390_SKEYS_BUFFER_SIZE);
|
if (error) {
|
||||||
eos = S390_SKEYS_SAVE_FLAG_ERROR;
|
/*
|
||||||
|
* Create a valid stream with all 0x00 and indicate
|
||||||
|
* S390_SKEYS_SAVE_FLAG_ERROR to the destination.
|
||||||
|
*/
|
||||||
|
error_report("S390_GET_KEYS error %d", error);
|
||||||
|
memset(buf, 0, S390_SKEYS_BUFFER_SIZE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qemu_put_buffer(f, buf, cur_pages);
|
||||||
|
gfn += cur_pages;
|
||||||
|
pages -= cur_pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_put_buffer(f, buf, read_count);
|
if (error) {
|
||||||
cur_gfn += read_count;
|
break;
|
||||||
pages_left -= read_count;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
guest_phys_blocks_free(&guest_phys_blocks);
|
||||||
g_free(buf);
|
g_free(buf);
|
||||||
end_stream:
|
end_stream:
|
||||||
qemu_put_be64(f, eos);
|
if (error) {
|
||||||
|
qemu_put_be64(f, S390_SKEYS_SAVE_FLAG_ERROR);
|
||||||
|
} else {
|
||||||
|
qemu_put_be64(f, S390_SKEYS_SAVE_FLAG_EOS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int s390_storage_keys_load(QEMUFile *f, void *opaque, int version_id)
|
static int s390_storage_keys_load(QEMUFile *f, void *opaque, int version_id)
|
||||||
|
Loading…
Reference in New Issue
Block a user