Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions Documentation/virt/kvm/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6441,15 +6441,18 @@ a single guest_memfd file, but the bound ranges must not overlap).
The capability KVM_CAP_GUEST_MEMFD_FLAGS enumerates the `flags` that can be
specified via KVM_CREATE_GUEST_MEMFD. Currently defined flags:

============================ ================================================
GUEST_MEMFD_FLAG_MMAP Enable using mmap() on the guest_memfd file
descriptor.
GUEST_MEMFD_FLAG_INIT_SHARED Make all memory in the file shared during
KVM_CREATE_GUEST_MEMFD (memory files created
without INIT_SHARED will be marked private).
Shared memory can be faulted into host userspace
page tables. Private memory cannot.
============================ ================================================
============================== ================================================
GUEST_MEMFD_FLAG_MMAP Enable using mmap() on the guest_memfd file
descriptor.
GUEST_MEMFD_FLAG_INIT_SHARED Make all memory in the file shared during
KVM_CREATE_GUEST_MEMFD (memory files created
without INIT_SHARED will be marked private).
Shared memory can be faulted into host userspace
page tables. Private memory cannot.
GUEST_MEMFD_FLAG_NO_DIRECT_MAP The guest_memfd instance will unmap the memory
backing it from the kernel's address space
before passing it off to userspace or the guest.
============================== ================================================

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
Expand Down
13 changes: 13 additions & 0 deletions arch/arm64/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <linux/maple_tree.h>
#include <linux/percpu.h>
#include <linux/psci.h>
#include <linux/set_memory.h>
#include <asm/arch_gicv3.h>
#include <asm/barrier.h>
#include <asm/cpufeature.h>
Expand Down Expand Up @@ -1678,6 +1679,18 @@ static __always_inline enum fgt_group_id __fgt_reg_to_group_id(enum vcpu_sysreg
\
p; \
})
#ifdef CONFIG_KVM_GUEST_MEMFD
static inline bool kvm_arch_gmem_supports_no_direct_map(struct kvm *kvm)
{
/*
* Without FWB, direct map access is needed in kvm_pgtable_stage2_map(),
* as it calls dcache_clean_inval_poc().
*/
return can_set_direct_map() && cpus_have_final_cap(ARM64_HAS_STAGE2_FWB);
}
#define kvm_arch_gmem_supports_no_direct_map kvm_arch_gmem_supports_no_direct_map
#endif /* CONFIG_KVM_GUEST_MEMFD */


long kvm_get_cap_for_kvm_ioctl(unsigned int ioctl, long *ext);

Expand Down
7 changes: 4 additions & 3 deletions arch/arm64/include/asm/set_memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ bool can_set_direct_map(void);

int set_memory_valid(unsigned long addr, int numpages, int enable);

int set_direct_map_invalid_noflush(struct page *page);
int set_direct_map_default_noflush(struct page *page);
int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid);
int set_direct_map_invalid_noflush(const void *addr);
int set_direct_map_default_noflush(const void *addr);
int set_direct_map_valid_noflush(const void *addr, unsigned long numpages,
bool valid);
bool kernel_page_present(struct page *page);

int set_memory_encrypted(unsigned long addr, int numpages);
Expand Down
19 changes: 9 additions & 10 deletions arch/arm64/mm/pageattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,28 +245,28 @@ int set_memory_valid(unsigned long addr, int numpages, int enable)
__pgprot(PTE_VALID));
}

int set_direct_map_invalid_noflush(struct page *page)
int set_direct_map_invalid_noflush(const void *addr)
{
pgprot_t clear_mask = __pgprot(PTE_VALID);
pgprot_t set_mask = __pgprot(0);

if (!can_set_direct_map())
return 0;

return update_range_prot((unsigned long)page_address(page),
PAGE_SIZE, set_mask, clear_mask);
return update_range_prot((unsigned long)addr, PAGE_SIZE, set_mask,
clear_mask);
}

