aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndre Przywara <andre.przywara@arm.com>2020-04-23 18:38:43 +0100
committerWill Deacon <will@kernel.org>2020-04-24 18:00:01 +0100
commit0480e04a559c477946fbc156490a19e8e70f3d4f (patch)
treee97ff62734f68bb9ef08d3ab9168e3265949d3b6
parent8d9877253b3c442868eb21bb4fd98cf177192993 (diff)
downloadkvmtool-0480e04a559c477946fbc156490a19e8e70f3d4f.tar.gz
memslot: Add support for READONLY mappings
A KVM memslot has a flags field, which allows to mark a region as read-only. Add another memory type bit to allow kvmtool-internal users to map a write-protected region. Write access would trap and can be handled by the MMIO emulation, which should register on the same guest address region. Tested-by: Ard Biesheuvel <ardb@kernel.org> Signed-off-by: Andre Przywara <andre.przywara@arm.com> Signed-off-by: Will Deacon <will@kernel.org>
-rw-r--r--include/kvm/kvm.h12
-rw-r--r--kvm.c5
2 files changed, 13 insertions, 4 deletions
diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
index 9428f57a..53373b08 100644
--- a/include/kvm/kvm.h
+++ b/include/kvm/kvm.h
@@ -40,10 +40,12 @@ enum kvm_mem_type {
KVM_MEM_TYPE_RAM = 1 << 0,
KVM_MEM_TYPE_DEVICE = 1 << 1,
KVM_MEM_TYPE_RESERVED = 1 << 2,
+ KVM_MEM_TYPE_READONLY = 1 << 3,
KVM_MEM_TYPE_ALL = KVM_MEM_TYPE_RAM
| KVM_MEM_TYPE_DEVICE
| KVM_MEM_TYPE_RESERVED
+ | KVM_MEM_TYPE_READONLY
};
struct kvm_ext {
@@ -158,17 +160,19 @@ u64 host_to_guest_flat(struct kvm *kvm, void *ptr);
bool kvm__arch_load_kernel_image(struct kvm *kvm, int fd_kernel, int fd_initrd,
const char *kernel_cmdline);
+#define add_read_only(type, str) \
+ (((type) & KVM_MEM_TYPE_READONLY) ? str " (read-only)" : str)
static inline const char *kvm_mem_type_to_string(enum kvm_mem_type type)
{
- switch (type) {
+ switch (type & ~KVM_MEM_TYPE_READONLY) {
case KVM_MEM_TYPE_ALL:
return "(all)";
case KVM_MEM_TYPE_RAM:
- return "RAM";
+ return add_read_only(type, "RAM");
case KVM_MEM_TYPE_DEVICE:
- return "device";
+ return add_read_only(type, "device");
case KVM_MEM_TYPE_RESERVED:
- return "reserved";
+ return add_read_only(type, "reserved");
}
return "???";
diff --git a/kvm.c b/kvm.c
index 26f6b9bc..e327541d 100644
--- a/kvm.c
+++ b/kvm.c
@@ -242,6 +242,7 @@ int kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size,
struct kvm_mem_bank *bank;
struct list_head *prev_entry;
u32 slot;
+ u32 flags = 0;
int ret;
mutex_lock(&kvm->mem_banks_lock);
@@ -313,9 +314,13 @@ int kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size,
bank->type = type;
bank->slot = slot;
+ if (type & KVM_MEM_TYPE_READONLY)
+ flags |= KVM_MEM_READONLY;
+
if (type != KVM_MEM_TYPE_RESERVED) {
mem = (struct kvm_userspace_memory_region) {
.slot = slot,
+ .flags = flags,
.guest_phys_addr = guest_phys,
.memory_size = size,
.userspace_addr = (unsigned long)userspace_addr,