Reimplement clear_page/copy_page
PATCH 1/1 Reimplement clear_page/copy_page
Fold the SB-1 specific implementation of clear_page/copy_page in the generic version, and rewrite that one in tlbex style. The immediate benefits:
- It converts the compile-time workaround for SB-1 pass 1 prefetches to a more efficient run-time check.
- It allows adjustment of loop unfolling, which helps to reduce the number of redundant cdex cache ops.
- It fixes some esoteric cornercases (the cache line length calculations can go wrong, and support for 64k pages without prefetch instructions will overflow the addiu immediate).
- Somewhat better guesses of "good" prefetch values.
---
Lmbench3 running on a BCM1480 system shows improvements for some benchmarks (three runs with the original kernel, then three runs with the patched kernel), most markedly (~5%) for open/close and exec:
Processor, Processes - times in microseconds - smaller is better
------------------------------------------------------------------------------
Host OS Mhz null null open slct sig sig fork exec sh
call I/O stat clos TCP inst hndl proc proc proc
--------- ------------- ---- ---- ---- ---- -------- ---- ---- ---- ---- ----
larsa Linux 2.6.25- 897 0.23 0.52 3.73 6.26 12.3 0.65 5.08 330. 1406 8997 larsa Linux 2.6.25- 897 0.23 0.52 3.72 6.26 12.3 0.65 4.94 330. 1401 8959 larsa Linux 2.6.25- 897 0.23 0.52 3.74 6.27 12.3 0.66 5.01 330. 1409 8983
larsa Linux 2.6.25- 897 0.23 0.52 3.65 5.82 12.3 0.66 4.88 329. 1335 8355 larsa Linux 2.6.25- 897 0.23 0.52 3.67 5.83 12.3 0.65 4.98 329. 1327 8376 larsa Linux 2.6.25- 897 0.23 0.52 3.66 5.85 12.3 0.65 4.81 330. 1334 8405
arch/mips/mm/pg-r4k.c deleted +0 -534
@@ -1,534 +0,0 @@ -/* -* This file is subject to the terms and conditions of the GNU General Public -* License. See the file "COPYING" in the main directory of this archive -* for more details. -* -* Copyright (C) 2003, 04, 05 Ralf Baechle ([email protected]) -* Copyright (C) 2007 Maciej W. Rozycki -*/ -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/proc_fs.h> - -#include <asm/bugs.h> -#include <asm/cacheops.h> -#include <asm/inst.h> -#include <asm/io.h> -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/prefetch.h> -#include <asm/system.h> -#include <asm/bootinfo.h> -#include <asm/mipsregs.h> -#include <asm/mmu_context.h> -#include <asm/cpu.h> -#include <asm/war.h> - -#define half_scache_line_size () (cpu_scache_line_size() >> 1) -#define cpu_is_r4600_v1_x () ((read_c0_prid() & 0xfffffff0) == 0x00002010) -#define cpu_is_r4600_v2_x () ((read_c0_prid() & 0xfffffff0) == 0x00002020) - - -/* -* Maximum sizes: -* -* R4000 128 bytes S-cache: 0x58 bytes -* R4600 v1.7: 0x5c bytes -* R4600 v2.0: 0x60 bytes -* With prefetching, 16 byte strides 0xa0 bytes -*/ - -static unsigned int clear_page_array[0x130 /4 ]; - -void clear_page (void * page) __attribute__((alias ("clear_page_array" ))); - -EXPORT_SYMBOL (clear_page); - -/* -* Maximum sizes: -* -* R4000 128 bytes S-cache: 0x11c bytes -* R4600 v1.7: 0x080 bytes -* R4600 v2.0: 0x07c bytes -* With prefetching, 16 byte strides 0x0b8 bytes -*/ -static unsigned int copy_page_array[0x148 /4 ]; - -void copy_page (void *to,void *from) __attribute__((alias ("copy_page_array" ))); - -EXPORT_SYMBOL (copy_page); - -/* -* This is suboptimal for 32-bit kernels; we assume that R10000 is only used -* with 64-bit kernels. The prefetch offsets have been experimentally tuned -* an Origin 200. -*/ -static int pref_offset_clear__initdata =512 ; -static int pref_offset_copy__initdata =256 ; - -static unsigned int pref_src_mode__initdata ; -static unsigned int pref_dst_mode__initdata ; - -static int load_offset__initdata ; -static int store_offset__initdata ; - -static unsigned int __initdata *dest, *epc; - -static unsigned int instruction_pending; -static union mips_instruction delayed_mi; - -static void __init emit_instruction (union mips_instruction mi) -{ -if (instruction_pending) - *epc++ = delayed_mi.word; - - instruction_pending =1 ; - delayed_mi = mi; -} - -static inline void flush_delay_slot_or_nop (void ) -{ -if (instruction_pending) { - *epc++ = delayed_mi.word; - instruction_pending =0 ; -return ; - } - - *epc++ =0 ; -} - -static inline unsigned int *label (void ) -{ -if (instruction_pending) { - *epc++ = delayed_mi.word; - instruction_pending =0 ; - } - -return epc; -} - -static inline void build_insn_word (unsigned int word) -{ -union mips_instruction mi; - - mi.word = word; - -emit_instruction (mi); -} - -static inline void build_nop (void ) -{ -build_insn_word (0 );/* nop */ -} - -static inline void build_src_pref (int advance) -{ -if (!(load_offset & (cpu_dcache_line_size () -1 )) && advance) { -union mips_instruction mi; - - mi.i_format.opcode = pref_op; - mi.i_format.rs =5 ;/* $a1 */ - mi.i_format.rt = pref_src_mode; - mi.i_format.simmediate = load_offset + advance; - -emit_instruction (mi); - } -} - -static inline void __build_load_reg (int reg) -{ -union mips_instruction mi; -unsigned int width; - -if (cpu_has_64bit_gp_regs) { - mi.i_format.opcode = ld_op; - width =8 ; - }else { - mi.i_format.opcode = lw_op; - width =4 ; - } - mi.i_format.rs =5 ;/* $a1 */ - mi.i_format.rt = reg;/* $reg */ - mi.i_format.simmediate = load_offset; - - load_offset += width; -emit_instruction (mi); -} - -static inline void build_load_reg (int reg) -{ -if (cpu_has_prefetch) -build_src_pref (pref_offset_copy); - -__build_load_reg (reg); -} - -static inline void build_dst_pref (int advance) -{ -if (!(store_offset & (cpu_dcache_line_size () -1 )) && advance) { -union mips_instruction mi; - - mi.i_format.opcode = pref_op; - mi.i_format.rs =4 ;/* $a0 */ - mi.i_format.rt = pref_dst_mode; - mi.i_format.simmediate = store_offset + advance; - -emit_instruction (mi); - } -} - -static inline void build_cdex_s (void ) -{ -union mips_instruction mi; - -if ((store_offset & (cpu_scache_line_size () -1 ))) -return ; - - mi.c_format.opcode = cache_op; - mi.c_format.rs =4 ;/* $a0 */ - mi.c_format.c_op =3 ;/* Create Dirty Exclusive */ - mi.c_format.cache =3 ;/* Secondary Data Cache */ - mi.c_format.simmediate = store_offset; - -emit_instruction (mi); -} - -static inline void build_cdex_p (void ) -{ -union mips_instruction mi; - -if (store_offset & (cpu_dcache_line_size () -1 )) -return ; - -if (R4600_V1_HIT_CACHEOP_WAR &&cpu_is_r4600_v1_x ()) { -build_nop (); -build_nop (); -build_nop (); -build_nop (); - } - -if (R4600_V2_HIT_CACHEOP_WAR &&cpu_is_r4600_v2_x ()) -build_insn_word (0x8c200000 );/* lw $zero, ($at) */ - - mi.c_format.opcode = cache_op; - mi.c_format.rs =4 ;/* $a0 */ - mi.c_format.c_op =3 ;/* Create Dirty Exclusive */ - mi.c_format.cache =1 ;/* Data Cache */ - mi.c_format.simmediate = store_offset; - -emit_instruction (mi); -} - -static void __init __build_store_reg (int reg) -{ -union mips_instruction mi; -unsigned int width; - -if (cpu_has_64bit_gp_regs || - (cpu_has_64bit_zero_reg && reg ==0 )) { - mi.i_format.opcode = sd_op; - width =8 ; - }else { - mi.i_format.opcode = sw_op; - width =4 ; - } - mi.i_format.rs =4 ;/* $a0 */ - mi.i_format.rt = reg;/* $reg */ - mi.i_format.simmediate = store_offset; - - store_offset += width; -emit_instruction (mi); -} - -static inline void build_store_reg (int reg) -{ -int pref_off = cpu_has_prefetch ? - (reg ? pref_offset_copy : pref_offset_clear) :0 ; -if (pref_off) -build_dst_pref (pref_off); -else if (cpu_has_cache_cdex_s) -build_cdex_s (); -else if (cpu_has_cache_cdex_p) -build_cdex_p (); - -__build_store_reg (reg); -} - -static inline void build_addiu_rt_rs (unsigned int rt,unsigned int rs, -unsigned long offset) -{ -union mips_instruction mi; - -BUG_ON (offset >0x7fff ); - -if (cpu_has_64bit_gp_regs &&DADDI_WAR &&r4k_daddiu_bug ()) { - mi.i_format.opcode = addiu_op; - mi.i_format.rs =0 ;/* $zero */ - mi.i_format.rt =25 ;/* $t9 */ - mi.i_format.simmediate = offset; -emit_instruction (mi); - - mi.r_format.opcode = spec_op; - mi.r_format.rs = rs; - mi.r_format.rt =25 ;/* $t9 */ - mi.r_format.rd = rt; - mi.r_format.re =0 ; - mi.r_format.func = daddu_op; - }else { - mi.i_format.opcode = cpu_has_64bit_gp_regs ? - daddiu_op : addiu_op; - mi.i_format.rs = rs; - mi.i_format.rt = rt; - mi.i_format.simmediate = offset; - } -emit_instruction (mi); -} - -static inline void build_addiu_a2_a0 (unsigned long offset) -{ -build_addiu_rt_rs (6 ,4 , offset);/* $a2, $a0, offset */ -} - -static inline void build_addiu_a2 (unsigned long offset) -{ -build_addiu_rt_rs (6 ,6 , offset);/* $a2, $a2, offset */ -} - -static inline void build_addiu_a1 (unsigned long offset) -{ -build_addiu_rt_rs (5 ,5 , offset);/* $a1, $a1, offset */ - - load_offset -= offset; -} - -static inline void build_addiu_a0 (unsigned long offset) -{ -build_addiu_rt_rs (4 ,4 , offset);/* $a0, $a0, offset */ - - store_offset -= offset; -} - -static inline void build_bne (unsigned int *dest) -{ -union mips_instruction mi; - - mi.i_format.opcode = bne_op; - mi.i_format.rs =6 ;/* $a2 */ - mi.i_format.rt =4 ;/* $a0 */ - mi.i_format.simmediate = dest - epc -1 ; - - *epc++ = mi.word; -flush_delay_slot_or_nop (); -} - -static inline void build_jr_ra (void ) -{ -union mips_instruction mi; - - mi.r_format.opcode = spec_op; - mi.r_format.rs =31 ; - mi.r_format.rt =0 ; - mi.r_format.rd =0 ; - mi.r_format.re =0 ; - mi.r_format.func = jr_op; - - *epc++ = mi.word; -flush_delay_slot_or_nop (); -} - -void __init build_clear_page (void ) -{ -unsigned int loop_start; -unsigned long off; -int i; - - epc = (unsigned int *) &clear_page_array; - instruction_pending =0 ; - store_offset =0 ; - -if (cpu_has_prefetch) { -switch (current_cpu_type ()) { -case CPU_TX49XX : -/* TX49 supports only Pref_Load */ - pref_offset_clear =0 ; - pref_offset_copy =0 ; -break ; - -case CPU_RM9000 : -/* -* As a workaround for erratum G105 which make the -* PrepareForStore hint unusable we fall back to -* StoreRetained on the RM9000. Once it is known which -* versions of the RM9000 we'll be able to condition- -* alize this. -*/ - -case CPU_R10000 : -case CPU_R12000 : -case CPU_R14000 : - pref_src_mode = Pref_LoadStreamed; - pref_dst_mode = Pref_StoreStreamed; -break ; - -default : - pref_src_mode = Pref_LoadStreamed; - pref_dst_mode = Pref_PrepareForStore; -break ; - } - } - - off =PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear :0 ); -if (off >0x7fff ) { -build_addiu_a2_a0 (off >>1 ); -build_addiu_a2 (off >>1 ); - }else -build_addiu_a2_a0 (off); - -if (R4600_V2_HIT_CACHEOP_WAR &&cpu_is_r4600_v2_x ()) -build_insn_word (0x3c01a000 );/* lui $at, 0xa000 */ - -dest =label (); -do { -build_store_reg (0 ); -build_store_reg (0 ); -build_store_reg (0 ); -build_store_reg (0 ); - }while (store_offset <half_scache_line_size ()); -build_addiu_a0 (2 * store_offset); - loop_start = store_offset; -do { -build_store_reg (0 ); -build_store_reg (0 ); -build_store_reg (0 ); -build_store_reg (0 ); - }while ((store_offset - loop_start) <half_scache_line_size ()); -build_bne (dest); - -if (cpu_has_prefetch && pref_offset_clear) { -build_addiu_a2_a0 (pref_offset_clear); - dest =label (); - loop_start = store_offset; -do { -__build_store_reg (0 ); -__build_store_reg (0 ); -__build_store_reg (0 ); -__build_store_reg (0 ); - }while ((store_offset - loop_start) <half_scache_line_size ()); -build_addiu_a0 (2 * store_offset); - loop_start = store_offset; -do { -__build_store_reg (0 ); -__build_store_reg (0 ); -__build_store_reg (0 ); -__build_store_reg (0 ); - }while ((store_offset - loop_start) <half_scache_line_size ()); -build_bne (dest); - } - -build_jr_ra (); - -BUG_ON (epc > clear_page_array +ARRAY_SIZE (clear_page_array)); - -pr_info ("Synthesized clear page handler (%u instructions).\n" , - (unsigned int )(epc - clear_page_array)); - -pr_debug ("\t.set push\n" ); -pr_debug ("\t.set noreorder\n" ); -for (i =0 ; i < (epc - clear_page_array); i++) -pr_debug ("\t.word 0x%08x\n" , clear_page_array[i]); -pr_debug ("\t.set pop\n" ); -} - -void __init build_copy_page (void ) -{ -unsigned int loop_start; -unsigned long off; -int i; - - epc = (unsigned int *) ©_page_array; - store_offset = load_offset =0 ; - instruction_pending =0 ; - - off =PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy :0 ); -if (off >0x7fff ) { -build_addiu_a2_a0 (off >>1 ); -build_addiu_a2 (off >>1 ); - }else -build_addiu_a2_a0 (off); - -if (R4600_V2_HIT_CACHEOP_WAR &&cpu_is_r4600_v2_x ()) -build_insn_word (0x3c01a000 );/* lui $at, 0xa000 */ - -dest =label (); - loop_start = store_offset; -do { -build_load_reg (8 ); -build_load_reg (9 ); -build_load_reg (10 ); -build_load_reg (11 ); -build_store_reg (8 ); -build_store_reg (9 ); -build_store_reg (10 ); -build_store_reg (11 ); - }while ((store_offset - loop_start) <half_scache_line_size ()); -build_addiu_a0 (2 * store_offset); -build_addiu_a1 (2 * load_offset); - loop_start = store_offset; -do { -build_load_reg (8 ); -build_load_reg (9 ); -build_load_reg (10 ); -build_load_reg (11 ); -build_store_reg (8 ); -build_store_reg (9 ); -build_store_reg (10 ); -build_store_reg (11 ); - }while ((store_offset - loop_start) <half_scache_line_size ()); -build_bne (dest); - -if (cpu_has_prefetch && pref_offset_copy) { -build_addiu_a2_a0 (pref_offset_copy); - dest =label (); - loop_start = store_offset; -do { -__build_load_reg (8 ); -__build_load_reg (9 ); -__build_load_reg (10 ); -__build_load_reg (11 ); -__build_store_reg (8 ); -__build_store_reg (9 ); -__build_store_reg (10 ); -__build_store_reg (11 ); - }while ((store_offset - loop_start) <half_scache_line_size ()); -build_addiu_a0 (2 * store_offset); -build_addiu_a1 (2 * load_offset); - loop_start = store_offset; -do { -__build_load_reg (8 ); -__build_load_reg (9 ); -__build_load_reg (10 ); -__build_load_reg (11 ); -__build_store_reg (8 ); -__build_store_reg (9 ); -__build_store_reg (10 ); -__build_store_reg (11 ); - }while ((store_offset - loop_start) <half_scache_line_size ()); -build_bne (dest); - } - -build_jr_ra (); - -BUG_ON (epc > copy_page_array +ARRAY_SIZE (copy_page_array)); - -pr_info ("Synthesized copy page handler (%u instructions).\n" , - (unsigned int )(epc - copy_page_array)); - -pr_debug ("\t.set push\n" ); -pr_debug ("\t.set noreorder\n" ); -for (i =0 ; i < (epc - copy_page_array); i++) -pr_debug ("\t.word 0x%08x\n" , copy_page_array[i]); -pr_debug ("\t.set pop\n" ); -}
arch/mips/mm/uasm.c +19 -7
@@ -58,13 +58,13 @@ insn_invalid, insn_addu, insn_addiu, insn_and, insn_andi, insn_beq, insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl, - insn_bne, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0, - insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, - insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld, - insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0, - insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll, - insn_sra, insn_srl, insn_subu, insn_sw, insn_tlbp, insn_tlbwi, - insn_tlbwr, insn_xor, insn_xori + insn_bne, insn_cache, insn_daddu, insn_daddiu, insn_dmfc0, + insn_dmtc0, insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, + insn_dsrl32, insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, + insn_ld, insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, + insn_mtc0, insn_ori, insn_pref, insn_rfe, insn_sc, insn_scd, + insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw, + insn_tlbp, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori }; struct insn {
@@ -94,6 +94,7 @@ { insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM }, { insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM }, { insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, + { insn_cache, M(cache_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD }, { insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET},
@@ -116,6 +117,7 @@ { insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET}, { insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET}, { insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, + { insn_pref, M(pref_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_rfe, M(cop0_op, cop_op, 0, 0, 0, rfe_op), 0 }, { insn_sc, M(sc_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_scd, M(scd_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
@@ -337,6 +339,7 @@ I_u1s2(_bltz) I_u1s2(_bltzl) I_u1u2s3(_bne) +I_u2s3u1(_cache) I_u1u2u3(_dmfc0) I_u1u2u3(_dmtc0) I_u2u1s3(_daddiu)
@@ -359,6 +362,7 @@ I_u1u2u3(_mfc0) I_u1u2u3(_mtc0) I_u2u1u3(_ori) +I_u2s3u1(_pref) I_0(_rfe) I_u2s3u1(_sc) I_u2s3u1(_scd)
@@ -555,6 +559,14 @@ }void __init +uasm_il_bne (u32 **p,struct uasm_reloc **r,unsigned int reg1, +unsigned int reg2,int lid) +{ +uasm_r_mips_pc16 (r, *p, lid); +uasm_i_bne (p, reg1, reg2,0 ); +} + +void __init uasm_il_bnez (u32 **p,struct uasm_reloc **r,unsigned int reg,int lid) {uasm_r_mips_pc16 (r, *p, lid);
arch/mips/mm/uasm.h +5 -0
@@ -55,6 +55,7 @@Ip_u1s2 (_bltz);Ip_u1s2 (_bltzl);Ip_u1u2s3 (_bne); +Ip_u2s3u1 (_cache);Ip_u1u2u3 (_dmfc0);Ip_u1u2u3 (_dmtc0);Ip_u2u1s3 (_daddiu);
@@ -77,6 +78,7 @@Ip_u1u2u3 (_mfc0);Ip_u1u2u3 (_mtc0);Ip_u2u1u3 (_ori); +Ip_u2s3u1 (_pref);Ip_0 (_rfe);Ip_u2s3u1 (_sc);Ip_u2s3u1 (_scd);
@@ -185,6 +187,9 @@void __init uasm_il_beqzl (u32 **p,struct uasm_reloc **r,unsigned int reg,int lid);void __init +uasm_il_bne (u32 **p,struct uasm_reloc **r,unsigned int reg1, +unsigned int reg2,int lid); +void __init uasm_il_bnez (u32 **p,struct uasm_reloc **r,unsigned int reg,int lid);void __init uasm_il_bgezl (u32 **p,struct uasm_reloc **r,unsigned int reg,int lid);
arch/mips/mm/pg-sb1.c deleted +0 -302
302 lines not on this page · raw message
arch/mips/mm/Makefile +18 -19
@@ -4,30 +4,29 @@ obj-y += cache.o dma-default.o extable.o fault.o \ init.o pgtable.o tlbex.o tlbex-fault.o \ - uasm.o + uasm.o page.o obj-$(CONFIG_32BIT) += ioremap.o pgtable-32.o obj-$(CONFIG_64BIT) += pgtable-64.o obj-$(CONFIG_HIGHMEM) += highmem.o -obj-$(CONFIG_CPU_LOONGSON2) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o -obj-$(CONFIG_CPU_MIPS32) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o -obj-$(CONFIG_CPU_MIPS64) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o -obj-$(CONFIG_CPU_NEVADA) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o -obj-$(CONFIG_CPU_R10000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o -obj-$(CONFIG_CPU_R3000) += c-r3k.o tlb-r3k.o pg-r4k.o -obj-$(CONFIG_CPU_R4300) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o -obj-$(CONFIG_CPU_R4X00) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o -obj-$(CONFIG_CPU_R5000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o -obj-$(CONFIG_CPU_R5432) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o -obj-$(CONFIG_CPU_R8000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r8k.o -obj-$(CONFIG_CPU_RM7000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o -obj-$(CONFIG_CPU_RM9000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o -obj-$(CONFIG_CPU_SB1) += c-r4k.o cerr-sb1.o cex-sb1.o pg-sb1.o \ - tlb-r4k.o -obj-$(CONFIG_CPU_TX39XX) += c-tx39.o pg-r4k.o tlb-r3k.o -obj-$(CONFIG_CPU_TX49XX) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o -obj-$(CONFIG_CPU_VR41XX) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o +obj-$(CONFIG_CPU_LOONGSON2) += c-r4k.o cex-gen.o tlb-r4k.o +obj-$(CONFIG_CPU_MIPS32) += c-r4k.o cex-gen.o tlb-r4k.o +obj-$(CONFIG_CPU_MIPS64) += c-r4k.o cex-gen.o tlb-r4k.o +obj-$(CONFIG_CPU_NEVADA) += c-r4k.o cex-gen.o tlb-r4k.o +obj-$(CONFIG_CPU_R10000) += c-r4k.o cex-gen.o tlb-r4k.o +obj-$(CONFIG_CPU_R3000) += c-r3k.o tlb-r3k.o +obj-$(CONFIG_CPU_R4300) += c-r4k.o cex-gen.o tlb-r4k.o +obj-$(CONFIG_CPU_R4X00) += c-r4k.o cex-gen.o tlb-r4k.o +obj-$(CONFIG_CPU_R5000) += c-r4k.o cex-gen.o tlb-r4k.o +obj-$(CONFIG_CPU_R5432) += c-r4k.o cex-gen.o tlb-r4k.o +obj-$(CONFIG_CPU_R8000) += c-r4k.o cex-gen.o tlb-r8k.o +obj-$(CONFIG_CPU_RM7000) += c-r4k.o cex-gen.o tlb-r4k.o +obj-$(CONFIG_CPU_RM9000) += c-r4k.o cex-gen.o tlb-r4k.o +obj-$(CONFIG_CPU_SB1) += c-r4k.o cerr-sb1.o cex-sb1.o tlb-r4k.o +obj-$(CONFIG_CPU_TX39XX) += c-tx39.o tlb-r3k.o +obj-$(CONFIG_CPU_TX49XX) += c-r4k.o cex-gen.o tlb-r4k.o +obj-$(CONFIG_CPU_VR41XX) += c-r4k.o cex-gen.o tlb-r4k.o obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o
arch/mips/mm/page.c new file +685 -0
685 lines not on this page · raw message
Quoted 13 lines · Thiemo Seufer
Fold the SB-1 specific implementation of clear_page/copy_page in the generic version, and rewrite that one in tlbex style. The immediate benefits:
- It converts the compile-time workaround for SB-1 pass 1 prefetches to a more efficient run-time check.
- It allows adjustment of loop unfolling, which helps to reduce the number of redundant cdex cache ops.
- It fixes some esoteric cornercases (the cache line length calculations can go wrong, and support for 64k pages without prefetch instructions will overflow the addiu immediate).
- Somewhat better guesses of "good" prefetch values.
Quoted 7 lines
Signed-off-by Thiemo Seufer <[email protected]>---
Lmbench3 running on a BCM1480 system shows improvements for some benchmarks (three runs with the original kernel, then three runs with the patched kernel), most markedly (~5%) for open/close and exec:
The patch is certainly a good thing but I somehow doubt for many of the improvments that they are a result of the patch and not the unavoidable benchmarking noise.
Queued for 2.6.26,
Ralf
Quoted 13 lines · Thiemo Seufer
Fold the SB-1 specific implementation of clear_page/copy_page in the generic version, and rewrite that one in tlbex style. The immediate benefits:
- It converts the compile-time workaround for SB-1 pass 1 prefetches to a more efficient run-time check.
- It allows adjustment of loop unfolling, which helps to reduce the number of redundant cdex cache ops.
- It fixes some esoteric cornercases (the cache line length calculations can go wrong, and support for 64k pages without prefetch instructions will overflow the addiu immediate).
- Somewhat better guesses of "good" prefetch values.
Quoted 1 line
Signed-off-by Thiemo Seufer <[email protected]>
With this patch, on platforms do not have prefetch instruction, a first instruction of clear_page and copy_page would be something like:
ori a2, a0, PAGE_SIZE
Of course this does not work for odd pages. Please fold this fix into your patch.
arch/mips/mm/page.c +2 -2
@@ -302,7 +302,7 @@ void __cpuinit build_clear_page(void)BUG_ON (PAGE_SIZE < pref_bias_clear_store); off =PAGE_SIZE - pref_bias_clear_store; -if (off >0xffff ) +if (off >0xffff || !pref_bias_clear_store)pg_addiu (&buf,A2 ,A0 , off);else uasm_i_ori (&buf,A2 ,A0 , off);
@@ -446,7 +446,7 @@ void __cpuinit build_copy_page(void)BUG_ON (pref_bias_copy_store > pref_bias_copy_load); off =PAGE_SIZE - pref_bias_copy_load; -if (off >0xffff ) +if (off >0xffff || !pref_bias_copy_load)pg_addiu (&buf,A2 ,A0 , off);else uasm_i_ori (&buf,A2 ,A0 , off);
Quoted 7 lines · Atsushi Nemoto
With this patch, on platforms do not have prefetch instruction, a first instruction of
clear_pageandcopy_pagewould be something like:ori a2, a0,
PAGE_SIZEOf course this does not work for odd pages. Please fold this fix into your patch.
Folded into the 2.6.26 queue. Thanks,
Ralf