diff options
| author | Jérôme Glisse <jglisse@redhat.com> | 2017-09-08 19:11:31 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-08 21:26:46 -0400 |
| commit | da4c3c735ea4dcc2a0b0ff0bd4803c336361b6f5 (patch) | |
| tree | 147e824606045d05f0cc2965d8fc3f4fafeba7b7 /include/linux | |
| parent | c0b124054f9e42eb6da545a10fe9122a7d7c3f72 (diff) | |
mm/hmm/mirror: helper to snapshot CPU page table
This does not use existing page table walker because we want to share
same code for our page fault handler.
Link: http://lkml.kernel.org/r/20170817000548.32038-5-jglisse@redhat.com
Signed-off-by: Jérôme Glisse <jglisse@redhat.com>
Signed-off-by: Evgeny Baskakov <ebaskakov@nvidia.com>
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
Signed-off-by: Mark Hairgrove <mhairgrove@nvidia.com>
Signed-off-by: Sherry Cheung <SCheung@nvidia.com>
Signed-off-by: Subhash Gutti <sgutti@nvidia.com>
Cc: Aneesh Kumar <aneesh.kumar@linux.vnet.ibm.com>
Cc: Balbir Singh <bsingharora@gmail.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: David Nellans <dnellans@nvidia.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
Cc: Vladimir Davydov <vdavydov.dev@gmail.com>
Cc: Bob Liu <liubo95@huawei.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/hmm.h | 55 |
1 files changed, 53 insertions, 2 deletions
diff --git a/include/linux/hmm.h b/include/linux/hmm.h index 76310726ee9c..62899c9829c9 100644 --- a/include/linux/hmm.h +++ b/include/linux/hmm.h | |||
| @@ -79,13 +79,26 @@ struct hmm; | |||
| 79 | * | 79 | * |
| 80 | * Flags: | 80 | * Flags: |
| 81 | * HMM_PFN_VALID: pfn is valid | 81 | * HMM_PFN_VALID: pfn is valid |
| 82 | * HMM_PFN_READ: CPU page table has read permission set | ||
| 82 | * HMM_PFN_WRITE: CPU page table has write permission set | 83 | * HMM_PFN_WRITE: CPU page table has write permission set |
| 84 | * HMM_PFN_ERROR: corresponding CPU page table entry points to poisoned memory | ||
| 85 | * HMM_PFN_EMPTY: corresponding CPU page table entry is pte_none() | ||
| 86 | * HMM_PFN_SPECIAL: corresponding CPU page table entry is special; i.e., the | ||
| 87 | * result of vm_insert_pfn() or vm_insert_page(). Therefore, it should not | ||
| 88 | * be mirrored by a device, because the entry will never have HMM_PFN_VALID | ||
| 89 | * set and the pfn value is undefined. | ||
| 90 | * HMM_PFN_DEVICE_UNADDRESSABLE: unaddressable device memory (ZONE_DEVICE) | ||
| 83 | */ | 91 | */ |
| 84 | typedef unsigned long hmm_pfn_t; | 92 | typedef unsigned long hmm_pfn_t; |
| 85 | 93 | ||
| 86 | #define HMM_PFN_VALID (1 << 0) | 94 | #define HMM_PFN_VALID (1 << 0) |
| 87 | #define HMM_PFN_WRITE (1 << 1) | 95 | #define HMM_PFN_READ (1 << 1) |
| 88 | #define HMM_PFN_SHIFT 2 | 96 | #define HMM_PFN_WRITE (1 << 2) |
| 97 | #define HMM_PFN_ERROR (1 << 3) | ||
| 98 | #define HMM_PFN_EMPTY (1 << 4) | ||
| 99 | #define HMM_PFN_SPECIAL (1 << 5) | ||
| 100 | #define HMM_PFN_DEVICE_UNADDRESSABLE (1 << 6) | ||
| 101 | #define HMM_PFN_SHIFT 7 | ||
| 89 | 102 | ||
| 90 | /* | 103 | /* |
| 91 | * hmm_pfn_t_to_page() - return struct page pointed to by a valid hmm_pfn_t | 104 | * hmm_pfn_t_to_page() - return struct page pointed to by a valid hmm_pfn_t |
| @@ -241,6 +254,44 @@ struct hmm_mirror { | |||
| 241 | 254 | ||
| 242 | int hmm_mirror_register(struct hmm_mirror *mirror, struct mm_struct *mm); | 255 | int hmm_mirror_register(struct hmm_mirror *mirror, struct mm_struct *mm); |
| 243 | void hmm_mirror_unregister(struct hmm_mirror *mirror); | 256 | void hmm_mirror_unregister(struct hmm_mirror *mirror); |
| 257 | |||
| 258 | |||
| 259 | /* | ||
| 260 | * struct hmm_range - track invalidation lock on virtual address range | ||
| 261 | * | ||
| 262 | * @list: all range lock are on a list | ||
| 263 | * @start: range virtual start address (inclusive) | ||
| 264 | * @end: range virtual end address (exclusive) | ||
| 265 | * @pfns: array of pfns (big enough for the range) | ||
| 266 | * @valid: pfns array did not change since it has been fill by an HMM function | ||
| 267 | */ | ||
| 268 | struct hmm_range { | ||
| 269 | struct list_head list; | ||
| 270 | unsigned long start; | ||
| 271 | unsigned long end; | ||
| 272 | hmm_pfn_t *pfns; | ||
| 273 | bool valid; | ||
| 274 | }; | ||
| 275 | |||
| 276 | /* | ||
| 277 | * To snapshot the CPU page table, call hmm_vma_get_pfns(), then take a device | ||
| 278 | * driver lock that serializes device page table updates, then call | ||
| 279 | * hmm_vma_range_done(), to check if the snapshot is still valid. The same | ||
| 280 | * device driver page table update lock must also be used in the | ||
| 281 | * hmm_mirror_ops.sync_cpu_device_pagetables() callback, so that CPU page | ||
| 282 | * table invalidation serializes on it. | ||
| 283 | * | ||
| 284 | * YOU MUST CALL hmm_vma_range_done() ONCE AND ONLY ONCE EACH TIME YOU CALL | ||
| 285 | * hmm_vma_get_pfns() WITHOUT ERROR ! | ||
| 286 | * | ||
| 287 | * IF YOU DO NOT FOLLOW THE ABOVE RULE THE SNAPSHOT CONTENT MIGHT BE INVALID ! | ||
| 288 | */ | ||
| 289 | int hmm_vma_get_pfns(struct vm_area_struct *vma, | ||
| 290 | struct hmm_range *range, | ||
| 291 | unsigned long start, | ||
| 292 | unsigned long end, | ||
| 293 | hmm_pfn_t *pfns); | ||
| 294 | bool hmm_vma_range_done(struct vm_area_struct *vma, struct hmm_range *range); | ||
| 244 | #endif /* IS_ENABLED(CONFIG_HMM_MIRROR) */ | 295 | #endif /* IS_ENABLED(CONFIG_HMM_MIRROR) */ |
| 245 | 296 | ||
| 246 | 297 | ||
