Re: [patch] pg-r4k.c bugs for R4k systems with a secondary cache
From: Maciej W. Rozycki <hidden>
Date: 2004-01-27 11:09:52
On Mon, 26 Jan 2004, Maciej W. Rozycki wrote:
This patch fixes a bug in build_cdex() that makes the function invoke the Create Dirty Exclusive command for the D-cache when a secondary cache is present. This is unnecessary as the Create Dirty Exclusive command for the S-cache acts upon the D-cache appropriately and (for reasons yet to be investigated) using the command on the D-cache directly leads to memory corruption on my R4400SC system. With the patch the system appears stable. The patch also removes references to has_scache which currently disable code for the S-cache line size of 128 bytes as the variable is always 0.
Here is a somewhat better version. It's functionally equivalent. OK to apply? Maciej -- + Maciej W. Rozycki, Technical University of Gdansk, Poland + +--------------------------------------------------------------+ + e-mail: macro@ds2.pg.gda.pl, PGP key available + patch-mips-2.4.24-pre2-20040116-mips-pg-r4k-scache-1 diff -up --recursive --new-file linux-mips-2.4.24-pre2-20040116.macro/arch/mips/mm/pg-r4k.c linux-mips-2.4.24-pre2-20040116/arch/mips/mm/pg-r4k.c
--- linux-mips-2.4.24-pre2-20040116.macro/arch/mips/mm/pg-r4k.c 2004-01-03 03:56:38.000000000 +0000
+++ linux-mips-2.4.24-pre2-20040116/arch/mips/mm/pg-r4k.c 2004-01-26 23:55:43.000000000 +0000@@ -67,7 +67,6 @@ static int pref_offset_copy __initdata static unsigned int pref_src_mode __initdata; static unsigned int pref_dst_mode __initdata; -static int has_scache __initdata = 0; static int load_offset __initdata = 0; static int store_offset __initdata = 0;
@@ -126,21 +125,25 @@ static inline void build_dst_pref(int ad } } -static inline void build_cdex(void) +static inline void build_cdex_s(void) { union mips_instruction mi; - if (cpu_has_cache_cdex_s && - !(store_offset & (cpu_scache_line_size() - 1))) { + 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; + 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; - *epc++ = mi.word; - } + *epc++ = mi.word; +} + +static inline void build_cdex_p(void) +{ + union mips_instruction mi; if (store_offset & (cpu_dcache_line_size() - 1)) return;
@@ -212,8 +215,10 @@ static inline void build_store_reg(int r build_dst_pref(pref_offset_copy); else build_dst_pref(pref_offset_clear); + else if (cpu_has_cache_cdex_s) + build_cdex_s(); else if (cpu_has_cache_cdex_p) - build_cdex(); + build_cdex_p(); __build_store_reg(reg); }
@@ -332,7 +337,7 @@ dest = epc; build_store_reg(0); build_store_reg(0); build_store_reg(0); - if (has_scache && cpu_scache_line_size() == 128) { + if (cpu_scache_line_size() == 128) { build_store_reg(0); build_store_reg(0); build_store_reg(0);
@@ -341,7 +346,7 @@ dest = epc; build_addiu_a0(2 * store_offset); build_store_reg(0); build_store_reg(0); - if (has_scache && cpu_scache_line_size() == 128) { + if (cpu_scache_line_size() == 128) { build_store_reg(0); build_store_reg(0); build_store_reg(0);
@@ -405,7 +410,7 @@ dest = epc; build_store_reg( 9); build_store_reg(10); build_store_reg(11); - if (has_scache && cpu_scache_line_size() == 128) { + if (cpu_scache_line_size() == 128) { build_load_reg( 8); build_load_reg( 9); build_load_reg(10);
@@ -424,7 +429,7 @@ dest = epc; build_store_reg( 8); build_store_reg( 9); build_store_reg(10); - if (has_scache && cpu_scache_line_size() == 128) { + if (cpu_scache_line_size() == 128) { build_store_reg(11); build_load_reg( 8); build_load_reg( 9);
diff -up --recursive --new-file linux-mips-2.4.24-pre2-20040116.macro/arch/mips64/mm/pg-r4k.c linux-mips-2.4.24-pre2-20040116/arch/mips64/mm/pg-r4k.c
--- linux-mips-2.4.24-pre2-20040116.macro/arch/mips64/mm/pg-r4k.c 2004-01-03 03:56:46.000000000 +0000
+++ linux-mips-2.4.24-pre2-20040116/arch/mips64/mm/pg-r4k.c 2004-01-26 23:55:43.000000000 +0000@@ -67,7 +67,6 @@ static int pref_offset_copy __initdata static unsigned int pref_src_mode __initdata; static unsigned int pref_dst_mode __initdata; -static int has_scache __initdata = 0; static int load_offset __initdata = 0; static int store_offset __initdata = 0;
@@ -126,21 +125,25 @@ static inline void build_dst_pref(int ad } } -static inline void build_cdex(void) +static inline void build_cdex_s(void) { union mips_instruction mi; - if (cpu_has_cache_cdex_s && - !(store_offset & (cpu_scache_line_size() - 1))) { + 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; + 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; - *epc++ = mi.word; - } + *epc++ = mi.word; +} + +static inline void build_cdex_p(void) +{ + union mips_instruction mi; if (store_offset & (cpu_dcache_line_size() - 1)) return;
@@ -212,8 +215,10 @@ static inline void build_store_reg(int r build_dst_pref(pref_offset_copy); else build_dst_pref(pref_offset_clear); + else if (cpu_has_cache_cdex_s) + build_cdex_s(); else if (cpu_has_cache_cdex_p) - build_cdex(); + build_cdex_p(); __build_store_reg(reg); }
@@ -332,7 +337,7 @@ dest = epc; build_store_reg(0); build_store_reg(0); build_store_reg(0); - if (has_scache && cpu_scache_line_size() == 128) { + if (cpu_scache_line_size() == 128) { build_store_reg(0); build_store_reg(0); build_store_reg(0);
@@ -341,7 +346,7 @@ dest = epc; build_addiu_a0(2 * store_offset); build_store_reg(0); build_store_reg(0); - if (has_scache && cpu_scache_line_size() == 128) { + if (cpu_scache_line_size() == 128) { build_store_reg(0); build_store_reg(0); build_store_reg(0);
@@ -405,7 +410,7 @@ dest = epc; build_store_reg( 9); build_store_reg(10); build_store_reg(11); - if (has_scache && cpu_scache_line_size() == 128) { + if (cpu_scache_line_size() == 128) { build_load_reg( 8); build_load_reg( 9); build_load_reg(10);
@@ -424,7 +429,7 @@ dest = epc; build_store_reg( 8); build_store_reg( 9); build_store_reg(10); - if (has_scache && cpu_scache_line_size() == 128) { + if (cpu_scache_line_size() == 128) { build_store_reg(11); build_load_reg( 8); build_load_reg( 9);