When a memory region is added with a src_type specifying that it should use some kind of shared memory, also create an alias mapping to the same underlying physical pages. And, add an API so tests can get access to these alias addresses. Basically, for a guest physical address, let us look up the analogous host *alias* address. In a future commit, we'll modify the demand paging test to take advantage of this to exercise UFFD minor faults. The idea is, we pre-fault the underlying pages *via the alias*. When the *guest* faults, it gets a "minor" fault (PTEs don't exist yet, but a page is already in the page cache). Then, the userfaultfd theads can handle the fault: they could potentially modify the underlying memory *via the alias* if they wanted to, and then they install the PTEs and let the guest carry on via a UFFDIO_CONTINUE ioctl. Reviewed-by: Ben Gardon <bgardon@google.com> Signed-off-by: Axel Rasmussen <axelrasmussen@google.com> Message-Id: <20210519200339.829146-9-axelrasmussen@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
128 lines
2.7 KiB
C
128 lines
2.7 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* tools/testing/selftests/kvm/lib/kvm_util_internal.h
|
|
*
|
|
* Copyright (C) 2018, Google LLC.
|
|
*/
|
|
|
|
#ifndef SELFTEST_KVM_UTIL_INTERNAL_H
|
|
#define SELFTEST_KVM_UTIL_INTERNAL_H
|
|
|
|
#include "linux/hashtable.h"
|
|
#include "linux/rbtree.h"
|
|
|
|
#include "sparsebit.h"
|
|
|
|
struct userspace_mem_region {
|
|
struct kvm_userspace_memory_region region;
|
|
struct sparsebit *unused_phy_pages;
|
|
int fd;
|
|
off_t offset;
|
|
void *host_mem;
|
|
void *host_alias;
|
|
void *mmap_start;
|
|
void *mmap_alias;
|
|
size_t mmap_size;
|
|
struct rb_node gpa_node;
|
|
struct rb_node hva_node;
|
|
struct hlist_node slot_node;
|
|
};
|
|
|
|
struct vcpu {
|
|
struct list_head list;
|
|
uint32_t id;
|
|
int fd;
|
|
struct kvm_run *state;
|
|
struct kvm_dirty_gfn *dirty_gfns;
|
|
uint32_t fetch_index;
|
|
uint32_t dirty_gfns_count;
|
|
};
|
|
|
|
struct userspace_mem_regions {
|
|
struct rb_root gpa_tree;
|
|
struct rb_root hva_tree;
|
|
DECLARE_HASHTABLE(slot_hash, 9);
|
|
};
|
|
|
|
struct kvm_vm {
|
|
int mode;
|
|
unsigned long type;
|
|
int kvm_fd;
|
|
int fd;
|
|
unsigned int pgtable_levels;
|
|
unsigned int page_size;
|
|
unsigned int page_shift;
|
|
unsigned int pa_bits;
|
|
unsigned int va_bits;
|
|
uint64_t max_gfn;
|
|
struct list_head vcpus;
|
|
struct userspace_mem_regions regions;
|
|
struct sparsebit *vpages_valid;
|
|
struct sparsebit *vpages_mapped;
|
|
bool has_irqchip;
|
|
bool pgd_created;
|
|
vm_paddr_t pgd;
|
|
vm_vaddr_t gdt;
|
|
vm_vaddr_t tss;
|
|
vm_vaddr_t idt;
|
|
vm_vaddr_t handlers;
|
|
uint32_t dirty_ring_size;
|
|
};
|
|
|
|
struct vcpu *vcpu_find(struct kvm_vm *vm, uint32_t vcpuid);
|
|
|
|
/*
|
|
* Virtual Translation Tables Dump
|
|
*
|
|
* Input Args:
|
|
* stream - Output FILE stream
|
|
* vm - Virtual Machine
|
|
* indent - Left margin indent amount
|
|
*
|
|
* Output Args: None
|
|
*
|
|
* Return: None
|
|
*
|
|
* Dumps to the FILE stream given by @stream, the contents of all the
|
|
* virtual translation tables for the VM given by @vm.
|
|
*/
|
|
void virt_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent);
|
|
|
|
/*
|
|
* Register Dump
|
|
*
|
|
* Input Args:
|
|
* stream - Output FILE stream
|
|
* regs - Registers
|
|
* indent - Left margin indent amount
|
|
*
|
|
* Output Args: None
|
|
*
|
|
* Return: None
|
|
*
|
|
* Dumps the state of the registers given by @regs, to the FILE stream
|
|
* given by @stream.
|
|
*/
|
|
void regs_dump(FILE *stream, struct kvm_regs *regs, uint8_t indent);
|
|
|
|
/*
|
|
* System Register Dump
|
|
*
|
|
* Input Args:
|
|
* stream - Output FILE stream
|
|
* sregs - System registers
|
|
* indent - Left margin indent amount
|
|
*
|
|
* Output Args: None
|
|
*
|
|
* Return: None
|
|
*
|
|
* Dumps the state of the system registers given by @sregs, to the FILE stream
|
|
* given by @stream.
|
|
*/
|
|
void sregs_dump(FILE *stream, struct kvm_sregs *sregs, uint8_t indent);
|
|
|
|
struct userspace_mem_region *
|
|
memslot2region(struct kvm_vm *vm, uint32_t memslot);
|
|
|
|
#endif /* SELFTEST_KVM_UTIL_INTERNAL_H */
|