@@ -28,6 +28,7 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *filp,
2828 unsigned long pgoff ,
2929 unsigned long flags )
3030{
31+ struct hstate * h = hstate_file (filp );
3132 unsigned long task_size = TASK_SIZE ;
3233 struct vm_unmapped_area_info info ;
3334
@@ -38,7 +39,7 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *filp,
3839 info .length = len ;
3940 info .low_limit = TASK_UNMAPPED_BASE ;
4041 info .high_limit = min (task_size , VA_EXCLUDE_START );
41- info .align_mask = PAGE_MASK & ~HPAGE_MASK ;
42+ info .align_mask = PAGE_MASK & ~huge_page_mask ( h ) ;
4243 info .align_offset = 0 ;
4344 addr = vm_unmapped_area (& info );
4445
@@ -58,6 +59,7 @@ hugetlb_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
5859 const unsigned long pgoff ,
5960 const unsigned long flags )
6061{
62+ struct hstate * h = hstate_file (filp );
6163 struct mm_struct * mm = current -> mm ;
6264 unsigned long addr = addr0 ;
6365 struct vm_unmapped_area_info info ;
@@ -69,7 +71,7 @@ hugetlb_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
6971 info .length = len ;
7072 info .low_limit = PAGE_SIZE ;
7173 info .high_limit = mm -> mmap_base ;
72- info .align_mask = PAGE_MASK & ~HPAGE_MASK ;
74+ info .align_mask = PAGE_MASK & ~huge_page_mask ( h ) ;
7375 info .align_offset = 0 ;
7476 addr = vm_unmapped_area (& info );
7577
@@ -94,14 +96,15 @@ unsigned long
9496hugetlb_get_unmapped_area (struct file * file , unsigned long addr ,
9597 unsigned long len , unsigned long pgoff , unsigned long flags )
9698{
99+ struct hstate * h = hstate_file (file );
97100 struct mm_struct * mm = current -> mm ;
98101 struct vm_area_struct * vma ;
99102 unsigned long task_size = TASK_SIZE ;
100103
101104 if (test_thread_flag (TIF_32BIT ))
102105 task_size = STACK_TOP32 ;
103106
104- if (len & ~HPAGE_MASK )
107+ if (len & ~huge_page_mask ( h ) )
105108 return - EINVAL ;
106109 if (len > task_size )
107110 return - ENOMEM ;
@@ -113,7 +116,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
113116 }
114117
115118 if (addr ) {
116- addr = ALIGN (addr , HPAGE_SIZE );
119+ addr = ALIGN (addr , huge_page_size ( h ) );
117120 vma = find_vma (mm , addr );
118121 if (task_size - len >= addr &&
119122 (!vma || addr + len <= vma -> vm_start ))
@@ -127,6 +130,112 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
127130 pgoff , flags );
128131}
129132
133+ static pte_t sun4u_hugepage_shift_to_tte (pte_t entry , unsigned int shift )
134+ {
135+ return entry ;
136+ }
137+
138+ static pte_t sun4v_hugepage_shift_to_tte (pte_t entry , unsigned int shift )
139+ {
140+ unsigned long hugepage_size = _PAGE_SZ4MB_4V ;
141+
142+ pte_val (entry ) = pte_val (entry ) & ~_PAGE_SZALL_4V ;
143+
144+ switch (shift ) {
145+ case HPAGE_256MB_SHIFT :
146+ hugepage_size = _PAGE_SZ256MB_4V ;
147+ pte_val (entry ) |= _PAGE_PMD_HUGE ;
148+ break ;
149+ case HPAGE_SHIFT :
150+ pte_val (entry ) |= _PAGE_PMD_HUGE ;
151+ break ;
152+ default :
153+ WARN_ONCE (1 , "unsupported hugepage shift=%u\n" , shift );
154+ }
155+
156+ pte_val (entry ) = pte_val (entry ) | hugepage_size ;
157+ return entry ;
158+ }
159+
160+ static pte_t hugepage_shift_to_tte (pte_t entry , unsigned int shift )
161+ {
162+ if (tlb_type == hypervisor )
163+ return sun4v_hugepage_shift_to_tte (entry , shift );
164+ else
165+ return sun4u_hugepage_shift_to_tte (entry , shift );
166+ }
167+
168+ pte_t arch_make_huge_pte (pte_t entry , struct vm_area_struct * vma ,
169+ struct page * page , int writeable )
170+ {
171+ unsigned int shift = huge_page_shift (hstate_vma (vma ));
172+
173+ return hugepage_shift_to_tte (entry , shift );
174+ }
175+
176+ static unsigned int sun4v_huge_tte_to_shift (pte_t entry )
177+ {
178+ unsigned long tte_szbits = pte_val (entry ) & _PAGE_SZALL_4V ;
179+ unsigned int shift ;
180+
181+ switch (tte_szbits ) {
182+ case _PAGE_SZ256MB_4V :
183+ shift = HPAGE_256MB_SHIFT ;
184+ break ;
185+ case _PAGE_SZ4MB_4V :
186+ shift = REAL_HPAGE_SHIFT ;
187+ break ;
188+ default :
189+ shift = PAGE_SHIFT ;
190+ break ;
191+ }
192+ return shift ;
193+ }
194+
195+ static unsigned int sun4u_huge_tte_to_shift (pte_t entry )
196+ {
197+ unsigned long tte_szbits = pte_val (entry ) & _PAGE_SZALL_4U ;
198+ unsigned int shift ;
199+
200+ switch (tte_szbits ) {
201+ case _PAGE_SZ256MB_4U :
202+ shift = HPAGE_256MB_SHIFT ;
203+ break ;
204+ case _PAGE_SZ4MB_4U :
205+ shift = REAL_HPAGE_SHIFT ;
206+ break ;
207+ default :
208+ shift = PAGE_SHIFT ;
209+ break ;
210+ }
211+ return shift ;
212+ }
213+
214+ static unsigned int huge_tte_to_shift (pte_t entry )
215+ {
216+ unsigned long shift ;
217+
218+ if (tlb_type == hypervisor )
219+ shift = sun4v_huge_tte_to_shift (entry );
220+ else
221+ shift = sun4u_huge_tte_to_shift (entry );
222+
223+ if (shift == PAGE_SHIFT )
224+ WARN_ONCE (1 , "tto_to_shift: invalid hugepage tte=0x%lx\n" ,
225+ pte_val (entry ));
226+
227+ return shift ;
228+ }
229+
230+ static unsigned long huge_tte_to_size (pte_t pte )
231+ {
232+ unsigned long size = 1UL << huge_tte_to_shift (pte );
233+
234+ if (size == REAL_HPAGE_SIZE )
235+ size = HPAGE_SIZE ;
236+ return size ;
237+ }
238+
130239pte_t * huge_pte_alloc (struct mm_struct * mm ,
131240 unsigned long addr , unsigned long sz )
132241{
@@ -160,35 +269,54 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
160269void set_huge_pte_at (struct mm_struct * mm , unsigned long addr ,
161270 pte_t * ptep , pte_t entry )
162271{
272+ unsigned int i , nptes , hugepage_shift ;
273+ unsigned long size ;
163274 pte_t orig ;
164275
276+ size = huge_tte_to_size (entry );
277+ nptes = size >> PMD_SHIFT ;
278+
165279 if (!pte_present (* ptep ) && pte_present (entry ))
166- mm -> context .hugetlb_pte_count ++ ;
280+ mm -> context .hugetlb_pte_count += nptes ;
167281
168- addr &= HPAGE_MASK ;
282+ addr &= ~( size - 1 ) ;
169283 orig = * ptep ;
170- * ptep = entry ;
284+ hugepage_shift = pte_none ( orig ) ? PAGE_SIZE : huge_tte_to_shift ( orig ) ;
171285
172- /* Issue TLB flush at REAL_HPAGE_SIZE boundaries */
173- maybe_tlb_batch_add (mm , addr , ptep , orig , 0 );
174- maybe_tlb_batch_add (mm , addr + REAL_HPAGE_SIZE , ptep , orig , 0 );
286+ for (i = 0 ; i < nptes ; i ++ )
287+ ptep [i ] = __pte (pte_val (entry ) + (i << PMD_SHIFT ));
288+
289+ maybe_tlb_batch_add (mm , addr , ptep , orig , 0 , hugepage_shift );
290+ /* An HPAGE_SIZE'ed page is composed of two REAL_HPAGE_SIZE'ed pages */
291+ if (size == HPAGE_SIZE )
292+ maybe_tlb_batch_add (mm , addr + REAL_HPAGE_SIZE , ptep , orig , 0 ,
293+ hugepage_shift );
175294}
176295
177296pte_t huge_ptep_get_and_clear (struct mm_struct * mm , unsigned long addr ,
178297 pte_t * ptep )
179298{
299+ unsigned int i , nptes , hugepage_shift ;
300+ unsigned long size ;
180301 pte_t entry ;
181302
182303 entry = * ptep ;
304+ size = huge_tte_to_size (entry );
305+ nptes = size >> PMD_SHIFT ;
306+ hugepage_shift = pte_none (entry ) ? PAGE_SIZE : huge_tte_to_shift (entry );
307+
183308 if (pte_present (entry ))
184- mm -> context .hugetlb_pte_count -- ;
309+ mm -> context .hugetlb_pte_count -= nptes ;
185310
186- addr &= HPAGE_MASK ;
187- * ptep = __pte (0UL );
311+ addr &= ~(size - 1 );
312+ for (i = 0 ; i < nptes ; i ++ )
313+ ptep [i ] = __pte (0UL );
188314
189- /* Issue TLB flush at REAL_HPAGE_SIZE boundaries */
190- maybe_tlb_batch_add (mm , addr , ptep , entry , 0 );
191- maybe_tlb_batch_add (mm , addr + REAL_HPAGE_SIZE , ptep , entry , 0 );
315+ maybe_tlb_batch_add (mm , addr , ptep , entry , 0 , hugepage_shift );
316+ /* An HPAGE_SIZE'ed page is composed of two REAL_HPAGE_SIZE'ed pages */
317+ if (size == HPAGE_SIZE )
318+ maybe_tlb_batch_add (mm , addr + REAL_HPAGE_SIZE , ptep , entry , 0 ,
319+ hugepage_shift );
192320
193321 return entry ;
194322}
0 commit comments