diff options
author | Andre Przywara <andre.przywara@arm.com> | 2020-04-23 18:38:43 +0100 |
---|---|---|
committer | Will Deacon <will@kernel.org> | 2020-04-24 18:00:01 +0100 |
commit | 0480e04a559c477946fbc156490a19e8e70f3d4f (patch) | |
tree | e97ff62734f68bb9ef08d3ab9168e3265949d3b6 | |
parent | 8d9877253b3c442868eb21bb4fd98cf177192993 (diff) | |
download | kvmtool-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.h | 12 | ||||
-rw-r--r-- | kvm.c | 5 |
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 "???"; @@ -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, |