* [PATCH 0/6] KVM: kvm_set_memory_region() cleanups
@ 2024-08-02 20:49 Sean Christopherson
2024-08-02 20:49 ` [PATCH 1/6] KVM: Open code kvm_set_memory_region() into its sole caller (ioctl() API) Sean Christopherson
` (5 more replies)
0 siblings, 6 replies; 12+ messages in thread
From: Sean Christopherson @ 2024-08-02 20:49 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel
Cleanups related to kvm_set_memory_region(), salvaged from similar patches
that were flying around when we were sorting out KVM_SET_USER_MEMORY_REGION2.
I'm honestly 50/50 on whether this is all worthwhile, but in the end, I
decided I like having kvm_set_internal_memslot(). I think.
Sean Christopherson (6):
KVM: Open code kvm_set_memory_region() into its sole caller (ioctl()
API)
KVM: Assert slots_lock is held in __kvm_set_memory_region()
KVM: Add a dedicated API for setting KVM-internal memslots
KVM: x86: Drop double-underscores from __kvm_set_memory_region()
KVM: Disallow all flags for KVM-internal memslots
KVM: Move flags check for user memory regions to the ioctl() specific
API
arch/x86/kvm/x86.c | 4 +-
include/linux/kvm_host.h | 8 ++--
virt/kvm/kvm_main.c | 87 +++++++++++++++++-----------------------
3 files changed, 41 insertions(+), 58 deletions(-)
base-commit: 332d2c1d713e232e163386c35a3ba0c1b90df83f
--
2.46.0.rc2.264.g509ed76dc8-goog
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/6] KVM: Open code kvm_set_memory_region() into its sole caller (ioctl() API)
2024-08-02 20:49 [PATCH 0/6] KVM: kvm_set_memory_region() cleanups Sean Christopherson
@ 2024-08-02 20:49 ` Sean Christopherson
2024-08-05 8:39 ` Tao Su
2024-08-02 20:49 ` [PATCH 2/6] KVM: Assert slots_lock is held in __kvm_set_memory_region() Sean Christopherson
` (4 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Sean Christopherson @ 2024-08-02 20:49 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel
Open code kvm_set_memory_region() into its sole caller in preparation for
adding a dedicated API for setting internal memslots.
Oppurtunistically use the fancy new guard(mutex) to avoid a local 'r'
variable.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
include/linux/kvm_host.h | 2 --
virt/kvm/kvm_main.c | 15 ++-------------
2 files changed, 2 insertions(+), 15 deletions(-)
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 689e8be873a7..b341d00aae37 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1179,8 +1179,6 @@ enum kvm_mr_change {
KVM_MR_FLAGS_ONLY,
};
-int kvm_set_memory_region(struct kvm *kvm,
- const struct kvm_userspace_memory_region2 *mem);
int __kvm_set_memory_region(struct kvm *kvm,
const struct kvm_userspace_memory_region2 *mem);
void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *slot);
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index d0788d0a72cc..0557d663b69b 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2105,25 +2105,14 @@ int __kvm_set_memory_region(struct kvm *kvm,
}
EXPORT_SYMBOL_GPL(__kvm_set_memory_region);
-int kvm_set_memory_region(struct kvm *kvm,
- const struct kvm_userspace_memory_region2 *mem)
-{
- int r;
-
- mutex_lock(&kvm->slots_lock);
- r = __kvm_set_memory_region(kvm, mem);
- mutex_unlock(&kvm->slots_lock);
- return r;
-}
-EXPORT_SYMBOL_GPL(kvm_set_memory_region);
-
static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
struct kvm_userspace_memory_region2 *mem)
{
if ((u16)mem->slot >= KVM_USER_MEM_SLOTS)
return -EINVAL;
- return kvm_set_memory_region(kvm, mem);
+ guard(mutex)(&kvm->slots_lock);
+ return __kvm_set_memory_region(kvm, mem);
}
#ifndef CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT
--
2.46.0.rc2.264.g509ed76dc8-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/6] KVM: Assert slots_lock is held in __kvm_set_memory_region()
2024-08-02 20:49 [PATCH 0/6] KVM: kvm_set_memory_region() cleanups Sean Christopherson
2024-08-02 20:49 ` [PATCH 1/6] KVM: Open code kvm_set_memory_region() into its sole caller (ioctl() API) Sean Christopherson
@ 2024-08-02 20:49 ` Sean Christopherson
2024-08-05 8:41 ` Tao Su
2024-08-02 20:50 ` [PATCH 3/6] KVM: Add a dedicated API for setting KVM-internal memslots Sean Christopherson
` (3 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Sean Christopherson @ 2024-08-02 20:49 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel
Add a proper lockdep assertion in __kvm_set_memory_region() instead of
relying on a function comment. Opportunistically delete the entire
function comment as the API doesn't allocate memory or select a gfn,
and the "mostly for framebuffers" comment hasn't been true for a very long
time.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
virt/kvm/kvm_main.c | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 0557d663b69b..f202bdbfca9e 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1973,14 +1973,6 @@ static bool kvm_check_memslot_overlap(struct kvm_memslots *slots, int id,
return false;
}
-/*
- * Allocate some memory and give it an address in the guest physical address
- * space.
- *
- * Discontiguous memory is allowed, mostly for framebuffers.
- *
- * Must be called holding kvm->slots_lock for write.
- */
int __kvm_set_memory_region(struct kvm *kvm,
const struct kvm_userspace_memory_region2 *mem)
{
@@ -1992,6 +1984,8 @@ int __kvm_set_memory_region(struct kvm *kvm,
int as_id, id;
int r;
+ lockdep_assert_held(&kvm->slots_lock);
+
r = check_memory_region_flags(kvm, mem);
if (r)
return r;
--
2.46.0.rc2.264.g509ed76dc8-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 3/6] KVM: Add a dedicated API for setting KVM-internal memslots
2024-08-02 20:49 [PATCH 0/6] KVM: kvm_set_memory_region() cleanups Sean Christopherson
2024-08-02 20:49 ` [PATCH 1/6] KVM: Open code kvm_set_memory_region() into its sole caller (ioctl() API) Sean Christopherson
2024-08-02 20:49 ` [PATCH 2/6] KVM: Assert slots_lock is held in __kvm_set_memory_region() Sean Christopherson
@ 2024-08-02 20:50 ` Sean Christopherson
2024-08-05 8:42 ` Tao Su
2024-08-02 20:50 ` [PATCH 4/6] KVM: x86: Drop double-underscores from __kvm_set_memory_region() Sean Christopherson
` (2 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Sean Christopherson @ 2024-08-02 20:50 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel
Add a dedicated API for setting internal memslots, and have it explicitly
disallow setting userspace memslots. Setting a userspace memslots without
a direct command from userspace would result in all manner of issues.
No functional change intended.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/x86.c | 2 +-
include/linux/kvm_host.h | 4 ++--
virt/kvm/kvm_main.c | 15 ++++++++++++---
3 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index af6c8cf6a37a..77949fee13f7 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -12794,7 +12794,7 @@ void __user * __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa,
m.guest_phys_addr = gpa;
m.userspace_addr = hva;
m.memory_size = size;
- r = __kvm_set_memory_region(kvm, &m);
+ r = kvm_set_internal_memslot(kvm, &m);
if (r < 0)
return ERR_PTR_USR(r);
}
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index b341d00aae37..cefa274c0852 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1179,8 +1179,8 @@ enum kvm_mr_change {
KVM_MR_FLAGS_ONLY,
};
-int __kvm_set_memory_region(struct kvm *kvm,
- const struct kvm_userspace_memory_region2 *mem);
+int kvm_set_internal_memslot(struct kvm *kvm,
+ const struct kvm_userspace_memory_region2 *mem);
void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *slot);
void kvm_arch_memslots_updated(struct kvm *kvm, u64 gen);
int kvm_arch_prepare_memory_region(struct kvm *kvm,
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index f202bdbfca9e..63b43644ed9f 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1973,8 +1973,8 @@ static bool kvm_check_memslot_overlap(struct kvm_memslots *slots, int id,
return false;
}
-int __kvm_set_memory_region(struct kvm *kvm,
- const struct kvm_userspace_memory_region2 *mem)
+static int __kvm_set_memory_region(struct kvm *kvm,
+ const struct kvm_userspace_memory_region2 *mem)
{
struct kvm_memory_slot *old, *new;
struct kvm_memslots *slots;
@@ -2097,7 +2097,16 @@ int __kvm_set_memory_region(struct kvm *kvm,
kfree(new);
return r;
}
-EXPORT_SYMBOL_GPL(__kvm_set_memory_region);
+
+int kvm_set_internal_memslot(struct kvm *kvm,
+ const struct kvm_userspace_memory_region2 *mem)
+{
+ if (WARN_ON_ONCE(mem->slot < KVM_USER_MEM_SLOTS))
+ return -EINVAL;
+
+ return __kvm_set_memory_region(kvm, mem);
+}
+EXPORT_SYMBOL_GPL(kvm_set_internal_memslot);
static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
struct kvm_userspace_memory_region2 *mem)
--
2.46.0.rc2.264.g509ed76dc8-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 4/6] KVM: x86: Drop double-underscores from __kvm_set_memory_region()
2024-08-02 20:49 [PATCH 0/6] KVM: kvm_set_memory_region() cleanups Sean Christopherson
` (2 preceding siblings ...)
2024-08-02 20:50 ` [PATCH 3/6] KVM: Add a dedicated API for setting KVM-internal memslots Sean Christopherson
@ 2024-08-02 20:50 ` Sean Christopherson
2024-08-02 20:50 ` [PATCH 5/6] KVM: Disallow all flags for KVM-internal memslots Sean Christopherson
2024-08-02 20:50 ` [PATCH 6/6] KVM: Move flags check for user memory regions to the ioctl() specific API Sean Christopherson
5 siblings, 0 replies; 12+ messages in thread
From: Sean Christopherson @ 2024-08-02 20:50 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel
Now that there's no outer wrapper for __kvm_set_memory_region() and it's
static, drop its double-underscore prefix.
No functional change intended.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/x86.c | 2 +-
include/linux/kvm_host.h | 2 +-
virt/kvm/kvm_main.c | 8 ++++----
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 77949fee13f7..bd365fb8ab6e 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -12895,7 +12895,7 @@ static int kvm_alloc_memslot_metadata(struct kvm *kvm,
/*
* Clear out the previous array pointers for the KVM_MR_MOVE case. The
- * old arrays will be freed by __kvm_set_memory_region() if installing
+ * old arrays will be freed by kvm_set_memory_region() if installing
* the new memslot is successful.
*/
memset(&slot->arch, 0, sizeof(slot->arch));
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index cefa274c0852..b5c048858fc4 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1170,7 +1170,7 @@ static inline bool kvm_memslot_iter_is_valid(struct kvm_memslot_iter *iter, gfn_
* -- just change its flags
*
* Since flags can be changed by some of these operations, the following
- * differentiation is the best we can do for __kvm_set_memory_region():
+ * differentiation is the best we can do for kvm_set_memory_region():
*/
enum kvm_mr_change {
KVM_MR_CREATE,
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 63b43644ed9f..42ec817d6a7e 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1973,8 +1973,8 @@ static bool kvm_check_memslot_overlap(struct kvm_memslots *slots, int id,
return false;
}
-static int __kvm_set_memory_region(struct kvm *kvm,
- const struct kvm_userspace_memory_region2 *mem)
+static int kvm_set_memory_region(struct kvm *kvm,
+ const struct kvm_userspace_memory_region2 *mem)
{
struct kvm_memory_slot *old, *new;
struct kvm_memslots *slots;
@@ -2104,7 +2104,7 @@ int kvm_set_internal_memslot(struct kvm *kvm,
if (WARN_ON_ONCE(mem->slot < KVM_USER_MEM_SLOTS))
return -EINVAL;
- return __kvm_set_memory_region(kvm, mem);
+ return kvm_set_memory_region(kvm, mem);
}
EXPORT_SYMBOL_GPL(kvm_set_internal_memslot);
@@ -2115,7 +2115,7 @@ static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
return -EINVAL;
guard(mutex)(&kvm->slots_lock);
- return __kvm_set_memory_region(kvm, mem);
+ return kvm_set_memory_region(kvm, mem);
}
#ifndef CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT
--
2.46.0.rc2.264.g509ed76dc8-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 5/6] KVM: Disallow all flags for KVM-internal memslots
2024-08-02 20:49 [PATCH 0/6] KVM: kvm_set_memory_region() cleanups Sean Christopherson
` (3 preceding siblings ...)
2024-08-02 20:50 ` [PATCH 4/6] KVM: x86: Drop double-underscores from __kvm_set_memory_region() Sean Christopherson
@ 2024-08-02 20:50 ` Sean Christopherson
2024-08-02 20:50 ` [PATCH 6/6] KVM: Move flags check for user memory regions to the ioctl() specific API Sean Christopherson
5 siblings, 0 replies; 12+ messages in thread
From: Sean Christopherson @ 2024-08-02 20:50 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel
Disallow all flags for KVM-internal memslots as all existing flags require
some amount of userspace interaction to have any meaning. This will allow
moving the flags checking from __kvm_set_memory_region() to
kvm_vm_ioctl_set_memory_region() without creating a hole where a KVM bug
could silently succeed and create a bogus memslot.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
virt/kvm/kvm_main.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 42ec817d6a7e..84fcb20e3e1c 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2104,6 +2104,9 @@ int kvm_set_internal_memslot(struct kvm *kvm,
if (WARN_ON_ONCE(mem->slot < KVM_USER_MEM_SLOTS))
return -EINVAL;
+ if (WARN_ON_ONCE(mem->flags))
+ return -EINVAL;
+
return kvm_set_memory_region(kvm, mem);
}
EXPORT_SYMBOL_GPL(kvm_set_internal_memslot);
--
2.46.0.rc2.264.g509ed76dc8-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 6/6] KVM: Move flags check for user memory regions to the ioctl() specific API
2024-08-02 20:49 [PATCH 0/6] KVM: kvm_set_memory_region() cleanups Sean Christopherson
` (4 preceding siblings ...)
2024-08-02 20:50 ` [PATCH 5/6] KVM: Disallow all flags for KVM-internal memslots Sean Christopherson
@ 2024-08-02 20:50 ` Sean Christopherson
2024-08-08 7:41 ` Xiaoyao Li
5 siblings, 1 reply; 12+ messages in thread
From: Sean Christopherson @ 2024-08-02 20:50 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel
Move the check on memory region flags to kvm_vm_ioctl_set_memory_region()
now that the internal API, kvm_set_internal_memslot(), disallows any and
all flags.
No functional change intended.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
virt/kvm/kvm_main.c | 54 ++++++++++++++++++---------------------------
1 file changed, 22 insertions(+), 32 deletions(-)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 84fcb20e3e1c..09cc261b080a 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1566,34 +1566,6 @@ static void kvm_replace_memslot(struct kvm *kvm,
#define KVM_SET_USER_MEMORY_REGION_V1_FLAGS \
(KVM_MEM_LOG_DIRTY_PAGES | KVM_MEM_READONLY)
-static int check_memory_region_flags(struct kvm *kvm,
- const struct kvm_userspace_memory_region2 *mem)
-{
- u32 valid_flags = KVM_MEM_LOG_DIRTY_PAGES;
-
- if (kvm_arch_has_private_mem(kvm))
- valid_flags |= KVM_MEM_GUEST_MEMFD;
-
- /* Dirty logging private memory is not currently supported. */
- if (mem->flags & KVM_MEM_GUEST_MEMFD)
- valid_flags &= ~KVM_MEM_LOG_DIRTY_PAGES;
-
-#ifdef CONFIG_HAVE_KVM_READONLY_MEM
- /*
- * GUEST_MEMFD is incompatible with read-only memslots, as writes to
- * read-only memslots have emulated MMIO, not page fault, semantics,
- * and KVM doesn't allow emulated MMIO for private memory.
- */
- if (!(mem->flags & KVM_MEM_GUEST_MEMFD))
- valid_flags |= KVM_MEM_READONLY;
-#endif
-
- if (mem->flags & ~valid_flags)
- return -EINVAL;
-
- return 0;
-}
-
static void kvm_swap_active_memslots(struct kvm *kvm, int as_id)
{
struct kvm_memslots *slots = kvm_get_inactive_memslots(kvm, as_id);
@@ -1986,10 +1958,6 @@ static int kvm_set_memory_region(struct kvm *kvm,
lockdep_assert_held(&kvm->slots_lock);
- r = check_memory_region_flags(kvm, mem);
- if (r)
- return r;
-
as_id = mem->slot >> 16;
id = (u16)mem->slot;
@@ -2114,6 +2082,28 @@ EXPORT_SYMBOL_GPL(kvm_set_internal_memslot);
static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
struct kvm_userspace_memory_region2 *mem)
{
+ u32 valid_flags = KVM_MEM_LOG_DIRTY_PAGES;
+
+ if (kvm_arch_has_private_mem(kvm))
+ valid_flags |= KVM_MEM_GUEST_MEMFD;
+
+ /* Dirty logging private memory is not currently supported. */
+ if (mem->flags & KVM_MEM_GUEST_MEMFD)
+ valid_flags &= ~KVM_MEM_LOG_DIRTY_PAGES;
+
+#ifdef CONFIG_HAVE_KVM_READONLY_MEM
+ /*
+ * GUEST_MEMFD is incompatible with read-only memslots, as writes to
+ * read-only memslots have emulated MMIO, not page fault, semantics,
+ * and KVM doesn't allow emulated MMIO for private memory.
+ */
+ if (!(mem->flags & KVM_MEM_GUEST_MEMFD))
+ valid_flags |= KVM_MEM_READONLY;
+#endif
+
+ if (mem->flags & ~valid_flags)
+ return -EINVAL;
+
if ((u16)mem->slot >= KVM_USER_MEM_SLOTS)
return -EINVAL;
--
2.46.0.rc2.264.g509ed76dc8-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 1/6] KVM: Open code kvm_set_memory_region() into its sole caller (ioctl() API)
2024-08-02 20:49 ` [PATCH 1/6] KVM: Open code kvm_set_memory_region() into its sole caller (ioctl() API) Sean Christopherson
@ 2024-08-05 8:39 ` Tao Su
0 siblings, 0 replies; 12+ messages in thread
From: Tao Su @ 2024-08-05 8:39 UTC (permalink / raw)
To: Sean Christopherson; +Cc: Paolo Bonzini, kvm, linux-kernel
On Fri, Aug 02, 2024 at 01:49:58PM -0700, Sean Christopherson wrote:
> Open code kvm_set_memory_region() into its sole caller in preparation for
> adding a dedicated API for setting internal memslots.
>
> Oppurtunistically use the fancy new guard(mutex) to avoid a local 'r'
> variable.
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
> include/linux/kvm_host.h | 2 --
> virt/kvm/kvm_main.c | 15 ++-------------
> 2 files changed, 2 insertions(+), 15 deletions(-)
>
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index 689e8be873a7..b341d00aae37 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -1179,8 +1179,6 @@ enum kvm_mr_change {
> KVM_MR_FLAGS_ONLY,
> };
>
> -int kvm_set_memory_region(struct kvm *kvm,
> - const struct kvm_userspace_memory_region2 *mem);
> int __kvm_set_memory_region(struct kvm *kvm,
> const struct kvm_userspace_memory_region2 *mem);
> void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *slot);
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index d0788d0a72cc..0557d663b69b 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -2105,25 +2105,14 @@ int __kvm_set_memory_region(struct kvm *kvm,
> }
> EXPORT_SYMBOL_GPL(__kvm_set_memory_region);
>
> -int kvm_set_memory_region(struct kvm *kvm,
> - const struct kvm_userspace_memory_region2 *mem)
> -{
> - int r;
> -
> - mutex_lock(&kvm->slots_lock);
> - r = __kvm_set_memory_region(kvm, mem);
> - mutex_unlock(&kvm->slots_lock);
> - return r;
> -}
> -EXPORT_SYMBOL_GPL(kvm_set_memory_region);
> -
> static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
> struct kvm_userspace_memory_region2 *mem)
> {
> if ((u16)mem->slot >= KVM_USER_MEM_SLOTS)
> return -EINVAL;
>
> - return kvm_set_memory_region(kvm, mem);
> + guard(mutex)(&kvm->slots_lock);
> + return __kvm_set_memory_region(kvm, mem);
^^
Two spaces are introduced here.
> }
>
> #ifndef CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT
> --
> 2.46.0.rc2.264.g509ed76dc8-goog
>
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/6] KVM: Assert slots_lock is held in __kvm_set_memory_region()
2024-08-02 20:49 ` [PATCH 2/6] KVM: Assert slots_lock is held in __kvm_set_memory_region() Sean Christopherson
@ 2024-08-05 8:41 ` Tao Su
2024-08-05 22:01 ` Sean Christopherson
0 siblings, 1 reply; 12+ messages in thread
From: Tao Su @ 2024-08-05 8:41 UTC (permalink / raw)
To: Sean Christopherson; +Cc: Paolo Bonzini, kvm, linux-kernel
On Fri, Aug 02, 2024 at 01:49:59PM -0700, Sean Christopherson wrote:
> Add a proper lockdep assertion in __kvm_set_memory_region() instead of
> relying on a function comment. Opportunistically delete the entire
> function comment as the API doesn't allocate memory or select a gfn,
> and the "mostly for framebuffers" comment hasn't been true for a very long
> time.
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
> virt/kvm/kvm_main.c | 10 ++--------
> 1 file changed, 2 insertions(+), 8 deletions(-)
>
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 0557d663b69b..f202bdbfca9e 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -1973,14 +1973,6 @@ static bool kvm_check_memslot_overlap(struct kvm_memslots *slots, int id,
> return false;
> }
>
> -/*
> - * Allocate some memory and give it an address in the guest physical address
> - * space.
> - *
> - * Discontiguous memory is allowed, mostly for framebuffers.
> - *
> - * Must be called holding kvm->slots_lock for write.
> - */
> int __kvm_set_memory_region(struct kvm *kvm,
> const struct kvm_userspace_memory_region2 *mem)
> {
> @@ -1992,6 +1984,8 @@ int __kvm_set_memory_region(struct kvm *kvm,
> int as_id, id;
> int r;
>
> + lockdep_assert_held(&kvm->slots_lock);
How about adding this lockdep assertion in __x86_set_memory_region() to replace
this comment "/* Called with kvm->slots_lock held. */" as well?
> +
> r = check_memory_region_flags(kvm, mem);
> if (r)
> return r;
> --
> 2.46.0.rc2.264.g509ed76dc8-goog
>
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/6] KVM: Add a dedicated API for setting KVM-internal memslots
2024-08-02 20:50 ` [PATCH 3/6] KVM: Add a dedicated API for setting KVM-internal memslots Sean Christopherson
@ 2024-08-05 8:42 ` Tao Su
0 siblings, 0 replies; 12+ messages in thread
From: Tao Su @ 2024-08-05 8:42 UTC (permalink / raw)
To: Sean Christopherson; +Cc: Paolo Bonzini, kvm, linux-kernel
On Fri, Aug 02, 2024 at 01:50:00PM -0700, Sean Christopherson wrote:
> Add a dedicated API for setting internal memslots, and have it explicitly
> disallow setting userspace memslots. Setting a userspace memslots without
> a direct command from userspace would result in all manner of issues.
>
> No functional change intended.
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
> arch/x86/kvm/x86.c | 2 +-
> include/linux/kvm_host.h | 4 ++--
> virt/kvm/kvm_main.c | 15 ++++++++++++---
> 3 files changed, 15 insertions(+), 6 deletions(-)
>
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index af6c8cf6a37a..77949fee13f7 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -12794,7 +12794,7 @@ void __user * __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa,
> m.guest_phys_addr = gpa;
> m.userspace_addr = hva;
> m.memory_size = size;
> - r = __kvm_set_memory_region(kvm, &m);
> + r = kvm_set_internal_memslot(kvm, &m);
> if (r < 0)
> return ERR_PTR_USR(r);
> }
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index b341d00aae37..cefa274c0852 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -1179,8 +1179,8 @@ enum kvm_mr_change {
> KVM_MR_FLAGS_ONLY,
> };
>
> -int __kvm_set_memory_region(struct kvm *kvm,
> - const struct kvm_userspace_memory_region2 *mem);
> +int kvm_set_internal_memslot(struct kvm *kvm,
> + const struct kvm_userspace_memory_region2 *mem);
> void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *slot);
> void kvm_arch_memslots_updated(struct kvm *kvm, u64 gen);
> int kvm_arch_prepare_memory_region(struct kvm *kvm,
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index f202bdbfca9e..63b43644ed9f 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -1973,8 +1973,8 @@ static bool kvm_check_memslot_overlap(struct kvm_memslots *slots, int id,
> return false;
> }
>
> -int __kvm_set_memory_region(struct kvm *kvm,
> - const struct kvm_userspace_memory_region2 *mem)
> +static int __kvm_set_memory_region(struct kvm *kvm,
> + const struct kvm_userspace_memory_region2 *mem)
> {
> struct kvm_memory_slot *old, *new;
> struct kvm_memslots *slots;
> @@ -2097,7 +2097,16 @@ int __kvm_set_memory_region(struct kvm *kvm,
> kfree(new);
> return r;
> }
> -EXPORT_SYMBOL_GPL(__kvm_set_memory_region);
> +
> +int kvm_set_internal_memslot(struct kvm *kvm,
> + const struct kvm_userspace_memory_region2 *mem)
> +{
> + if (WARN_ON_ONCE(mem->slot < KVM_USER_MEM_SLOTS))
> + return -EINVAL;
> +
> + return __kvm_set_memory_region(kvm, mem);
^^
Two spaces are introduced here.
> +}
> +EXPORT_SYMBOL_GPL(kvm_set_internal_memslot);
>
> static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
> struct kvm_userspace_memory_region2 *mem)
> --
> 2.46.0.rc2.264.g509ed76dc8-goog
>
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/6] KVM: Assert slots_lock is held in __kvm_set_memory_region()
2024-08-05 8:41 ` Tao Su
@ 2024-08-05 22:01 ` Sean Christopherson
0 siblings, 0 replies; 12+ messages in thread
From: Sean Christopherson @ 2024-08-05 22:01 UTC (permalink / raw)
To: Tao Su; +Cc: Paolo Bonzini, kvm, linux-kernel
On Mon, Aug 05, 2024, Tao Su wrote:
> On Fri, Aug 02, 2024 at 01:49:59PM -0700, Sean Christopherson wrote:
> > Add a proper lockdep assertion in __kvm_set_memory_region() instead of
> > relying on a function comment. Opportunistically delete the entire
> > function comment as the API doesn't allocate memory or select a gfn,
> > and the "mostly for framebuffers" comment hasn't been true for a very long
> > time.
> >
> > Signed-off-by: Sean Christopherson <seanjc@google.com>
> > ---
> > virt/kvm/kvm_main.c | 10 ++--------
> > 1 file changed, 2 insertions(+), 8 deletions(-)
> >
> > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> > index 0557d663b69b..f202bdbfca9e 100644
> > --- a/virt/kvm/kvm_main.c
> > +++ b/virt/kvm/kvm_main.c
> > @@ -1973,14 +1973,6 @@ static bool kvm_check_memslot_overlap(struct kvm_memslots *slots, int id,
> > return false;
> > }
> >
> > -/*
> > - * Allocate some memory and give it an address in the guest physical address
> > - * space.
> > - *
> > - * Discontiguous memory is allowed, mostly for framebuffers.
> > - *
> > - * Must be called holding kvm->slots_lock for write.
> > - */
> > int __kvm_set_memory_region(struct kvm *kvm,
> > const struct kvm_userspace_memory_region2 *mem)
> > {
> > @@ -1992,6 +1984,8 @@ int __kvm_set_memory_region(struct kvm *kvm,
> > int as_id, id;
> > int r;
> >
> > + lockdep_assert_held(&kvm->slots_lock);
>
> How about adding this lockdep assertion in __x86_set_memory_region() to replace
> this comment "/* Called with kvm->slots_lock held. */" as well?
Ya, will do, I didn't see that comment.
Thanks!
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 6/6] KVM: Move flags check for user memory regions to the ioctl() specific API
2024-08-02 20:50 ` [PATCH 6/6] KVM: Move flags check for user memory regions to the ioctl() specific API Sean Christopherson
@ 2024-08-08 7:41 ` Xiaoyao Li
0 siblings, 0 replies; 12+ messages in thread
From: Xiaoyao Li @ 2024-08-08 7:41 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel
On 8/3/2024 4:50 AM, Sean Christopherson wrote:
> Move the check on memory region flags to kvm_vm_ioctl_set_memory_region()
> now that the internal API, kvm_set_internal_memslot(), disallows any and
> all flags.
>
> No functional change intended.
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
> virt/kvm/kvm_main.c | 54 ++++++++++++++++++---------------------------
> 1 file changed, 22 insertions(+), 32 deletions(-)
>
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 84fcb20e3e1c..09cc261b080a 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -1566,34 +1566,6 @@ static void kvm_replace_memslot(struct kvm *kvm,
> #define KVM_SET_USER_MEMORY_REGION_V1_FLAGS \
> (KVM_MEM_LOG_DIRTY_PAGES | KVM_MEM_READONLY)
>
> -static int check_memory_region_flags(struct kvm *kvm,
> - const struct kvm_userspace_memory_region2 *mem)
> -{
> - u32 valid_flags = KVM_MEM_LOG_DIRTY_PAGES;
> -
> - if (kvm_arch_has_private_mem(kvm))
> - valid_flags |= KVM_MEM_GUEST_MEMFD;
> -
> - /* Dirty logging private memory is not currently supported. */
> - if (mem->flags & KVM_MEM_GUEST_MEMFD)
> - valid_flags &= ~KVM_MEM_LOG_DIRTY_PAGES;
> -
> -#ifdef CONFIG_HAVE_KVM_READONLY_MEM
> - /*
> - * GUEST_MEMFD is incompatible with read-only memslots, as writes to
> - * read-only memslots have emulated MMIO, not page fault, semantics,
> - * and KVM doesn't allow emulated MMIO for private memory.
> - */
> - if (!(mem->flags & KVM_MEM_GUEST_MEMFD))
> - valid_flags |= KVM_MEM_READONLY;
> -#endif
> -
> - if (mem->flags & ~valid_flags)
> - return -EINVAL;
> -
> - return 0;
> -}
I would vote for keeping it instead of open coding it.
> -
> static void kvm_swap_active_memslots(struct kvm *kvm, int as_id)
> {
> struct kvm_memslots *slots = kvm_get_inactive_memslots(kvm, as_id);
> @@ -1986,10 +1958,6 @@ static int kvm_set_memory_region(struct kvm *kvm,
>
> lockdep_assert_held(&kvm->slots_lock);
>
> - r = check_memory_region_flags(kvm, mem);
> - if (r)
> - return r;
> -
> as_id = mem->slot >> 16;
> id = (u16)mem->slot;
>
> @@ -2114,6 +2082,28 @@ EXPORT_SYMBOL_GPL(kvm_set_internal_memslot);
> static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
> struct kvm_userspace_memory_region2 *mem)
> {
> + u32 valid_flags = KVM_MEM_LOG_DIRTY_PAGES;
> +
> + if (kvm_arch_has_private_mem(kvm))
> + valid_flags |= KVM_MEM_GUEST_MEMFD;
> +
> + /* Dirty logging private memory is not currently supported. */
> + if (mem->flags & KVM_MEM_GUEST_MEMFD)
> + valid_flags &= ~KVM_MEM_LOG_DIRTY_PAGES;
> +
> +#ifdef CONFIG_HAVE_KVM_READONLY_MEM
> + /*
> + * GUEST_MEMFD is incompatible with read-only memslots, as writes to
> + * read-only memslots have emulated MMIO, not page fault, semantics,
> + * and KVM doesn't allow emulated MMIO for private memory.
> + */
> + if (!(mem->flags & KVM_MEM_GUEST_MEMFD))
> + valid_flags |= KVM_MEM_READONLY;
> +#endif
> +
> + if (mem->flags & ~valid_flags)
> + return -EINVAL;
> +
> if ((u16)mem->slot >= KVM_USER_MEM_SLOTS)
> return -EINVAL;
>
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2024-08-08 7:41 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-02 20:49 [PATCH 0/6] KVM: kvm_set_memory_region() cleanups Sean Christopherson
2024-08-02 20:49 ` [PATCH 1/6] KVM: Open code kvm_set_memory_region() into its sole caller (ioctl() API) Sean Christopherson
2024-08-05 8:39 ` Tao Su
2024-08-02 20:49 ` [PATCH 2/6] KVM: Assert slots_lock is held in __kvm_set_memory_region() Sean Christopherson
2024-08-05 8:41 ` Tao Su
2024-08-05 22:01 ` Sean Christopherson
2024-08-02 20:50 ` [PATCH 3/6] KVM: Add a dedicated API for setting KVM-internal memslots Sean Christopherson
2024-08-05 8:42 ` Tao Su
2024-08-02 20:50 ` [PATCH 4/6] KVM: x86: Drop double-underscores from __kvm_set_memory_region() Sean Christopherson
2024-08-02 20:50 ` [PATCH 5/6] KVM: Disallow all flags for KVM-internal memslots Sean Christopherson
2024-08-02 20:50 ` [PATCH 6/6] KVM: Move flags check for user memory regions to the ioctl() specific API Sean Christopherson
2024-08-08 7:41 ` Xiaoyao Li
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox