Re: [HMM 10/16] mm/hmm/mirror: helper to snapshot CPU page table v2
On Mon, 10 Apr 2017 21:33:51 -0400 (EDT) Jerome Glissewrote: > > On Mon, 10 Apr 2017 10:43:26 +0200 Michal Hocko wrote: > > > > > There are more for alpha allmodconfig > > > > HMM is rather a compile catastrophe, as was the earlier version I > > merged. > > > > Jerome, I'm thinking you need to install some cross-compilers! > > Sorry about that. > > I tested some but obviously not all, in the v20 i did on top of Michal > patchset i simply made everything to be x86-64 only. So if you revert > v19 and wait for Michal to finish his v3 then i will post v20 that is > x86-64 only which i do build and use. At least from my discussion with > Michal i thought you were dropping v19 until Michal could finish his > memory hotplug rework. OK, I'll quietly drop the hmm series again for now.
Re: [HMM 10/16] mm/hmm/mirror: helper to snapshot CPU page table v2
On Mon, 10 Apr 2017 21:33:51 -0400 (EDT) Jerome Glisse wrote: > > On Mon, 10 Apr 2017 10:43:26 +0200 Michal Hocko wrote: > > > > > There are more for alpha allmodconfig > > > > HMM is rather a compile catastrophe, as was the earlier version I > > merged. > > > > Jerome, I'm thinking you need to install some cross-compilers! > > Sorry about that. > > I tested some but obviously not all, in the v20 i did on top of Michal > patchset i simply made everything to be x86-64 only. So if you revert > v19 and wait for Michal to finish his v3 then i will post v20 that is > x86-64 only which i do build and use. At least from my discussion with > Michal i thought you were dropping v19 until Michal could finish his > memory hotplug rework. OK, I'll quietly drop the hmm series again for now.
Re: [HMM 10/16] mm/hmm/mirror: helper to snapshot CPU page table v2
> On Mon, 10 Apr 2017 10:43:26 +0200 Michal Hockowrote: > > > There are more for alpha allmodconfig > > HMM is rather a compile catastrophe, as was the earlier version I > merged. > > Jerome, I'm thinking you need to install some cross-compilers! Sorry about that. I tested some but obviously not all, in the v20 i did on top of Michal patchset i simply made everything to be x86-64 only. So if you revert v19 and wait for Michal to finish his v3 then i will post v20 that is x86-64 only which i do build and use. At least from my discussion with Michal i thought you were dropping v19 until Michal could finish his memory hotplug rework. Cheers, Jérôme
Re: [HMM 10/16] mm/hmm/mirror: helper to snapshot CPU page table v2
> On Mon, 10 Apr 2017 10:43:26 +0200 Michal Hocko wrote: > > > There are more for alpha allmodconfig > > HMM is rather a compile catastrophe, as was the earlier version I > merged. > > Jerome, I'm thinking you need to install some cross-compilers! Sorry about that. I tested some but obviously not all, in the v20 i did on top of Michal patchset i simply made everything to be x86-64 only. So if you revert v19 and wait for Michal to finish his v3 then i will post v20 that is x86-64 only which i do build and use. At least from my discussion with Michal i thought you were dropping v19 until Michal could finish his memory hotplug rework. Cheers, Jérôme
Re: [HMM 10/16] mm/hmm/mirror: helper to snapshot CPU page table v2
On Mon, 10 Apr 2017 10:43:26 +0200 Michal Hockowrote: > There are more for alpha allmodconfig HMM is rather a compile catastrophe, as was the earlier version I merged. Jerome, I'm thinking you need to install some cross-compilers!
Re: [HMM 10/16] mm/hmm/mirror: helper to snapshot CPU page table v2
On Mon, 10 Apr 2017 10:43:26 +0200 Michal Hocko wrote: > There are more for alpha allmodconfig HMM is rather a compile catastrophe, as was the earlier version I merged. Jerome, I'm thinking you need to install some cross-compilers!
Re: [HMM 10/16] mm/hmm/mirror: helper to snapshot CPU page table v2
There are more for alpha allmodconfig === Config /home/mhocko/work/build-test/configs/alpha/allmodconfig mm/hmm.c: In function 'hmm_vma_walk_pmd': mm/hmm.c:370:4: error: implicit declaration of function 'pmd_pfn' [-Werror=implicit-function-declaration] unsigned long pfn = pmd_pfn(pmd) + pte_index(addr); ^ mm/hmm.c:370:4: error: implicit declaration of function 'pte_index' [-Werror=implicit-function-declaration] mm/hmm.c: In function 'hmm_devmem_radix_release': mm/hmm.c:784:30: error: 'PA_SECTION_SHIFT' undeclared (first use in this function) #define SECTION_SIZE (1UL << PA_SECTION_SHIFT) ^ mm/hmm.c:790:36: note: in expansion of macro 'SECTION_SIZE' align_start = resource->start & ~(SECTION_SIZE - 1); ^ mm/hmm.c:784:30: note: each undeclared identifier is reported only once for each function it appears in #define SECTION_SIZE (1UL << PA_SECTION_SHIFT) ^ mm/hmm.c:790:36: note: in expansion of macro 'SECTION_SIZE' align_start = resource->start & ~(SECTION_SIZE - 1); ^ mm/hmm.c: In function 'hmm_devmem_release': mm/hmm.c:784:30: error: 'PA_SECTION_SHIFT' undeclared (first use in this function) #define SECTION_SIZE (1UL << PA_SECTION_SHIFT) ^ mm/hmm.c:812:36: note: in expansion of macro 'SECTION_SIZE' align_start = resource->start & ~(SECTION_SIZE - 1); ^ mm/hmm.c:816:2: error: implicit declaration of function 'arch_remove_memory' [-Werror=implicit-function-declaration] arch_remove_memory(align_start, align_size, devmem->pagemap.type); ^ mm/hmm.c: In function 'hmm_devmem_find': mm/hmm.c:827:54: error: 'PA_SECTION_SHIFT' undeclared (first use in this function) return radix_tree_lookup(_devmem_radix, phys >> PA_SECTION_SHIFT); ^ mm/hmm.c: In function 'hmm_devmem_pages_create': mm/hmm.c:784:30: error: 'PA_SECTION_SHIFT' undeclared (first use in this function) #define SECTION_SIZE (1UL << PA_SECTION_SHIFT) ^ mm/hmm.c:838:44: note: in expansion of macro 'SECTION_SIZE' align_start = devmem->resource->start & ~(SECTION_SIZE - 1); ^ In file included from ./include/linux/cache.h:4:0, from ./include/linux/printk.h:8, from ./include/linux/kernel.h:13, from ./include/asm-generic/bug.h:13, from ./arch/alpha/include/asm/bug.h:22, from ./include/linux/bug.h:4, from ./include/linux/mmdebug.h:4, from ./include/linux/mm.h:8, from mm/hmm.c:20: mm/hmm.c: In function 'hmm_devmem_add': mm/hmm.c:784:30: error: 'PA_SECTION_SHIFT' undeclared (first use in this function) #define SECTION_SIZE (1UL << PA_SECTION_SHIFT) ^ ./include/uapi/linux/kernel.h:10:47: note: in definition of macro '__ALIGN_KERNEL_MASK' #define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask)) ^ ./include/linux/kernel.h:49:22: note: in expansion of macro '__ALIGN_KERNEL' #define ALIGN(x, a) __ALIGN_KERNEL((x), (a)) ^ mm/hmm.c:982:9: note: in expansion of macro 'ALIGN' size = ALIGN(size, SECTION_SIZE); ^ mm/hmm.c:982:21: note: in expansion of macro 'SECTION_SIZE' size = ALIGN(size, SECTION_SIZE); ^ mm/hmm.c: In function 'hmm_devmem_find': mm/hmm.c:828:1: warning: control reaches end of non-void function [-Wreturn-type] } ^ cc1: some warnings being treated as errors make[1]: *** [mm/hmm.o] Error 1 make[1]: *** Waiting for unfinished jobs make: *** [mm] Error 2 make: *** Waiting for unfinished jobs -- Michal Hocko SUSE Labs
Re: [HMM 10/16] mm/hmm/mirror: helper to snapshot CPU page table v2
There are more for alpha allmodconfig === Config /home/mhocko/work/build-test/configs/alpha/allmodconfig mm/hmm.c: In function 'hmm_vma_walk_pmd': mm/hmm.c:370:4: error: implicit declaration of function 'pmd_pfn' [-Werror=implicit-function-declaration] unsigned long pfn = pmd_pfn(pmd) + pte_index(addr); ^ mm/hmm.c:370:4: error: implicit declaration of function 'pte_index' [-Werror=implicit-function-declaration] mm/hmm.c: In function 'hmm_devmem_radix_release': mm/hmm.c:784:30: error: 'PA_SECTION_SHIFT' undeclared (first use in this function) #define SECTION_SIZE (1UL << PA_SECTION_SHIFT) ^ mm/hmm.c:790:36: note: in expansion of macro 'SECTION_SIZE' align_start = resource->start & ~(SECTION_SIZE - 1); ^ mm/hmm.c:784:30: note: each undeclared identifier is reported only once for each function it appears in #define SECTION_SIZE (1UL << PA_SECTION_SHIFT) ^ mm/hmm.c:790:36: note: in expansion of macro 'SECTION_SIZE' align_start = resource->start & ~(SECTION_SIZE - 1); ^ mm/hmm.c: In function 'hmm_devmem_release': mm/hmm.c:784:30: error: 'PA_SECTION_SHIFT' undeclared (first use in this function) #define SECTION_SIZE (1UL << PA_SECTION_SHIFT) ^ mm/hmm.c:812:36: note: in expansion of macro 'SECTION_SIZE' align_start = resource->start & ~(SECTION_SIZE - 1); ^ mm/hmm.c:816:2: error: implicit declaration of function 'arch_remove_memory' [-Werror=implicit-function-declaration] arch_remove_memory(align_start, align_size, devmem->pagemap.type); ^ mm/hmm.c: In function 'hmm_devmem_find': mm/hmm.c:827:54: error: 'PA_SECTION_SHIFT' undeclared (first use in this function) return radix_tree_lookup(_devmem_radix, phys >> PA_SECTION_SHIFT); ^ mm/hmm.c: In function 'hmm_devmem_pages_create': mm/hmm.c:784:30: error: 'PA_SECTION_SHIFT' undeclared (first use in this function) #define SECTION_SIZE (1UL << PA_SECTION_SHIFT) ^ mm/hmm.c:838:44: note: in expansion of macro 'SECTION_SIZE' align_start = devmem->resource->start & ~(SECTION_SIZE - 1); ^ In file included from ./include/linux/cache.h:4:0, from ./include/linux/printk.h:8, from ./include/linux/kernel.h:13, from ./include/asm-generic/bug.h:13, from ./arch/alpha/include/asm/bug.h:22, from ./include/linux/bug.h:4, from ./include/linux/mmdebug.h:4, from ./include/linux/mm.h:8, from mm/hmm.c:20: mm/hmm.c: In function 'hmm_devmem_add': mm/hmm.c:784:30: error: 'PA_SECTION_SHIFT' undeclared (first use in this function) #define SECTION_SIZE (1UL << PA_SECTION_SHIFT) ^ ./include/uapi/linux/kernel.h:10:47: note: in definition of macro '__ALIGN_KERNEL_MASK' #define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask)) ^ ./include/linux/kernel.h:49:22: note: in expansion of macro '__ALIGN_KERNEL' #define ALIGN(x, a) __ALIGN_KERNEL((x), (a)) ^ mm/hmm.c:982:9: note: in expansion of macro 'ALIGN' size = ALIGN(size, SECTION_SIZE); ^ mm/hmm.c:982:21: note: in expansion of macro 'SECTION_SIZE' size = ALIGN(size, SECTION_SIZE); ^ mm/hmm.c: In function 'hmm_devmem_find': mm/hmm.c:828:1: warning: control reaches end of non-void function [-Wreturn-type] } ^ cc1: some warnings being treated as errors make[1]: *** [mm/hmm.o] Error 1 make[1]: *** Waiting for unfinished jobs make: *** [mm] Error 2 make: *** Waiting for unfinished jobs -- Michal Hocko SUSE Labs
Re: [HMM 10/16] mm/hmm/mirror: helper to snapshot CPU page table v2
On Wed 05-04-17 16:40:20, Jérôme Glisse wrote: > This does not use existing page table walker because we want to share > same code for our page fault handler. I am getting the following compilation error with sparc32 allmodconfig. I didn't check more closely yet. mm/hmm.c: In function 'hmm_vma_walk_pmd': mm/hmm.c:370:53: error: macro "pte_index" requires 2 arguments, but only 1 given unsigned long pfn = pmd_pfn(pmd) + pte_index(addr); ^ mm/hmm.c:370:39: error: 'pte_index' undeclared (first use in this function) unsigned long pfn = pmd_pfn(pmd) + pte_index(addr); ^ mm/hmm.c:370:39: note: each undeclared identifier is reported only once for each function it appears in mm/hmm.c: In function 'hmm_devmem_release': mm/hmm.c:816:2: error: implicit declaration of function 'arch_remove_memory' [-Werror=implicit-function-declaration] arch_remove_memory(align_start, align_size, devmem->pagemap.type); ^ cc1: some warnings being treated as errors -- Michal Hocko SUSE Labs
Re: [HMM 10/16] mm/hmm/mirror: helper to snapshot CPU page table v2
On Wed 05-04-17 16:40:20, Jérôme Glisse wrote: > This does not use existing page table walker because we want to share > same code for our page fault handler. I am getting the following compilation error with sparc32 allmodconfig. I didn't check more closely yet. mm/hmm.c: In function 'hmm_vma_walk_pmd': mm/hmm.c:370:53: error: macro "pte_index" requires 2 arguments, but only 1 given unsigned long pfn = pmd_pfn(pmd) + pte_index(addr); ^ mm/hmm.c:370:39: error: 'pte_index' undeclared (first use in this function) unsigned long pfn = pmd_pfn(pmd) + pte_index(addr); ^ mm/hmm.c:370:39: note: each undeclared identifier is reported only once for each function it appears in mm/hmm.c: In function 'hmm_devmem_release': mm/hmm.c:816:2: error: implicit declaration of function 'arch_remove_memory' [-Werror=implicit-function-declaration] arch_remove_memory(align_start, align_size, devmem->pagemap.type); ^ cc1: some warnings being treated as errors -- Michal Hocko SUSE Labs
[HMM 10/16] mm/hmm/mirror: helper to snapshot CPU page table v2
This does not use existing page table walker because we want to share same code for our page fault handler. Changes since v1: - Use spinlock instead of rcu synchronized list traversal Signed-off-by: Jérôme GlisseSigned-off-by: Evgeny Baskakov Signed-off-by: John Hubbard Signed-off-by: Mark Hairgrove Signed-off-by: Sherry Cheung Signed-off-by: Subhash Gutti --- include/linux/hmm.h | 55 +- mm/hmm.c| 285 2 files changed, 338 insertions(+), 2 deletions(-) diff --git a/include/linux/hmm.h b/include/linux/hmm.h index 6668a1b..defa7cd 100644 --- a/include/linux/hmm.h +++ b/include/linux/hmm.h @@ -79,13 +79,26 @@ struct hmm; * * Flags: * HMM_PFN_VALID: pfn is valid + * HMM_PFN_READ: CPU page table has read permission set * HMM_PFN_WRITE: CPU page table has write permission set + * HMM_PFN_ERROR: corresponding CPU page table entry points to poisoned memory + * HMM_PFN_EMPTY: corresponding CPU page table entry is pte_none() + * HMM_PFN_SPECIAL: corresponding CPU page table entry is special; i.e., the + * result of vm_insert_pfn() or vm_insert_page(). Therefore, it should not + * be mirrored by a device, because the entry will never have HMM_PFN_VALID + * set and the pfn value is undefined. + * HMM_PFN_DEVICE_UNADDRESSABLE: unaddressable device memory (ZONE_DEVICE) */ typedef unsigned long hmm_pfn_t; #define HMM_PFN_VALID (1 << 0) -#define HMM_PFN_WRITE (1 << 1) -#define HMM_PFN_SHIFT 2 +#define HMM_PFN_READ (1 << 1) +#define HMM_PFN_WRITE (1 << 2) +#define HMM_PFN_ERROR (1 << 3) +#define HMM_PFN_EMPTY (1 << 4) +#define HMM_PFN_SPECIAL (1 << 5) +#define HMM_PFN_DEVICE_UNADDRESSABLE (1 << 6) +#define HMM_PFN_SHIFT 7 /* * hmm_pfn_t_to_page() - return struct page pointed to by a valid hmm_pfn_t @@ -241,6 +254,44 @@ struct hmm_mirror { int hmm_mirror_register(struct hmm_mirror *mirror, struct mm_struct *mm); void hmm_mirror_unregister(struct hmm_mirror *mirror); + + +/* + * struct hmm_range - track invalidation lock on virtual address range + * + * @list: all range lock are on a list + * @start: range virtual start address (inclusive) + * @end: range virtual end address (exclusive) + * @pfns: array of pfns (big enough for the range) + * @valid: pfns array did not change since it has been fill by an HMM function + */ +struct hmm_range { + struct list_headlist; + unsigned long start; + unsigned long end; + hmm_pfn_t *pfns; + boolvalid; +}; + +/* + * To snapshot the CPU page table, call hmm_vma_get_pfns(), then take a device + * driver lock that serializes device page table updates, then call + * hmm_vma_range_done(), to check if the snapshot is still valid. The same + * device driver page table update lock must also be used in the + * hmm_mirror_ops.sync_cpu_device_pagetables() callback, so that CPU page + * table invalidation serializes on it. + * + * YOU MUST CALL hmm_vma_range_done() ONCE AND ONLY ONCE EACH TIME YOU CALL + * hmm_vma_get_pfns() WITHOUT ERROR ! + * + * IF YOU DO NOT FOLLOW THE ABOVE RULE THE SNAPSHOT CONTENT MIGHT BE INVALID ! + */ +int hmm_vma_get_pfns(struct vm_area_struct *vma, +struct hmm_range *range, +unsigned long start, +unsigned long end, +hmm_pfn_t *pfns); +bool hmm_vma_range_done(struct vm_area_struct *vma, struct hmm_range *range); #endif /* IS_ENABLED(CONFIG_HMM_MIRROR) */ diff --git a/mm/hmm.c b/mm/hmm.c index 7ed4b4c..4828b97 100644 --- a/mm/hmm.c +++ b/mm/hmm.c @@ -19,8 +19,12 @@ */ #include #include +#include +#include #include #include +#include +#include #include static const struct mmu_notifier_ops hmm_mmu_notifier_ops; @@ -30,14 +34,18 @@ static const struct mmu_notifier_ops hmm_mmu_notifier_ops; * struct hmm - HMM per mm struct * * @mm: mm struct this HMM struct is bound to + * @lock: lock protecting ranges list * @sequence: we track updates to the CPU page table with a sequence number + * @ranges: list of range being snapshotted * @mirrors: list of mirrors for this mm * @mmu_notifier: mmu notifier to track updates to CPU page table * @mirrors_sem: read/write semaphore protecting the mirrors list */ struct hmm { struct mm_struct*mm; + spinlock_t lock; atomic_tsequence; + struct list_headranges; struct list_headmirrors; struct mmu_notifier mmu_notifier; struct rw_semaphore mirrors_sem; @@ -71,6 +79,8 @@ static struct hmm *hmm_register(struct mm_struct *mm) init_rwsem(>mirrors_sem); atomic_set(>sequence, 0); hmm->mmu_notifier.ops = NULL; + INIT_LIST_HEAD(>ranges); +
[HMM 10/16] mm/hmm/mirror: helper to snapshot CPU page table v2
This does not use existing page table walker because we want to share same code for our page fault handler. Changes since v1: - Use spinlock instead of rcu synchronized list traversal Signed-off-by: Jérôme Glisse Signed-off-by: Evgeny Baskakov Signed-off-by: John Hubbard Signed-off-by: Mark Hairgrove Signed-off-by: Sherry Cheung Signed-off-by: Subhash Gutti --- include/linux/hmm.h | 55 +- mm/hmm.c| 285 2 files changed, 338 insertions(+), 2 deletions(-) diff --git a/include/linux/hmm.h b/include/linux/hmm.h index 6668a1b..defa7cd 100644 --- a/include/linux/hmm.h +++ b/include/linux/hmm.h @@ -79,13 +79,26 @@ struct hmm; * * Flags: * HMM_PFN_VALID: pfn is valid + * HMM_PFN_READ: CPU page table has read permission set * HMM_PFN_WRITE: CPU page table has write permission set + * HMM_PFN_ERROR: corresponding CPU page table entry points to poisoned memory + * HMM_PFN_EMPTY: corresponding CPU page table entry is pte_none() + * HMM_PFN_SPECIAL: corresponding CPU page table entry is special; i.e., the + * result of vm_insert_pfn() or vm_insert_page(). Therefore, it should not + * be mirrored by a device, because the entry will never have HMM_PFN_VALID + * set and the pfn value is undefined. + * HMM_PFN_DEVICE_UNADDRESSABLE: unaddressable device memory (ZONE_DEVICE) */ typedef unsigned long hmm_pfn_t; #define HMM_PFN_VALID (1 << 0) -#define HMM_PFN_WRITE (1 << 1) -#define HMM_PFN_SHIFT 2 +#define HMM_PFN_READ (1 << 1) +#define HMM_PFN_WRITE (1 << 2) +#define HMM_PFN_ERROR (1 << 3) +#define HMM_PFN_EMPTY (1 << 4) +#define HMM_PFN_SPECIAL (1 << 5) +#define HMM_PFN_DEVICE_UNADDRESSABLE (1 << 6) +#define HMM_PFN_SHIFT 7 /* * hmm_pfn_t_to_page() - return struct page pointed to by a valid hmm_pfn_t @@ -241,6 +254,44 @@ struct hmm_mirror { int hmm_mirror_register(struct hmm_mirror *mirror, struct mm_struct *mm); void hmm_mirror_unregister(struct hmm_mirror *mirror); + + +/* + * struct hmm_range - track invalidation lock on virtual address range + * + * @list: all range lock are on a list + * @start: range virtual start address (inclusive) + * @end: range virtual end address (exclusive) + * @pfns: array of pfns (big enough for the range) + * @valid: pfns array did not change since it has been fill by an HMM function + */ +struct hmm_range { + struct list_headlist; + unsigned long start; + unsigned long end; + hmm_pfn_t *pfns; + boolvalid; +}; + +/* + * To snapshot the CPU page table, call hmm_vma_get_pfns(), then take a device + * driver lock that serializes device page table updates, then call + * hmm_vma_range_done(), to check if the snapshot is still valid. The same + * device driver page table update lock must also be used in the + * hmm_mirror_ops.sync_cpu_device_pagetables() callback, so that CPU page + * table invalidation serializes on it. + * + * YOU MUST CALL hmm_vma_range_done() ONCE AND ONLY ONCE EACH TIME YOU CALL + * hmm_vma_get_pfns() WITHOUT ERROR ! + * + * IF YOU DO NOT FOLLOW THE ABOVE RULE THE SNAPSHOT CONTENT MIGHT BE INVALID ! + */ +int hmm_vma_get_pfns(struct vm_area_struct *vma, +struct hmm_range *range, +unsigned long start, +unsigned long end, +hmm_pfn_t *pfns); +bool hmm_vma_range_done(struct vm_area_struct *vma, struct hmm_range *range); #endif /* IS_ENABLED(CONFIG_HMM_MIRROR) */ diff --git a/mm/hmm.c b/mm/hmm.c index 7ed4b4c..4828b97 100644 --- a/mm/hmm.c +++ b/mm/hmm.c @@ -19,8 +19,12 @@ */ #include #include +#include +#include #include #include +#include +#include #include static const struct mmu_notifier_ops hmm_mmu_notifier_ops; @@ -30,14 +34,18 @@ static const struct mmu_notifier_ops hmm_mmu_notifier_ops; * struct hmm - HMM per mm struct * * @mm: mm struct this HMM struct is bound to + * @lock: lock protecting ranges list * @sequence: we track updates to the CPU page table with a sequence number + * @ranges: list of range being snapshotted * @mirrors: list of mirrors for this mm * @mmu_notifier: mmu notifier to track updates to CPU page table * @mirrors_sem: read/write semaphore protecting the mirrors list */ struct hmm { struct mm_struct*mm; + spinlock_t lock; atomic_tsequence; + struct list_headranges; struct list_headmirrors; struct mmu_notifier mmu_notifier; struct rw_semaphore mirrors_sem; @@ -71,6 +79,8 @@ static struct hmm *hmm_register(struct mm_struct *mm) init_rwsem(>mirrors_sem); atomic_set(>sequence, 0); hmm->mmu_notifier.ops = NULL; + INIT_LIST_HEAD(>ranges); + spin_lock_init(>lock); hmm->mm = mm; /* @@ -111,6 +121,22 @@ static void hmm_invalidate_range(struct hmm *hmm,