lkml.org 
[lkml]   [2024]   [Feb]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v19 048/130] KVM: Allow page-sized MMU caches to be initialized with custom 64-bit values
    Date
    From: Sean Christopherson <seanjc@google.com>

    Add support to MMU caches for initializing a page with a custom 64-bit
    value, e.g. to pre-fill an entire page table with non-zero PTE values.
    The functionality will be used by x86 to support Intel's TDX, which needs
    to set bit 63 in all non-present PTEs in order to prevent !PRESENT page
    faults from getting reflected into the guest (Intel's EPT Violation #VE
    architecture made the less than brilliant decision of having the per-PTE
    behavior be opt-out instead of opt-in).

    Signed-off-by: Sean Christopherson <seanjc@google.com>
    Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
    ---
    include/linux/kvm_types.h | 1 +
    virt/kvm/kvm_main.c | 16 ++++++++++++++--
    2 files changed, 15 insertions(+), 2 deletions(-)

    diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
    index 9d1f7835d8c1..60c8d5c9eab9 100644
    --- a/include/linux/kvm_types.h
    +++ b/include/linux/kvm_types.h
    @@ -94,6 +94,7 @@ struct gfn_to_pfn_cache {
    struct kvm_mmu_memory_cache {
    gfp_t gfp_zero;
    gfp_t gfp_custom;
    + u64 init_value;
    struct kmem_cache *kmem_cache;
    int capacity;
    int nobjs;
    diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
    index de38f308738e..d399009ef1d7 100644
    --- a/virt/kvm/kvm_main.c
    +++ b/virt/kvm/kvm_main.c
    @@ -401,12 +401,17 @@ static void kvm_flush_shadow_all(struct kvm *kvm)
    static inline void *mmu_memory_cache_alloc_obj(struct kvm_mmu_memory_cache *mc,
    gfp_t gfp_flags)
    {
    + void *page;
    +
    gfp_flags |= mc->gfp_zero;

    if (mc->kmem_cache)
    return kmem_cache_alloc(mc->kmem_cache, gfp_flags);
    - else
    - return (void *)__get_free_page(gfp_flags);
    +
    + page = (void *)__get_free_page(gfp_flags);
    + if (page && mc->init_value)
    + memset64(page, mc->init_value, PAGE_SIZE / sizeof(mc->init_value));
    + return page;
    }

    int __kvm_mmu_topup_memory_cache(struct kvm_mmu_memory_cache *mc, int capacity, int min)
    @@ -421,6 +426,13 @@ int __kvm_mmu_topup_memory_cache(struct kvm_mmu_memory_cache *mc, int capacity,
    if (WARN_ON_ONCE(!capacity))
    return -EIO;

    + /*
    + * Custom init values can be used only for page allocations,
    + * and obviously conflict with __GFP_ZERO.
    + */
    + if (WARN_ON_ONCE(mc->init_value && (mc->kmem_cache || mc->gfp_zero)))
    + return -EIO;
    +
    mc->objects = kvmalloc_array(sizeof(void *), capacity, gfp);
    if (!mc->objects)
    return -ENOMEM;
    --
    2.25.1

    \
     
     \ /
      Last update: 2024-05-27 15:21    [W:4.037 / U:0.312 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site