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>
This commit is contained in:
parent
4efb55e691
commit
5b8b93c4ab
@ -20,4 +20,26 @@
|
|||||||
/* All traps low-level code here must end with this macro. */
|
/* All traps low-level code here must end with this macro. */
|
||||||
#define RESTORE_ALL b ret_trap_entry; clr %l6;
|
#define RESTORE_ALL b ret_trap_entry; clr %l6;
|
||||||
|
|
||||||
|
/* Support for run-time patching of single instructions.
|
||||||
|
* This is used to handle the differences in the ASI for
|
||||||
|
* MMUREGS for LEON and SUN.
|
||||||
|
*
|
||||||
|
* Sample:
|
||||||
|
* LEON_PI(lda [%g0] ASI_LEON_MMUREGS, %o0
|
||||||
|
* SUN_PI_(lda [%g0] ASI_M_MMUREGS, %o0
|
||||||
|
* PI == Patch Instruction
|
||||||
|
*
|
||||||
|
* For LEON we will use the first variant,
|
||||||
|
* and for all other we will use the SUN variant.
|
||||||
|
* The order is important.
|
||||||
|
*/
|
||||||
|
#define LEON_PI(...) \
|
||||||
|
662: __VA_ARGS__
|
||||||
|
|
||||||
|
#define SUN_PI_(...) \
|
||||||
|
.section .leon_1insn_patch, "ax"; \
|
||||||
|
.word 662b; \
|
||||||
|
__VA_ARGS__; \
|
||||||
|
.previous
|
||||||
|
|
||||||
#endif /* !(_SPARC_ASMMACRO_H) */
|
#endif /* !(_SPARC_ASMMACRO_H) */
|
||||||
|
@ -7,4 +7,7 @@
|
|||||||
/* sparc entry point */
|
/* sparc entry point */
|
||||||
extern char _start[];
|
extern char _start[];
|
||||||
|
|
||||||
|
extern char __leon_1insn_patch[];
|
||||||
|
extern char __leon_1insn_patch_end[];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include <asm/cpudata.h>
|
#include <asm/cpudata.h>
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
|
#include <asm/sections.h>
|
||||||
|
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
|
|
||||||
@ -238,11 +239,34 @@ static void __init per_cpu_patch(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct leon_1insn_patch_entry {
|
||||||
|
unsigned int addr;
|
||||||
|
unsigned int insn;
|
||||||
|
};
|
||||||
|
|
||||||
enum sparc_cpu sparc_cpu_model;
|
enum sparc_cpu sparc_cpu_model;
|
||||||
EXPORT_SYMBOL(sparc_cpu_model);
|
EXPORT_SYMBOL(sparc_cpu_model);
|
||||||
|
|
||||||
struct tt_entry *sparc_ttable;
|
static __init void leon_patch(void)
|
||||||
|
{
|
||||||
|
struct leon_1insn_patch_entry *start = (void *)__leon_1insn_patch;
|
||||||
|
struct leon_1insn_patch_entry *end = (void *)__leon_1insn_patch_end;
|
||||||
|
|
||||||
|
/* Default instruction is leon - no patching */
|
||||||
|
if (sparc_cpu_model == sparc_leon)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (start < end) {
|
||||||
|
unsigned long addr = start->addr;
|
||||||
|
|
||||||
|
*(unsigned int *)(addr) = start->insn;
|
||||||
|
flushi(addr);
|
||||||
|
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tt_entry *sparc_ttable;
|
||||||
struct pt_regs fake_swapper_regs;
|
struct pt_regs fake_swapper_regs;
|
||||||
|
|
||||||
/* Called from head_32.S - before we have setup anything
|
/* Called from head_32.S - before we have setup anything
|
||||||
@ -251,6 +275,23 @@ struct pt_regs fake_swapper_regs;
|
|||||||
void __init sparc32_start_kernel(struct linux_romvec *rp)
|
void __init sparc32_start_kernel(struct linux_romvec *rp)
|
||||||
{
|
{
|
||||||
prom_init(rp);
|
prom_init(rp);
|
||||||
|
|
||||||
|
/* Set sparc_cpu_model */
|
||||||
|
sparc_cpu_model = sun_unknown;
|
||||||
|
if (!strcmp(&cputypval[0], "sun4m"))
|
||||||
|
sparc_cpu_model = sun4m;
|
||||||
|
if (!strcmp(&cputypval[0], "sun4s"))
|
||||||
|
sparc_cpu_model = sun4m; /* CP-1200 with PROM 2.30 -E */
|
||||||
|
if (!strcmp(&cputypval[0], "sun4d"))
|
||||||
|
sparc_cpu_model = sun4d;
|
||||||
|
if (!strcmp(&cputypval[0], "sun4e"))
|
||||||
|
sparc_cpu_model = sun4e;
|
||||||
|
if (!strcmp(&cputypval[0], "sun4u"))
|
||||||
|
sparc_cpu_model = sun4u;
|
||||||
|
if (!strncmp(&cputypval[0], "leon" , 4))
|
||||||
|
sparc_cpu_model = sparc_leon;
|
||||||
|
|
||||||
|
leon_patch();
|
||||||
start_kernel();
|
start_kernel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,21 +311,6 @@ void __init setup_arch(char **cmdline_p)
|
|||||||
|
|
||||||
register_console(&prom_early_console);
|
register_console(&prom_early_console);
|
||||||
|
|
||||||
/* Set sparc_cpu_model */
|
|
||||||
sparc_cpu_model = sun_unknown;
|
|
||||||
if (!strcmp(&cputypval[0], "sun4m"))
|
|
||||||
sparc_cpu_model = sun4m;
|
|
||||||
if (!strcmp(&cputypval[0], "sun4s"))
|
|
||||||
sparc_cpu_model = sun4m; /* CP-1200 with PROM 2.30 -E */
|
|
||||||
if (!strcmp(&cputypval[0], "sun4d"))
|
|
||||||
sparc_cpu_model = sun4d;
|
|
||||||
if (!strcmp(&cputypval[0], "sun4e"))
|
|
||||||
sparc_cpu_model = sun4e;
|
|
||||||
if (!strcmp(&cputypval[0], "sun4u"))
|
|
||||||
sparc_cpu_model = sun4u;
|
|
||||||
if (!strncmp(&cputypval[0], "leon" , 4))
|
|
||||||
sparc_cpu_model = sparc_leon;
|
|
||||||
|
|
||||||
printk("ARCH: ");
|
printk("ARCH: ");
|
||||||
switch(sparc_cpu_model) {
|
switch(sparc_cpu_model) {
|
||||||
case sun4m:
|
case sun4m:
|
||||||
|
@ -107,6 +107,11 @@ SECTIONS
|
|||||||
*(.sun4v_2insn_patch)
|
*(.sun4v_2insn_patch)
|
||||||
__sun4v_2insn_patch_end = .;
|
__sun4v_2insn_patch_end = .;
|
||||||
}
|
}
|
||||||
|
.leon_1insn_patch : {
|
||||||
|
__leon_1insn_patch = .;
|
||||||
|
*(.leon_1insn_patch)
|
||||||
|
__leon_1insn_patch_end = .;
|
||||||
|
}
|
||||||
.swapper_tsb_phys_patch : {
|
.swapper_tsb_phys_patch : {
|
||||||
__swapper_tsb_phys_patch = .;
|
__swapper_tsb_phys_patch = .;
|
||||||
*(.swapper_tsb_phys_patch)
|
*(.swapper_tsb_phys_patch)
|
||||||
|
Loading…
Reference in New Issue
Block a user