aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorSam Ravnborg <sam@ravnborg.org>2012-05-25 17:20:09 -0400
committerDavid S. Miller <davem@davemloft.net>2012-05-28 02:52:43 -0400
commit5b8b93c4ab17a250a35e6db1cce094bf599a21c6 (patch)
tree9ce54b39fe8193d245a4511f23d02d4b037d0245 /arch
parent4efb55e6916628fde549b0ef1c2830593ccf19c4 (diff)
sparc32: add support for run-time patching of leon/sun single instructions
This will be used to handle that MMUREGS has different ASI for SUN and LEON. This is the infrastructure only - users will come later. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Cc: Daniel Hellstrom <daniel@gaisler.com> Cc: Konrad Eisele <konrad@gaisler.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc/include/asm/asmmacro.h22
-rw-r--r--arch/sparc/include/asm/sections.h3
-rw-r--r--arch/sparc/kernel/setup_32.c58
-rw-r--r--arch/sparc/kernel/vmlinux.lds.S5
4 files changed, 72 insertions, 16 deletions
diff --git a/arch/sparc/include/asm/asmmacro.h b/arch/sparc/include/asm/asmmacro.h
index 02a172fb193a..a0e28ef02558 100644
--- a/arch/sparc/include/asm/asmmacro.h
+++ b/arch/sparc/include/asm/asmmacro.h
@@ -20,4 +20,26 @@
20/* All traps low-level code here must end with this macro. */ 20/* All traps low-level code here must end with this macro. */
21#define RESTORE_ALL b ret_trap_entry; clr %l6; 21#define RESTORE_ALL b ret_trap_entry; clr %l6;
22 22
23/* Support for run-time patching of single instructions.
24 * This is used to handle the differences in the ASI for
25 * MMUREGS for LEON and SUN.
26 *
27 * Sample:
28 * LEON_PI(lda [%g0] ASI_LEON_MMUREGS, %o0
29 * SUN_PI_(lda [%g0] ASI_M_MMUREGS, %o0
30 * PI == Patch Instruction
31 *
32 * For LEON we will use the first variant,
33 * and for all other we will use the SUN variant.
34 * The order is important.
35 */
36#define LEON_PI(...) \
37662: __VA_ARGS__
38
39#define SUN_PI_(...) \
40 .section .leon_1insn_patch, "ax"; \
41 .word 662b; \
42 __VA_ARGS__; \
43 .previous
44
23#endif /* !(_SPARC_ASMMACRO_H) */ 45#endif /* !(_SPARC_ASMMACRO_H) */
diff --git a/arch/sparc/include/asm/sections.h b/arch/sparc/include/asm/sections.h
index 0b0553bbd8a0..f300d1a9b2b6 100644
--- a/arch/sparc/include/asm/sections.h
+++ b/arch/sparc/include/asm/sections.h
@@ -7,4 +7,7 @@
7/* sparc entry point */ 7/* sparc entry point */
8extern char _start[]; 8extern char _start[];
9 9
10extern char __leon_1insn_patch[];
11extern char __leon_1insn_patch_end[];
12
10#endif 13#endif
diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c
index 68dd63dea36f..efe3e64bba38 100644
--- a/arch/sparc/kernel/setup_32.c
+++ b/arch/sparc/kernel/setup_32.c
@@ -46,6 +46,7 @@
46#include <asm/cpudata.h> 46#include <asm/cpudata.h>
47#include <asm/setup.h> 47#include <asm/setup.h>
48#include <asm/cacheflush.h> 48#include <asm/cacheflush.h>
49#include <asm/sections.h>
49 50
50#include "kernel.h" 51#include "kernel.h"
51 52
@@ -238,11 +239,34 @@ static void __init per_cpu_patch(void)
238 } 239 }
239} 240}
240 241
242struct leon_1insn_patch_entry {
243 unsigned int addr;
244 unsigned int insn;
245};
246
241enum sparc_cpu sparc_cpu_model; 247enum sparc_cpu sparc_cpu_model;
242EXPORT_SYMBOL(sparc_cpu_model); 248EXPORT_SYMBOL(sparc_cpu_model);
243 249
244struct tt_entry *sparc_ttable; 250static __init void leon_patch(void)
251{
252 struct leon_1insn_patch_entry *start = (void *)__leon_1insn_patch;
253 struct leon_1insn_patch_entry *end = (void *)__leon_1insn_patch_end;
254
255 /* Default instruction is leon - no patching */
256 if (sparc_cpu_model == sparc_leon)
257 return;
258
259 while (start < end) {
260 unsigned long addr = start->addr;
261
262 *(unsigned int *)(addr) = start->insn;
263 flushi(addr);
264
265 start++;
266 }
267}
245 268
269struct tt_entry *sparc_ttable;
246struct pt_regs fake_swapper_regs; 270struct pt_regs fake_swapper_regs;
247 271
248/* Called from head_32.S - before we have setup anything 272/* Called from head_32.S - before we have setup anything
@@ -251,6 +275,23 @@ struct pt_regs fake_swapper_regs;
251void __init sparc32_start_kernel(struct linux_romvec *rp) 275void __init sparc32_start_kernel(struct linux_romvec *rp)
252{ 276{
253 prom_init(rp); 277 prom_init(rp);
278
279 /* Set sparc_cpu_model */
280 sparc_cpu_model = sun_unknown;
281 if (!strcmp(&cputypval[0], "sun4m"))
282 sparc_cpu_model = sun4m;
283 if (!strcmp(&cputypval[0], "sun4s"))
284 sparc_cpu_model = sun4m; /* CP-1200 with PROM 2.30 -E */
285 if (!strcmp(&cputypval[0], "sun4d"))
286 sparc_cpu_model = sun4d;
287 if (!strcmp(&cputypval[0], "sun4e"))
288 sparc_cpu_model = sun4e;
289 if (!strcmp(&cputypval[0], "sun4u"))
290 sparc_cpu_model = sun4u;
291 if (!strncmp(&cputypval[0], "leon" , 4))
292 sparc_cpu_model = sparc_leon;
293
294 leon_patch();
254 start_kernel(); 295 start_kernel();
255} 296}
256 297
@@ -270,21 +311,6 @@ void __init setup_arch(char **cmdline_p)
270 311
271 register_console(&prom_early_console); 312 register_console(&prom_early_console);
272 313
273 /* Set sparc_cpu_model */
274 sparc_cpu_model = sun_unknown;
275 if (!strcmp(&cputypval[0], "sun4m"))
276 sparc_cpu_model = sun4m;
277 if (!strcmp(&cputypval[0], "sun4s"))
278 sparc_cpu_model = sun4m; /* CP-1200 with PROM 2.30 -E */
279 if (!strcmp(&cputypval[0], "sun4d"))
280 sparc_cpu_model = sun4d;
281 if (!strcmp(&cputypval[0], "sun4e"))
282 sparc_cpu_model = sun4e;
283 if (!strcmp(&cputypval[0], "sun4u"))
284 sparc_cpu_model = sun4u;
285 if (!strncmp(&cputypval[0], "leon" , 4))
286 sparc_cpu_model = sparc_leon;
287
288 printk("ARCH: "); 314 printk("ARCH: ");
289 switch(sparc_cpu_model) { 315 switch(sparc_cpu_model) {
290 case sun4m: 316 case sun4m:
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 0e1605697b49..89c2c29f154b 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -107,6 +107,11 @@ SECTIONS
107 *(.sun4v_2insn_patch) 107 *(.sun4v_2insn_patch)
108 __sun4v_2insn_patch_end = .; 108 __sun4v_2insn_patch_end = .;
109 } 109 }
110 .leon_1insn_patch : {
111 __leon_1insn_patch = .;
112 *(.leon_1insn_patch)
113 __leon_1insn_patch_end = .;
114 }
110 .swapper_tsb_phys_patch : { 115 .swapper_tsb_phys_patch : {
111 __swapper_tsb_phys_patch = .; 116 __swapper_tsb_phys_patch = .;
112 *(.swapper_tsb_phys_patch) 117 *(.swapper_tsb_phys_patch)