diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2006-10-23 21:29:01 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2006-11-01 12:46:09 -0500 |
commit | 242954b5aa8e5ec84f46a84637daf08ee4247c6e (patch) | |
tree | 7fb896349b377f5f819d4050bb92eeee05598571 /arch/mips | |
parent | 4b1c46a383aafc137bc91a0f9698bfc11e062d1b (diff) |
[MIPS] 16K & 64K page size fixes
Derived from Peter Watkins <treestem@gmail.com>'s work.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/kernel/asm-offsets.c | 2 | ||||
-rw-r--r-- | arch/mips/kernel/head.S | 3 | ||||
-rw-r--r-- | arch/mips/kernel/r4k_switch.S | 5 | ||||
-rw-r--r-- | arch/mips/kernel/vmlinux.lds.S | 10 | ||||
-rw-r--r-- | arch/mips/lib-64/dump_tlb.c | 6 | ||||
-rw-r--r-- | arch/mips/mips-boards/generic/memory.c | 2 | ||||
-rw-r--r-- | arch/mips/mm/pg-r4k.c | 30 | ||||
-rw-r--r-- | arch/mips/mm/tlbex.c | 13 |
8 files changed, 60 insertions, 11 deletions
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index e9ce5b3721af..ff88b06f89df 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #define offset(string, ptr, member) \ | 22 | #define offset(string, ptr, member) \ |
23 | __asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member))) | 23 | __asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member))) |
24 | #define constant(string, member) \ | 24 | #define constant(string, member) \ |
25 | __asm__("\n@@@" string "%x0" : : "ri" (member)) | 25 | __asm__("\n@@@" string "%X0" : : "ri" (member)) |
26 | #define size(string, size) \ | 26 | #define size(string, size) \ |
27 | __asm__("\n@@@" string "%0" : : "i" (sizeof(size))) | 27 | __asm__("\n@@@" string "%0" : : "i" (sizeof(size))) |
28 | #define linefeed text("") | 28 | #define linefeed text("") |
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index 8c6db0fc72f0..ddc1b71c9378 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S | |||
@@ -189,7 +189,8 @@ NESTED(kernel_entry, 16, sp) # kernel entry point | |||
189 | 189 | ||
190 | MTC0 zero, CP0_CONTEXT # clear context register | 190 | MTC0 zero, CP0_CONTEXT # clear context register |
191 | PTR_LA $28, init_thread_union | 191 | PTR_LA $28, init_thread_union |
192 | PTR_ADDIU sp, $28, _THREAD_SIZE - 32 | 192 | PTR_LI sp, _THREAD_SIZE - 32 |
193 | PTR_ADDU sp, $28 | ||
193 | set_saved_sp sp, t0, t1 | 194 | set_saved_sp sp, t0, t1 |
194 | PTR_SUBU sp, 4 * SZREG # init stack pointer | 195 | PTR_SUBU sp, 4 * SZREG # init stack pointer |
195 | 196 | ||
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S index d5c8b82fed72..cc566cf12246 100644 --- a/arch/mips/kernel/r4k_switch.S +++ b/arch/mips/kernel/r4k_switch.S | |||
@@ -85,7 +85,12 @@ | |||
85 | move $28, a2 | 85 | move $28, a2 |
86 | cpu_restore_nonscratch a1 | 86 | cpu_restore_nonscratch a1 |
87 | 87 | ||
88 | #if (_THREAD_SIZE - 32) < 0x10000 | ||
88 | PTR_ADDIU t0, $28, _THREAD_SIZE - 32 | 89 | PTR_ADDIU t0, $28, _THREAD_SIZE - 32 |
90 | #else | ||
91 | PTR_LI t0, _THREAD_SIZE - 32 | ||
92 | PTR_ADDU t0, $28 | ||
93 | #endif | ||
89 | set_saved_sp t0, t1, t2 | 94 | set_saved_sp t0, t1, t2 |
90 | #ifdef CONFIG_MIPS_MT_SMTC | 95 | #ifdef CONFIG_MIPS_MT_SMTC |
91 | /* Read-modify-writes of Status must be atomic on a VPE */ | 96 | /* Read-modify-writes of Status must be atomic on a VPE */ |
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 25ed3337ce35..79f0317d84ac 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S | |||
@@ -50,6 +50,16 @@ SECTIONS | |||
50 | /* writeable */ | 50 | /* writeable */ |
51 | .data : { /* Data */ | 51 | .data : { /* Data */ |
52 | . = . + DATAOFFSET; /* for CONFIG_MAPPED_KERNEL */ | 52 | . = . + DATAOFFSET; /* for CONFIG_MAPPED_KERNEL */ |
53 | /* | ||
54 | * This ALIGN is needed as a workaround for a bug a gcc bug upto 4.1 which | ||
55 | * limits the maximum alignment to at most 32kB and results in the following | ||
56 | * warning: | ||
57 | * | ||
58 | * CC arch/mips/kernel/init_task.o | ||
59 | * arch/mips/kernel/init_task.c:30: warning: alignment of ‘init_thread_union’ | ||
60 | * is greater than maximum object file alignment. Using 32768 | ||
61 | */ | ||
62 | . = ALIGN(_PAGE_SIZE); | ||
53 | *(.data.init_task) | 63 | *(.data.init_task) |
54 | 64 | ||
55 | *(.data) | 65 | *(.data) |
diff --git a/arch/mips/lib-64/dump_tlb.c b/arch/mips/lib-64/dump_tlb.c index be8261be679b..594df1a05ecc 100644 --- a/arch/mips/lib-64/dump_tlb.c +++ b/arch/mips/lib-64/dump_tlb.c | |||
@@ -149,7 +149,7 @@ void dump_list_process(struct task_struct *t, void *address) | |||
149 | printk("Addr == %08lx\n", addr); | 149 | printk("Addr == %08lx\n", addr); |
150 | printk("tasks->mm.pgd == %08lx\n", (unsigned long) t->mm->pgd); | 150 | printk("tasks->mm.pgd == %08lx\n", (unsigned long) t->mm->pgd); |
151 | 151 | ||
152 | page_dir = pgd_offset(t->mm, 0); | 152 | page_dir = pgd_offset(t->mm, 0UL); |
153 | printk("page_dir == %016lx\n", (unsigned long) page_dir); | 153 | printk("page_dir == %016lx\n", (unsigned long) page_dir); |
154 | 154 | ||
155 | pgd = pgd_offset(t->mm, addr); | 155 | pgd = pgd_offset(t->mm, addr); |
@@ -184,13 +184,13 @@ void dump_list_current(void *address) | |||
184 | dump_list_process(current, address); | 184 | dump_list_process(current, address); |
185 | } | 185 | } |
186 | 186 | ||
187 | unsigned int vtop(void *address) | 187 | unsigned long vtop(void *address) |
188 | { | 188 | { |
189 | pgd_t *pgd; | 189 | pgd_t *pgd; |
190 | pud_t *pud; | 190 | pud_t *pud; |
191 | pmd_t *pmd; | 191 | pmd_t *pmd; |
192 | pte_t *pte; | 192 | pte_t *pte; |
193 | unsigned int addr, paddr; | 193 | unsigned long addr, paddr; |
194 | 194 | ||
195 | addr = (unsigned long) address; | 195 | addr = (unsigned long) address; |
196 | pgd = pgd_offset(current->mm, addr); | 196 | pgd = pgd_offset(current->mm, addr); |
diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c index be80c5dd4a0c..eeed944e0f83 100644 --- a/arch/mips/mips-boards/generic/memory.c +++ b/arch/mips/mips-boards/generic/memory.c | |||
@@ -176,7 +176,7 @@ unsigned long __init prom_free_prom_memory(void) | |||
176 | if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) | 176 | if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) |
177 | continue; | 177 | continue; |
178 | 178 | ||
179 | addr = boot_mem_map.map[i].addr; | 179 | addr = PAGE_ALIGN(boot_mem_map.map[i].addr); |
180 | while (addr < boot_mem_map.map[i].addr | 180 | while (addr < boot_mem_map.map[i].addr |
181 | + boot_mem_map.map[i].size) { | 181 | + boot_mem_map.map[i].size) { |
182 | ClearPageReserved(virt_to_page(__va(addr))); | 182 | ClearPageReserved(virt_to_page(__va(addr))); |
diff --git a/arch/mips/mm/pg-r4k.c b/arch/mips/mm/pg-r4k.c index b7c749232ffe..d41fc5885e87 100644 --- a/arch/mips/mm/pg-r4k.c +++ b/arch/mips/mm/pg-r4k.c | |||
@@ -270,6 +270,20 @@ static inline void build_addiu_a2_a0(unsigned long offset) | |||
270 | emit_instruction(mi); | 270 | emit_instruction(mi); |
271 | } | 271 | } |
272 | 272 | ||
273 | static inline void build_addiu_a2(unsigned long offset) | ||
274 | { | ||
275 | union mips_instruction mi; | ||
276 | |||
277 | BUG_ON(offset > 0x7fff); | ||
278 | |||
279 | mi.i_format.opcode = cpu_has_64bit_gp_regs ? daddiu_op : addiu_op; | ||
280 | mi.i_format.rs = 6; /* $a2 */ | ||
281 | mi.i_format.rt = 6; /* $a2 */ | ||
282 | mi.i_format.simmediate = offset; | ||
283 | |||
284 | emit_instruction(mi); | ||
285 | } | ||
286 | |||
273 | static inline void build_addiu_a1(unsigned long offset) | 287 | static inline void build_addiu_a1(unsigned long offset) |
274 | { | 288 | { |
275 | union mips_instruction mi; | 289 | union mips_instruction mi; |
@@ -333,6 +347,7 @@ static inline void build_jr_ra(void) | |||
333 | void __init build_clear_page(void) | 347 | void __init build_clear_page(void) |
334 | { | 348 | { |
335 | unsigned int loop_start; | 349 | unsigned int loop_start; |
350 | unsigned long off; | ||
336 | 351 | ||
337 | epc = (unsigned int *) &clear_page_array; | 352 | epc = (unsigned int *) &clear_page_array; |
338 | instruction_pending = 0; | 353 | instruction_pending = 0; |
@@ -369,7 +384,12 @@ void __init build_clear_page(void) | |||
369 | } | 384 | } |
370 | } | 385 | } |
371 | 386 | ||
372 | build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0)); | 387 | off = PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0); |
388 | if (off > 0x7fff) { | ||
389 | build_addiu_a2_a0(off >> 1); | ||
390 | build_addiu_a2(off >> 1); | ||
391 | } else | ||
392 | build_addiu_a2_a0(off); | ||
373 | 393 | ||
374 | if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) | 394 | if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) |
375 | build_insn_word(0x3c01a000); /* lui $at, 0xa000 */ | 395 | build_insn_word(0x3c01a000); /* lui $at, 0xa000 */ |
@@ -420,12 +440,18 @@ dest = label(); | |||
420 | void __init build_copy_page(void) | 440 | void __init build_copy_page(void) |
421 | { | 441 | { |
422 | unsigned int loop_start; | 442 | unsigned int loop_start; |
443 | unsigned long off; | ||
423 | 444 | ||
424 | epc = (unsigned int *) ©_page_array; | 445 | epc = (unsigned int *) ©_page_array; |
425 | store_offset = load_offset = 0; | 446 | store_offset = load_offset = 0; |
426 | instruction_pending = 0; | 447 | instruction_pending = 0; |
427 | 448 | ||
428 | build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0)); | 449 | off = PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0); |
450 | if (off > 0x7fff) { | ||
451 | build_addiu_a2_a0(off >> 1); | ||
452 | build_addiu_a2(off >> 1); | ||
453 | } else | ||
454 | build_addiu_a2_a0(off); | ||
429 | 455 | ||
430 | if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) | 456 | if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) |
431 | build_insn_word(0x3c01a000); /* lui $at, 0xa000 */ | 457 | build_insn_word(0x3c01a000); /* lui $at, 0xa000 */ |
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 6f8b25cfa6f0..fec318a1c8c5 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c | |||
@@ -102,7 +102,7 @@ enum opcode { | |||
102 | insn_addu, insn_addiu, insn_and, insn_andi, insn_beq, | 102 | insn_addu, insn_addiu, insn_and, insn_andi, insn_beq, |
103 | insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl, | 103 | insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl, |
104 | insn_bne, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0, | 104 | insn_bne, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0, |
105 | insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, | 105 | insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, |
106 | insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld, | 106 | insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld, |
107 | insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0, | 107 | insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0, |
108 | insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll, | 108 | insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll, |
@@ -145,6 +145,7 @@ static __initdata struct insn insn_table[] = { | |||
145 | { insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE }, | 145 | { insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE }, |
146 | { insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE }, | 146 | { insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE }, |
147 | { insn_dsrl, M(spec_op,0,0,0,0,dsrl_op), RT | RD | RE }, | 147 | { insn_dsrl, M(spec_op,0,0,0,0,dsrl_op), RT | RD | RE }, |
148 | { insn_dsrl32, M(spec_op,0,0,0,0,dsrl32_op), RT | RD | RE }, | ||
148 | { insn_dsubu, M(spec_op,0,0,0,0,dsubu_op), RS | RT | RD }, | 149 | { insn_dsubu, M(spec_op,0,0,0,0,dsubu_op), RS | RT | RD }, |
149 | { insn_eret, M(cop0_op,cop_op,0,0,0,eret_op), 0 }, | 150 | { insn_eret, M(cop0_op,cop_op,0,0,0,eret_op), 0 }, |
150 | { insn_j, M(j_op,0,0,0,0,0), JIMM }, | 151 | { insn_j, M(j_op,0,0,0,0,0), JIMM }, |
@@ -385,6 +386,7 @@ I_u2u1u3(_dsll); | |||
385 | I_u2u1u3(_dsll32); | 386 | I_u2u1u3(_dsll32); |
386 | I_u2u1u3(_dsra); | 387 | I_u2u1u3(_dsra); |
387 | I_u2u1u3(_dsrl); | 388 | I_u2u1u3(_dsrl); |
389 | I_u2u1u3(_dsrl32); | ||
388 | I_u3u1u2(_dsubu); | 390 | I_u3u1u2(_dsubu); |
389 | I_0(_eret); | 391 | I_0(_eret); |
390 | I_u1(_j); | 392 | I_u1(_j); |
@@ -996,7 +998,12 @@ build_get_pmde64(u32 **p, struct label **l, struct reloc **r, | |||
996 | #endif | 998 | #endif |
997 | 999 | ||
998 | l_vmalloc_done(l, *p); | 1000 | l_vmalloc_done(l, *p); |
999 | i_dsrl(p, tmp, tmp, PGDIR_SHIFT-3); /* get pgd offset in bytes */ | 1001 | |
1002 | if (PGDIR_SHIFT - 3 < 32) /* get pgd offset in bytes */ | ||
1003 | i_dsrl(p, tmp, tmp, PGDIR_SHIFT-3); | ||
1004 | else | ||
1005 | i_dsrl32(p, tmp, tmp, PGDIR_SHIFT - 3 - 32); | ||
1006 | |||
1000 | i_andi(p, tmp, tmp, (PTRS_PER_PGD - 1)<<3); | 1007 | i_andi(p, tmp, tmp, (PTRS_PER_PGD - 1)<<3); |
1001 | i_daddu(p, ptr, ptr, tmp); /* add in pgd offset */ | 1008 | i_daddu(p, ptr, ptr, tmp); /* add in pgd offset */ |
1002 | i_dmfc0(p, tmp, C0_BADVADDR); /* get faulting address */ | 1009 | i_dmfc0(p, tmp, C0_BADVADDR); /* get faulting address */ |
@@ -1073,7 +1080,7 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr) | |||
1073 | 1080 | ||
1074 | static __init void build_adjust_context(u32 **p, unsigned int ctx) | 1081 | static __init void build_adjust_context(u32 **p, unsigned int ctx) |
1075 | { | 1082 | { |
1076 | unsigned int shift = 4 - (PTE_T_LOG2 + 1); | 1083 | unsigned int shift = 4 - (PTE_T_LOG2 + 1) + PAGE_SHIFT - 12; |
1077 | unsigned int mask = (PTRS_PER_PTE / 2 - 1) << (PTE_T_LOG2 + 1); | 1084 | unsigned int mask = (PTRS_PER_PTE / 2 - 1) << (PTE_T_LOG2 + 1); |
1078 | 1085 | ||
1079 | switch (current_cpu_data.cputype) { | 1086 | switch (current_cpu_data.cputype) { |