Merge jmallett@'s n64 work into HEAD - changeset 7

Initial support for n32 and n64 ABIs from
http://svn.freebsd.org/base/user/jmallett/octeon

Changes are:
 - syscall, exception and trap support for n32/n64 ABIs
 - 64-bit address space defines
 - _jmp_buf for n32/n64
 - casts between registers and ptr/int updated to work on n32/n64

Approved by:	rrs(mentor), jmallett
This commit is contained in:
Jayachandran C. 2010-06-24 08:08:43 +00:00
parent 370d524f00
commit 9fa0972cf9
9 changed files with 146 additions and 62 deletions

View File

@ -806,10 +806,11 @@ _C_LABEL(x):
* 9 S7
* 10 SP
* 11 S8
* 12 signal mask (dependant on magic)
* 13 (con't)
* 12 GP (dependent on ABI)
* 13 signal mask (dependant on magic)
* 14 (con't)
* 15 (con't)
* 16 (con't)
*
* The magic number number identifies the jmp_buf and
* how the buffer was created as well as providing
@ -834,9 +835,12 @@ _C_LABEL(x):
#define _JB_REG_S7 9
#define _JB_REG_SP 10
#define _JB_REG_S8 11
#if defined(__mips_n32) || defined(__mips_n64)
#define _JB_REG_GP 12
#endif
/* Only valid with the _JB_MAGIC_SETJMP magic */
#define _JB_SIGMASK 12
#define _JB_SIGMASK 13
#endif /* !_MACHINE_ASM_H_ */

View File

@ -49,7 +49,7 @@
#include <machine/endian.h>
#define MIPS_KSEG0_LARGEST_PHYS 0x20000000
#define MIPS_KSEG0_LARGEST_PHYS (0x20000000)
#define MIPS_PHYS_MASK (0x1fffffff)
#define MIPS_PHYS_TO_KSEG0(x) ((uintptr_t)(x) | MIPS_KSEG0_START)
@ -162,11 +162,11 @@
/*
* Location of exception vectors.
*/
#define RESET_EXC_VEC 0xbfc00000
#define TLB_MISS_EXC_VEC 0x80000000
#define XTLB_MISS_EXC_VEC 0x80000080
#define CACHE_ERR_EXC_VEC 0x80000100
#define GEN_EXC_VEC 0x80000180
#define RESET_EXC_VEC ((intptr_t)(int32_t)0xbfc00000)
#define TLB_MISS_EXC_VEC ((intptr_t)(int32_t)0x80000000)
#define XTLB_MISS_EXC_VEC ((intptr_t)(int32_t)0x80000080)
#define CACHE_ERR_EXC_VEC ((intptr_t)(int32_t)0x80000100)
#define GEN_EXC_VEC ((intptr_t)(int32_t)0x80000180)
/*
* Coprocessor 0 registers:

View File

@ -39,7 +39,7 @@
#include <sys/cdefs.h>
#define _JBLEN 95 /* size, in longs, of a jmp_buf */
#define _JBLEN 95 /* size, in longs (or long longs), of a jmp_buf */
/*
* jmp_buf and sigjmp_buf are encapsulated in different structs to force
@ -49,10 +49,18 @@
#ifndef _LOCORE
#ifndef __ASSEMBLER__
#if __BSD_VISIBLE || __POSIX_VISIBLE || __XSI_VISIBLE
#ifdef __mips_n32
typedef struct _sigjmp_buf { long long _sjb[_JBLEN + 1]; } sigjmp_buf[1];
#else
typedef struct _sigjmp_buf { long _sjb[_JBLEN + 1]; } sigjmp_buf[1];
#endif
#endif
#ifdef __mips_n32
typedef struct _jmp_buf { long long _jb[_JBLEN + 1]; } jmp_buf[1];
#else
typedef struct _jmp_buf { long _jb[_JBLEN + 1]; } jmp_buf[1];
#endif
#endif /* __ASSEMBLER__ */
#endif /* _LOCORE */

View File

@ -100,11 +100,17 @@
#define VM_MAX_ADDRESS ((vm_offset_t)(intptr_t)(int32_t)0xffffffff)
#define VM_MINUSER_ADDRESS ((vm_offset_t)0x00000000)
#define VM_MAXUSER_ADDRESS ((vm_offset_t)0x80000000)
#define VM_MAX_MMAP_ADDR VM_MAXUSER_ADDRESS
#define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)0xC0000000)
#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)0xFFFFC000)
#if defined(__mips_n64)
#define VM_MAXUSER_ADDRESS (VM_MINUSER_ADDRESS + (NPDEPG * NPTEPG * PAGE_SIZE))
#define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)0xc000000000000000)
#define VM_MAX_KERNEL_ADDRESS (VM_MIN_KERNEL_ADDRESS + (NPDEPG * NPTEPG * PAGE_SIZE))
#else
#define VM_MAXUSER_ADDRESS ((vm_offset_t)0x80000000)
#define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)0xC0000000)
#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)0xFFFFC000)
#endif
#if 0
#define KERNBASE (VM_MIN_KERNEL_ADDRESS)
#else

View File

@ -89,6 +89,15 @@
#define ITLBNOPFIX nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;
#define HAZARD_DELAY nop;nop;nop;nop;nop;
/* Pointer size and mask for n64 */
#if defined(__mips_n64)
#define PTRSHIFT 3
#define PTRMASK 0xff8
#else
#define PTRSHIFT 2
#define PTRMASK 0xffc
#endif
/*
*----------------------------------------------------------------------------
*
@ -126,12 +135,12 @@ VECTOR_END(MipsTLBMiss)
.set noat
MipsDoTLBMiss:
bltz k0, 1f #02: k0<0 -> 1f (kernel fault)
PTR_SRL k0, k0, SEGSHIFT - 2 #03: k0=seg offset (almost)
PTR_SRL k0, k0, SEGSHIFT - PTRSHIFT #03: k0=seg offset (almost)
GET_CPU_PCPU(k1)
PTR_L k1, PC_SEGBASE(k1)
beqz k1, 2f #05: make sure segbase is not null
andi k0, k0, 0xffc #06: k0=seg offset (mask 0x3)
andi k0, k0, PTRMASK #06: k0=seg offset
PTR_ADDU k1, k0, k1 #07: k1=seg entry address
PTR_L k1, 0(k1) #08: k1=seg entry
@ -175,6 +184,9 @@ VECTOR(MipsException, unknown)
sll k0, k0, 3 # shift user bit for cause index
and k1, k1, CR_EXC_CODE # Mask out the cause bits.
or k1, k1, k0 # change index to user table
#if defined(__mips_n64)
PTR_SLL k1, k1, 1 # shift to get 8-byte offset
#endif
1:
PTR_LA k0, _C_LABEL(machExceptionTable) # get base of the jump table
PTR_ADDU k0, k0, k1 # Get the address of the
@ -798,9 +810,9 @@ NLEAF(MipsTLBInvalidException)
beqz k1, 3f
nop
PTR_SRL k0, SEGSHIFT - 2 # k0=seg offset (almost)
PTR_SRL k0, SEGSHIFT - PTRSHIFT # k0=seg offset (almost)
beq k1, zero, MipsKernGenException # ==0 -- no seg tab
andi k0, k0, 0xffc # k0=seg offset (mask 0x3)
andi k0, k0, PTRMASK # k0=seg offset
PTR_ADDU k1, k0, k1 # k1=seg entry address
PTR_L k1, 0(k1) # k1=seg entry
@ -960,10 +972,10 @@ NLEAF(MipsTLBMissException)
sltu k1, k1, k0 # upper bound of kernel_segmap
bnez k1, MipsKernGenException # out of bound
lui k1, %hi(kernel_segmap) # k1=hi of segbase
PTR_SRL k0, SEGSHIFT - 2 # k0=seg offset (almost)
PTR_SRL k0, SEGSHIFT - PTRSHIFT # k0=seg offset (almost)
PTR_L k1, %lo(kernel_segmap)(k1) # k1=segment tab base
beq k1, zero, MipsKernGenException # ==0 -- no seg tab
andi k0, k0, 0xffc # k0=seg offset (mask 0x3)
andi k0, k0, PTRMASK # k0=seg offset
PTR_ADDU k1, k0, k1 # k1=seg entry address
PTR_L k1, 0(k1) # k1=seg entry
MFC0 k0, COP_0_BAD_VADDR # k0=bad address (again)

View File

@ -140,16 +140,16 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
/* Build the argument list for the signal handler. */
regs->a0 = sig;
regs->a2 = (register_t)&sfp->sf_uc;
regs->a2 = (register_t)(intptr_t)&sfp->sf_uc;
if (SIGISMEMBER(psp->ps_siginfo, sig)) {
/* Signal handler installed with SA_SIGINFO. */
regs->a1 = (register_t)&sfp->sf_si;
regs->a1 = (register_t)(intptr_t)&sfp->sf_si;
/* sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; */
/* fill siginfo structure */
sf.sf_si.si_signo = sig;
sf.sf_si.si_code = ksi->ksi_code;
sf.sf_si.si_addr = (void*)regs->badvaddr;
sf.sf_si.si_addr = (void*)(intptr_t)regs->badvaddr;
} else {
/* Old FreeBSD-style arguments. */
regs->a1 = ksi->ksi_code;
@ -172,13 +172,13 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
sigexit(td, SIGILL);
}
regs->pc = (register_t) catcher;
regs->t9 = (register_t) catcher;
regs->sp = (register_t) sfp;
regs->pc = (register_t)(intptr_t)catcher;
regs->t9 = (register_t)(intptr_t)catcher;
regs->sp = (register_t)(intptr_t)sfp;
/*
* Signal trampoline code is at base of user stack.
*/
regs->ra = (register_t) PS_STRINGS - *(p->p_sysent->sv_szsigcode);
regs->ra = (register_t)(intptr_t)PS_STRINGS - *(p->p_sysent->sv_szsigcode);
PROC_LOCK(p);
mtx_lock(&psp->ps_mtx);
}
@ -231,12 +231,12 @@ sigreturn(struct thread *td, struct sigreturn_args *uap)
if (ucp->uc_mcontext.mc_regs[ZERO] != UCONTEXT_MAGIC) {
printf("sigreturn: pid %d, ucp %p\n", td->td_proc->p_pid, ucp);
printf(" old sp %p ra %p pc %p\n",
(void *)regs->sp, (void *)regs->ra, (void *)regs->pc);
(void *)(intptr_t)regs->sp, (void *)(intptr_t)regs->ra, (void *)(intptr_t)regs->pc);
printf(" new sp %p ra %p pc %p z %p\n",
(void *)ucp->uc_mcontext.mc_regs[SP],
(void *)ucp->uc_mcontext.mc_regs[RA],
(void *)ucp->uc_mcontext.mc_regs[PC],
(void *)ucp->uc_mcontext.mc_regs[ZERO]);
(void *)(intptr_t)ucp->uc_mcontext.mc_regs[SP],
(void *)(intptr_t)ucp->uc_mcontext.mc_regs[RA],
(void *)(intptr_t)ucp->uc_mcontext.mc_regs[PC],
(void *)(intptr_t)ucp->uc_mcontext.mc_regs[ZERO]);
return EINVAL;
}
/* #endif */
@ -483,12 +483,10 @@ exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
td->td_frame->sp = ((register_t) stack) & ~(sizeof(__int64_t) - 1);
td->td_frame->pc = imgp->entry_addr & ~3;
td->td_frame->t9 = imgp->entry_addr & ~3; /* abicall req */
#if 0
// td->td_frame->sr = SR_KSU_USER | SR_EXL | SR_INT_ENAB;
//? td->td_frame->sr |= idle_mask & ALL_INT_MASK;
#else
td->td_frame->sr = SR_KSU_USER | SR_EXL | SR_INT_ENAB |
(mips_rd_status() & ALL_INT_MASK);
#if defined(__mips_n32) || defined(__mips_n64)
td->td_frame->sr |= SR_PX;
#endif
#ifdef TARGET_OCTEON
td->td_frame->sr |= MIPS_SR_COP_2_BIT | MIPS32_SR_PX | MIPS_SR_UX |

View File

@ -43,7 +43,7 @@ static u_register_t
stack_register_fetch(u_register_t sp, u_register_t stack_pos)
{
u_register_t * stack =
((u_register_t *)sp + stack_pos/sizeof(u_register_t));
((u_register_t *)(intptr_t)sp + (size_t)stack_pos/sizeof(u_register_t));
return *stack;
}
@ -59,19 +59,22 @@ stack_capture(struct stack *st, u_register_t pc, u_register_t sp)
for (;;) {
stacksize = 0;
if (pc <= (u_register_t)btext)
if (pc <= (u_register_t)(intptr_t)btext)
break;
for (i = pc; i >= (u_register_t)btext; i -= sizeof (insn)) {
bcopy((void *)i, &insn, sizeof insn);
for (i = pc; i >= (u_register_t)(intptr_t)btext; i -= sizeof (insn)) {
bcopy((void *)(intptr_t)i, &insn, sizeof insn);
switch (insn.IType.op) {
case OP_ADDI:
case OP_ADDIU:
case OP_DADDI:
case OP_DADDIU:
if (insn.IType.rs != SP || insn.IType.rt != SP)
break;
stacksize = -(short)insn.IType.imm;
break;
case OP_SW:
case OP_SD:
if (insn.IType.rs != SP || insn.IType.rt != RA)
break;
ra_stack_pos = (short)insn.IType.imm;
@ -88,13 +91,13 @@ stack_capture(struct stack *st, u_register_t pc, u_register_t sp)
break;
for (i = pc; !ra; i += sizeof (insn)) {
bcopy((void *)i, &insn, sizeof insn);
bcopy((void *)(intptr_t)i, &insn, sizeof insn);
switch (insn.IType.op) {
case OP_SPECIAL:
if((insn.RType.func == OP_JR))
{
if (ra >= (u_register_t)btext)
if (ra >= (u_register_t)(intptr_t)btext)
break;
if (insn.RType.rs != RA)
break;

View File

@ -625,6 +625,15 @@ trap(struct trapframe *trapframe)
code = locr0->v0;
switch (code) {
#if defined(__mips_n32) || defined(__mips_n64)
case SYS___syscall:
/*
* Quads fit in a single register in
* new ABIs.
*
* XXX o64?
*/
#endif
case SYS_syscall:
/*
* Code is first argument, followed by
@ -635,8 +644,16 @@ trap(struct trapframe *trapframe)
args[1] = locr0->a2;
args[2] = locr0->a3;
nsaved = 3;
#if defined(__mips_n32) || defined(__mips_n64)
args[3] = locr0->t4;
args[4] = locr0->t5;
args[5] = locr0->t6;
args[6] = locr0->t7;
nsaved += 4;
#endif
break;
#if defined(__mips_o32)
case SYS___syscall:
/*
* Like syscall, but code is a quad, so as
@ -652,6 +669,7 @@ trap(struct trapframe *trapframe)
args[1] = locr0->a3;
nsaved = 2;
break;
#endif
default:
args[0] = locr0->a0;
@ -659,6 +677,13 @@ trap(struct trapframe *trapframe)
args[2] = locr0->a2;
args[3] = locr0->a3;
nsaved = 4;
#if defined (__mips_n32) || defined(__mips_n64)
args[4] = locr0->t4;
args[5] = locr0->t5;
args[6] = locr0->t6;
args[7] = locr0->t7;
nsaved += 4;
#endif
}
#ifdef TRAP_DEBUG
printf("SYSCALL #%d pid:%u\n", code, p->p_pid);
@ -675,6 +700,15 @@ trap(struct trapframe *trapframe)
nargs = callp->sy_narg;
if (nargs > nsaved) {
#if defined(__mips_n32) || defined(__mips_n64)
/*
* XXX
* Is this right for new ABIs? I think the 4 there
* should be 8, size there are 8 registers to skip,
* not 4, but I'm not certain.
*/
printf("SYSCALL #%u pid:%u, nargs > nsaved.\n", code, p->p_pid);
#endif
i = copyin((caddr_t)(intptr_t)(locr0->sp +
4 * sizeof(register_t)), (caddr_t)&args[nsaved],
(u_int)(nargs - nsaved) * sizeof(register_t));
@ -688,6 +722,18 @@ trap(struct trapframe *trapframe)
goto done;
}
}
#ifdef TRAP_DEBUG
for (i = 0; i < nargs; i++) {
printf("args[%d] = %#jx\n", i, (intmax_t)args[i]);
}
#endif
#ifdef SYSCALL_TRACING
printf("%s(", syscallnames[code]);
for (i = 0; i < nargs; i++) {
printf("%s%#jx", i == 0 ? "" : ", ", (intmax_t)args[i]);
}
printf(")\n");
#endif
#ifdef KTRACE
if (KTRPOINT(td, KTR_SYSCALL))
ktrsyscall(code, nargs, args);

View File

@ -141,13 +141,13 @@ cpu_fork(register struct thread *td1,register struct proc *p2,
if (td1 == PCPU_GET(fpcurthread))
MipsSaveCurFPState(td1);
pcb2->pcb_context[PCB_REG_RA] = (register_t)fork_trampoline;
pcb2->pcb_context[PCB_REG_RA] = (register_t)(intptr_t)fork_trampoline;
/* Make sp 64-bit aligned */
pcb2->pcb_context[PCB_REG_SP] = (register_t)(((vm_offset_t)td2->td_pcb &
~(sizeof(__int64_t) - 1)) - CALLFRAME_SIZ);
pcb2->pcb_context[PCB_REG_S0] = (register_t)fork_return;
pcb2->pcb_context[PCB_REG_S1] = (register_t)td2;
pcb2->pcb_context[PCB_REG_S2] = (register_t)td2->td_frame;
pcb2->pcb_context[PCB_REG_S0] = (register_t)(intptr_t)fork_return;
pcb2->pcb_context[PCB_REG_S1] = (register_t)(intptr_t)td2;
pcb2->pcb_context[PCB_REG_S2] = (register_t)(intptr_t)td2->td_frame;
pcb2->pcb_context[PCB_REG_SR] = SR_INT_MASK & mips_rd_status();
/*
* FREEBSD_DEVELOPERS_FIXME:
@ -178,8 +178,8 @@ cpu_set_fork_handler(struct thread *td, void (*func) __P((void *)), void *arg)
* Note that the trap frame follows the args, so the function
* is really called like this: func(arg, frame);
*/
td->td_pcb->pcb_context[PCB_REG_S0] = (register_t) func;
td->td_pcb->pcb_context[PCB_REG_S1] = (register_t) arg;
td->td_pcb->pcb_context[PCB_REG_S0] = (register_t)(intptr_t)func;
td->td_pcb->pcb_context[PCB_REG_S1] = (register_t)(intptr_t)arg;
}
void
@ -254,11 +254,18 @@ cpu_set_syscall_retval(struct thread *td, int error)
code = locr0->v0;
quad_syscall = 0;
#if defined(__mips_o32)
if (code == SYS___syscall)
quad_syscall = 1;
#endif
if (code == SYS_syscall)
code = locr0->a0;
else if (code == SYS___syscall) {
code = _QUAD_LOWWORD ? locr0->a1 : locr0->a0;
quad_syscall = 1;
if (quad_syscall)
code = _QUAD_LOWWORD ? locr0->a1 : locr0->a0;
else
code = locr0->a0;
}
switch (error) {
@ -336,13 +343,13 @@ cpu_set_upcall(struct thread *td, struct thread *td0)
* Set registers for trampoline to user mode.
*/
pcb2->pcb_context[PCB_REG_RA] = (register_t)fork_trampoline;
pcb2->pcb_context[PCB_REG_RA] = (register_t)(intptr_t)fork_trampoline;
/* Make sp 64-bit aligned */
pcb2->pcb_context[PCB_REG_SP] = (register_t)(((vm_offset_t)td->td_pcb &
~(sizeof(__int64_t) - 1)) - CALLFRAME_SIZ);
pcb2->pcb_context[PCB_REG_S0] = (register_t)fork_return;
pcb2->pcb_context[PCB_REG_S1] = (register_t)td;
pcb2->pcb_context[PCB_REG_S2] = (register_t)td->td_frame;
pcb2->pcb_context[PCB_REG_S0] = (register_t)(intptr_t)fork_return;
pcb2->pcb_context[PCB_REG_S1] = (register_t)(intptr_t)td;
pcb2->pcb_context[PCB_REG_S2] = (register_t)(intptr_t)td->td_frame;
/* Dont set IE bit in SR. sched lock release will take care of it */
pcb2->pcb_context[PCB_REG_SR] = SR_INT_MASK & mips_rd_status();
@ -385,7 +392,7 @@ cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
* byte aligned[for compatibility with 64-bit CPUs]
* in ``See MIPS Run'' by D. Sweetman, p. 269
* align stack */
sp = ((register_t)(stack->ss_sp + stack->ss_size) & ~0x7) -
sp = ((register_t)(intptr_t)(stack->ss_sp + stack->ss_size) & ~0x7) -
CALLFRAME_SIZ;
/*
@ -394,14 +401,14 @@ cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
*/
tf = td->td_frame;
bzero(tf, sizeof(struct trapframe));
tf->sp = (register_t)sp;
tf->pc = (register_t)entry;
tf->sp = sp;
tf->pc = (register_t)(intptr_t)entry;
/*
* MIPS ABI requires T9 to be the same as PC
* in subroutine entry point
*/
tf->t9 = (register_t)entry;
tf->a0 = (register_t)arg;
tf->t9 = (register_t)(intptr_t)entry;
tf->a0 = (register_t)(intptr_t)arg;
/*
* Keep interrupt mask
@ -409,7 +416,7 @@ cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
tf->sr = SR_KSU_USER | SR_EXL | (SR_INT_MASK & mips_rd_status()) |
MIPS_SR_INT_IE;
#ifdef TARGET_OCTEON
tf->sr |= MIPS_SR_INT_IE | MIPS_SR_COP_0_BIT | MIPS_SR_UX |
tf->sr |= MIPS_SR_INT_IE | MIPS_SR_COP_0_BIT | MIPS32_SR_PX | MIPS_SR_UX |
MIPS_SR_KX;
#endif
/* tf->sr |= (ALL_INT_MASK & idle_mask) | SR_INT_ENAB; */
@ -431,7 +438,7 @@ kvtop(void *addr)
va = pmap_kextract((vm_offset_t)addr);
if (va == 0)
panic("kvtop: zero page frame");
return((int)va);
return((intptr_t)va);
}
/*
@ -547,10 +554,10 @@ cpu_throw(struct thread *old, struct thread *new)
#include <ddb/ddb.h>
#define DB_PRINT_REG(ptr, regname) \
db_printf(" %-12s 0x%lx\n", #regname, (long)((ptr)->regname))
db_printf(" %-12s %p\n", #regname, (void *)(intptr_t)((ptr)->regname))
#define DB_PRINT_REG_ARRAY(ptr, arrname, regname) \
db_printf(" %-12s 0x%lx\n", #regname, (long)((ptr)->arrname[regname]))
db_printf(" %-12s %p\n", #regname, (void *)(intptr_t)((ptr)->arrname[regname]))
static void
dump_trapframe(struct trapframe *trapframe)