diff mbox series

[kvmtool,v4,4/5] memslot: Add support for READONLY mappings

Message ID 20200423173844.24220-5-andre.przywara@arm.com (mailing list archive)
State New, archived
Headers show
Series Add CFI flash emulation | expand

Commit Message

Andre Przywara April 23, 2020, 5:38 p.m. UTC
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.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 include/kvm/kvm.h | 12 ++++++++----
 kvm.c             |  5 +++++
 2 files changed, 13 insertions(+), 4 deletions(-)

Comments

Will Deacon April 24, 2020, 8:41 a.m. UTC | #1
On Thu, Apr 23, 2020 at 06:38:43PM +0100, Andre Przywara wrote:
> 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.
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  include/kvm/kvm.h | 12 ++++++++----
>  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)					\

nit: this is a bit broad to throw in a header file. How about
__kvm_mem_add_read_only()  instead?

Will
diff mbox series

Patch

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,