When migrating memory the same array for HMM page table entry might be
use with several different devices. Add a new select flag so current
device driver callback can know which entry are selected for the device.

Signed-off-by: Jérôme Glisse <[email protected]>
---
 include/linux/hmm_pt.h | 6 ++++--
 mm/hmm.c               | 5 ++++-
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/include/linux/hmm_pt.h b/include/linux/hmm_pt.h
index b017aa7..f745d6c 100644
--- a/include/linux/hmm_pt.h
+++ b/include/linux/hmm_pt.h
@@ -77,8 +77,9 @@ static inline unsigned long hmm_pde_pfn(dma_addr_t pde)
 #define HMM_PTE_VALID_DEV_BIT  0
 #define HMM_PTE_VALID_DMA_BIT  1
 #define HMM_PTE_VALID_PFN_BIT  2
-#define HMM_PTE_WRITE_BIT      3
-#define HMM_PTE_DIRTY_BIT      4
+#define HMM_PTE_SELECT         3
+#define HMM_PTE_WRITE_BIT      4
+#define HMM_PTE_DIRTY_BIT      5
 /*
  * Reserve some bits for device driver private flags. Note that thus can only
  * be manipulated using the hmm_pte_*_bit() sets of helpers.
@@ -170,6 +171,7 @@ static inline bool hmm_pte_test_and_set_bit(dma_addr_t 
*ptep,
 HMM_PTE_BIT_HELPER(valid_dev, HMM_PTE_VALID_DEV_BIT)
 HMM_PTE_BIT_HELPER(valid_dma, HMM_PTE_VALID_DMA_BIT)
 HMM_PTE_BIT_HELPER(valid_pfn, HMM_PTE_VALID_PFN_BIT)
+HMM_PTE_BIT_HELPER(select, HMM_PTE_SELECT)
 HMM_PTE_BIT_HELPER(dirty, HMM_PTE_DIRTY_BIT)
 HMM_PTE_BIT_HELPER(write, HMM_PTE_WRITE_BIT)
 
diff --git a/mm/hmm.c b/mm/hmm.c
index 4c0d2c0..a5706d2 100644
--- a/mm/hmm.c
+++ b/mm/hmm.c
@@ -749,6 +749,7 @@ static int hmm_mirror_fault_hpmd(struct hmm_mirror *mirror,
                        BUG_ON(hmm_pte_pfn(hmm_pte[i]) != pfn);
                        if (pmd_write(*pmdp))
                                hmm_pte_set_write(&hmm_pte[i]);
+                       hmm_pte_set_select(&hmm_pte[i]);
                } while (addr += PAGE_SIZE, pfn++, i++, addr != next);
                hmm_pt_iter_directory_unlock(iter);
                mirror_fault->addr = addr;
@@ -825,6 +826,7 @@ static int hmm_mirror_fault_pmd(pmd_t *pmdp,
                        BUG_ON(hmm_pte_pfn(hmm_pte[i]) != pte_pfn(*ptep));
                        if (pte_write(*ptep))
                                hmm_pte_set_write(&hmm_pte[i]);
+                       hmm_pte_set_select(&hmm_pte[i]);
                } while (addr += PAGE_SIZE, ptep++, i++, addr != next);
                hmm_pt_iter_directory_unlock(iter);
                pte_unmap(ptep - 1);
@@ -916,7 +918,8 @@ static int hmm_mirror_dma_map(struct hmm_mirror *mirror,
 
 again:
                        pte = ACCESS_ONCE(hmm_pte[i]);
-                       if (!hmm_pte_test_valid_pfn(&pte)) {
+                       if (!hmm_pte_test_valid_pfn(&pte) ||
+                           !hmm_pte_test_select(&pte)) {
                                if (!hmm_pte_test_valid_dma(&pte)) {
                                        ret = -ENOENT;
                                        break;
-- 
2.4.3

Reply via email to