aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/ivt.S
diff options
context:
space:
mode:
authorKen Chen <kenneth.w.chen@intel.com>2005-06-21 17:40:31 -0400
committerTony Luck <tony.luck@intel.com>2005-06-21 17:40:31 -0400
commit0393eed5c3220c9c3823a09a2d02329b8ff08b45 (patch)
treec465ee4c3a0322a4e6533f4e1ec0968b8b254907 /arch/ia64/kernel/ivt.S
parent52a0de2cd2d3da8f90d88e2eccb63d0cadd6ae26 (diff)
[IA64] fix nested_dtlb_miss handler for hugetlb address
The nested_dtlb_miss handler currently does not handle fault from hugetlb address correctly. It walks the page table assuming PAGE_SIZE. Thus when taking a fault triggered from hugetlb address, it would not calculate the pgd/pmd/pte address correctly and thus result an incorrect invocation of ia64_do_page_fault(). In there, kernel will signal SIGBUS and application dies (The faulting address is perfectly legal and we have a valid pte for the corresponding user hugetlb address as well). This patch fix the described kernel bug. Since nested_dtlb_miss is a rare event and a slow path anyway, I'm making the change without #ifdef CONFIG_HUGETLB_PAGE for code readability. Tony, please apply. Signed-off-by: Ken Chen <kenneth.w.chen@intel.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/kernel/ivt.S')
-rw-r--r--arch/ia64/kernel/ivt.S13
1 files changed, 9 insertions, 4 deletions
diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
index d9c05d53435b..2bc085a73e30 100644
--- a/arch/ia64/kernel/ivt.S
+++ b/arch/ia64/kernel/ivt.S
@@ -405,17 +405,22 @@ ENTRY(nested_dtlb_miss)
405 * r30: continuation address 405 * r30: continuation address
406 * r31: saved pr 406 * r31: saved pr
407 * 407 *
408 * Clobbered: b0, r18, r19, r21, psr.dt (cleared) 408 * Clobbered: b0, r18, r19, r21, r22, psr.dt (cleared)
409 */ 409 */
410 rsm psr.dt // switch to using physical data addressing 410 rsm psr.dt // switch to using physical data addressing
411 mov r19=IA64_KR(PT_BASE) // get the page table base address 411 mov r19=IA64_KR(PT_BASE) // get the page table base address
412 shl r21=r16,3 // shift bit 60 into sign bit 412 shl r21=r16,3 // shift bit 60 into sign bit
413 mov r18=cr.itir
413 ;; 414 ;;
414 shr.u r17=r16,61 // get the region number into r17 415 shr.u r17=r16,61 // get the region number into r17
416 extr.u r18=r18,2,6 // get the faulting page size
415 ;; 417 ;;
416 cmp.eq p6,p7=5,r17 // is faulting address in region 5? 418 cmp.eq p6,p7=5,r17 // is faulting address in region 5?
417 shr.u r18=r16,PGDIR_SHIFT // get bits 33-63 of faulting address 419 add r22=-PAGE_SHIFT,r18 // adjustment for hugetlb address
420 add r18=PGDIR_SHIFT-PAGE_SHIFT,r18
418 ;; 421 ;;
422 shr.u r22=r16,r22
423 shr.u r18=r16,r18
419(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place 424(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
420 425
421 srlz.d 426 srlz.d
@@ -428,7 +433,7 @@ ENTRY(nested_dtlb_miss)
428(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8 433(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8
429(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8) 434(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8)
430 cmp.eq p7,p6=0,r21 // unused address bits all zeroes? 435 cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
431 shr.u r18=r16,PMD_SHIFT // shift L2 index into position 436 shr.u r18=r22,PMD_SHIFT // shift L2 index into position
432 ;; 437 ;;
433 ld8 r17=[r17] // fetch the L1 entry (may be 0) 438 ld8 r17=[r17] // fetch the L1 entry (may be 0)
434 ;; 439 ;;
@@ -436,7 +441,7 @@ ENTRY(nested_dtlb_miss)
436 dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry 441 dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry
437 ;; 442 ;;
438(p7) ld8 r17=[r17] // fetch the L2 entry (may be 0) 443(p7) ld8 r17=[r17] // fetch the L2 entry (may be 0)
439 shr.u r19=r16,PAGE_SHIFT // shift L3 index into position 444 shr.u r19=r22,PAGE_SHIFT // shift L3 index into position
440 ;; 445 ;;
441(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was L2 entry NULL? 446(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was L2 entry NULL?
442 dep r17=r19,r17,3,(PAGE_SHIFT-3) // compute address of L3 page table entry 447 dep r17=r19,r17,3,(PAGE_SHIFT-3) // compute address of L3 page table entry