?? tlb.patch
字號(hào):
Patch to fix the TLB fastpath with 36 bit physical addresses. Needed for MAE drivers.From Matthias:If using the the 64-bit address option the so called PTE (page table entries) in the kernel are no longer single 32 bit words containing the PFN (page frame number) and all related flags, but two 32 bit words. The high word contains the PFN and hardware flags and the low word contains the hardware and software flags. The high word gets finally written into the hardware TLB. If you look at the code that gets synthesized in tlbex.c it is responsible to set the dirty (writable) bit in the TLB. This bit, however, gets only set in the low word. So that way it will not be written into the TLB marking the page read-only and causing an endless loop. My fix also sets the dirty bit in the high word and will thus mark the page writable.The MAE driver uses this type of memory mapping. So the first write access to MAE memory would hang the application that requested the mmap.I don't yet know why it works for addresses below 0x6000000 (if using mem=96M), but I assume that the slow path in tlb-r4k.c has been used for this (instead of the synthesized fastpath TLB exception handlers). diff -rwbupN linux26-cvs/arch/mips/mm/tlbex.c linux26-amd/arch/mips/mm/tlbex.c--- linux26-cvs/arch/mips/mm/tlbex.c Wed Mar 9 10:19:14 2005+++ linux26-amd/arch/mips/mm/tlbex.c Tue Apr 5 17:02:30 2005@@ -1316,16 +1316,9 @@ iPTE_SW(u32 **p, struct reloc **r, unsig il_beqz(p, r, pte, label_smp_pgtable_change); # ifdef CONFIG_64BIT_PHYS_ADDR- if (!cpu_has_64bits) {- /* no i_nop needed */- i_ll(p, pte, sizeof(pte_t) / 2, ptr);- i_ori(p, pte, pte, _PAGE_VALID);- i_sc(p, pte, sizeof(pte_t) / 2, ptr);- il_beqz(p, r, pte, label_smp_pgtable_change);- /* no i_nop needed */- i_lw(p, pte, 0, ptr);- } else+ if (cpu_has_64bits) { i_nop(p);+ } # else i_nop(p); # endif@@ -1336,15 +1329,6 @@ iPTE_SW(u32 **p, struct reloc **r, unsig else # endif i_SW(p, pte, offset, ptr);--# ifdef CONFIG_64BIT_PHYS_ADDR- if (!cpu_has_64bits) {- i_lw(p, pte, sizeof(pte_t) / 2, ptr);- i_ori(p, pte, pte, _PAGE_VALID);- i_sw(p, pte, sizeof(pte_t) / 2, ptr);- i_lw(p, pte, 0, ptr);- }-# endif #endif } @@ -1365,11 +1349,28 @@ build_pte_present(u32 **p, struct label /* Make PTE valid, store result in PTR. */ static void __init-build_make_valid(u32 **p, struct reloc **r, unsigned int pte,+build_make_valid(u32 **p, struct label **l, struct reloc **r, unsigned int pte, unsigned int ptr) {+#ifdef CONFIG_64BIT_PHYS_ADDR+ if (!cpu_has_64bits)+ {+ i_ori(p, pte, pte, _PAGE_VALID | _PAGE_ACCESSED);+ iPTE_SW(p, r, pte, 0, ptr);+ iPTE_LW(p, l, pte, sizeof(pte_t) / 2, ptr);+ i_ori(p, pte, pte, _PAGE_VALID);+ iPTE_SW(p, r, pte, sizeof(pte_t) / 2, ptr);+ iPTE_LW(p, l, pte, 0, ptr);+ }+ else+ {+ i_ori(p, pte, pte, _PAGE_VALID | _PAGE_ACCESSED);+ iPTE_SW(p, r, pte, 0, ptr);+ }+#else i_ori(p, pte, pte, _PAGE_VALID | _PAGE_ACCESSED); iPTE_SW(p, r, pte, 0, ptr);+#endif } /*@@ -1390,12 +1391,31 @@ build_pte_writable(u32 **p, struct label * at PTR. */ static void __init-build_make_write(u32 **p, struct reloc **r, unsigned int pte,+build_make_write(u32 **p, struct label **l, struct reloc **r, unsigned int pte, unsigned int ptr) {+#ifdef CONFIG_64BIT_PHYS_ADDR+ if (!cpu_has_64bits)+ { i_ori(p, pte, pte, _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY); iPTE_SW(p, r, pte, 0, ptr);+ iPTE_LW(p, l, pte, sizeof(pte_t) / 2, ptr);+ i_ori(p, pte, pte, _PAGE_VALID | _PAGE_DIRTY);+ iPTE_SW(p, r, pte, sizeof(pte_t) / 2, ptr);+ iPTE_LW(p, l, pte, 0, ptr);+ }+ else+ {+ i_ori(p, pte, pte,+ _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY);+ iPTE_SW(p, r, pte, 0, ptr);+ }+#else + i_ori(p, pte, pte,+ _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY);+ iPTE_SW(p, r, pte, 0, ptr);+#endif } /*@@ -1487,7 +1507,7 @@ static void __init build_r3000_tlb_load_ build_r3000_tlbchange_handler_head(&p, K0, K1); build_pte_present(&p, &l, &r, K0, K1, label_nopage_tlbl);- build_make_valid(&p, &r, K0, K1);+ build_make_valid(&p, &l, &r, K0, K1); build_r3000_pte_reload(&p, K1); build_r3000_tlb_write(&p, &l, &r, K0); build_r3000_tlbchange_handler_tail(&p, K0);@@ -1528,7 +1548,7 @@ static void __init build_r3000_tlb_store build_r3000_tlbchange_handler_head(&p, K0, K1); build_pte_writable(&p, &l, &r, K0, K1, label_nopage_tlbs);- build_make_write(&p, &r, K0, K1);+ build_make_write(&p, &l, &r, K0, K1); build_r3000_pte_reload(&p, K1); build_r3000_tlb_write(&p, &l, &r, K0); build_r3000_tlbchange_handler_tail(&p, K0);@@ -1569,7 +1589,7 @@ static void __init build_r3000_tlb_modif build_r3000_tlbchange_handler_head(&p, K0, K1); build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm);- build_make_write(&p, &r, K0, K1);+ build_make_write(&p, &l, &r, K0, K1); build_r3000_pte_reload(&p, K1); i_tlbwi(&p); build_r3000_tlbchange_handler_tail(&p, K0);@@ -1663,7 +1683,7 @@ static void __init build_r4000_tlb_load_ build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1); build_pte_present(&p, &l, &r, K0, K1, label_nopage_tlbl);- build_make_valid(&p, &r, K0, K1);+ build_make_valid(&p, &l, &r, K0, K1); build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1); l_nopage_tlbl(&l, p);@@ -1702,7 +1722,7 @@ static void __init build_r4000_tlb_store build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1); build_pte_writable(&p, &l, &r, K0, K1, label_nopage_tlbs);- build_make_write(&p, &r, K0, K1);+ build_make_write(&p, &l, &r, K0, K1); build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1); l_nopage_tlbs(&l, p);@@ -1742,7 +1762,7 @@ static void __init build_r4000_tlb_modif build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1); build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm); /* Present and writable bits set, set accessed and dirty bits. */- build_make_write(&p, &r, K0, K1);+ build_make_write(&p, &l, &r, K0, K1); build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1); l_nopage_tlbm(&l, p);
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -