Module Name: src Committed By: matt Date: Thu Feb 9 20:01:21 UTC 2012
Modified Files: src/sys/arch/mips/include [matt-nb5-mips64]: locore.h src/sys/arch/mips/mips [matt-nb5-mips64]: locore.S locore_mips1.S mipsX_subr.S mips_fixup.c Log Message: Update mips_fixup.c to version from -HEAD. Move cpu_switchto to locore jumpvec and create a stub for it. To generate a diff of this commit: cvs rdiff -u -r1.78.36.1.2.31 -r1.78.36.1.2.32 \ src/sys/arch/mips/include/locore.h cvs rdiff -u -r1.167.38.24 -r1.167.38.25 src/sys/arch/mips/mips/locore.S cvs rdiff -u -r1.64.26.1.2.14 -r1.64.26.1.2.15 \ src/sys/arch/mips/mips/locore_mips1.S cvs rdiff -u -r1.26.36.1.2.54 -r1.26.36.1.2.55 \ src/sys/arch/mips/mips/mipsX_subr.S cvs rdiff -u -r1.1.2.12 -r1.1.2.13 src/sys/arch/mips/mips/mips_fixup.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/mips/include/locore.h diff -u src/sys/arch/mips/include/locore.h:1.78.36.1.2.31 src/sys/arch/mips/include/locore.h:1.78.36.1.2.32 --- src/sys/arch/mips/include/locore.h:1.78.36.1.2.31 Fri Dec 23 08:09:08 2011 +++ src/sys/arch/mips/include/locore.h Thu Feb 9 20:01:21 2012 @@ -111,6 +111,8 @@ struct mips_jump_fixup_info { void fixup_splcalls(void); /* splstubs.c */ bool mips_fixup_exceptions(mips_fixup_callback_t); bool mips_fixup_zero_relative(int32_t, uint32_t [2]); +intptr_t + mips_fixup_addr(const uint32_t *); void mips_fixup_stubs(uint32_t *, uint32_t *); /* @@ -348,6 +350,7 @@ typedef struct { void (*ljv_tlb_enter)(size_t, vaddr_t, uint32_t); void (*ljv_tlb_read_indexed)(size_t, struct tlbmask *); void (*ljv_tlb_write_indexed)(size_t, const struct tlbmask *); + lwp_t * (*ljv_cpu_switchto)(lwp_t *, lwp_t *, bool); } mips_locore_jumpvec_t; typedef struct { Index: src/sys/arch/mips/mips/locore.S diff -u src/sys/arch/mips/mips/locore.S:1.167.38.24 src/sys/arch/mips/mips/locore.S:1.167.38.25 --- src/sys/arch/mips/mips/locore.S:1.167.38.24 Thu Jan 19 08:28:49 2012 +++ src/sys/arch/mips/mips/locore.S Thu Feb 9 20:01:21 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: locore.S,v 1.167.38.24 2012/01/19 08:28:49 matt Exp $ */ +/* locore.S,v 1.167.38.24 2012/01/19 08:28:49 matt Exp */ /* * Copyright (c) 1992, 1993 @@ -172,17 +172,18 @@ _C_LABEL(kernel_text): _C_LABEL(verylocore): /* - * struct lwp *cpu_switchto(struct lwp *cur, struct lwp *next) + * lwp_t *mips_cpu_switchto(lwp_t *cur, lwp_t *next, bool returning) * Switch to the specified next LWP * Arguments: * a0 the current LWP * a1 the LWP to switch to + * a2 returning to a softint LWP * Returns: * v0 the LWP we have switched from * * called at IPL_SCHED */ -NESTED(cpu_switchto, CALLFRAME_SIZ, ra) +NESTED(mips_cpu_switchto, CALLFRAME_SIZ, ra) #ifdef PARANOIA /* * Make sure we are at IPL_SCHED @@ -299,7 +300,7 @@ NESTED(cpu_switchto, CALLFRAME_SIZ, ra) #else JR_HB_RA #endif /* PARANOIA */ -END(cpu_switchto) +END(mips_cpu_switchto) #ifdef __HAVE_FAST_SOFTINTS /* Index: src/sys/arch/mips/mips/locore_mips1.S diff -u src/sys/arch/mips/mips/locore_mips1.S:1.64.26.1.2.14 src/sys/arch/mips/mips/locore_mips1.S:1.64.26.1.2.15 --- src/sys/arch/mips/mips/locore_mips1.S:1.64.26.1.2.14 Fri Dec 23 23:12:34 2011 +++ src/sys/arch/mips/mips/locore_mips1.S Thu Feb 9 20:01:21 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: locore_mips1.S,v 1.64.26.1.2.14 2011/12/23 23:12:34 matt Exp $ */ +/* locore_mips1.S,v 1.64.26.1.2.14 2011/12/23 23:12:34 matt Exp */ /* * Copyright (c) 1992, 1993 @@ -1735,6 +1735,7 @@ _C_LABEL(MIPSX(locore_vec)): PTR_WORD _C_LABEL(MIPSX(tlb_enter)) PTR_WORD _C_LABEL(MIPSX(tlb_read_indexed)) PTR_WORD _C_LABEL(MIPSX(tlb_write_indexed)) + PTR_WORD _C_LABEL(mips_cpu_switchto) .globl _C_LABEL(MIPSX(locoresw)) _C_LABEL(MIPSX(locoresw)): Index: src/sys/arch/mips/mips/mipsX_subr.S diff -u src/sys/arch/mips/mips/mipsX_subr.S:1.26.36.1.2.54 src/sys/arch/mips/mips/mipsX_subr.S:1.26.36.1.2.55 --- src/sys/arch/mips/mips/mipsX_subr.S:1.26.36.1.2.54 Thu Jan 19 08:28:49 2012 +++ src/sys/arch/mips/mips/mipsX_subr.S Thu Feb 9 20:01:21 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: mipsX_subr.S,v 1.26.36.1.2.54 2012/01/19 08:28:49 matt Exp $ */ +/* $NetBSD: mipsX_subr.S,v 1.26.36.1.2.55 2012/02/09 20:01:21 matt Exp $ */ /* * Copyright 2002 Wasabi Systems, Inc. @@ -2912,6 +2912,7 @@ _C_LABEL(MIPSX(locore_vec)): PTR_WORD _C_LABEL(MIPSX(tlb_enter)) PTR_WORD _C_LABEL(MIPSX(tlb_read_indexed)) PTR_WORD _C_LABEL(MIPSX(tlb_write_indexed)) + PTR_WORD _C_LABEL(mips_cpu_switchto) .globl _C_LABEL(MIPSX(locoresw)) _C_LABEL(MIPSX(locoresw)): Index: src/sys/arch/mips/mips/mips_fixup.c diff -u src/sys/arch/mips/mips/mips_fixup.c:1.1.2.12 src/sys/arch/mips/mips/mips_fixup.c:1.1.2.13 --- src/sys/arch/mips/mips/mips_fixup.c:1.1.2.12 Fri Nov 4 07:47:40 2011 +++ src/sys/arch/mips/mips/mips_fixup.c Thu Feb 9 20:01:21 2012 @@ -1,3 +1,5 @@ +/* $NetBSD: mips_fixup.c,v 1.1.2.13 2012/02/09 20:01:21 matt Exp $ */ + /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. * All rights reserved. @@ -28,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "mips_fixup.c,v 1.1.2.10 2011/04/29 08:26:28 matt Exp"); +__KERNEL_RCSID(0, "$NetBSD: mips_fixup.c,v 1.1.2.13 2012/02/09 20:01:21 matt Exp $"); #include "opt_mips3_wired.h" #include "opt_multiprocessor.h" @@ -40,12 +42,13 @@ __KERNEL_RCSID(0, "mips_fixup.c,v 1.1.2. #include <mips/cache.h> #include <mips/mips3_pte.h> #include <mips/regnum.h> +#include <mips/mips_opcode.h> -#define INSN_LUI_P(insn) (((insn) >> 26) == 017) -#define INSN_LW_P(insn) (((insn) >> 26) == 043) -#define INSN_SW_P(insn) (((insn) >> 26) == 053) -#define INSN_LD_P(insn) (((insn) >> 26) == 067) -#define INSN_SD_P(insn) (((insn) >> 26) == 077) +#define INSN_LUI_P(insn) (((insn) >> 26) == OP_LUI) +#define INSN_LW_P(insn) (((insn) >> 26) == OP_LW) +#define INSN_SW_P(insn) (((insn) >> 26) == OP_SW) +#define INSN_LD_P(insn) (((insn) >> 26) == OP_LD) +#define INSN_SD_P(insn) (((insn) >> 26) == OP_SD) #define INSN_LOAD_P(insn) (INSN_LD_P(insn) || INSN_LW_P(insn)) #define INSN_STORE_P(insn) (INSN_SD_P(insn) || INSN_SW_P(insn)) @@ -136,7 +139,7 @@ mips_fixup_exceptions(mips_fixup_callbac if (fixed) mips_icache_sync_range((vaddr_t)start, - sizeof(start[0]) * (end - start)); + sizeof(start[0]) * (end - start)); return fixed; } @@ -226,13 +229,151 @@ fixup_mips_jump(uint32_t *insnp, const s *insnp = insn; } +intptr_t +mips_fixup_addr(const uint32_t *stubp) +{ + /* + * Stubs typically look like: + * lui v0, %hi(sym) + * lX t9, %lo(sym)(v0) + * [nop] + * jr t9 + * nop + * + * Or for loongson2 ( + * lui v0, %hi(sym) + * lX t9, %lo(sym)(v0) + * lui at,0xcfff + * ori at,at,0xffff + * and t9,t9,at + * jr t9 + * move at,at + * or: + * lui v0, %hi(sym) + * lX t9, %lo(sym)(v0) + * li at, 0x3 + * dmtc0 at, $22 + * jr t9 + * nop + */ + mips_reg_t regs[32]; + uint32_t used = 1; + size_t n; + const char *errstr = "mips"; + /* + * This is basically a small MIPS emulator for those instructions + * that might in a stub routine. + */ + for (n = 0; n < 16; n++) { + const InstFmt insn = { .word = stubp[n] }; + switch (insn.IType.op) { + case OP_LUI: + regs[insn.IType.rt] = (int16_t)insn.IType.imm << 16; + used |= (1 << insn.IType.rt); + break; +#ifdef _LP64 + case OP_LD: + if ((used & (1 << insn.IType.rs)) == 0) { + errstr = "LD"; + goto out; + } + regs[insn.IType.rt] = *(const int64_t *) + (regs[insn.IType.rs] + (int16_t)insn.IType.imm); + used |= (1 << insn.IType.rt); + break; +#else + case OP_LW: + if ((used & (1 << insn.IType.rs)) == 0) { + errstr = "LW"; + goto out; + } + regs[insn.IType.rt] = *(const int32_t *) + ((intptr_t)regs[insn.IType.rs] + + (int16_t)insn.IType.imm); + used |= (1 << insn.IType.rt); + break; +#endif + case OP_ORI: + if ((used & (1 << insn.IType.rs)) == 0) { + errstr = "ORI"; + goto out; + } + regs[insn.IType.rt] |= insn.IType.imm; + used |= (1 << insn.IType.rt); + break; + case OP_COP0: + switch (insn.RType.rs) { + case OP_DMT: + if (insn.RType.rd != 22) { + errstr = "dmtc0 dst"; + goto out; + } + if ((used & (1 << insn.RType.rt)) == 0) { + errstr = "dmtc0 src"; + goto out; + } + break; + default: + errstr = "COP0"; + goto out; + } + break; + case OP_SPECIAL: + switch (insn.RType.func) { + case OP_JR: + if ((used & (1 << insn.RType.rs)) == 0) { + errstr = "JR"; + goto out; + } + if (stubp[n+1] != 0 + && stubp[n+1] != 0x30c600ff /* and a2,a2,0xff */ + && stubp[n+1] != 0x00200825) { + n++; + errstr = "delay slot"; + goto out; + } + return regs[insn.RType.rs]; + case OP_AND: + if ((used & (1 << insn.RType.rs)) == 0 + || (used & (1 << insn.RType.rt)) == 0) { + errstr = "AND"; + goto out; + } + regs[insn.RType.rd] = + regs[insn.RType.rs] & regs[insn.RType.rt]; + used |= (1 << insn.RType.rd); + break; + case OP_SLL: /* nop */ + if (insn.RType.rd != _R_ZERO) { + errstr = "NOP"; + goto out; + } + break; + default: + errstr = "SPECIAL"; + goto out; + } + break; + default: + errstr = "mips"; + goto out; + } + } + + out: + printf("%s: unexpected %s insn %#x at %p\n", + __func__, errstr, + stubp[n], &stubp[n]); + return 0; +} + void mips_fixup_stubs(uint32_t *start, uint32_t *end) { #ifdef DEBUG size_t fixups_done = 0; uint32_t cycles = -#if (MIPS3 + MIPS4 + MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2 + MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 +#if (MIPS3 + MIPS4 + MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 (CPUISMIPS3 ? mips3_cp0_count_read() : 0); #else 0; @@ -262,43 +403,8 @@ mips_fixup_stubs(uint32_t *start, uint32 || stubp < __stub_start || __stub_end <= stubp) continue; - /* - * Stubs typically look like: - * lui v0, %hi(sym) - * lX t9, %lo(sym)(v0) - * [nop] - * jr t9 - * nop - */ - const uint32_t lui_insn = stubp[0]; - const uint32_t load_insn = stubp[1]; -#ifdef DIAGNOSTIC - if (stubp[2] == 0) { - KASSERT(stubp[3] == 0x03200008); /* jr t9 */ - KASSERT(stubp[4] == 0); /* nop */ - } else { - KASSERT(stubp[2] == 0x03200008); /* jr t9 */ - KASSERT(stubp[3] == 0); /* nop */ - } + const intptr_t real_addr = mips_fixup_addr(stubp); - KASSERT(INSN_LUI_P(lui_insn)); -#ifdef _LP64 - KASSERT(INSN_LD_P(load_insn)); -#else - KASSERT(INSN_LW_P(load_insn)); -#endif - const u_int lui_reg = (lui_insn >> 16) & 31; - const u_int load_reg = (load_insn >> 16) & 31; -#endif - KASSERT(((load_insn >> 21) & 31) == lui_reg); - KASSERT(load_reg == _R_T9); - - intptr_t load_addr = ((int16_t)lui_insn << 16) + (int16_t) load_insn; -#ifdef _LP64 - const intptr_t real_addr = *(int64_t *)load_addr; -#else - const intptr_t real_addr = *(int32_t *)load_addr; -#endif /* * If the real_addr has been set yet, don't fix up. */ @@ -333,7 +439,7 @@ mips_fixup_stubs(uint32_t *start, uint32 sizeof(uint32_t [end - start])); #ifdef DEBUG -#if (MIPS3 + MIPS4 + MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2 + MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 +#if (MIPS3 + MIPS4 + MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 if (CPUISMIPS3) cycles = mips3_cp0_count_read() - cycles; #endif @@ -346,6 +452,7 @@ mips_fixup_stubs(uint32_t *start, uint32 #define __stub __section(".stub") void mips_cpu_switch_resume(struct lwp *) __stub; +lwp_t * cpu_switchto(lwp_t *, lwp_t *, bool) __stub; void tlb_set_asid(uint32_t) __stub; void tlb_invalidate_all(void) __stub; void tlb_invalidate_globals(void) __stub; @@ -369,6 +476,12 @@ mips_cpu_switch_resume(struct lwp *l) (*mips_locore_jumpvec.ljv_cpu_switch_resume)(l); } +lwp_t * +cpu_switchto(lwp_t *from, lwp_t *to, bool returning) +{ + return (*mips_locore_jumpvec.ljv_cpu_switchto)(from, to, returning); +} + void tlb_set_asid(uint32_t asid) {