int set_direct_map_default_noflush(struct page *page)
int set_direct_map_default_noflush(const void *addr)
{
pgprot_t set_mask = __pgprot(PTE_VALID | PTE_WRITE);
pgprot_t clear_mask = __pgprot(PTE_RDONLY);

if (!can_set_direct_map())
return 0;

return update_range_prot((unsigned long)page_address(page),
PAGE_SIZE, set_mask, clear_mask);
return update_range_prot((unsigned long)addr, PAGE_SIZE, set_mask,
clear_mask);
}

static int __set_memory_enc_dec(unsigned long addr,
Expand Down Expand Up @@ -349,14 +349,13 @@ int realm_register_memory_enc_ops(void)
return arm64_mem_crypt_ops_register(&realm_crypt_ops);
}

int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
int set_direct_map_valid_noflush(const void *addr, unsigned long numpages,
bool valid)
{
unsigned long addr = (unsigned long)page_address(page);

if (!can_set_direct_map())
return 0;

return set_memory_valid(addr, nr, valid);
return set_memory_valid((unsigned long)addr, numpages, valid);
}

#ifdef CONFIG_DEBUG_PAGEALLOC
Expand Down
7 changes: 4 additions & 3 deletions arch/loongarch/include/asm/set_memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ int set_memory_ro(unsigned long addr, int numpages);
int set_memory_rw(unsigned long addr, int numpages);

bool kernel_page_present(struct page *page);
int set_direct_map_default_noflush(struct page *page);
int set_direct_map_invalid_noflush(struct page *page);
int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid);
int set_direct_map_invalid_noflush(const void *addr);
int set_direct_map_default_noflush(const void *addr);
int set_direct_map_valid_noflush(const void *addr, unsigned long numpages,
bool valid);

#endif /* _ASM_LOONGARCH_SET_MEMORY_H */
25 changes: 11 additions & 14 deletions arch/loongarch/mm/pageattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,32 +198,29 @@ bool kernel_page_present(struct page *page)
return pte_present(ptep_get(pte));
}

int set_direct_map_default_noflush(struct page *page)
int set_direct_map_default_noflush(const void *addr)
{
unsigned long addr = (unsigned long)page_address(page);

if (addr < vm_map_base)
if ((unsigned long)addr < vm_map_base)
return 0;

return __set_memory(addr, 1, PAGE_KERNEL, __pgprot(0));
return __set_memory((unsigned long)addr, 1, PAGE_KERNEL, __pgprot(0));
}

int set_direct_map_invalid_noflush(struct page *page)
int set_direct_map_invalid_noflush(const void *addr)
{
unsigned long addr = (unsigned long)page_address(page);

if (addr < vm_map_base)
if ((unsigned long)addr < vm_map_base)
return 0;

return __set_memory(addr, 1, __pgprot(0), __pgprot(_PAGE_PRESENT | _PAGE_VALID));
return __set_memory((unsigned long)addr, 1, __pgprot(0),
__pgprot(_PAGE_PRESENT | _PAGE_VALID));
}

int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
int set_direct_map_valid_noflush(const void *addr, unsigned long numpages,
bool valid)
{
unsigned long addr = (unsigned long)page_address(page);
pgprot_t set, clear;

if (addr < vm_map_base)
if ((unsigned long)addr < vm_map_base)
return 0;

if (valid) {
Expand All @@ -234,5 +231,5 @@ int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
clear = __pgprot(_PAGE_PRESENT | _PAGE_VALID);
}

return __set_memory(addr, 1, set, clear);
return __set_memory((unsigned long)addr, 1, set, clear);
}
7 changes: 4 additions & 3 deletions arch/riscv/include/asm/set_memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ static inline int set_kernel_memory(char *startp, char *endp,
}
#endif

