lkml.org 
[lkml]   [2023]   [Jul]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v15 031/115] 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 6f4737d5046a..4932bc90a0a0 100644
    --- a/include/linux/kvm_types.h
    +++ b/include/linux/kvm_types.h
    @@ -93,6 +93,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 60ed0f613bce..14b1fa9fe644 100644
    --- a/virt/kvm/kvm_main.c
    +++ b/virt/kvm/kvm_main.c
    @@ -378,12 +378,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)
    @@ -398,6 +403,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: 2023-07-26 00:20    [W:2.033 / U:0.180 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site