diff options
author | Thiemo Seufer <ths@networkno.de> | 2005-04-01 09:07:13 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2005-10-29 14:31:00 -0400 |
commit | 1b3a6e975cbe81c5abc55e4c1b9f5b5250c5f20e (patch) | |
tree | 541db3912172f82d30244cf215b1a1b91d8c6f7f | |
parent | 7c2740f1c1a7ff2767a92042f39edad7fad95c92 (diff) |
Fix 64bit SMP TLB handler and stack frame handling, optimize 32bit SMP
TLB handlers a bit, match definitions in pgtable-{32,64}.h better.
Signed-off-by: Thiemo Seufer <ths@networkno.de>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | arch/mips/kernel/head.S | 1 | ||||
-rw-r--r-- | arch/mips/mm/tlbex.c | 50 | ||||
-rw-r--r-- | include/asm-mips/mmu_context.h | 4 | ||||
-rw-r--r-- | include/asm-mips/pgtable-64.h | 10 | ||||
-rw-r--r-- | include/asm-mips/stackframe.h | 10 |
5 files changed, 34 insertions, 41 deletions
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index 124c27e908f4..9f6927169358 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S | |||
@@ -157,6 +157,7 @@ NESTED(kernel_entry, 16, sp) # kernel entry point | |||
157 | LONG_S a2, fw_arg2 | 157 | LONG_S a2, fw_arg2 |
158 | LONG_S a3, fw_arg3 | 158 | LONG_S a3, fw_arg3 |
159 | 159 | ||
160 | MTC0 zero, CP0_CONTEXT # clear context register | ||
160 | PTR_LA $28, init_thread_union | 161 | PTR_LA $28, init_thread_union |
161 | PTR_ADDIU sp, $28, _THREAD_SIZE - 32 | 162 | PTR_ADDIU sp, $28, _THREAD_SIZE - 32 |
162 | set_saved_sp sp, t0, t1 | 163 | set_saved_sp sp, t0, t1 |
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index bcf87a2b554c..018f7527a724 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c | |||
@@ -91,7 +91,7 @@ enum opcode { | |||
91 | insn_addu, insn_addiu, insn_and, insn_andi, insn_beq, | 91 | insn_addu, insn_addiu, insn_and, insn_andi, insn_beq, |
92 | insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl, | 92 | insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl, |
93 | insn_bne, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0, | 93 | insn_bne, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0, |
94 | insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, | 94 | insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, |
95 | insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld, | 95 | insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld, |
96 | insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0, | 96 | insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0, |
97 | insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll, | 97 | insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll, |
@@ -134,7 +134,6 @@ static __initdata struct insn insn_table[] = { | |||
134 | { insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE }, | 134 | { insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE }, |
135 | { insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE }, | 135 | { insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE }, |
136 | { insn_dsrl, M(spec_op,0,0,0,0,dsrl_op), RT | RD | RE }, | 136 | { insn_dsrl, M(spec_op,0,0,0,0,dsrl_op), RT | RD | RE }, |
137 | { insn_dsrl32, M(spec_op,0,0,0,0,dsrl32_op), RT | RD | RE }, | ||
138 | { insn_dsubu, M(spec_op,0,0,0,0,dsubu_op), RS | RT | RD }, | 137 | { insn_dsubu, M(spec_op,0,0,0,0,dsubu_op), RS | RT | RD }, |
139 | { insn_eret, M(cop0_op,cop_op,0,0,0,eret_op), 0 }, | 138 | { insn_eret, M(cop0_op,cop_op,0,0,0,eret_op), 0 }, |
140 | { insn_j, M(j_op,0,0,0,0,0), JIMM }, | 139 | { insn_j, M(j_op,0,0,0,0,0), JIMM }, |
@@ -366,7 +365,6 @@ I_u2u1u3(_dsll); | |||
366 | I_u2u1u3(_dsll32); | 365 | I_u2u1u3(_dsll32); |
367 | I_u2u1u3(_dsra); | 366 | I_u2u1u3(_dsra); |
368 | I_u2u1u3(_dsrl); | 367 | I_u2u1u3(_dsrl); |
369 | I_u2u1u3(_dsrl32); | ||
370 | I_u3u1u2(_dsubu); | 368 | I_u3u1u2(_dsubu); |
371 | I_0(_eret); | 369 | I_0(_eret); |
372 | I_u1(_j); | 370 | I_u1(_j); |
@@ -944,34 +942,29 @@ build_get_pmde64(u32 **p, struct label **l, struct reloc **r, | |||
944 | /* No i_nop needed here, since the next insn doesn't touch TMP. */ | 942 | /* No i_nop needed here, since the next insn doesn't touch TMP. */ |
945 | 943 | ||
946 | #ifdef CONFIG_SMP | 944 | #ifdef CONFIG_SMP |
945 | # ifdef CONFIG_BUILD_ELF64 | ||
947 | /* | 946 | /* |
948 | * 64 bit SMP has the lower part of &pgd_current[smp_processor_id()] | 947 | * 64 bit SMP running in XKPHYS has smp_processor_id() << 3 |
949 | * stored in CONTEXT. | 948 | * stored in CONTEXT. |
950 | */ | 949 | */ |
951 | if (in_compat_space_p(pgdc)) { | 950 | i_dmfc0(p, ptr, C0_CONTEXT); |
952 | i_dmfc0(p, ptr, C0_CONTEXT); | 951 | i_dsrl(p, ptr, ptr, 23); |
953 | i_dsra(p, ptr, ptr, 23); | 952 | i_LA_mostly(p, tmp, pgdc); |
954 | i_ld(p, ptr, 0, ptr); | 953 | i_daddu(p, ptr, ptr, tmp); |
955 | } else { | 954 | i_dmfc0(p, tmp, C0_BADVADDR); |
956 | #ifdef CONFIG_BUILD_ELF64 | 955 | i_ld(p, ptr, rel_lo(pgdc), ptr); |
957 | i_dmfc0(p, ptr, C0_CONTEXT); | 956 | # else |
958 | i_dsrl(p, ptr, ptr, 23); | 957 | /* |
959 | i_dsll(p, ptr, ptr, 3); | 958 | * 64 bit SMP running in compat space has the lower part of |
960 | i_LA_mostly(p, tmp, pgdc); | 959 | * &pgd_current[smp_processor_id()] stored in CONTEXT. |
961 | i_daddu(p, ptr, ptr, tmp); | 960 | */ |
962 | i_dmfc0(p, tmp, C0_BADVADDR); | 961 | if (!in_compat_space_p(pgdc)) |
963 | i_ld(p, ptr, rel_lo(pgdc), ptr); | 962 | panic("Invalid page directory address!"); |
964 | #else | 963 | |
965 | i_dmfc0(p, ptr, C0_CONTEXT); | 964 | i_dmfc0(p, ptr, C0_CONTEXT); |
966 | i_lui(p, tmp, rel_highest(pgdc)); | 965 | i_dsra(p, ptr, ptr, 23); |
967 | i_dsll(p, ptr, ptr, 9); | 966 | i_ld(p, ptr, 0, ptr); |
968 | i_daddiu(p, tmp, tmp, rel_higher(pgdc)); | 967 | # endif |
969 | i_dsrl32(p, ptr, ptr, 0); | ||
970 | i_and(p, ptr, ptr, tmp); | ||
971 | i_dmfc0(p, tmp, C0_BADVADDR); | ||
972 | i_ld(p, ptr, 0, ptr); | ||
973 | #endif | ||
974 | } | ||
975 | #else | 968 | #else |
976 | i_LA_mostly(p, ptr, pgdc); | 969 | i_LA_mostly(p, ptr, pgdc); |
977 | i_ld(p, ptr, rel_lo(pgdc), ptr); | 970 | i_ld(p, ptr, rel_lo(pgdc), ptr); |
@@ -1028,7 +1021,6 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr) | |||
1028 | i_mfc0(p, ptr, C0_CONTEXT); | 1021 | i_mfc0(p, ptr, C0_CONTEXT); |
1029 | i_LA_mostly(p, tmp, pgdc); | 1022 | i_LA_mostly(p, tmp, pgdc); |
1030 | i_srl(p, ptr, ptr, 23); | 1023 | i_srl(p, ptr, ptr, 23); |
1031 | i_sll(p, ptr, ptr, 2); | ||
1032 | i_addu(p, ptr, tmp, ptr); | 1024 | i_addu(p, ptr, tmp, ptr); |
1033 | #else | 1025 | #else |
1034 | i_LA_mostly(p, ptr, pgdc); | 1026 | i_LA_mostly(p, ptr, pgdc); |
diff --git a/include/asm-mips/mmu_context.h b/include/asm-mips/mmu_context.h index 45cd72d172e8..19cdf7642e66 100644 --- a/include/asm-mips/mmu_context.h +++ b/include/asm-mips/mmu_context.h | |||
@@ -30,7 +30,7 @@ extern unsigned long pgd_current[]; | |||
30 | 30 | ||
31 | #ifdef CONFIG_32BIT | 31 | #ifdef CONFIG_32BIT |
32 | #define TLBMISS_HANDLER_SETUP() \ | 32 | #define TLBMISS_HANDLER_SETUP() \ |
33 | write_c0_context((unsigned long) smp_processor_id() << 23); \ | 33 | write_c0_context((unsigned long) smp_processor_id() << 25); \ |
34 | TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir) | 34 | TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir) |
35 | #endif | 35 | #endif |
36 | #if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64) | 36 | #if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64) |
@@ -40,7 +40,7 @@ extern unsigned long pgd_current[]; | |||
40 | #endif | 40 | #endif |
41 | #if defined(CONFIG_64BIT) && defined(CONFIG_BUILD_ELF64) | 41 | #if defined(CONFIG_64BIT) && defined(CONFIG_BUILD_ELF64) |
42 | #define TLBMISS_HANDLER_SETUP() \ | 42 | #define TLBMISS_HANDLER_SETUP() \ |
43 | write_c0_context((unsigned long) smp_processor_id() << 23); \ | 43 | write_c0_context((unsigned long) smp_processor_id() << 26); \ |
44 | TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir) | 44 | TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir) |
45 | #endif | 45 | #endif |
46 | 46 | ||
diff --git a/include/asm-mips/pgtable-64.h b/include/asm-mips/pgtable-64.h index 35007250ac2b..3e0a522c0f0e 100644 --- a/include/asm-mips/pgtable-64.h +++ b/include/asm-mips/pgtable-64.h | |||
@@ -114,7 +114,7 @@ extern pmd_t invalid_pmd_table[PTRS_PER_PMD]; | |||
114 | extern pmd_t empty_bad_pmd_table[PTRS_PER_PMD]; | 114 | extern pmd_t empty_bad_pmd_table[PTRS_PER_PMD]; |
115 | 115 | ||
116 | /* | 116 | /* |
117 | * Empty pmd entries point to the invalid_pte_table. | 117 | * Empty pgd/pmd entries point to the invalid_pte_table. |
118 | */ | 118 | */ |
119 | static inline int pmd_none(pmd_t pmd) | 119 | static inline int pmd_none(pmd_t pmd) |
120 | { | 120 | { |
@@ -156,7 +156,8 @@ static inline void pud_clear(pud_t *pudp) | |||
156 | pud_val(*pudp) = ((unsigned long) invalid_pmd_table); | 156 | pud_val(*pudp) = ((unsigned long) invalid_pmd_table); |
157 | } | 157 | } |
158 | 158 | ||
159 | #define pte_page(x) pfn_to_page((unsigned long)((pte_val(x) >> PAGE_SHIFT))) | 159 | #define pte_page(x) pfn_to_page(pte_pfn(x)) |
160 | |||
160 | #ifdef CONFIG_CPU_VR41XX | 161 | #ifdef CONFIG_CPU_VR41XX |
161 | #define pte_pfn(x) ((unsigned long)((x).pte >> (PAGE_SHIFT + 2))) | 162 | #define pte_pfn(x) ((unsigned long)((x).pte >> (PAGE_SHIFT + 2))) |
162 | #define pfn_pte(pfn, prot) __pte(((pfn) << (PAGE_SHIFT + 2)) | pgprot_val(prot)) | 163 | #define pfn_pte(pfn, prot) __pte(((pfn) << (PAGE_SHIFT + 2)) | pgprot_val(prot)) |
@@ -167,12 +168,14 @@ static inline void pud_clear(pud_t *pudp) | |||
167 | 168 | ||
168 | #define __pgd_offset(address) pgd_index(address) | 169 | #define __pgd_offset(address) pgd_index(address) |
169 | #define __pud_offset(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1)) | 170 | #define __pud_offset(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1)) |
171 | #define __pmd_offset(address) pmd_index(address) | ||
170 | #define page_pte(page) page_pte_prot(page, __pgprot(0)) | 172 | #define page_pte(page) page_pte_prot(page, __pgprot(0)) |
171 | 173 | ||
172 | /* to find an entry in a kernel page-table-directory */ | 174 | /* to find an entry in a kernel page-table-directory */ |
173 | #define pgd_offset_k(address) pgd_offset(&init_mm, 0) | 175 | #define pgd_offset_k(address) pgd_offset(&init_mm, 0) |
174 | 176 | ||
175 | #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) | 177 | #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) |
178 | #define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) | ||
176 | 179 | ||
177 | /* to find an entry in a page-table-directory */ | 180 | /* to find an entry in a page-table-directory */ |
178 | #define pgd_offset(mm,addr) ((mm)->pgd + pgd_index(addr)) | 181 | #define pgd_offset(mm,addr) ((mm)->pgd + pgd_index(addr)) |
@@ -185,8 +188,7 @@ static inline unsigned long pud_page(pud_t pud) | |||
185 | /* Find an entry in the second-level page table.. */ | 188 | /* Find an entry in the second-level page table.. */ |
186 | static inline pmd_t *pmd_offset(pud_t * pud, unsigned long address) | 189 | static inline pmd_t *pmd_offset(pud_t * pud, unsigned long address) |
187 | { | 190 | { |
188 | return (pmd_t *) pud_page(*pud) + | 191 | return (pmd_t *) pud_page(*pud) + pmd_index(address); |
189 | ((address >> PMD_SHIFT) & (PTRS_PER_PMD - 1)); | ||
190 | } | 192 | } |
191 | 193 | ||
192 | /* Find an entry in the third-level page table.. */ | 194 | /* Find an entry in the third-level page table.. */ |
diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h index e33e302c3429..de303e96260e 100644 --- a/include/asm-mips/stackframe.h +++ b/include/asm-mips/stackframe.h | |||
@@ -60,7 +60,6 @@ | |||
60 | mfc0 k0, CP0_CONTEXT | 60 | mfc0 k0, CP0_CONTEXT |
61 | lui k1, %hi(kernelsp) | 61 | lui k1, %hi(kernelsp) |
62 | srl k0, k0, 23 | 62 | srl k0, k0, 23 |
63 | sll k0, k0, 2 | ||
64 | addu k1, k0 | 63 | addu k1, k0 |
65 | LONG_L k1, %lo(kernelsp)(k1) | 64 | LONG_L k1, %lo(kernelsp)(k1) |
66 | #endif | 65 | #endif |
@@ -76,12 +75,12 @@ | |||
76 | #endif | 75 | #endif |
77 | #if defined(CONFIG_64BIT) && defined(CONFIG_BUILD_ELF64) | 76 | #if defined(CONFIG_64BIT) && defined(CONFIG_BUILD_ELF64) |
78 | MFC0 k1, CP0_CONTEXT | 77 | MFC0 k1, CP0_CONTEXT |
79 | dsrl k1, 23 | ||
80 | dsll k1, k1, 3 | ||
81 | lui k0, %highest(kernelsp) | 78 | lui k0, %highest(kernelsp) |
79 | dsrl k1, 23 | ||
82 | daddiu k0, %higher(kernelsp) | 80 | daddiu k0, %higher(kernelsp) |
83 | dsll k0, k0, 16 | 81 | dsll k0, k0, 16 |
84 | daddiu k0, %hi(kernelsp) | 82 | daddiu k0, %hi(kernelsp) |
83 | dsll k0, k0, 16 | ||
85 | daddu k1, k1, k0 | 84 | daddu k1, k1, k0 |
86 | LONG_L k1, %lo(kernelsp)(k1) | 85 | LONG_L k1, %lo(kernelsp)(k1) |
87 | #endif | 86 | #endif |
@@ -91,7 +90,6 @@ | |||
91 | #ifdef CONFIG_32BIT | 90 | #ifdef CONFIG_32BIT |
92 | mfc0 \temp, CP0_CONTEXT | 91 | mfc0 \temp, CP0_CONTEXT |
93 | srl \temp, 23 | 92 | srl \temp, 23 |
94 | sll \temp, 2 | ||
95 | LONG_S \stackp, kernelsp(\temp) | 93 | LONG_S \stackp, kernelsp(\temp) |
96 | #endif | 94 | #endif |
97 | #if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64) | 95 | #if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64) |
@@ -102,8 +100,8 @@ | |||
102 | LONG_S \stackp, %lo(kernelsp)(\temp) | 100 | LONG_S \stackp, %lo(kernelsp)(\temp) |
103 | #endif | 101 | #endif |
104 | #if defined(CONFIG_64BIT) && defined(CONFIG_BUILD_ELF64) | 102 | #if defined(CONFIG_64BIT) && defined(CONFIG_BUILD_ELF64) |
105 | lw \temp, TI_CPU(gp) | 103 | MFC0 \temp, CP0_CONTEXT |
106 | dsll \temp, 3 | 104 | dsrl \temp, 23 |
107 | LONG_S \stackp, kernelsp(\temp) | 105 | LONG_S \stackp, kernelsp(\temp) |
108 | #endif | 106 | #endif |
109 | .endm | 107 | .endm |