int set_direct_map_invalid_noflush(struct page *page);
int set_direct_map_default_noflush(struct page *page);
int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid);
int set_direct_map_invalid_noflush(const void *addr);
int set_direct_map_default_noflush(const void *addr);
int set_direct_map_valid_noflush(const void *addr, unsigned long numpages,
bool valid);
bool kernel_page_present(struct page *page);

#endif /* __ASSEMBLER__ */
Expand Down
17 changes: 9 additions & 8 deletions arch/riscv/mm/pageattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,19 +374,20 @@ int set_memory_nx(unsigned long addr, int numpages)
return __set_memory(addr, numpages, __pgprot(0), __pgprot(_PAGE_EXEC));
}

int set_direct_map_invalid_noflush(struct page *page)
int set_direct_map_invalid_noflush(const void *addr)
{
return __set_memory((unsigned long)page_address(page), 1,
__pgprot(0), __pgprot(_PAGE_PRESENT));
return __set_memory((unsigned long)addr, 1, __pgprot(0),
__pgprot(_PAGE_PRESENT));
}

int set_direct_map_default_noflush(struct page *page)
int set_direct_map_default_noflush(const void *addr)
{
return __set_memory((unsigned long)page_address(page), 1,
PAGE_KERNEL, __pgprot(_PAGE_EXEC));
return __set_memory((unsigned long)addr, 1, PAGE_KERNEL,
__pgprot(_PAGE_EXEC));
}

int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
int set_direct_map_valid_noflush(const void *addr, unsigned long numpages,
bool valid)
{
pgprot_t set, clear;

Expand All @@ -398,7 +399,7 @@ int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
clear = __pgprot(_PAGE_PRESENT);
}

return __set_memory((unsigned long)page_address(page), nr, set, clear);
return __set_memory((unsigned long)addr, numpages, set, clear);
}

#ifdef CONFIG_DEBUG_PAGEALLOC
Expand Down
7 changes: 4 additions & 3 deletions arch/s390/include/asm/set_memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,10 @@ __SET_MEMORY_FUNC(set_memory_rox, SET_MEMORY_RO | SET_MEMORY_X)
__SET_MEMORY_FUNC(set_memory_rwnx, SET_MEMORY_RW | SET_MEMORY_NX)
__SET_MEMORY_FUNC(set_memory_4k, SET_MEMORY_4K)

int set_direct_map_invalid_noflush(struct page *page);
int set_direct_map_default_noflush(struct page *page);
int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid);
int set_direct_map_invalid_noflush(const void *addr);
int set_direct_map_default_noflush(const void *addr);
int set_direct_map_valid_noflush(const void *addr, unsigned long numpages,
bool valid);
bool kernel_page_present(struct page *page);

#endif
13 changes: 7 additions & 6 deletions arch/s390/mm/pageattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -383,17 +383,18 @@ int __set_memory(unsigned long addr, unsigned long numpages, unsigned long flags
return rc;
}

int set_direct_map_invalid_noflush(struct page *page)
int set_direct_map_invalid_noflush(const void *addr)
{
return __set_memory((unsigned long)page_to_virt(page), 1, SET_MEMORY_INV);
return __set_memory((unsigned long)addr, 1, SET_MEMORY_INV);
}

int set_direct_map_default_noflush(struct page *page)
int set_direct_map_default_noflush(const void *addr)
{
return __set_memory((unsigned long)page_to_virt(page), 1, SET_MEMORY_DEF);
return __set_memory((unsigned long)addr, 1, SET_MEMORY_DEF);
}

int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
int set_direct_map_valid_noflush(const void *addr, unsigned long numpages,
bool valid)
{
unsigned long flags;

Expand All @@ -402,7 +403,7 @@ int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
else
flags = SET_MEMORY_INV;

return __set_memory((unsigned long)page_to_virt(page), nr, flags);
return __set_memory((unsigned long)addr, numpages, flags);
}

bool kernel_page_present(struct page *page)
Expand Down
6 changes: 6 additions & 0 deletions arch/x86/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <linux/sched/vhost_task.h>
#include <linux/call_once.h>
#include <linux/atomic.h>
#include <linux/set_memory.h>

#include <asm/apic.h>
#include <asm/pvclock-abi.h>
Expand Down Expand Up @@ -2503,4 +2504,9 @@ static inline bool kvm_arch_has_irq_bypass(void)
return enable_device_posted_irqs;
}

#ifdef CONFIG_KVM_GUEST_MEMFD
bool kvm_arch_gmem_supports_no_direct_map(struct kvm *kvm);
#define kvm_arch_gmem_supports_no_direct_map kvm_arch_gmem_supports_no_direct_map
#endif /* CONFIG_KVM_GUEST_MEMFD */

#endif /* _ASM_X86_KVM_HOST_H */
7 changes: 4 additions & 3 deletions arch/x86/include/asm/set_memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,10 @@ int set_pages_wb(struct page *page, int numpages);
int set_pages_ro(struct page *page, int numpages);
int set_pages_rw(struct page *page, int numpages);

int set_direct_map_invalid_noflush(struct page *page);
int set_direct_map_default_noflush(struct page *page);
int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid);
int set_direct_map_invalid_noflush(const void *addr);
int set_direct_map_default_noflush(const void *addr);
int set_direct_map_valid_noflush(const void *addr, unsigned long numpages,
bool valid);
bool kernel_page_present(struct page *page);

extern int kernel_set_to_readonly;
Expand Down
5 changes: 5 additions & 0 deletions arch/x86/kvm/x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -14080,6 +14080,11 @@ void kvm_arch_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end)
kvm_x86_call(gmem_invalidate)(start, end);
}
#endif

bool kvm_arch_gmem_supports_no_direct_map(struct kvm *kvm)
{
return can_set_direct_map() && kvm->arch.vm_type != KVM_X86_TDX_VM;
}
#endif

int kvm_spec_ctrl_test_value(u64 value)
Expand Down
23 changes: 12 additions & 11 deletions arch/x86/mm/pat/set_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -2587,9 +2587,9 @@ int set_pages_rw(struct page *page, int numpages)
return set_memory_rw(addr, numpages);
}

static int __set_pages_p(struct page *page, int numpages)
static int __set_pages_p(const void *addr, int numpages)
{
unsigned long tempaddr = (unsigned long) page_address(page);
unsigned long tempaddr = (unsigned long)addr;
struct cpa_data cpa = { .vaddr = &tempaddr,
.pgd = NULL,
.numpages = numpages,
Expand All @@ -2606,9 +2606,9 @@ static int __set_pages_p(struct page *page, int numpages)
return __change_page_attr_set_clr(&cpa, 1);
}

static int __set_pages_np(struct page *page, int numpages)
static int __set_pages_np(const void *addr, int numpages)
{
unsigned long tempaddr = (unsigned long) page_address(page);
unsigned long tempaddr = (unsigned long)addr;
struct cpa_data cpa = { .vaddr = &tempaddr,
.pgd = NULL,
.numpages = numpages,
Expand All @@ -2625,22 +2625,23 @@ static int __set_pages_np(struct page *page, int numpages)
return __change_page_attr_set_clr(&cpa, 1);
}

int set_direct_map_invalid_noflush(struct page *page)
int set_direct_map_invalid_noflush(const void *addr)
{
return __set_pages_np(page, 1);
return __set_pages_np(addr, 1);
}

int set_direct_map_default_noflush(struct page *page)
int set_direct_map_default_noflush(const void *addr)
{
return __set_pages_p(page, 1);
return __set_pages_p(addr, 1);
}

int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
int set_direct_map_valid_noflush(const void *addr, unsigned long numpages,
bool valid)
{
if (valid)
return __set_pages_p(page, nr);
return __set_pages_p(addr, numpages);

return __set_pages_np(page, nr);
return __set_pages_np(addr, numpages);
}

#ifdef CONFIG_DEBUG_PAGEALLOC
Expand Down
Loading
Loading