Message ID | 20120520211839.GA4563@merkur.ravnborg.org |
---|---|
State | RFC |
Delegated to: | David Miller |
Headers | show |
From: Sam Ravnborg <sam@ravnborg.org> Date: Sun, 20 May 2012 23:18:39 +0200 > Updated RFC patch below. Looks good. Two small things. First, you might want to make the LEON case the default, because then it'll get tested more extensively. Second, have you audited to make sure that none of this code runs before the patchup code does? -- To unsubscribe from this list: send the line "unsubscribe sparclinux" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Sun, May 20, 2012 at 05:24:01PM -0400, David Miller wrote: > From: Sam Ravnborg <sam@ravnborg.org> > Date: Sun, 20 May 2012 23:18:39 +0200 > > > Updated RFC patch below. > > Looks good. > > Two small things. > > First, you might want to make the LEON case the default, > because then it'll get tested more extensively. Good point - will do. > Second, have you audited to make sure that none of this > code runs before the patchup code does? Yes - but a lot of other places that require patching will run long time before (wof.S, wuf.S etc). At least I assume so. My plan is to introduce a sparc_start_kernel() function in setup_32.c which is called from head_32.S. There I will do the initial stuff like patching and prom_init. And then call the real start_kernel(). The final patchset will establish this before introducing any users so I do not change when I patch in the middle of the patch-set. The current patch was to make sure I was on the right track, hence the RFC. Sam -- To unsubscribe from this list: send the line "unsubscribe sparclinux" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Sam Ravnborg <sam@ravnborg.org> Date: Sun, 20 May 2012 23:34:52 +0200 > On Sun, May 20, 2012 at 05:24:01PM -0400, David Miller wrote: >> Second, have you audited to make sure that none of this >> code runs before the patchup code does? > Yes - but a lot of other places that require patching will run > long time before (wof.S, wuf.S etc). At least I assume so. The wof.S and wuf.S cases would only execute after we've started userland, as that code is used to validate the user stack in the register window store area. Therefore it won't run unless PSR_PS is clear in %psr or there are user register windows in the cpu. Neither of which will be true during early boot. You should therefore be fine except for the bits in head_32.S which you'll need to use tests and branches for anyways. -- To unsubscribe from this list: send the line "unsubscribe sparclinux" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Sun, May 20, 2012 at 05:40:50PM -0400, David Miller wrote: > From: Sam Ravnborg <sam@ravnborg.org> > Date: Sun, 20 May 2012 23:34:52 +0200 > > > On Sun, May 20, 2012 at 05:24:01PM -0400, David Miller wrote: > >> Second, have you audited to make sure that none of this > >> code runs before the patchup code does? > > Yes - but a lot of other places that require patching will run > > long time before (wof.S, wuf.S etc). At least I assume so. > > The wof.S and wuf.S cases would only execute after we've started > userland, as that code is used to validate the user stack in the > register window store area. > > Therefore it won't run unless PSR_PS is clear in %psr or there > are user register windows in the cpu. > > Neither of which will be true during early boot. Thanks for the explanation, but wof.S and wuf.S was bad examples.. > > You should therefore be fine except for the bits in head_32.S > which you'll need to use tests and branches for anyways. We have ~27 places where we reference MMUREGS in kernel/* on top of head_32.S. Rather than trying to convince myself that they are not called in between start_kernel() and setup_arch() I prefer to patch is all up before calling start_kernel(). This also matches what we do on sparc64 for sun4v. Anyway - as the merge window is now opened I will put this on hold until -rc2 or so unless you say otherwise. Sam -- To unsubscribe from this list: send the line "unsubscribe sparclinux" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Sam Ravnborg <sam@ravnborg.org> Date: Mon, 21 May 2012 07:51:55 +0200 > Anyway - as the merge window is now opened I will put this on hold > until -rc2 or so unless you say otherwise. I encourage you to keep working on it, getting rid of the LEON config option would be a major improvement in maintainability. -- To unsubscribe from this list: send the line "unsubscribe sparclinux" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/arch/sparc/include/asm/asmmacro.h b/arch/sparc/include/asm/asmmacro.h index 02a172f..010eaed 100644 --- a/arch/sparc/include/asm/asmmacro.h +++ b/arch/sparc/include/asm/asmmacro.h @@ -20,4 +20,13 @@ /* All traps low-level code here must end with this macro. */ #define RESTORE_ALL b ret_trap_entry; clr %l6; +#define SUN_INS(...) \ +662: __VA_ARGS__ + +#define LEON_IN(...) \ + .section leon_1insn_patch, "ax"; \ + .word 662b; \ + __VA_ARGS__; \ + .previous + #endif /* !(_SPARC_ASMMACRO_H) */ diff --git a/arch/sparc/include/asm/pgtsrmmu.h b/arch/sparc/include/asm/pgtsrmmu.h index cb82870..5d3413a 100644 --- a/arch/sparc/include/asm/pgtsrmmu.h +++ b/arch/sparc/include/asm/pgtsrmmu.h @@ -148,67 +148,13 @@ extern void *srmmu_nocache_pool; #define __nocache_fix(VADDR) __va(__nocache_pa(VADDR)) /* Accessing the MMU control register. */ -static inline unsigned int srmmu_get_mmureg(void) -{ - unsigned int retval; - __asm__ __volatile__("lda [%%g0] %1, %0\n\t" : - "=r" (retval) : - "i" (ASI_M_MMUREGS)); - return retval; -} - -static inline void srmmu_set_mmureg(unsigned long regval) -{ - __asm__ __volatile__("sta %0, [%%g0] %1\n\t" : : - "r" (regval), "i" (ASI_M_MMUREGS) : "memory"); - -} - -static inline void srmmu_set_ctable_ptr(unsigned long paddr) -{ - paddr = ((paddr >> 4) & SRMMU_CTX_PMASK); - __asm__ __volatile__("sta %0, [%1] %2\n\t" : : - "r" (paddr), "r" (SRMMU_CTXTBL_PTR), - "i" (ASI_M_MMUREGS) : - "memory"); -} - -static inline void srmmu_set_context(int context) -{ - __asm__ __volatile__("sta %0, [%1] %2\n\t" : : - "r" (context), "r" (SRMMU_CTX_REG), - "i" (ASI_M_MMUREGS) : "memory"); -} - -static inline int srmmu_get_context(void) -{ - register int retval; - __asm__ __volatile__("lda [%1] %2, %0\n\t" : - "=r" (retval) : - "r" (SRMMU_CTX_REG), - "i" (ASI_M_MMUREGS)); - return retval; -} - -static inline unsigned int srmmu_get_fstatus(void) -{ - unsigned int retval; - - __asm__ __volatile__("lda [%1] %2, %0\n\t" : - "=r" (retval) : - "r" (SRMMU_FAULT_STATUS), "i" (ASI_M_MMUREGS)); - return retval; -} - -static inline unsigned int srmmu_get_faddr(void) -{ - unsigned int retval; - - __asm__ __volatile__("lda [%1] %2, %0\n\t" : - "=r" (retval) : - "r" (SRMMU_FAULT_ADDR), "i" (ASI_M_MMUREGS)); - return retval; -} +unsigned int srmmu_get_mmureg(void); +void srmmu_set_mmureg(unsigned long regval); +void srmmu_set_ctable_ptr(unsigned long paddr); +void srmmu_set_context(int context); +int srmmu_get_context(void); +unsigned int srmmu_get_fstatus(void); +unsigned int srmmu_get_faddr(void); /* This is guaranteed on all SRMMU's. */ static inline void srmmu_flush_whole_tlb(void) diff --git a/arch/sparc/include/asm/sections.h b/arch/sparc/include/asm/sections.h index 0b0553b..f300d1a 100644 --- a/arch/sparc/include/asm/sections.h +++ b/arch/sparc/include/asm/sections.h @@ -7,4 +7,7 @@ /* sparc entry point */ extern char _start[]; +extern char __leon_1insn_patch[]; +extern char __leon_1insn_patch_end[]; + #endif diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c index c052313..7c239e5 100644 --- a/arch/sparc/kernel/setup_32.c +++ b/arch/sparc/kernel/setup_32.c @@ -45,6 +45,7 @@ #include <asm/cpudata.h> #include <asm/setup.h> #include <asm/cacheflush.h> +#include <asm/sections.h> #include "kernel.h" @@ -237,6 +238,29 @@ static void __init per_cpu_patch(void) } } +struct leon_1insn_patch_entry { + unsigned int addr; + unsigned int insn; +}; + +static 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; + + if (sparc_cpu_model != sparc_leon) + return; + + while (start < end) { + unsigned long addr = start->addr; + + *(unsigned int *) (addr + 0) = start->insn; + flushi(addr); + + start++; + } +} + enum sparc_cpu sparc_cpu_model; EXPORT_SYMBOL(sparc_cpu_model); @@ -340,6 +364,7 @@ void __init setup_arch(char **cmdline_p) /* Run-time patch instructions to match the cpu model */ per_cpu_patch(); + leon_patch(); paging_init(); diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index 0e16056..89c2c29 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S @@ -107,6 +107,11 @@ SECTIONS *(.sun4v_2insn_patch) __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) diff --git a/arch/sparc/mm/Makefile b/arch/sparc/mm/Makefile index 69ffd31..a214829 100644 --- a/arch/sparc/mm/Makefile +++ b/arch/sparc/mm/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o gup.o obj-y += fault_$(BITS).o obj-y += init_$(BITS).o obj-$(CONFIG_SPARC32) += extable.o srmmu.o iommu.o io-unit.o +obj-$(CONFIG_SPARC32) += srmmu_access.o obj-$(CONFIG_SPARC32) += hypersparc.o viking.o tsunami.o swift.o obj-$(CONFIG_SPARC_LEON)+= leon_mm.o diff --git a/arch/sparc/mm/srmmu_access.S b/arch/sparc/mm/srmmu_access.S new file mode 100644 index 0000000..d91e5c1 --- /dev/null +++ b/arch/sparc/mm/srmmu_access.S @@ -0,0 +1,82 @@ +/* Assembler variants of srmmu access functions. + * Implemented in assembler to allow run-time patching. + * LEON uses a different ASI for MMUREGS than SUN. + * + * The leon_1insn_patch infrastructure is used + * for the run-time patching. + */ + +#include <linux/linkage.h> + +#include <asm/asmmacro.h> +#include <asm/pgtsrmmu.h> +#include <asm/asi.h> + +/* unsigned int srmmu_get_mmureg(void) */ +ENTRY(srmmu_get_mmureg) +SUN_INS(lda [%g0] ASI_M_MMUREGS, %o0) +LEON_IN(lda [%g0] ASI_LEON_MMUREGS, %o0) + retl + nop +ENDPROC(srmmu_get_mmureg) + +/* void srmmu_set_mmureg(unsigned long regval) */ +ENTRY(srmmu_set_mmureg) +SUN_INS(sta %o0, [%g0] ASI_M_MMUREGS) +LEON_IN(sta %o0, [%g0] ASI_LEON_MMUREGS) + retl + nop +ENDPROC(srmmu_set_mmureg) + +/* void srmmu_set_ctable_ptr(unsigned long paddr) */ +ENTRY(srmmu_set_ctable_ptr) + /* paddr = ((paddr >> 4) & SRMMU_CTX_PMASK); */ + srl %o0, 4, %g1 + and %g1, SRMMU_CTX_PMASK, %g1 + + mov SRMMU_CTXTBL_PTR, %g2 +SUN_INS(sta %g1, [%g2] ASI_M_MMUREGS) +LEON_IN(sta %g1, [%g2] ASI_LEON_MMUREGS) + retl + nop +ENDPROC(srmmu_set_ctable_ptr) + + +/* void srmmu_set_context(int context) */ +ENTRY(srmmu_set_context) + mov SRMMU_CTX_REG, %g1 +SUN_INS(sta %o0, [%g1] ASI_M_MMUREGS) +LEON_IN(sta %o0, [%g1] ASI_LEON_MMUREGS) + retl + nop +ENDPROC(srmmu_set_context) + + +/* int srmmu_get_context(void) */ +ENTRY(srmmu_get_context) + mov SRMMU_CTX_REG, %o0 +SUN_INS(lda [%o0] ASI_M_MMUREGS, %o0) +LEON_IN(lda [%o0] ASI_LEON_MMUREGS, %o0) + retl + nop +ENDPROC(srmmu_get_context) + + +/* unsigned int srmmu_get_fstatus(void) */ +ENTRY(srmmu_get_fstatus) + mov SRMMU_FAULT_STATUS, %o0 +SUN_INS(lda [%o0] ASI_M_MMUREGS, %o0) +LEON_IN(lda [%o0] ASI_LEON_MMUREGS, %o0) + retl + nop +ENDPROC(srmmu_get_fstatus) + + +/* unsigned int srmmu_get_faddr(void) */ +ENTRY(srmmu_get_faddr) + mov SRMMU_FAULT_ADDR, %o0 +SUN_INS(lda [%o0] ASI_M_MMUREGS, %o0) +LEON_IN(lda [%o0] ASI_LEON_MMUREGS, %o0) + retl + nop +ENDPROC(srmmu_get_faddr)