aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiemo Seufer <ths@networkno.de>2005-04-01 09:07:13 -0500
committerRalf Baechle <ralf@linux-mips.org>2005-10-29 14:31:00 -0400
commit1b3a6e975cbe81c5abc55e4c1b9f5b5250c5f20e (patch)
tree541db3912172f82d30244cf215b1a1b91d8c6f7f
parent7c2740f1c1a7ff2767a92042f39edad7fad95c92 (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.S1
-rw-r--r--arch/mips/mm/tlbex.c50
-rw-r--r--include/asm-mips/mmu_context.h4
-rw-r--r--include/asm-mips/pgtable-64.h10
-rw-r--r--include/asm-mips/stackframe.h10
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);
366I_u2u1u3(_dsll32); 365I_u2u1u3(_dsll32);
367I_u2u1u3(_dsra); 366I_u2u1u3(_dsra);
368I_u2u1u3(_dsrl); 367I_u2u1u3(_dsrl);
369I_u2u1u3(_dsrl32);
370I_u3u1u2(_dsubu); 368I_u3u1u2(_dsubu);
371I_0(_eret); 369I_0(_eret);
372I_u1(_j); 370I_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];
114extern pmd_t empty_bad_pmd_table[PTRS_PER_PMD]; 114extern 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 */
119static inline int pmd_none(pmd_t pmd) 119static 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.. */
186static inline pmd_t *pmd_offset(pud_t * pud, unsigned long address) 189static 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