2020#include <linux/eventfd.h>
2121#include <linux/poll.h>
2222#include <linux/file.h>
23+ #include <linux/pagemap.h>
2324#include <linux/user-return-notifier.h>
2425#include <linux/vmalloc.h>
2526#include <asm/boot.h>
@@ -1154,6 +1155,15 @@ static int vtl_set_vp_register(struct hv_register_assoc *reg)
11541155
11551156#define DECRYPTED_MASK (1ul << 51)
11561157
1158+ /*
1159+ * /dev/mshv_vtl_low address_space, captured on first open.
1160+ * Used by add_vtl0_mem() to zap stale 4K PTEs.
1161+ */
1162+ static struct address_space * mshv_vtl_low_mapping ;
1163+
1164+ /* Identity token tagged on every mshv_vtl pgmap; only its address matters. */
1165+ static const u8 mshv_vtl_pgmap_token ;
1166+
11571167static int mshv_vtl_ioctl_add_vtl0_mem (struct mshv_vtl * vtl , void __user * arg )
11581168{
11591169 struct mshv_vtl_ram_disposition vtl0_mem ;
@@ -1182,6 +1192,7 @@ static int mshv_vtl_ioctl_add_vtl0_mem(struct mshv_vtl *vtl, void __user *arg)
11821192 pgmap -> ranges [0 ].end = PFN_PHYS (vtl0_mem .last_pfn ) - 1 ;
11831193 pgmap -> nr_range = 1 ;
11841194 pgmap -> type = MEMORY_DEVICE_GENERIC ;
1195+ pgmap -> owner = (void * )& mshv_vtl_pgmap_token ;
11851196 if (decrypted )
11861197 pgmap -> flags = PGMAP_DECRYPTED ;
11871198
@@ -1205,6 +1216,20 @@ static int mshv_vtl_ioctl_add_vtl0_mem(struct mshv_vtl *vtl, void __user *arg)
12051216 return PTR_ERR (addr );
12061217 }
12071218
1219+ /*
1220+ * Zap stale pte_special PTEs the 4K fallback installed before this
1221+ * range had a pgmap, so the next access re-faults into the folio path.
1222+ * Both encrypted (pfn) and decrypted (pfn | DECRYPTED_MASK) aliases.
1223+ */
1224+ if (READ_ONCE (mshv_vtl_low_mapping )) {
1225+ pgoff_t start = vtl0_mem .start_pfn ;
1226+ pgoff_t nr = vtl0_mem .last_pfn - vtl0_mem .start_pfn ;
1227+
1228+ unmap_mapping_pages (mshv_vtl_low_mapping , start , nr , true);
1229+ unmap_mapping_pages (mshv_vtl_low_mapping ,
1230+ start | DECRYPTED_MASK , nr , true);
1231+ }
1232+
12081233 /* Don't free pgmap, since it has to stick around until the memory
12091234 * is unmapped, which will never happen as there is no scenario
12101235 * where VTL0 can be released/shutdown without bringing down VTL2.
@@ -3640,6 +3665,18 @@ static struct miscdevice mshv_vtl_hvcall_dev = {
36403665 .minor = MISC_DYNAMIC_MINOR ,
36413666};
36423667
3668+ /*
3669+ * Mirror drivers/dax/device.c: once the fault path publishes folio->mapping
3670+ * to this inode's address_space, writeback-side helpers (e.g.
3671+ * folio_mark_dirty() called from bio_set_pages_dirty() after direct I/O into
3672+ * a GUP'd VTL0 buffer) will dispatch through mapping->a_ops->dirty_folio.
3673+ * The default empty_aops leaves dirty_folio NULL, so install noop_dirty_folio
3674+ * to keep that dispatch safe; nothing here participates in real writeback.
3675+ */
3676+ static const struct address_space_operations mshv_vtl_low_aops = {
3677+ .dirty_folio = noop_dirty_folio ,
3678+ };
3679+
36433680static int mshv_vtl_low_open (struct inode * inodep , struct file * filp )
36443681{
36453682 pid_t pid = task_pid_vnr (current );
@@ -3650,6 +3687,10 @@ static int mshv_vtl_low_open(struct inode *inodep, struct file *filp)
36503687
36513688 if (capable (CAP_SYS_ADMIN )) {
36523689 filp -> private_data = inodep ;
3690+ /* All opens share one inode; first one publishes the address_space. */
3691+ if (!READ_ONCE (mshv_vtl_low_mapping ))
3692+ cmpxchg (& mshv_vtl_low_mapping , NULL , inodep -> i_mapping );
3693+ inodep -> i_mapping -> a_ops = & mshv_vtl_low_aops ;
36533694 } else {
36543695 pr_err ("%s: VTL low open failed: CAP_SYS_ADMIN required. task group %d, uid %d" ,
36553696 __func__ , pid , uid );
@@ -3678,26 +3719,113 @@ static bool can_fault(struct vm_fault *vmf, unsigned long size, unsigned long *p
36783719 return is_valid ;
36793720}
36803721
3722+ /*
3723+ * Resolve a user-supplied PFN to a page owned by an mshv_vtl pgmap, or NULL.
3724+ * Look up the pgmap via get_dev_pagemap() rather than page_pgmap(): the pgmap
3725+ * is published in pgmap_array before per-page state is initialized, so a
3726+ * concurrent MSHV_ADD_VTL0_MEMORY can leave folio->pgmap unset while pfn_valid
3727+ * and is_zone_device_page already return true. The owner check additionally
3728+ * rejects foreign MEMORY_DEVICE_GENERIC pgmaps (e.g. DAX).
3729+ */
3730+ static struct page * mshv_vtl_low_resolve_page (unsigned long pfn )
3731+ {
3732+ struct dev_pagemap * pgmap ;
3733+ struct page * page ;
3734+
3735+ pgmap = get_dev_pagemap (pfn );
3736+ if (!pgmap )
3737+ return NULL ;
3738+ page = NULL ;
3739+ if (pgmap -> type == MEMORY_DEVICE_GENERIC &&
3740+ pgmap -> owner == & mshv_vtl_pgmap_token )
3741+ page = pfn_to_page (pfn );
3742+ /* Safe to drop here: mshv_vtl pgmaps are never released for the life of the module. */
3743+ put_dev_pagemap (pgmap );
3744+ return page ;
3745+ }
3746+
3747+ /*
3748+ * Mirror dax_set_mapping(): rmap walkers locate a file-rmapped folio via
3749+ * folio->mapping/index. ZONE_DEVICE init only fills ->pgmap, so set the
3750+ * file-mapping fields here before each insert that adds file rmap.
3751+ * Idempotent: only the head folio carries mapping/index, and once set the
3752+ * fields persist for the lifetime of the (never-released) pgmap.
3753+ */
3754+ static void mshv_vtl_low_set_mapping (struct vm_fault * vmf , struct folio * folio ,
3755+ unsigned long fault_size )
3756+ {
3757+ if (folio -> mapping )
3758+ return ;
3759+
3760+ folio -> mapping = vmf -> vma -> vm_file -> f_mapping ;
3761+ folio -> index = linear_page_index (vmf -> vma ,
3762+ ALIGN_DOWN (vmf -> address , fault_size ));
3763+ }
3764+
3765+ /*
3766+ * Note on rmap/RSS accounting for huge VTL0 mappings:
3767+ * vmf_insert_folio_{pmd,pud}() takes a folio reference, adds a file rmap,
3768+ * and bumps mm RSS, but the matching teardown is skipped at zap/split time
3769+ * because vma_is_special_huge() is true (VM_MIXEDMAP) while vma_is_dax() is
3770+ * false (CONFIG_FS_DAX is not set in OHCL). The drift is theoretical for
3771+ * OpenVMM/OpenHCL: VTL0 memory is mapped once per partition and held for
3772+ * its lifetime - there is no map/unmap cycling, no partial munmap, and the
3773+ * driver is not unloaded. Stale refs land on ZONE_DEVICE folios whose
3774+ * pgmap is intentionally never released, no real bytes are leaked, and the
3775+ * mm's inflated RSS is discarded with the mm at process exit.
3776+ */
36813777static vm_fault_t mshv_vtl_low_huge_fault (struct vm_fault * vmf , unsigned int order )
36823778{
36833779 unsigned long pfn = vmf -> pgoff & ~DECRYPTED_MASK ;
3684- vm_fault_t ret = VM_FAULT_FALLBACK ;
3780+ bool write = vmf -> flags & FAULT_FLAG_WRITE ;
3781+ struct page * page ;
3782+ struct folio * folio ;
36853783
36863784 switch (order ) {
36873785 case 0 :
3688- /* __pfn_to_pfn_t ? */
3689- return vmf_insert_mixed (vmf -> vma , vmf -> address , pfn );
3786+ page = mshv_vtl_low_resolve_page (pfn );
3787+ if (!page ) {
3788+ /*
3789+ * No pgmap yet: install pte_special so CPU access succeeds.
3790+ * The unmap_mapping_range() in add_vtl0_mem() invalidates this
3791+ * PTE on registration so a later GUP-bound access re-faults
3792+ * into the folio path below.
3793+ */
3794+ return vmf_insert_mixed (vmf -> vma , vmf -> address , pfn );
3795+ }
3796+ /* Inserter operates on the compound-head folio per PTE; refcounts stay balanced. */
3797+ mshv_vtl_low_set_mapping (vmf , page_folio (page ), PAGE_SIZE );
3798+ return vmf_insert_page_mkwrite (vmf , page , write );
36903799
36913800 case PMD_ORDER :
3692- if (can_fault (vmf , PMD_SIZE , & pfn ))
3693- ret = vmf_insert_pfn_pmd (vmf , pfn , vmf -> flags & FAULT_FLAG_WRITE );
3694- return ret ;
3801+ if (!can_fault (vmf , PMD_SIZE , & pfn ))
3802+ return VM_FAULT_FALLBACK ;
3803+ page = mshv_vtl_low_resolve_page (pfn );
3804+ if (!page )
3805+ return VM_FAULT_FALLBACK ;
3806+ folio = page_folio (page );
3807+ /*
3808+ * vmf_insert_folio_pmd() needs an exact-order folio; let core
3809+ * retry smaller on mismatch.
3810+ */
3811+ if (folio_order (folio ) != PMD_ORDER )
3812+ return VM_FAULT_FALLBACK ;
3813+ mshv_vtl_low_set_mapping (vmf , folio , PMD_SIZE );
3814+ return vmf_insert_folio_pmd (vmf , folio , write );
36953815
36963816#if defined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD )
36973817 case PUD_ORDER :
3698- if (can_fault (vmf , PUD_SIZE , & pfn ))
3699- ret = vmf_insert_pfn_pud (vmf , pfn , vmf -> flags & FAULT_FLAG_WRITE );
3700- return ret ;
3818+ if (!can_fault (vmf , PUD_SIZE , & pfn ))
3819+ return VM_FAULT_FALLBACK ;
3820+ page = mshv_vtl_low_resolve_page (pfn );
3821+ if (!page )
3822+ return VM_FAULT_FALLBACK ;
3823+ folio = page_folio (page );
3824+ /* Same exact-order requirement as the PMD case above. */
3825+ if (folio_order (folio ) != PUD_ORDER )
3826+ return VM_FAULT_FALLBACK ;
3827+ mshv_vtl_low_set_mapping (vmf , folio , PUD_SIZE );
3828+ return vmf_insert_folio_pud (vmf , folio , write );
37013829#endif
37023830
37033831 default :
@@ -3717,8 +3845,18 @@ static const struct vm_operations_struct mshv_vtl_low_vm_ops = {
37173845
37183846static int mshv_vtl_low_mmap (struct file * filp , struct vm_area_struct * vma )
37193847{
3848+ /*
3849+ * Reject MAP_PRIVATE: the fault path installs PTEs via
3850+ * vmf_insert_{page,folio}_{,pmd,pud}() and bypasses core-mm COW, so
3851+ * MAP_PRIVATE writes would land on the underlying VTL0/device page
3852+ * instead of a private copy. Mirror device-dax (drivers/dax/device.c).
3853+ */
3854+ if ((vma -> vm_flags & VM_MAYSHARE ) != VM_MAYSHARE )
3855+ return - EINVAL ;
3856+
37203857 vma -> vm_ops = & mshv_vtl_low_vm_ops ;
3721- vm_flags_set (vma , VM_HUGEPAGE | VM_MIXEDMAP );
3858+ /* VM_MIXEDMAP for pte_special 4K fallback; VM_DONTEXPAND pins size to pgmap. */
3859+ vm_flags_set (vma , VM_HUGEPAGE | VM_MIXEDMAP | VM_DONTEXPAND );
37223860
37233861 if (vma -> vm_pgoff & DECRYPTED_MASK )
37243862 vma -> vm_page_prot = pgprot_decrypted (vma -> vm_page_prot );
0 commit comments