hw/s390x/s390-skeys: use memory mapping to detect which storage keys to dump
Handle it similar to migration. Assert that we're holding the BQL, to make sure we don't see concurrent modifications. Signed-off-by: David Hildenbrand <david@redhat.com> Reviewed-by: Thomas Huth <thuth@redhat.com> Message-Id: <20210903155514.44772-11-david@redhat.com> Signed-off-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
parent
67db1306a2
commit
78eedc60aa
@ -110,11 +110,10 @@ void qmp_dump_skeys(const char *filename, Error **errp)
|
|||||||
{
|
{
|
||||||
S390SKeysState *ss = s390_get_skeys_device();
|
S390SKeysState *ss = s390_get_skeys_device();
|
||||||
S390SKeysClass *skeyclass = S390_SKEYS_GET_CLASS(ss);
|
S390SKeysClass *skeyclass = S390_SKEYS_GET_CLASS(ss);
|
||||||
MachineState *ms = MACHINE(qdev_get_machine());
|
GuestPhysBlockList guest_phys_blocks;
|
||||||
const uint64_t total_count = ms->ram_size / TARGET_PAGE_SIZE;
|
GuestPhysBlock *block;
|
||||||
uint64_t handled_count = 0, cur_count;
|
uint64_t pages, gfn;
|
||||||
Error *lerr = NULL;
|
Error *lerr = NULL;
|
||||||
vaddr cur_gfn = 0;
|
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
int ret;
|
int ret;
|
||||||
int fd;
|
int fd;
|
||||||
@ -145,28 +144,39 @@ void qmp_dump_skeys(const char *filename, Error **errp)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we'll only dump initial memory for now */
|
assert(qemu_mutex_iothread_locked());
|
||||||
while (handled_count < total_count) {
|
guest_phys_blocks_init(&guest_phys_blocks);
|
||||||
/* Calculate how many keys to ask for & handle overflow case */
|
guest_phys_blocks_append(&guest_phys_blocks);
|
||||||
cur_count = MIN(total_count - handled_count, S390_SKEYS_BUFFER_SIZE);
|
|
||||||
|
|
||||||
ret = skeyclass->get_skeys(ss, cur_gfn, cur_count, buf);
|
QTAILQ_FOREACH(block, &guest_phys_blocks.head, next) {
|
||||||
if (ret < 0) {
|
assert(QEMU_IS_ALIGNED(block->target_start, TARGET_PAGE_SIZE));
|
||||||
error_setg(errp, "get_keys error %d", ret);
|
assert(QEMU_IS_ALIGNED(block->target_end, TARGET_PAGE_SIZE));
|
||||||
goto out_free;
|
|
||||||
|
gfn = block->target_start / TARGET_PAGE_SIZE;
|
||||||
|
pages = (block->target_end - block->target_start) / TARGET_PAGE_SIZE;
|
||||||
|
|
||||||
|
while (pages) {
|
||||||
|
const uint64_t cur_pages = MIN(pages, S390_SKEYS_BUFFER_SIZE);
|
||||||
|
|
||||||
|
ret = skeyclass->get_skeys(ss, gfn, cur_pages, buf);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "get_keys error");
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write keys to stream */
|
||||||
|
write_keys(f, buf, gfn, cur_pages, &lerr);
|
||||||
|
if (lerr) {
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfn += cur_pages;
|
||||||
|
pages -= cur_pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write keys to stream */
|
|
||||||
write_keys(f, buf, cur_gfn, cur_count, &lerr);
|
|
||||||
if (lerr) {
|
|
||||||
goto out_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_gfn += cur_count;
|
|
||||||
handled_count += cur_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out_free:
|
out_free:
|
||||||
|
guest_phys_blocks_free(&guest_phys_blocks);
|
||||||
error_propagate(errp, lerr);
|
error_propagate(errp, lerr);
|
||||||
g_free(buf);
|
g_free(buf);
|
||||||
out:
|
out:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user