mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
KVM: Rework KVM_CAP_GUEST_MEMFD_MMAP into KVM_CAP_GUEST_MEMFD_FLAGS
Rework the not-yet-released KVM_CAP_GUEST_MEMFD_MMAP into a more generic KVM_CAP_GUEST_MEMFD_FLAGS capability so that adding new flags doesn't require a new capability, and so that developers aren't tempted to bundle multiple flags into a single capability. Note, kvm_vm_ioctl_check_extension_generic() can only return a 32-bit value, but that limitation can be easily circumvented by adding e.g. KVM_CAP_GUEST_MEMFD_FLAGS2 in the unlikely event guest_memfd supports more than 32 flags. Reviewed-by: Ackerley Tng <ackerleytng@google.com> Tested-by: Ackerley Tng <ackerleytng@google.com> Reviewed-by: David Hildenbrand <david@redhat.com> Link: https://lore.kernel.org/r/20251003232606.4070510-2-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
This commit is contained in:
@@ -6432,9 +6432,13 @@ most one mapping per page, i.e. binding multiple memory regions to a single
|
|||||||
guest_memfd range is not allowed (any number of memory regions can be bound to
|
guest_memfd range is not allowed (any number of memory regions can be bound to
|
||||||
a single guest_memfd file, but the bound ranges must not overlap).
|
a single guest_memfd file, but the bound ranges must not overlap).
|
||||||
|
|
||||||
When the capability KVM_CAP_GUEST_MEMFD_MMAP is supported, the 'flags' field
|
The capability KVM_CAP_GUEST_MEMFD_FLAGS enumerates the `flags` that can be
|
||||||
supports GUEST_MEMFD_FLAG_MMAP. Setting this flag on guest_memfd creation
|
specified via KVM_CREATE_GUEST_MEMFD. Currently defined flags:
|
||||||
enables mmap() and faulting of guest_memfd memory to host userspace.
|
|
||||||
|
============================ ================================================
|
||||||
|
GUEST_MEMFD_FLAG_MMAP Enable using mmap() on the guest_memfd file
|
||||||
|
descriptor.
|
||||||
|
============================ ================================================
|
||||||
|
|
||||||
When the KVM MMU performs a PFN lookup to service a guest fault and the backing
|
When the KVM MMU performs a PFN lookup to service a guest fault and the backing
|
||||||
guest_memfd has the GUEST_MEMFD_FLAG_MMAP set, then the fault will always be
|
guest_memfd has the GUEST_MEMFD_FLAG_MMAP set, then the fault will always be
|
||||||
|
|||||||
@@ -962,7 +962,7 @@ struct kvm_enable_cap {
|
|||||||
#define KVM_CAP_ARM_EL2_E2H0 241
|
#define KVM_CAP_ARM_EL2_E2H0 241
|
||||||
#define KVM_CAP_RISCV_MP_STATE_RESET 242
|
#define KVM_CAP_RISCV_MP_STATE_RESET 242
|
||||||
#define KVM_CAP_ARM_CACHEABLE_PFNMAP_SUPPORTED 243
|
#define KVM_CAP_ARM_CACHEABLE_PFNMAP_SUPPORTED 243
|
||||||
#define KVM_CAP_GUEST_MEMFD_MMAP 244
|
#define KVM_CAP_GUEST_MEMFD_FLAGS 244
|
||||||
|
|
||||||
struct kvm_irq_routing_irqchip {
|
struct kvm_irq_routing_irqchip {
|
||||||
__u32 irqchip;
|
__u32 irqchip;
|
||||||
|
|||||||
@@ -262,19 +262,17 @@ static void test_guest_memfd_flags(struct kvm_vm *vm, uint64_t valid_flags)
|
|||||||
|
|
||||||
static void test_guest_memfd(unsigned long vm_type)
|
static void test_guest_memfd(unsigned long vm_type)
|
||||||
{
|
{
|
||||||
uint64_t flags = 0;
|
|
||||||
struct kvm_vm *vm;
|
struct kvm_vm *vm;
|
||||||
size_t total_size;
|
size_t total_size;
|
||||||
size_t page_size;
|
size_t page_size;
|
||||||
|
uint64_t flags;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
page_size = getpagesize();
|
page_size = getpagesize();
|
||||||
total_size = page_size * 4;
|
total_size = page_size * 4;
|
||||||
|
|
||||||
vm = vm_create_barebones_type(vm_type);
|
vm = vm_create_barebones_type(vm_type);
|
||||||
|
flags = vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS);
|
||||||
if (vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_MMAP))
|
|
||||||
flags |= GUEST_MEMFD_FLAG_MMAP;
|
|
||||||
|
|
||||||
test_create_guest_memfd_multiple(vm);
|
test_create_guest_memfd_multiple(vm);
|
||||||
test_create_guest_memfd_invalid_sizes(vm, flags, page_size);
|
test_create_guest_memfd_invalid_sizes(vm, flags, page_size);
|
||||||
@@ -328,13 +326,14 @@ static void test_guest_memfd_guest(void)
|
|||||||
size_t size;
|
size_t size;
|
||||||
int fd, i;
|
int fd, i;
|
||||||
|
|
||||||
if (!kvm_has_cap(KVM_CAP_GUEST_MEMFD_MMAP))
|
if (!kvm_check_cap(KVM_CAP_GUEST_MEMFD_FLAGS))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
vm = __vm_create_shape_with_one_vcpu(VM_SHAPE_DEFAULT, &vcpu, 1, guest_code);
|
vm = __vm_create_shape_with_one_vcpu(VM_SHAPE_DEFAULT, &vcpu, 1, guest_code);
|
||||||
|
|
||||||
TEST_ASSERT(vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_MMAP),
|
TEST_ASSERT(vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS) & GUEST_MEMFD_FLAG_MMAP,
|
||||||
"Default VM type should always support guest_memfd mmap()");
|
"Default VM type should support MMAP, supported flags = 0x%x",
|
||||||
|
vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS));
|
||||||
|
|
||||||
size = vm->page_size;
|
size = vm->page_size;
|
||||||
fd = vm_create_guest_memfd(vm, size, GUEST_MEMFD_FLAG_MMAP);
|
fd = vm_create_guest_memfd(vm, size, GUEST_MEMFD_FLAG_MMAP);
|
||||||
|
|||||||
@@ -4928,8 +4928,11 @@ static int kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
|
|||||||
#ifdef CONFIG_KVM_GUEST_MEMFD
|
#ifdef CONFIG_KVM_GUEST_MEMFD
|
||||||
case KVM_CAP_GUEST_MEMFD:
|
case KVM_CAP_GUEST_MEMFD:
|
||||||
return 1;
|
return 1;
|
||||||
case KVM_CAP_GUEST_MEMFD_MMAP:
|
case KVM_CAP_GUEST_MEMFD_FLAGS:
|
||||||
return !kvm || kvm_arch_supports_gmem_mmap(kvm);
|
if (!kvm || kvm_arch_supports_gmem_mmap(kvm))
|
||||||
|
return GUEST_MEMFD_FLAG_MMAP;
|
||||||
|
|
||||||
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user