Next round of ia64 work, including fixes to context switching,

implementing cpu_fork(), copy*str(), bcopy(), copy{in,out}(). With these
changes, my test kernel reaches the mountroot prompt.
This commit is contained in:
Doug Rabson 2000-09-30 17:48:44 +00:00
parent 534f2a9dad
commit 431f3cb41d
19 changed files with 828 additions and 1131 deletions

View File

@ -87,7 +87,7 @@ static struct timecounter ia64_timecounter = {
0, /* no poll_pps */
~0u, /* counter_mask */
0, /* frequency */
"alpha" /* name */
"IA64 ITC" /* name */
};
SYSCTL_OPAQUE(_debug, OID_AUTO, ia64_timecounter, CTLFLAG_RD,
@ -158,9 +158,15 @@ cpu_initclocks()
{
u_int32_t freq;
#if 0
if (clockdev == NULL)
panic("cpu_initclocks: no clock attached");
#endif
/*
* We use cr.itc and cr.itm to implement a 1024hz clock.
*/
hz = 1024;
tick = 1000000 / hz; /* number of microseconds between interrupts */
tickfix = 1000000 - (hz * tick);
if (tickfix) {
@ -172,19 +178,14 @@ cpu_initclocks()
}
/*
* Establish the clock interrupt; it's a special case.
*
* We establish the clock interrupt this late because if
* we do it at clock attach time, we may have never been at
* spl0() since taking over the system. Some versions of
* PALcode save a clock interrupt, which would get delivered
* when we spl0() in autoconf.c. If established the clock
* interrupt handler earlier, that interrupt would go to
* hardclock, which would then fall over because p->p_stats
* isn't set at that time.
* XXX we should call SAL_FREQ_BASE_INTERVAL_TIMER here.
*/
cycles_per_sec = 700000000;
ia64_set_itm(ia64_get_itc() + (cycles_per_sec + hz/2) / hz);
freq = cycles_per_sec;
last_time = ia64_read_itc();
last_time = ia64_get_itc();
scaled_ticks_per_cycle = ((u_int64_t)hz << FIX_SHIFT) / freq;
max_cycles_per_tick = 2*freq / hz;
@ -193,10 +194,12 @@ cpu_initclocks()
stathz = 128;
#if 0
/*
* Get the clock started.
*/
CLOCK_INIT(clockdev);
#endif
}
static u_int32_t
@ -222,7 +225,7 @@ calibrate_clocks(u_int32_t firmware_freq)
}
/* Start keeping track of the PCC. */
start_pcc = ia64_read_itc();
start_pcc = ia64_get_itc();
/*
* Wait for the mc146818A seconds counter to change.
@ -238,7 +241,7 @@ calibrate_clocks(u_int32_t firmware_freq)
/*
* Read the PCC again to work out frequency.
*/
stop_pcc = ia64_read_itc();
stop_pcc = ia64_get_itc();
if (bootverbose) {
printf("PCC clock: %u Hz (firmware %u Hz)\n",
@ -256,7 +259,7 @@ calibrate_clocks(u_int32_t firmware_freq)
static void
handleclock(void* arg)
{
u_int32_t now = ia64_read_itc();
u_int32_t now = ia64_get_itc();
u_int32_t delta = now - last_time;
last_time = now;
@ -432,7 +435,7 @@ resettodr()
static unsigned
ia64_get_timecount(struct timecounter* tc)
{
return ia64_read_itc();
return ia64_get_itc();
}
int

View File

@ -48,6 +48,7 @@
movl r17=exception_return; \
mov out0=_n_; \
mov out1=sp;; \
add sp=-16,sp;; \
mov rp=r17; \
br.call.sptk.few b6=trap
@ -780,15 +781,16 @@ ia64_vhpt: .quad 0
* exception_return: restore interrupted state
*
* Arguments:
* sp trapframe pointer
* sp+16 trapframe pointer
*
*/
LEAF(exception_return, 0)
rsm psr.ic|psr.dt // disable interrupt collection and vm
add r3=16,sp;
;;
srlz.d
dep r3=0,sp,61,3 // physical address
dep r3=0,r3,61,3 // physical address
;;
add r1=SIZEOF_TRAPFRAME-16,r3 // r1=&tf_f[FRAME_F15]
add r2=SIZEOF_TRAPFRAME-32,r3 // r2=&tf_f[FRAME_F14]
@ -805,7 +807,7 @@ LEAF(exception_return, 0)
ldf.fill f9=[r1],-32 // r1=&tf_f[FRAME_F7]
ldf.fill f8=[r2],-32 // r2=&tf_f[FRAME_F6]
;;
ldf.fill f7=[r1],-24 // r1=&tf_r[FRAME_R31]
ldf.fill f7=[r1],-32 // r1=&tf_r[FRAME_R31]
ldf.fill f6=[r2],-24 // r2=&tf_r[FRAME_R30]
;;
ld8.fill r31=[r1],-16 // r1=&tf_r[FRAME_R29]

View File

@ -48,6 +48,7 @@
movl r17=exception_return; \
mov out0=_n_; \
mov out1=sp;; \
add sp=-16,sp;; \
mov rp=r17; \
br.call.sptk.few b6=trap
@ -780,15 +781,16 @@ ia64_vhpt: .quad 0
* exception_return: restore interrupted state
*
* Arguments:
* sp trapframe pointer
* sp+16 trapframe pointer
*
*/
LEAF(exception_return, 0)
rsm psr.ic|psr.dt // disable interrupt collection and vm
add r3=16,sp;
;;
srlz.d
dep r3=0,sp,61,3 // physical address
dep r3=0,r3,61,3 // physical address
;;
add r1=SIZEOF_TRAPFRAME-16,r3 // r1=&tf_f[FRAME_F15]
add r2=SIZEOF_TRAPFRAME-32,r3 // r2=&tf_f[FRAME_F14]
@ -805,7 +807,7 @@ LEAF(exception_return, 0)
ldf.fill f9=[r1],-32 // r1=&tf_f[FRAME_F7]
ldf.fill f8=[r2],-32 // r2=&tf_f[FRAME_F6]
;;
ldf.fill f7=[r1],-24 // r1=&tf_r[FRAME_R31]
ldf.fill f7=[r1],-32 // r1=&tf_r[FRAME_R31]
ldf.fill f6=[r2],-24 // r2=&tf_r[FRAME_R30]
;;
ld8.fill r31=[r1],-16 // r1=&tf_r[FRAME_R29]

View File

@ -67,6 +67,13 @@
#include <nfs/nfs.h>
#include <nfs/nfsdiskless.h>
ASSYM(GD_CURPROC, offsetof(struct globaldata, gd_curproc));
ASSYM(GD_FPCURPROC, offsetof(struct globaldata, gd_fpcurproc));
ASSYM(GD_CURPCB, offsetof(struct globaldata, gd_curpcb));
ASSYM(GD_SWITCHTIME, offsetof(struct globaldata, gd_switchtime));
ASSYM(GD_CPUNO, offsetof(struct globaldata, gd_cpuno));
ASSYM(GD_ASTPENDING, offsetof(struct globaldata, gd_astpending));
ASSYM(MTX_LOCK, offsetof(struct mtx, mtx_lock));
ASSYM(MTX_RECURSE, offsetof(struct mtx, mtx_recurse));
ASSYM(MTX_SAVEPSR, offsetof(struct mtx, mtx_savepsr));
@ -74,7 +81,6 @@ ASSYM(MTX_UNOWNED, MTX_UNOWNED);
ASSYM(P_ADDR, offsetof(struct proc, p_addr));
ASSYM(P_MD_FLAGS, offsetof(struct proc, p_md.md_flags));
ASSYM(P_MD_PCBPADDR, offsetof(struct proc, p_md.md_pcbpaddr));
ASSYM(VM_MAXUSER_ADDRESS, VM_MAXUSER_ADDRESS);
@ -90,6 +96,13 @@ ASSYM(U_PCB_F3, offsetof(struct user, u_pcb.pcb_f3));
ASSYM(U_PCB_F4, offsetof(struct user, u_pcb.pcb_f4));
ASSYM(U_PCB_F5, offsetof(struct user, u_pcb.pcb_f5));
ASSYM(U_PCB_B0, offsetof(struct user, u_pcb.pcb_b0));
ASSYM(U_PCB_B1, offsetof(struct user, u_pcb.pcb_b1));
ASSYM(U_PCB_B2, offsetof(struct user, u_pcb.pcb_b2));
ASSYM(U_PCB_B3, offsetof(struct user, u_pcb.pcb_b3));
ASSYM(U_PCB_B4, offsetof(struct user, u_pcb.pcb_b4));
ASSYM(U_PCB_B5, offsetof(struct user, u_pcb.pcb_b5));
ASSYM(U_PCB_OLD_UNAT, offsetof(struct user, u_pcb.pcb_old_unat));
ASSYM(U_PCB_SP, offsetof(struct user, u_pcb.pcb_sp));
ASSYM(U_PCB_PFS, offsetof(struct user, u_pcb.pcb_pfs));
@ -98,7 +111,8 @@ ASSYM(U_PCB_BSPSTORE, offsetof(struct user, u_pcb.pcb_bspstore));
ASSYM(U_PCB_UNAT, offsetof(struct user, u_pcb.pcb_unat));
ASSYM(U_PCB_RNAT, offsetof(struct user, u_pcb.pcb_rnat));
ASSYM(U_PCB_PR, offsetof(struct user, u_pcb.pcb_pr));
ASSYM(U_PCB_IIP, offsetof(struct user, u_pcb.pcb_iip));
ASSYM(U_PCB_ONFAULT, offsetof(struct user, u_pcb.pcb_onfault));
ASSYM(UC_MCONTEXT_MC_AR_BSP, offsetof(ucontext_t, uc_mcontext.mc_ar_bsp));
ASSYM(UC_MCONTEXT_MC_AR_RNAT, offsetof(ucontext_t, uc_mcontext.mc_ar_rnat));

View File

@ -63,17 +63,6 @@
#include <machine/intrcnt.h>
#endif
/*
* Perform actions necessary to switch to a new context. The
* hwpcb should be in a0.
*/
#define SWITCH_CONTEXT \
/* Make a note of the context we're running on. */ \
stq a0, curpcb ; \
\
/* Swap in the new context. */ \
call_pal PAL_OSF1_swpctx
.text
/*
@ -81,8 +70,8 @@
*/
LEAF(locorestart, 1)
movl r8=ia64_vector_table /* set up IVT early */
movl r9=ia64_vhpt+(1<<8)+(15<<2)+1 /* and VHPT */
movl r8=ia64_vector_table // set up IVT early
movl r9=ia64_vhpt+(1<<8)+(15<<2)+1 // and VHPT
;;
mov cr.iva=r8
mov cr.pta=r9
@ -91,87 +80,30 @@ LEAF(locorestart, 1)
;;
srlz.d
;;
movl gp=__gp /* find kernel globals */
movl gp=__gp // find kernel globals
;;
br.call.sptk.many rp=ia64_init
/* XXX switch to proc0 here */
movl r16=proc0
/*
* switch to proc0 and then initialise the rest of the kernel.
*/
alloc r16=ar.pfs,0,0,1,0
;;
movl out0=proc0
;;
add r16=P_ADDR,r16
add out0=P_ADDR,out0
;;
ld8 r16=[r16]
ld8 out0=[out0]
;;
add r17=SIZEOF_USER,r16 /* address of backing store */
add r18=U_PCB_SP,r16 /* stack pointer */
add r16=U_PCB_B0,out0 // return to mi_startup
movl r17=mi_startup
;;
ld8 r18=[r18]
mov ar.rsc=0
cover
st8 [r16]=r17
;;
flushrs
;;
mov ar.bspstore=r17
mov sp=r18
;;
loadrs
mov ar.rsc=3
;;
alloc r16=ar.pfs,0,0,0,0
;;
br.call.sptk.many rp=mi_startup
br.call.sptk.many rp=restorectx
/* NOTREACHED */
#if 0
/* Load KGP with current GP. */
or a0,zero,s0 /* save pfn */
or gp,zero,a0
call_pal PAL_OSF1_wrkgp /* clobbers a0, t0, t8-t11 */
or s0,zero,a0 /* restore pfn */
/*
* Call alpha_init() to do pre-main initialization.
* alpha_init() gets the arguments we were called with,
* which are already in a0, a1, a2, a3, and a4.
*/
CALL(alpha_init)
/* Set up the virtual page table pointer. */
ldiq a0, VPTBASE
call_pal PAL_OSF1_wrvptptr /* clobbers a0, t0, t8-t11 */
/*
* Switch to proc0's PCB, which is at U_PCB off of proc0paddr.
*/
lda t0,proc0 /* get phys addr of pcb */
ldq a0,P_MD_PCBPADDR(t0)
SWITCH_CONTEXT
/*
* We've switched to a new page table base, so invalidate the TLB
* and I-stream. This happens automatically everywhere but here.
*/
ldiq a0, -2 /* TBIA */
call_pal PAL_OSF1_tbi
call_pal PAL_imb
/*
* Construct a fake trap frame, so execve() can work normally.
* Note that setregs() is responsible for setting its contents
* to 'reasonable' values.
*/
lda sp,-(FRAME_SIZE * 8)(sp) /* space for struct trapframe */
mov sp, a0 /* arg is frame ptr */
CALL(mi_startup) /* go to mi_startup()! */
/*
* Call exception_return, to simulate return from (fake)
* exception to user-land, running process 1, init!
*/
jmp zero, exception_return /* "And that's all she wrote." */
#endif
END(locorestart)
@ -187,48 +119,48 @@ LEAF(locorestart, 1)
* r16 pointer to signal context frame (scp)
* r17 address of handler function descriptor
* r18 address of new backing store (if any)
* sp pointer to sigframe
* sp+16 pointer to sigframe
*/
LEAF(sigcode,0)
ld8 r8=[r17],8 /* function address */
ld8 r8=[r17],8 // function address
;;
ld8 gp=[r17] /* function's gp value */
mov b6=r8 /* transfer to a branch register */
ld8 gp=[r17] // function's gp value
mov b6=r8 // transfer to a branch register
cover
;;
alloc r5=ar.pfs,0,0,3,0 /* register frame for call */
alloc r5=ar.pfs,0,0,3,0 // register frame for call
;;
mov out0=r14 /* signal number */
add r8=UC_MCONTEXT_MC_AR_BSP,r16 /* address or mc_ar_bsp */
mov r9=ar.bsp /* save ar.bsp */
mov out0=r14 // signal number
add r8=UC_MCONTEXT_MC_AR_BSP,r16 // address or mc_ar_bsp
mov r9=ar.bsp // save ar.bsp
;;
st8 [r8]=r9
cmp.eq p1,p0=r0,r18 /* check for new bs */
(p1) br.cond.sptk.few 1f /* branch if not switching */
flushrs /* flush out to old bs */
mov ar.rsc=0 /* switch off RSE */
add r8=UC_MCONTEXT_MC_AR_RNAT,r16 /* address of mc_ar_rnat */
cmp.eq p1,p0=r0,r18 // check for new bs
(p1) br.cond.sptk.few 1f // branch if not switching
flushrs // flush out to old bs
mov ar.rsc=0 // switch off RSE
add r8=UC_MCONTEXT_MC_AR_RNAT,r16 // address of mc_ar_rnat
;;
mov r9=ar.rnat /* value of ar.rnat after flush */
mov ar.bspstore=r18 /* point at new bs */
mov r9=ar.rnat // value of ar.rnat after flush
mov ar.bspstore=r18 // point at new bs
;;
st8 [r8]=r9 /* remember ar.rnat */
mov ar.rsc=15 /* XXX bogus value - check */
st8 [r8]=r9 // remember ar.rnat
mov ar.rsc=15 // XXX bogus value - check
invala
;;
1: mov out1=r15 /* siginfo */
mov out2=r16 /* ucontext */
mov r4=r17 /* save ucontext pointer from call */
br.call.sptk.few rp=b6 /* call the signal handler */
(p1) br.cond.sptk.few 2f /* note: p1 is preserved */
1: mov out1=r15 // siginfo
mov out2=r16 // ucontext
mov r4=r17 // save ucontext pointer from call
br.call.sptk.few rp=b6 // call the signal handler
(p1) br.cond.sptk.few 2f // note: p1 is preserved
flushrs
mov ar.rsc=0
add r8=UC_MCONTEXT_MC_AR_RNAT,r4 /* address of mc_ar_rnat */
add r8=UC_MCONTEXT_MC_AR_RNAT,r4 // address of mc_ar_rnat
;;
ld8 r9=[r8]
;;
add r8=UC_MCONTEXT_MC_AR_BSP,r4 /* address of mc_ar_bsp */
add r8=UC_MCONTEXT_MC_AR_BSP,r4 // address of mc_ar_bsp
;;
ld8 r10=[r8]
;;
@ -237,9 +169,9 @@ LEAF(sigcode,0)
mov ar.rnat=r9
mov ar.rsc=15
2:
CALLSYS_NOERROR(sigreturn) /* and call sigreturn() with it. */
mov out0=ret0 /* if that failed, get error code */
CALLSYS_NOERROR(exit) /* and call exit() with it. */
CALLSYS_NOERROR(sigreturn) // and call sigreturn() with it.
mov out0=ret0 // if that failed, get error code
CALLSYS_NOERROR(exit) // and call exit() with it.
XLEAF(esigcode)
END(sigcode)

View File

@ -63,17 +63,6 @@
#include <machine/intrcnt.h>
#endif
/*
* Perform actions necessary to switch to a new context. The
* hwpcb should be in a0.
*/
#define SWITCH_CONTEXT \
/* Make a note of the context we're running on. */ \
stq a0, curpcb ; \
\
/* Swap in the new context. */ \
call_pal PAL_OSF1_swpctx
.text
/*
@ -81,8 +70,8 @@
*/
LEAF(locorestart, 1)
movl r8=ia64_vector_table /* set up IVT early */
movl r9=ia64_vhpt+(1<<8)+(15<<2)+1 /* and VHPT */
movl r8=ia64_vector_table // set up IVT early
movl r9=ia64_vhpt+(1<<8)+(15<<2)+1 // and VHPT
;;
mov cr.iva=r8
mov cr.pta=r9
@ -91,87 +80,30 @@ LEAF(locorestart, 1)
;;
srlz.d
;;
movl gp=__gp /* find kernel globals */
movl gp=__gp // find kernel globals
;;
br.call.sptk.many rp=ia64_init
/* XXX switch to proc0 here */
movl r16=proc0
/*
* switch to proc0 and then initialise the rest of the kernel.
*/
alloc r16=ar.pfs,0,0,1,0
;;
movl out0=proc0
;;
add r16=P_ADDR,r16
add out0=P_ADDR,out0
;;
ld8 r16=[r16]
ld8 out0=[out0]
;;
add r17=SIZEOF_USER,r16 /* address of backing store */
add r18=U_PCB_SP,r16 /* stack pointer */
add r16=U_PCB_B0,out0 // return to mi_startup
movl r17=mi_startup
;;
ld8 r18=[r18]
mov ar.rsc=0
cover
st8 [r16]=r17
;;
flushrs
;;
mov ar.bspstore=r17
mov sp=r18
;;
loadrs
mov ar.rsc=3
;;
alloc r16=ar.pfs,0,0,0,0
;;
br.call.sptk.many rp=mi_startup
br.call.sptk.many rp=restorectx
/* NOTREACHED */
#if 0
/* Load KGP with current GP. */
or a0,zero,s0 /* save pfn */
or gp,zero,a0
call_pal PAL_OSF1_wrkgp /* clobbers a0, t0, t8-t11 */
or s0,zero,a0 /* restore pfn */
/*
* Call alpha_init() to do pre-main initialization.
* alpha_init() gets the arguments we were called with,
* which are already in a0, a1, a2, a3, and a4.
*/
CALL(alpha_init)
/* Set up the virtual page table pointer. */
ldiq a0, VPTBASE
call_pal PAL_OSF1_wrvptptr /* clobbers a0, t0, t8-t11 */
/*
* Switch to proc0's PCB, which is at U_PCB off of proc0paddr.
*/
lda t0,proc0 /* get phys addr of pcb */
ldq a0,P_MD_PCBPADDR(t0)
SWITCH_CONTEXT
/*
* We've switched to a new page table base, so invalidate the TLB
* and I-stream. This happens automatically everywhere but here.
*/
ldiq a0, -2 /* TBIA */
call_pal PAL_OSF1_tbi
call_pal PAL_imb
/*
* Construct a fake trap frame, so execve() can work normally.
* Note that setregs() is responsible for setting its contents
* to 'reasonable' values.
*/
lda sp,-(FRAME_SIZE * 8)(sp) /* space for struct trapframe */
mov sp, a0 /* arg is frame ptr */
CALL(mi_startup) /* go to mi_startup()! */
/*
* Call exception_return, to simulate return from (fake)
* exception to user-land, running process 1, init!
*/
jmp zero, exception_return /* "And that's all she wrote." */
#endif
END(locorestart)
@ -187,48 +119,48 @@ LEAF(locorestart, 1)
* r16 pointer to signal context frame (scp)
* r17 address of handler function descriptor
* r18 address of new backing store (if any)
* sp pointer to sigframe
* sp+16 pointer to sigframe
*/
LEAF(sigcode,0)
ld8 r8=[r17],8 /* function address */
ld8 r8=[r17],8 // function address
;;
ld8 gp=[r17] /* function's gp value */
mov b6=r8 /* transfer to a branch register */
ld8 gp=[r17] // function's gp value
mov b6=r8 // transfer to a branch register
cover
;;
alloc r5=ar.pfs,0,0,3,0 /* register frame for call */
alloc r5=ar.pfs,0,0,3,0 // register frame for call
;;
mov out0=r14 /* signal number */
add r8=UC_MCONTEXT_MC_AR_BSP,r16 /* address or mc_ar_bsp */
mov r9=ar.bsp /* save ar.bsp */
mov out0=r14 // signal number
add r8=UC_MCONTEXT_MC_AR_BSP,r16 // address or mc_ar_bsp
mov r9=ar.bsp // save ar.bsp
;;
st8 [r8]=r9
cmp.eq p1,p0=r0,r18 /* check for new bs */
(p1) br.cond.sptk.few 1f /* branch if not switching */
flushrs /* flush out to old bs */
mov ar.rsc=0 /* switch off RSE */
add r8=UC_MCONTEXT_MC_AR_RNAT,r16 /* address of mc_ar_rnat */
cmp.eq p1,p0=r0,r18 // check for new bs
(p1) br.cond.sptk.few 1f // branch if not switching
flushrs // flush out to old bs
mov ar.rsc=0 // switch off RSE
add r8=UC_MCONTEXT_MC_AR_RNAT,r16 // address of mc_ar_rnat
;;
mov r9=ar.rnat /* value of ar.rnat after flush */
mov ar.bspstore=r18 /* point at new bs */
mov r9=ar.rnat // value of ar.rnat after flush
mov ar.bspstore=r18 // point at new bs
;;
st8 [r8]=r9 /* remember ar.rnat */
mov ar.rsc=15 /* XXX bogus value - check */
st8 [r8]=r9 // remember ar.rnat
mov ar.rsc=15 // XXX bogus value - check
invala
;;
1: mov out1=r15 /* siginfo */
mov out2=r16 /* ucontext */
mov r4=r17 /* save ucontext pointer from call */
br.call.sptk.few rp=b6 /* call the signal handler */
(p1) br.cond.sptk.few 2f /* note: p1 is preserved */
1: mov out1=r15 // siginfo
mov out2=r16 // ucontext
mov r4=r17 // save ucontext pointer from call
br.call.sptk.few rp=b6 // call the signal handler
(p1) br.cond.sptk.few 2f // note: p1 is preserved
flushrs
mov ar.rsc=0
add r8=UC_MCONTEXT_MC_AR_RNAT,r4 /* address of mc_ar_rnat */
add r8=UC_MCONTEXT_MC_AR_RNAT,r4 // address of mc_ar_rnat
;;
ld8 r9=[r8]
;;
add r8=UC_MCONTEXT_MC_AR_BSP,r4 /* address of mc_ar_bsp */
add r8=UC_MCONTEXT_MC_AR_BSP,r4 // address of mc_ar_bsp
;;
ld8 r10=[r8]
;;
@ -237,9 +169,9 @@ LEAF(sigcode,0)
mov ar.rnat=r9
mov ar.rsc=15
2:
CALLSYS_NOERROR(sigreturn) /* and call sigreturn() with it. */
mov out0=ret0 /* if that failed, get error code */
CALLSYS_NOERROR(exit) /* and call exit() with it. */
CALLSYS_NOERROR(sigreturn) // and call sigreturn() with it.
mov out0=ret0 // if that failed, get error code
CALLSYS_NOERROR(exit) // and call exit() with it.
XLEAF(esigcode)
END(sigcode)

View File

@ -87,8 +87,6 @@ struct cpuhead cpuhead;
struct mtx sched_lock;
struct mtx Giant;
struct user *proc0paddr;
char machine[] = "ia64";
SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
@ -573,7 +571,7 @@ ia64_init()
/*
* Init mapping for u page(s) for proc 0
*/
proc0.p_addr = proc0paddr =
proc0.p_addr =
(struct user *)pmap_steal_memory(UPAGES * PAGE_SIZE);
/*
@ -593,20 +591,18 @@ ia64_init()
pmap_bootstrap();
/*
* Initialize the rest of proc 0's PCB, and cache its physical
* address.
*/
proc0.p_md.md_pcbpaddr =
(struct pcb *)IA64_RR_MASK((vm_offset_t)&proc0paddr->u_pcb);
/*
* Initialize the rest of proc 0's PCB.
*
* Set the kernel sp, reserving space for an (empty) trapframe,
* and make proc0's trapframe pointer point to it for sanity.
* Initialise proc0's backing store to start after u area.
*/
proc0paddr->u_pcb.pcb_sp =
(u_int64_t)proc0paddr + USPACE - sizeof(struct trapframe);
proc0.p_addr->u_pcb.pcb_sp =
(u_int64_t)proc0.p_addr + USPACE - sizeof(struct trapframe) - 16;
proc0.p_addr->u_pcb.pcb_bspstore = (u_int64_t) (proc0.p_addr + 1);
proc0.p_md.md_tf =
(struct trapframe *)proc0paddr->u_pcb.pcb_sp;
(struct trapframe *)(proc0.p_addr->u_pcb.pcb_sp + 16);
PCPU_SET(curproc, &proc0);
/*
@ -710,6 +706,11 @@ ia64_init()
}
}
/*
* Force verbose mode for a while.
*/
bootverbose = 1;
/*
* Initialize debuggers, and break into them if appropriate.
*/
@ -898,7 +899,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
frame->tf_r[FRAME_R3] = (u_int64_t)&(sfp->sf_uc);
frame->tf_r[FRAME_R4] = (u_int64_t)catcher;
frame->tf_r[FRAME_R5] = sbs;
frame->tf_r[FRAME_SP] = (unsigned long)sfp;
frame->tf_r[FRAME_SP] = (u_int64_t)sfp - 16;
#ifdef DEBUG
if (sigdebug & SDB_FOLLOW)

View File

@ -34,17 +34,21 @@ BSS(ia64_pal_entry, 8)
* struct ia64_pal_result ia64_call_pal_static(u_int64_t proc,
u_int64_t arg1, u_int64_t arg2, u_int64_t arg3)
*/
NESTED(ia64_call_pal_static, 4, 5, 0, r39, r40)
NESTED(ia64_call_pal_static, 4)
.regstk 4,5,0,0
palret = loc0
entry = loc1
rpsave = loc2
pfssave = loc3
psrsave = loc4
alloc pfssave=ar.pfs,4,5,0,0
;;
mov rpsave=rp
movl entry=ia64_pal_entry
1: mov palret=ip // for return address
mov rpsave=rp
;;
mov psrsave=psr
mov r28=in0 // procedure number
@ -62,10 +66,10 @@ psrsave = loc4
;;
br.cond.sptk b1 // call into firmware
2: mov psr.l=psrsave
mov b0=rpsave
mov rp=rpsave
mov ar.pfs=pfssave
;;
srlz.d
br.ret.sptk b0
br.ret.sptk rp
END(ia64_call_pal_static)

View File

@ -34,17 +34,21 @@ BSS(ia64_pal_entry, 8)
* struct ia64_pal_result ia64_call_pal_static(u_int64_t proc,
u_int64_t arg1, u_int64_t arg2, u_int64_t arg3)
*/
NESTED(ia64_call_pal_static, 4, 5, 0, r39, r40)
NESTED(ia64_call_pal_static, 4)
.regstk 4,5,0,0
palret = loc0
entry = loc1
rpsave = loc2
pfssave = loc3
psrsave = loc4
alloc pfssave=ar.pfs,4,5,0,0
;;
mov rpsave=rp
movl entry=ia64_pal_entry
1: mov palret=ip // for return address
mov rpsave=rp
;;
mov psrsave=psr
mov r28=in0 // procedure number
@ -62,10 +66,10 @@ psrsave = loc4
;;
br.cond.sptk b1 // call into firmware
2: mov psr.l=psrsave
mov b0=rpsave
mov rp=rpsave
mov ar.pfs=pfssave
;;
srlz.d
br.ret.sptk b0
br.ret.sptk rp
END(ia64_call_pal_static)

View File

@ -667,12 +667,6 @@ pmap_swapin_proc(p)
vm_page_wakeup(m);
vm_page_flag_set(m, PG_MAPPED | PG_WRITEABLE);
}
/*
* The pcb may be at a different physical address now so cache the
* new address.
*/
p->p_md.md_pcbpaddr = (void*) vtophys((vm_offset_t) &p->p_addr->u_pcb);
}
/***************************************************

View File

@ -97,7 +97,7 @@ ssc(u_int64_t in0, u_int64_t in1, u_int64_t in2, u_int64_t in3, int which)
return ret0;
}
void
static void
ssccnputc(dev_t dev, int c)
{
ssc(c, 0, 0, 0, SSC_PUTCHAR);
@ -106,13 +106,22 @@ ssccnputc(dev_t dev, int c)
static int
ssccngetc(dev_t dev)
{
return -1;
int c;
do {
c = ssc(0, 0, 0, 0, SSC_GETCHAR);
} while (c == 0);
return c;
}
static int
ssccncheckc(dev_t dev)
{
return -1;
int c;
c = ssc(0, 0, 0, 0, SSC_GETCHAR);
if (!c)
return -1;
return c;
}
static int

View File

@ -63,7 +63,7 @@
* fu{byte,word} : fetch a byte (word) from user memory
*/
LEAF(suword, 1)
LEAF(suword, 1)
#if 0
LDGP(pv)
@ -83,9 +83,9 @@
mov zero, v0
RET
#endif
END(suword)
END(suword)
LEAF(subyte, 1)
LEAF(subyte, 1)
#if 0
LDGP(pv)
@ -110,9 +110,9 @@
mov zero, v0
RET
#endif
END(subyte)
END(subyte)
LEAF(fuword, 1)
LEAF(fuword, 1)
#if 0
LDGP(pv)
@ -131,9 +131,9 @@
RET
#endif
END(fuword)
END(fuword)
LEAF(fubyte, 1)
LEAF(fubyte, 1)
#if 0
LDGP(pv)
@ -153,9 +153,9 @@
RET
#endif
END(fubyte)
END(fubyte)
LEAF(suibyte, 2)
LEAF(suibyte, 2)
#if 0
ldiq v0, -1
RET
@ -170,7 +170,7 @@
ldiq v0, -1
RET
#endif
END(fusufault)
END(fusufault)
LEAF(fswintrberr, 0)
XLEAF(fuswintr) /* XXX what is a 'word'? */
@ -180,7 +180,7 @@ XLEAF(suswintr) /* XXX what is a 'word'? */
ldiq v0, -1
RET
#endif
END(fswintrberr)
END(fswintrberr)
/**************************************************************************/
@ -191,406 +191,266 @@ XLEAF(suswintr) /* XXX what is a 'word'? */
* int copystr(char *from, char *to, size_t len, size_t *lenp);
*/
LEAF(copystr, 4)
#if 0
LDGP(pv)
mov r14=in2 // r14 = i = len
cmp.eq p6,p0=r0,in2
(p6) br.cond.spnt.few 2f // if (len == 0), bail out
mov a2, t0 /* t0 = i = len */
beq a2, Lcopystr2 /* if (len == 0), bail out */
1: ld1 r15=[in0],1 // read one byte
;;
st1 [in1]=r15,1 // write that byte
add in2=-1,in2 // len--
;;
cmp.eq p6,p0=r0,r15
cmp.ne p7,p0=r0,in2
;;
(p6) br.cond.spnt.few 2f // if (*from == 0), bail out
(p7) br.cond.sptk.few 1b // if (len != 0) copy more
Lcopystr1:
ldq_u t1, 0(a0) /* t1 = *from */
extbl t1, a0, t1
ldq_u t3, 0(a1) /* set up t2 with quad around *to */
insbl t1, a1, t2
mskbl t3, a1, t3
or t3, t2, t3 /* add *from to quad around *to */
stq_u t3, 0(a1) /* write out that quad */
subl a2, 1, a2 /* len-- */
beq t1, Lcopystr2 /* if (*from == 0), bail out */
addq a1, 1, a1 /* to++ */
addq a0, 1, a0 /* from++ */
bne a2, Lcopystr1 /* if (len != 0) copy more */
Lcopystr2:
beq a3, Lcopystr3 /* if (lenp != NULL) */
subl t0, a2, t0 /* *lenp = (i - len) */
stq t0, 0(a3)
Lcopystr3:
beq t1, Lcopystr4 /* *from == '\0'; leave quietly */
ldiq v0, ENAMETOOLONG /* *from != '\0'; error. */
RET
Lcopystr4:
mov zero, v0 /* return 0. */
RET
#endif
END(copystr)
LEAF(copyinstr, 4)
#if 0
LDGP(pv)
lda sp, -16(sp) /* set up stack frame */
stq ra, (16-8)(sp) /* save ra */
ldiq t0, VM_MAXUSER_ADDRESS /* make sure that src addr */
cmpult a0, t0, t1 /* is in user space. */
beq t1, copyerr /* if it's not, error out. */
lda v0, copyerr /* set up fault handler. */
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq v0, U_PCB_ONFAULT(at_reg)
.set at
CALL(copystr) /* do the copy. */
.set noat
ldq at_reg, curproc /* kill the fault handler. */
ldq at_reg, P_ADDR(at_reg)
stq zero, U_PCB_ONFAULT(at_reg)
.set at
ldq ra, (16-8)(sp) /* restore ra. */
lda sp, 16(sp) /* kill stack frame. */
RET /* v0 left over from copystr */
#endif
END(copyinstr)
LEAF(copyoutstr, 4)
#if 0
LDGP(pv)
lda sp, -16(sp) /* set up stack frame */
stq ra, (16-8)(sp) /* save ra */
ldiq t0, VM_MAXUSER_ADDRESS /* make sure that dest addr */
cmpult a1, t0, t1 /* is in user space. */
beq t1, copyerr /* if it's not, error out. */
lda v0, copyerr /* set up fault handler. */
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq v0, U_PCB_ONFAULT(at_reg)
.set at
CALL(copystr) /* do the copy. */
.set noat
ldq at_reg, curproc /* kill the fault handler. */
ldq at_reg, P_ADDR(at_reg)
stq zero, U_PCB_ONFAULT(at_reg)
.set at
ldq ra, (16-8)(sp) /* restore ra. */
lda sp, 16(sp) /* kill stack frame. */
RET /* v0 left over from copystr */
#endif
END(copyoutstr)
/*
* Alternative memory mover
*/
LEAF(memcpy,3)
#if 0
mov a0,t0
mov a1,a0
mov t0,a1
br bcopy
#endif
END(memcpy)
2: cmp.eq p6,p0=r0,in3
(p6) br.cond.dpnt.few 3f // if (lenp != NULL)
sub r14=in2,r14 // *lenp = (i - len)
;;
st8 [in3]=r14
3: cmp.eq p6,p0=r0,r15
(p6) br.cond.spnt.few 4f // *from == '\0'; leave quietly
mov ret0=ENAMETOOLONG // *from != '\0'; error.
br.ret.sptk.few rp
4: mov ret0=0 // return 0.
br.ret.sptk.few rp
END(copystr)
NESTED(copyinstr, 4)
alloc loc0=ar.pfs,4,3,4,0
mov loc1=rp
movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr
;;
cmp.ltu p6,p0=in0,loc2 // is in user space.
;;
(p6) br.cond.spnt.few copyerr // if it's not, error out.
movl r14=copyerr // set up fault handler.
add r15=GD_CURPROC,r13 // find curproc
;;
ld8 r15=[r15]
;;
add r15=P_ADDR,r15 // find pcb
;;
ld8 r15=[r15]
;;
add loc2=U_PCB_ONFAULT,r15
;;
st8 [loc2]=r14
;;
mov out0=in0
mov out1=in1
mov out2=in2
mov out3=in3
;;
br.call.sptk.few rp=copystr // do the copy.
st8 [loc2]=r0 // kill the fault handler.
mov rp=loc1 // restore ra.
br.ret.sptk.few rp // ret0 left over from copystr
END(copyinstr)
NESTED(copyoutstr, 4)
alloc loc0=ar.pfs,4,3,4,0
mov loc1=rp
movl loc2=VM_MAXUSER_ADDRESS // make sure that dest addr
;;
cmp.ltu p6,p0=in1,loc2 // is in user space.
;;
(p6) br.cond.spnt.few copyerr // if it's not, error out.
movl r14=copyerr // set up fault handler.
add r15=GD_CURPROC,r13 // find curproc
;;
ld8 r15=[r15]
;;
add r15=P_ADDR,r15 // find pcb
;;
ld8 r15=[r15]
;;
add loc2=U_PCB_ONFAULT,r15
;;
st8 [loc2]=r14
;;
mov out0=in0
mov out1=in1
mov out2=in2
mov out3=in3
;;
br.call.sptk.few rp=copystr // do the copy.
st8 [loc2]=r0 // kill the fault handler.
mov rp=loc1 // restore ra.
br.ret.sptk.few rp // ret0 left over from copystr
END(copyoutstr)
/*
* Copy a bytes within the kernel's address space.
*
* In the kernel, bcopy() doesn't have to handle the overlapping
* case; that's that ovbcopy() is for. However, it doesn't hurt
* to do both in bcopy, and it does provide a measure of safety.
*
* void bcopy(char *from, char *to, size_t len);
* void ovbcopy(char *from, char *to, size_t len);
* Not the fastest bcopy in the world.
*/
LEAF(bcopy,3)
LEAF(bcopy, 3)
XLEAF(ovbcopy)
#if 0
/* Check for negative length */
ble a2,bcopy_done
/* Check for overlap */
subq a1,a0,t5
cmpult t5,a2,t5
bne t5,bcopy_overlap
mov ret0=r0 // return zero for copy{in,out}
;;
cmp.le p6,p0=in2,r0 // bail if len <= 0
(p6) br.ret.spnt.few rp
/* a3 = end address */
addq a0,a2,a3
sub r14=in1,in0 ;; // check for overlap
cmp.ltu p6,p0=r14,in2 // dst-src < len
(p6) br.cond.spnt.few 5f
/* Get the first word */
ldq_u t2,0(a0)
extr.u r14=in0,0,3 // src & 7
extr.u r15=in1,0,3 ;; // dst & 7
cmp.eq p6,p0=r14,r15 // different alignment?
(p6) br.cond.spnt.few 2f // branch if same alignment
/* Do they have the same alignment? */
xor a0,a1,t0
and t0,7,t0
and a1,7,t1
bne t0,bcopy_different_alignment
1: ld1 r14=[in0],1 ;; // copy bytewise
st1 [in1]=r14,1
add in2=-1,in2 ;; // len--
cmp.ne p6,p0=r0,in2
(p6) br.cond.dptk.few 1b // loop
br.ret.sptk.few rp // done
/* src & dst have same alignment */
beq t1,bcopy_all_aligned
2: cmp.eq p6,p0=r14,r0 // aligned?
(p6) br.cond.sptk.few 4f
ldq_u t3,0(a1)
addq a2,t1,a2
mskqh t2,a0,t2
mskql t3,a0,t3
or t2,t3,t2
3: ld1 r14=[in0],1 ;; // copy bytewise
st1 [in1]=r14,1
extr.u r15=in0,0,3 // src & 7
add in2=-1,in2 ;; // len--
cmp.eq p6,p0=r0,in2 // done?
cmp.eq p7,p0=r0,r15 ;; // aligned now?
(p6) br.ret.spnt.few rp // return if done
(p7) br.cond.spnt.few 4f // go to main copy
br.cond.sptk.few 3b // more bytes to copy
/* Dst is 8-byte aligned */
// At this point, in2 is non-zero
bcopy_all_aligned:
/* If less than 8 bytes,skip loop */
subq a2,1,t0
and a2,7,a2
bic t0,7,t0
beq t0,bcopy_samealign_lp_end
4: mov r14=8 ;;
cmp.ltu p6,p0=in2,r14 ;; // len < 8?
(p6) br.cond.spnt.few 1b // byte copy the end
ld8 r15=[in0],8 ;; // copy word
st8 [in1]=r15,8
add in2=-8,in2 ;; // len -= 8
cmp.ne p6,p0=r0,in2 // done?
(p6) br.cond.spnt.few 4b // again
bcopy_samealign_lp:
stq_u t2,0(a1)
addq a1,8,a1
ldq_u t2,8(a0)
subq t0,8,t0
addq a0,8,a0
bne t0,bcopy_samealign_lp
br.ret.sptk.few rp // return
bcopy_samealign_lp_end:
/* If we're done, exit */
bne a2,bcopy_small_left
stq_u t2,0(a1)
RET
// Don't bother optimising overlap case
bcopy_small_left:
mskql t2,a2,t4
ldq_u t3,0(a1)
mskqh t3,a2,t3
or t4,t3,t4
stq_u t4,0(a1)
RET
5: add in0=in0,in2
add in1=in1,in2 ;;
add in0=-1,in0
add in1=-1,in1 ;;
bcopy_different_alignment:
/*
* this is the fun part
*/
addq a0,a2,a3
cmpule a2,8,t0
bne t0,bcopy_da_finish
6: ld1 r14=[in0],-1 ;;
st1 [in1]=r14,-1
add in2=-1,in2 ;;
cmp.ne p6,p0=r0,in2
(p6) br.cond.spnt.few 6b
beq t1,bcopy_da_noentry
br.ret.sptk.few rp
/* Do the initial partial word */
subq zero,a1,t0
and t0,7,t0
ldq_u t3,7(a0)
extql t2,a0,t2
extqh t3,a0,t3
or t2,t3,t5
insql t5,a1,t5
ldq_u t6,0(a1)
mskql t6,a1,t6
or t5,t6,t5
stq_u t5,0(a1)
addq a0,t0,a0
addq a1,t0,a1
subq a2,t0,a2
ldq_u t2,0(a0)
END(bcopy)
bcopy_da_noentry:
subq a2,1,t0
bic t0,7,t0
and a2,7,a2
beq t0,bcopy_da_finish2
bcopy_da_lp:
ldq_u t3,7(a0)
addq a0,8,a0
extql t2,a0,t4
extqh t3,a0,t5
subq t0,8,t0
or t4,t5,t5
stq t5,0(a1)
addq a1,8,a1
beq t0,bcopy_da_finish1
ldq_u t2,7(a0)
addq a0,8,a0
extql t3,a0,t4
extqh t2,a0,t5
subq t0,8,t0
or t4,t5,t5
stq t5,0(a1)
addq a1,8,a1
bne t0,bcopy_da_lp
bcopy_da_finish2:
/* Do the last new word */
mov t2,t3
bcopy_da_finish1:
/* Do the last partial word */
ldq_u t2,-1(a3)
extql t3,a0,t3
extqh t2,a0,t2
or t2,t3,t2
br zero,bcopy_samealign_lp_end
bcopy_da_finish:
/* Do the last word in the next source word */
ldq_u t3,-1(a3)
extql t2,a0,t2
extqh t3,a0,t3
or t2,t3,t2
insqh t2,a1,t3
insql t2,a1,t2
lda t4,-1(zero)
mskql t4,a2,t5
cmovne t5,t5,t4
insqh t4,a1,t5
insql t4,a1,t4
addq a1,a2,a4
ldq_u t6,0(a1)
ldq_u t7,-1(a4)
bic t6,t4,t6
bic t7,t5,t7
and t2,t4,t2
and t3,t5,t3
or t2,t6,t2
or t3,t7,t3
stq_u t3,-1(a4)
stq_u t2,0(a1)
RET
bcopy_overlap:
/*
* Basically equivalent to previous case, only backwards.
* Not quite as highly optimized
*/
addq a0,a2,a3
addq a1,a2,a4
/* less than 8 bytes - don't worry about overlap */
cmpule a2,8,t0
bne t0,bcopy_ov_short
/* Possibly do a partial first word */
and a4,7,t4
beq t4,bcopy_ov_nostart2
subq a3,t4,a3
subq a4,t4,a4
ldq_u t1,0(a3)
subq a2,t4,a2
ldq_u t2,7(a3)
ldq t3,0(a4)
extql t1,a3,t1
extqh t2,a3,t2
or t1,t2,t1
mskqh t3,t4,t3
mskql t1,t4,t1
or t1,t3,t1
stq t1,0(a4)
bcopy_ov_nostart2:
bic a2,7,t4
and a2,7,a2
beq t4,bcopy_ov_lp_end
bcopy_ov_lp:
/* This could be more pipelined, but it doesn't seem worth it */
ldq_u t0,-8(a3)
subq a4,8,a4
ldq_u t1,-1(a3)
subq a3,8,a3
extql t0,a3,t0
extqh t1,a3,t1
subq t4,8,t4
or t0,t1,t0
stq t0,0(a4)
bne t4,bcopy_ov_lp
bcopy_ov_lp_end:
beq a2,bcopy_done
ldq_u t0,0(a0)
ldq_u t1,7(a0)
ldq_u t2,0(a1)
extql t0,a0,t0
extqh t1,a0,t1
or t0,t1,t0
insql t0,a1,t0
mskql t2,a1,t2
or t2,t0,t2
stq_u t2,0(a1)
bcopy_done:
RET
bcopy_ov_short:
ldq_u t2,0(a0)
br zero,bcopy_da_finish
#endif
END(bcopy)
LEAF(memcpy,3)
LEAF(copyin, 3)
#if 0
LDGP(pv)
lda sp, -16(sp) /* set up stack frame */
stq ra, (16-8)(sp) /* save ra */
ldiq t0, VM_MAXUSER_ADDRESS /* make sure that src addr */
cmpult a0, t0, t1 /* is in user space. */
beq t1, copyerr /* if it's not, error out. */
lda v0, copyerr /* set up fault handler. */
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq v0, U_PCB_ONFAULT(at_reg)
.set at
CALL(bcopy) /* do the copy. */
.set noat
ldq at_reg, curproc /* kill the fault handler. */
ldq at_reg, P_ADDR(at_reg)
stq zero, U_PCB_ONFAULT(at_reg)
.set at
ldq ra, (16-8)(sp) /* restore ra. */
lda sp, 16(sp) /* kill stack frame. */
mov zero, v0 /* return 0. */
RET
#endif
END(copyin)
mov r14=in0 ;;
mov in0=in1 ;;
mov in1=r14
br.cond.sptk.few bcopy
END(memcpy)
NESTED(copyin, 3)
alloc loc0=ar.pfs,3,3,3,0
mov loc1=rp
LEAF(copyout, 3)
#if 0
LDGP(pv)
lda sp, -16(sp) /* set up stack frame */
stq ra, (16-8)(sp) /* save ra */
ldiq t0, VM_MAXUSER_ADDRESS /* make sure that dest addr */
cmpult a1, t0, t1 /* is in user space. */
beq t1, copyerr /* if it's not, error out. */
lda v0, copyerr /* set up fault handler. */
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq v0, U_PCB_ONFAULT(at_reg)
.set at
CALL(bcopy) /* do the copy. */
.set noat
ldq at_reg, curproc /* kill the fault handler. */
ldq at_reg, P_ADDR(at_reg)
stq zero, U_PCB_ONFAULT(at_reg)
.set at
ldq ra, (16-8)(sp) /* restore ra. */
lda sp, 16(sp) /* kill stack frame. */
mov zero, v0 /* return 0. */
RET
#endif
END(copyout)
movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr
;;
cmp.ltu p6,p0=in0,loc2 // is in user space.
;;
(p6) br.cond.spnt.few copyerr // if it's not, error out.
movl r14=copyerr // set up fault handler.
add r15=GD_CURPROC,r13 // find curproc
;;
ld8 r15=[r15]
;;
add r15=P_ADDR,r15 // find pcb
;;
ld8 r15=[r15]
;;
add loc2=U_PCB_ONFAULT,r15
;;
st8 [loc2]=r14
;;
mov out0=in0
mov out1=in1
mov out2=in2
;;
br.call.sptk.few rp=bcopy // do the copy.
st8 [loc2]=r0 // kill the fault handler.
mov rp=loc1 // restore ra.
br.ret.sptk.few rp // ret0 left over from bcopy
END(copyin)
NESTED(copyout, 3)
alloc loc0=ar.pfs,3,3,3,0
mov loc1=rp
movl loc2=VM_MAXUSER_ADDRESS // make sure that dest addr
;;
cmp.ltu p6,p0=in1,loc2 // is in user space.
;;
(p6) br.cond.spnt.few copyerr // if it's not, error out.
movl r14=copyerr // set up fault handler.
add r15=GD_CURPROC,r13 // find curproc
;;
ld8 r15=[r15]
;;
add r15=P_ADDR,r15 // find pcb
;;
ld8 r15=[r15]
;;
add loc2=U_PCB_ONFAULT,r15
;;
st8 [loc2]=r14
;;
mov out0=in0
mov out1=in1
mov out2=in2
;;
br.call.sptk.few rp=bcopy // do the copy.
st8 [loc2]=r0 // kill the fault handler.
mov rp=loc1 // restore ra.
br.ret.sptk.few rp // ret0 left over from bcopy
END(copyout)
LEAF(copyerr, 0)
#if 0
ldq t0, curproc
ldq t0, P_ADDR(t0)
stq zero, U_PCB_ONFAULT(t0) /* reset fault handler. */
ldq ra, (16-8)(sp) /* restore ra. */
lda sp, 16(sp) /* kill stack frame. */
ldiq v0, EFAULT /* return EFAULT. */
RET
#endif
END(copyerr)
add r14=GD_CURPROC,r13 ;; // find curproc
ld8 r14=[r14] ;;
add r14=P_ADDR,r14 ;; // curproc->p_addr
ld8 r14=[r14] ;;
add r14=U_PCB_ONFAULT,r14 ;; // &curproc->p_addr->u_pcb.pcb_onfault
st8 [r14]=r0 // reset fault handler
mov ret0=EFAULT // return EFAULT
br.ret.sptk.few rp
END(copyerr)
/**************************************************************************/

View File

@ -63,7 +63,7 @@
* fu{byte,word} : fetch a byte (word) from user memory
*/
LEAF(suword, 1)
LEAF(suword, 1)
#if 0
LDGP(pv)
@ -83,9 +83,9 @@
mov zero, v0
RET
#endif
END(suword)
END(suword)
LEAF(subyte, 1)
LEAF(subyte, 1)
#if 0
LDGP(pv)
@ -110,9 +110,9 @@
mov zero, v0
RET
#endif
END(subyte)
END(subyte)
LEAF(fuword, 1)
LEAF(fuword, 1)
#if 0
LDGP(pv)
@ -131,9 +131,9 @@
RET
#endif
END(fuword)
END(fuword)
LEAF(fubyte, 1)
LEAF(fubyte, 1)
#if 0
LDGP(pv)
@ -153,9 +153,9 @@
RET
#endif
END(fubyte)
END(fubyte)
LEAF(suibyte, 2)
LEAF(suibyte, 2)
#if 0
ldiq v0, -1
RET
@ -170,7 +170,7 @@
ldiq v0, -1
RET
#endif
END(fusufault)
END(fusufault)
LEAF(fswintrberr, 0)
XLEAF(fuswintr) /* XXX what is a 'word'? */
@ -180,7 +180,7 @@ XLEAF(suswintr) /* XXX what is a 'word'? */
ldiq v0, -1
RET
#endif
END(fswintrberr)
END(fswintrberr)
/**************************************************************************/
@ -191,406 +191,266 @@ XLEAF(suswintr) /* XXX what is a 'word'? */
* int copystr(char *from, char *to, size_t len, size_t *lenp);
*/
LEAF(copystr, 4)
#if 0
LDGP(pv)
mov r14=in2 // r14 = i = len
cmp.eq p6,p0=r0,in2
(p6) br.cond.spnt.few 2f // if (len == 0), bail out
mov a2, t0 /* t0 = i = len */
beq a2, Lcopystr2 /* if (len == 0), bail out */
1: ld1 r15=[in0],1 // read one byte
;;
st1 [in1]=r15,1 // write that byte
add in2=-1,in2 // len--
;;
cmp.eq p6,p0=r0,r15
cmp.ne p7,p0=r0,in2
;;
(p6) br.cond.spnt.few 2f // if (*from == 0), bail out
(p7) br.cond.sptk.few 1b // if (len != 0) copy more
Lcopystr1:
ldq_u t1, 0(a0) /* t1 = *from */
extbl t1, a0, t1
ldq_u t3, 0(a1) /* set up t2 with quad around *to */
insbl t1, a1, t2
mskbl t3, a1, t3
or t3, t2, t3 /* add *from to quad around *to */
stq_u t3, 0(a1) /* write out that quad */
subl a2, 1, a2 /* len-- */
beq t1, Lcopystr2 /* if (*from == 0), bail out */
addq a1, 1, a1 /* to++ */
addq a0, 1, a0 /* from++ */
bne a2, Lcopystr1 /* if (len != 0) copy more */
Lcopystr2:
beq a3, Lcopystr3 /* if (lenp != NULL) */
subl t0, a2, t0 /* *lenp = (i - len) */
stq t0, 0(a3)
Lcopystr3:
beq t1, Lcopystr4 /* *from == '\0'; leave quietly */
ldiq v0, ENAMETOOLONG /* *from != '\0'; error. */
RET
Lcopystr4:
mov zero, v0 /* return 0. */
RET
#endif
END(copystr)
LEAF(copyinstr, 4)
#if 0
LDGP(pv)
lda sp, -16(sp) /* set up stack frame */
stq ra, (16-8)(sp) /* save ra */
ldiq t0, VM_MAXUSER_ADDRESS /* make sure that src addr */
cmpult a0, t0, t1 /* is in user space. */
beq t1, copyerr /* if it's not, error out. */
lda v0, copyerr /* set up fault handler. */
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq v0, U_PCB_ONFAULT(at_reg)
.set at
CALL(copystr) /* do the copy. */
.set noat
ldq at_reg, curproc /* kill the fault handler. */
ldq at_reg, P_ADDR(at_reg)
stq zero, U_PCB_ONFAULT(at_reg)
.set at
ldq ra, (16-8)(sp) /* restore ra. */
lda sp, 16(sp) /* kill stack frame. */
RET /* v0 left over from copystr */
#endif
END(copyinstr)
LEAF(copyoutstr, 4)
#if 0
LDGP(pv)
lda sp, -16(sp) /* set up stack frame */
stq ra, (16-8)(sp) /* save ra */
ldiq t0, VM_MAXUSER_ADDRESS /* make sure that dest addr */
cmpult a1, t0, t1 /* is in user space. */
beq t1, copyerr /* if it's not, error out. */
lda v0, copyerr /* set up fault handler. */
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq v0, U_PCB_ONFAULT(at_reg)
.set at
CALL(copystr) /* do the copy. */
.set noat
ldq at_reg, curproc /* kill the fault handler. */
ldq at_reg, P_ADDR(at_reg)
stq zero, U_PCB_ONFAULT(at_reg)
.set at
ldq ra, (16-8)(sp) /* restore ra. */
lda sp, 16(sp) /* kill stack frame. */
RET /* v0 left over from copystr */
#endif
END(copyoutstr)
/*
* Alternative memory mover
*/
LEAF(memcpy,3)
#if 0
mov a0,t0
mov a1,a0
mov t0,a1
br bcopy
#endif
END(memcpy)
2: cmp.eq p6,p0=r0,in3
(p6) br.cond.dpnt.few 3f // if (lenp != NULL)
sub r14=in2,r14 // *lenp = (i - len)
;;
st8 [in3]=r14
3: cmp.eq p6,p0=r0,r15
(p6) br.cond.spnt.few 4f // *from == '\0'; leave quietly
mov ret0=ENAMETOOLONG // *from != '\0'; error.
br.ret.sptk.few rp
4: mov ret0=0 // return 0.
br.ret.sptk.few rp
END(copystr)
NESTED(copyinstr, 4)
alloc loc0=ar.pfs,4,3,4,0
mov loc1=rp
movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr
;;
cmp.ltu p6,p0=in0,loc2 // is in user space.
;;
(p6) br.cond.spnt.few copyerr // if it's not, error out.
movl r14=copyerr // set up fault handler.
add r15=GD_CURPROC,r13 // find curproc
;;
ld8 r15=[r15]
;;
add r15=P_ADDR,r15 // find pcb
;;
ld8 r15=[r15]
;;
add loc2=U_PCB_ONFAULT,r15
;;
st8 [loc2]=r14
;;
mov out0=in0
mov out1=in1
mov out2=in2
mov out3=in3
;;
br.call.sptk.few rp=copystr // do the copy.
st8 [loc2]=r0 // kill the fault handler.
mov rp=loc1 // restore ra.
br.ret.sptk.few rp // ret0 left over from copystr
END(copyinstr)
NESTED(copyoutstr, 4)
alloc loc0=ar.pfs,4,3,4,0
mov loc1=rp
movl loc2=VM_MAXUSER_ADDRESS // make sure that dest addr
;;
cmp.ltu p6,p0=in1,loc2 // is in user space.
;;
(p6) br.cond.spnt.few copyerr // if it's not, error out.
movl r14=copyerr // set up fault handler.
add r15=GD_CURPROC,r13 // find curproc
;;
ld8 r15=[r15]
;;
add r15=P_ADDR,r15 // find pcb
;;
ld8 r15=[r15]
;;
add loc2=U_PCB_ONFAULT,r15
;;
st8 [loc2]=r14
;;
mov out0=in0
mov out1=in1
mov out2=in2
mov out3=in3
;;
br.call.sptk.few rp=copystr // do the copy.
st8 [loc2]=r0 // kill the fault handler.
mov rp=loc1 // restore ra.
br.ret.sptk.few rp // ret0 left over from copystr
END(copyoutstr)
/*
* Copy a bytes within the kernel's address space.
*
* In the kernel, bcopy() doesn't have to handle the overlapping
* case; that's that ovbcopy() is for. However, it doesn't hurt
* to do both in bcopy, and it does provide a measure of safety.
*
* void bcopy(char *from, char *to, size_t len);
* void ovbcopy(char *from, char *to, size_t len);
* Not the fastest bcopy in the world.
*/
LEAF(bcopy,3)
LEAF(bcopy, 3)
XLEAF(ovbcopy)
#if 0
/* Check for negative length */
ble a2,bcopy_done
/* Check for overlap */
subq a1,a0,t5
cmpult t5,a2,t5
bne t5,bcopy_overlap
mov ret0=r0 // return zero for copy{in,out}
;;
cmp.le p6,p0=in2,r0 // bail if len <= 0
(p6) br.ret.spnt.few rp
/* a3 = end address */
addq a0,a2,a3
sub r14=in1,in0 ;; // check for overlap
cmp.ltu p6,p0=r14,in2 // dst-src < len
(p6) br.cond.spnt.few 5f
/* Get the first word */
ldq_u t2,0(a0)
extr.u r14=in0,0,3 // src & 7
extr.u r15=in1,0,3 ;; // dst & 7
cmp.eq p6,p0=r14,r15 // different alignment?
(p6) br.cond.spnt.few 2f // branch if same alignment
/* Do they have the same alignment? */
xor a0,a1,t0
and t0,7,t0
and a1,7,t1
bne t0,bcopy_different_alignment
1: ld1 r14=[in0],1 ;; // copy bytewise
st1 [in1]=r14,1
add in2=-1,in2 ;; // len--
cmp.ne p6,p0=r0,in2
(p6) br.cond.dptk.few 1b // loop
br.ret.sptk.few rp // done
/* src & dst have same alignment */
beq t1,bcopy_all_aligned
2: cmp.eq p6,p0=r14,r0 // aligned?
(p6) br.cond.sptk.few 4f
ldq_u t3,0(a1)
addq a2,t1,a2
mskqh t2,a0,t2
mskql t3,a0,t3
or t2,t3,t2
3: ld1 r14=[in0],1 ;; // copy bytewise
st1 [in1]=r14,1
extr.u r15=in0,0,3 // src & 7
add in2=-1,in2 ;; // len--
cmp.eq p6,p0=r0,in2 // done?
cmp.eq p7,p0=r0,r15 ;; // aligned now?
(p6) br.ret.spnt.few rp // return if done
(p7) br.cond.spnt.few 4f // go to main copy
br.cond.sptk.few 3b // more bytes to copy
/* Dst is 8-byte aligned */
// At this point, in2 is non-zero
bcopy_all_aligned:
/* If less than 8 bytes,skip loop */
subq a2,1,t0
and a2,7,a2
bic t0,7,t0
beq t0,bcopy_samealign_lp_end
4: mov r14=8 ;;
cmp.ltu p6,p0=in2,r14 ;; // len < 8?
(p6) br.cond.spnt.few 1b // byte copy the end
ld8 r15=[in0],8 ;; // copy word
st8 [in1]=r15,8
add in2=-8,in2 ;; // len -= 8
cmp.ne p6,p0=r0,in2 // done?
(p6) br.cond.spnt.few 4b // again
bcopy_samealign_lp:
stq_u t2,0(a1)
addq a1,8,a1
ldq_u t2,8(a0)
subq t0,8,t0
addq a0,8,a0
bne t0,bcopy_samealign_lp
br.ret.sptk.few rp // return
bcopy_samealign_lp_end:
/* If we're done, exit */
bne a2,bcopy_small_left
stq_u t2,0(a1)
RET
// Don't bother optimising overlap case
bcopy_small_left:
mskql t2,a2,t4
ldq_u t3,0(a1)
mskqh t3,a2,t3
or t4,t3,t4
stq_u t4,0(a1)
RET
5: add in0=in0,in2
add in1=in1,in2 ;;
add in0=-1,in0
add in1=-1,in1 ;;
bcopy_different_alignment:
/*
* this is the fun part
*/
addq a0,a2,a3
cmpule a2,8,t0
bne t0,bcopy_da_finish
6: ld1 r14=[in0],-1 ;;
st1 [in1]=r14,-1
add in2=-1,in2 ;;
cmp.ne p6,p0=r0,in2
(p6) br.cond.spnt.few 6b
beq t1,bcopy_da_noentry
br.ret.sptk.few rp
/* Do the initial partial word */
subq zero,a1,t0
and t0,7,t0
ldq_u t3,7(a0)
extql t2,a0,t2
extqh t3,a0,t3
or t2,t3,t5
insql t5,a1,t5
ldq_u t6,0(a1)
mskql t6,a1,t6
or t5,t6,t5
stq_u t5,0(a1)
addq a0,t0,a0
addq a1,t0,a1
subq a2,t0,a2
ldq_u t2,0(a0)
END(bcopy)
bcopy_da_noentry:
subq a2,1,t0
bic t0,7,t0
and a2,7,a2
beq t0,bcopy_da_finish2
bcopy_da_lp:
ldq_u t3,7(a0)
addq a0,8,a0
extql t2,a0,t4
extqh t3,a0,t5
subq t0,8,t0
or t4,t5,t5
stq t5,0(a1)
addq a1,8,a1
beq t0,bcopy_da_finish1
ldq_u t2,7(a0)
addq a0,8,a0
extql t3,a0,t4
extqh t2,a0,t5
subq t0,8,t0
or t4,t5,t5
stq t5,0(a1)
addq a1,8,a1
bne t0,bcopy_da_lp
bcopy_da_finish2:
/* Do the last new word */
mov t2,t3
bcopy_da_finish1:
/* Do the last partial word */
ldq_u t2,-1(a3)
extql t3,a0,t3
extqh t2,a0,t2
or t2,t3,t2
br zero,bcopy_samealign_lp_end
bcopy_da_finish:
/* Do the last word in the next source word */
ldq_u t3,-1(a3)
extql t2,a0,t2
extqh t3,a0,t3
or t2,t3,t2
insqh t2,a1,t3
insql t2,a1,t2
lda t4,-1(zero)
mskql t4,a2,t5
cmovne t5,t5,t4
insqh t4,a1,t5
insql t4,a1,t4
addq a1,a2,a4
ldq_u t6,0(a1)
ldq_u t7,-1(a4)
bic t6,t4,t6
bic t7,t5,t7
and t2,t4,t2
and t3,t5,t3
or t2,t6,t2
or t3,t7,t3
stq_u t3,-1(a4)
stq_u t2,0(a1)
RET
bcopy_overlap:
/*
* Basically equivalent to previous case, only backwards.
* Not quite as highly optimized
*/
addq a0,a2,a3
addq a1,a2,a4
/* less than 8 bytes - don't worry about overlap */
cmpule a2,8,t0
bne t0,bcopy_ov_short
/* Possibly do a partial first word */
and a4,7,t4
beq t4,bcopy_ov_nostart2
subq a3,t4,a3
subq a4,t4,a4
ldq_u t1,0(a3)
subq a2,t4,a2
ldq_u t2,7(a3)
ldq t3,0(a4)
extql t1,a3,t1
extqh t2,a3,t2
or t1,t2,t1
mskqh t3,t4,t3
mskql t1,t4,t1
or t1,t3,t1
stq t1,0(a4)
bcopy_ov_nostart2:
bic a2,7,t4
and a2,7,a2
beq t4,bcopy_ov_lp_end
bcopy_ov_lp:
/* This could be more pipelined, but it doesn't seem worth it */
ldq_u t0,-8(a3)
subq a4,8,a4
ldq_u t1,-1(a3)
subq a3,8,a3
extql t0,a3,t0
extqh t1,a3,t1
subq t4,8,t4
or t0,t1,t0
stq t0,0(a4)
bne t4,bcopy_ov_lp
bcopy_ov_lp_end:
beq a2,bcopy_done
ldq_u t0,0(a0)
ldq_u t1,7(a0)
ldq_u t2,0(a1)
extql t0,a0,t0
extqh t1,a0,t1
or t0,t1,t0
insql t0,a1,t0
mskql t2,a1,t2
or t2,t0,t2
stq_u t2,0(a1)
bcopy_done:
RET
bcopy_ov_short:
ldq_u t2,0(a0)
br zero,bcopy_da_finish
#endif
END(bcopy)
LEAF(memcpy,3)
LEAF(copyin, 3)
#if 0
LDGP(pv)
lda sp, -16(sp) /* set up stack frame */
stq ra, (16-8)(sp) /* save ra */
ldiq t0, VM_MAXUSER_ADDRESS /* make sure that src addr */
cmpult a0, t0, t1 /* is in user space. */
beq t1, copyerr /* if it's not, error out. */
lda v0, copyerr /* set up fault handler. */
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq v0, U_PCB_ONFAULT(at_reg)
.set at
CALL(bcopy) /* do the copy. */
.set noat
ldq at_reg, curproc /* kill the fault handler. */
ldq at_reg, P_ADDR(at_reg)
stq zero, U_PCB_ONFAULT(at_reg)
.set at
ldq ra, (16-8)(sp) /* restore ra. */
lda sp, 16(sp) /* kill stack frame. */
mov zero, v0 /* return 0. */
RET
#endif
END(copyin)
mov r14=in0 ;;
mov in0=in1 ;;
mov in1=r14
br.cond.sptk.few bcopy
END(memcpy)
NESTED(copyin, 3)
alloc loc0=ar.pfs,3,3,3,0
mov loc1=rp
LEAF(copyout, 3)
#if 0
LDGP(pv)
lda sp, -16(sp) /* set up stack frame */
stq ra, (16-8)(sp) /* save ra */
ldiq t0, VM_MAXUSER_ADDRESS /* make sure that dest addr */
cmpult a1, t0, t1 /* is in user space. */
beq t1, copyerr /* if it's not, error out. */
lda v0, copyerr /* set up fault handler. */
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq v0, U_PCB_ONFAULT(at_reg)
.set at
CALL(bcopy) /* do the copy. */
.set noat
ldq at_reg, curproc /* kill the fault handler. */
ldq at_reg, P_ADDR(at_reg)
stq zero, U_PCB_ONFAULT(at_reg)
.set at
ldq ra, (16-8)(sp) /* restore ra. */
lda sp, 16(sp) /* kill stack frame. */
mov zero, v0 /* return 0. */
RET
#endif
END(copyout)
movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr
;;
cmp.ltu p6,p0=in0,loc2 // is in user space.
;;
(p6) br.cond.spnt.few copyerr // if it's not, error out.
movl r14=copyerr // set up fault handler.
add r15=GD_CURPROC,r13 // find curproc
;;
ld8 r15=[r15]
;;
add r15=P_ADDR,r15 // find pcb
;;
ld8 r15=[r15]
;;
add loc2=U_PCB_ONFAULT,r15
;;
st8 [loc2]=r14
;;
mov out0=in0
mov out1=in1
mov out2=in2
;;
br.call.sptk.few rp=bcopy // do the copy.
st8 [loc2]=r0 // kill the fault handler.
mov rp=loc1 // restore ra.
br.ret.sptk.few rp // ret0 left over from bcopy
END(copyin)
NESTED(copyout, 3)
alloc loc0=ar.pfs,3,3,3,0
mov loc1=rp
movl loc2=VM_MAXUSER_ADDRESS // make sure that dest addr
;;
cmp.ltu p6,p0=in1,loc2 // is in user space.
;;
(p6) br.cond.spnt.few copyerr // if it's not, error out.
movl r14=copyerr // set up fault handler.
add r15=GD_CURPROC,r13 // find curproc
;;
ld8 r15=[r15]
;;
add r15=P_ADDR,r15 // find pcb
;;
ld8 r15=[r15]
;;
add loc2=U_PCB_ONFAULT,r15
;;
st8 [loc2]=r14
;;
mov out0=in0
mov out1=in1
mov out2=in2
;;
br.call.sptk.few rp=bcopy // do the copy.
st8 [loc2]=r0 // kill the fault handler.
mov rp=loc1 // restore ra.
br.ret.sptk.few rp // ret0 left over from bcopy
END(copyout)
LEAF(copyerr, 0)
#if 0
ldq t0, curproc
ldq t0, P_ADDR(t0)
stq zero, U_PCB_ONFAULT(t0) /* reset fault handler. */
ldq ra, (16-8)(sp) /* restore ra. */
lda sp, 16(sp) /* kill stack frame. */
ldiq v0, EFAULT /* return EFAULT. */
RET
#endif
END(copyerr)
add r14=GD_CURPROC,r13 ;; // find curproc
ld8 r14=[r14] ;;
add r14=P_ADDR,r14 ;; // curproc->p_addr
ld8 r14=[r14] ;;
add r14=U_PCB_ONFAULT,r14 ;; // &curproc->p_addr->u_pcb.pcb_onfault
st8 [r14]=r0 // reset fault handler
mov ret0=EFAULT // return EFAULT
br.ret.sptk.few rp
END(copyerr)
/**************************************************************************/

View File

@ -30,8 +30,6 @@
#include <machine/mutex.h>
#include "assym.s"
/**************************************************************************/
/*
* savectx: save process context, i.e. callee-saved registers
*
@ -45,16 +43,20 @@
*/
LEAF(savectx, 1)
alloc r2=ar.pfs,1,0,0,0
;;
flushrs // push out caller's dirty regs
mov r3=ar.unat // caller's value for ar.unat
;;
mov ar.rsc=r0 // stop the RSE after the flush
mov ar.rsc=0 // stop the RSE after the flush
;;
mov r16=ar.rnat // read RSE's NaT collection
mov r17=in0
mov r18=ar.bspstore
mov r19=b0
mov r20=b1
mov r21=b2
mov r22=b3
mov r23=b4
mov r24=b5
;;
st8.spill [r17]=r4,8 ;; // save r4..r6
st8.spill [r17]=r5,8 ;; // and accumulate NaT bits
@ -65,10 +67,16 @@ LEAF(savectx, 1)
stf.spill [r17]=f3,16 ;;
stf.spill [r17]=f4,16 ;;
stf.spill [r17]=f5,16 ;;
st8 [r17]=r19,8 ;; // save b0..b5
st8 [r17]=r20,8 ;;
st8 [r17]=r21,8 ;;
st8 [r17]=r22,8 ;;
st8 [r17]=r23,8 ;;
st8 [r17]=r24,8 ;;
mov r19=ar.unat // NaT bits for r4..r6
mov r20=pr
mov r21=rp
mov ret0=r0 // return zero
st8 [r17]=r3,8 ;; // save caller's ar.unat
@ -78,7 +86,6 @@ LEAF(savectx, 1)
st8 [r17]=r19,8 ;; // our NaT bits
st8 [r17]=r16,8 ;; // ar.rnat
st8 [r17]=r20,8 ;; // pr
st8 [r17]=r21,8 ;; // return address
mov ar.rsc=3 // turn RSE back on
@ -97,21 +104,35 @@ LEAF(savectx, 1)
*/
LEAF(restorectx, 1)
alloc r2=ar.pfs,1,0,0,0
add r3=U_PCB_UNAT,in0 // point at NaT for r4..r7
mov ar.rsc=r0 ;; // switch off the RSE
mov ar.rsc=0 ;; // switch off the RSE
ld8 r16=[r3] // load NaT for r4..r7
;;
mov ar.unat=r16
;;
ld8.fill r4=[in0],8 ;; // restore r4
ld8.fill r5=[in0],8 ;; // restore r5
ld8.fill r6=[in0],8 ;; // restore r6
ld8.fill r7=[in0],8 ;; // restore r7
ldf.fill f2=[in0],8 ;; // restore f2
ldf.fill f3=[in0],8 ;; // restore f3
ldf.fill f4=[in0],8 ;; // restore f4
ldf.fill f5=[in0],8 ;; // restore f5
ldf.fill f2=[in0],16 ;; // restore f2
ldf.fill f3=[in0],16 ;; // restore f3
ldf.fill f4=[in0],16 ;; // restore f4
ldf.fill f5=[in0],16 ;; // restore f5
ld8 r16=[in0],8 ;; // restore b0
ld8 r17=[in0],8 ;; // restore b1
ld8 r18=[in0],8 ;; // restore b2
ld8 r19=[in0],8 ;; // restore b3
ld8 r20=[in0],8 ;; // restore b4
ld8 r21=[in0],8 ;; // restore b5
mov b0=r16
mov b1=r17
mov b2=r18
mov b3=r19
mov b4=r20
mov b5=r21
ld8 r16=[in0],8 ;; // caller's ar.unat
ld8 sp=[in0],8 ;; // stack pointer
@ -119,37 +140,39 @@ LEAF(restorectx, 1)
ld8 r18=[in0],16 ;; // ar.bspstore, skip ar.unat
ld8 r19=[in0],8 ;; // ar.rnat
ld8 r20=[in0],8 ;; // pr
ld8 r21=[in0],8 ;; // iip
mov ar.unat=r16
mov ar.pfs=r17
mov ar.bspstore=r18 ;;
mov ar.rnat=r19
mov pr=r20,0x1ffff
mov rp=r21
mov ret0=r21 // non-zero return
mov ret0=r18 // non-zero return
;;
loadrs
mov ar.rsc=3 // restart RSE
invala
;;
br.ret.sptk.few rp
END(restorectx)
/**************************************************************************/
IMPORT(want_resched, 4)
/*
* switch_trampoline()
*
* Arrange for a function to be invoked neatly, after a cpu_switch().
*
* Invokes the function specified by the s0 register with the return
* address specified by the s1 register and with one argument, a
* pointer to the executing process's proc structure.
* Invokes the function specified by the r4 register with the return
* address specified by the r5 register and with one argument, taken
* from r6.
*/
LEAF(switch_trampoline, 0)
MTX_EXIT(sched_lock#, r14, r15)
/* XXX write this */
MTX_EXIT(sched_lock, r14, r15)
alloc r16=ar.pfs,0,0,1,0
mov b7=r4
mov b0=r5
mov out0=r6
;;
br.call.sptk.few b6=b7
END(switch_trampoline)

View File

@ -126,12 +126,6 @@ cpu_fork(p1, p2, flags)
p2->p_md.md_tf = p1->p_md.md_tf;
p2->p_md.md_flags = p1->p_md.md_flags & (MDP_FPUSED | MDP_UAC_MASK);
/*
* Cache the physical address of the pcb, so we can
* swap to it easily.
*/
p2->p_md.md_pcbpaddr = (void*)vtophys((vm_offset_t)&p2->p_addr->u_pcb);
/*
* Copy floating point state from the FP chip to the PCB
* if this process has state stored there.
@ -145,10 +139,6 @@ cpu_fork(p1, p2, flags)
* new process has FEN disabled.
*/
p2->p_addr->u_pcb = p1->p_addr->u_pcb;
#if 0
p2->p_addr->u_pcb.pcb_hw.apcb_usp = ia64_pal_rdusp();
p2->p_addr->u_pcb.pcb_hw.apcb_flags &= ~IA64_PCB_FLAGS_FEN;
#endif
/*
* Set the floating point state.
@ -179,6 +169,7 @@ cpu_fork(p1, p2, flags)
{
struct user *up = p2->p_addr;
struct trapframe *p2tf;
u_int64_t bspstore, *p1bs, *p2bs, rnatloc, rnat;
/*
* Pick a stack pointer, leaving room for a trapframe;
@ -193,27 +184,77 @@ cpu_fork(p1, p2, flags)
/*
* Set up return-value registers as fork() libc stub expects.
*/
#if 0
p2tf->tf_regs[FRAME_V0] = 0; /* child's pid (linux) */
p2tf->tf_regs[FRAME_A3] = 0; /* no error */
p2tf->tf_regs[FRAME_A4] = 1; /* is child (FreeBSD) */
p2tf->tf_r[FRAME_R8] = 0; /* child's pid (linux) */
p2tf->tf_r[FRAME_R9] = 0; /* no error */
p2tf->tf_r[FRAME_R10] = 1; /* is child (FreeBSD) */
/*
* Turn off RSE for a moment and work out our current
* ar.bspstore. This assumes that p1==curproc. Also
* flush dirty regs to ensure that the user's stacked
* regs are written out to backing store.
*
* We could cope with p1!=curproc by digging values
* out of its PCB but I don't see the point since
* current usage never allows it.
*/
__asm __volatile("mov ar.rsc=0;;");
__asm __volatile("flushrs;;" ::: "memory");
__asm __volatile("mov %0=ar.bspstore" : "=r"(bspstore));
p1bs = (u_int64_t *) (p1->p_addr + 1);
p2bs = (u_int64_t *) (p2->p_addr + 1);
/*
* Copy enough of p1's backing store to include all
* the user's stacked regs.
*/
bcopy(p1bs, p2bs, (p1->p_md.md_tf->tf_ar_bsp
- p1->p_md.md_tf->tf_ar_bspstore));
/*
* To calculate the ar.rnat for p2, we need to decide
* if p1's ar.bspstore has advanced past the place
* where the last ar.rnat which covers the user's
* saved registers would be placed. If so, we read
* that one from memory, otherwise we take p1's
* current ar.rnat.
*/
rnatloc = (u_int64_t)
(p1bs + (p1->p_md.md_tf->tf_ar_bsp
- p1->p_md.md_tf->tf_ar_bspstore));
rnatloc |= 0x1f8;
if (bspstore > rnatloc)
rnat = *(u_int64_t *) rnatloc;
else
__asm __volatile("mov %0=ar.rnat;;" : "=r"(rnat));
/*
* Switch the RSE back on.
*/
__asm __volatile("mov ar.rsc=3;;");
/*
* Setup the child's pcb so that its ar.bspstore
* starts just above the region which we copied. This
* should work since the child will normally return
* straight into exception_return.
*/
up->u_pcb.pcb_bspstore = (u_int64_t)
(p2bs + (p1->p_md.md_tf->tf_ar_bsp
- p1->p_md.md_tf->tf_ar_bspstore));
up->u_pcb.pcb_rnat = rnat;
/*
* Arrange for continuation at child_return(), which
* will return to exception_return(). Note that the child
* process doesn't stay in the kernel for long!
*
* This is an inlined version of cpu_set_kpc.
*/
up->u_pcb.pcb_hw.apcb_ksp = (u_int64_t)p2tf;
up->u_pcb.pcb_context[0] =
(u_int64_t)child_return; /* s0: pc */
up->u_pcb.pcb_context[1] =
(u_int64_t)exception_return; /* s1: ra */
up->u_pcb.pcb_context[2] = (u_long) p2; /* s2: a0 */
up->u_pcb.pcb_context[7] =
(u_int64_t)switch_trampoline; /* ra: assembly magic */
#endif
up->u_pcb.pcb_sp = (u_int64_t)p2tf - 16;
up->u_pcb.pcb_r4 = (u_int64_t)child_return;
up->u_pcb.pcb_r5 = (u_int64_t)exception_return;
up->u_pcb.pcb_r6 = (u_int64_t)p2;
up->u_pcb.pcb_b0 = (u_int64_t)switch_trampoline;
}
}
@ -229,14 +270,8 @@ cpu_set_fork_handler(p, func, arg)
void (*func) __P((void *));
void *arg;
{
#if 0
/*
* Note that the trap frame follows the args, so the function
* is really called like this: func(arg, frame);
*/
p->p_addr->u_pcb.pcb_context[0] = (u_long) func;
p->p_addr->u_pcb.pcb_context[2] = (u_long) arg;
#endif
p->p_addr->u_pcb.pcb_r4 = (u_int64_t) func;
p->p_addr->u_pcb.pcb_r6 = (u_int64_t) arg;
}
/*

View File

@ -114,33 +114,27 @@ _name_:; \
* A nested function calls other functions and needs
* to use alloc to save registers.
*/
#define NESTED(_name_,_n_args_,_n_locals_,_n_outputs_, \
_pfs_reg_,_rp_reg_) \
.globl _name_; \
.proc _name_; \
_name_:; \
alloc _pfs_reg_=ar.pfs,_n_args_,_n_locals_,_n_outputs_,0;; \
mov _rp_reg_=rp \
#define NESTED(_name_,_n_args_) \
.globl _name_; \
.proc _name_; \
_name_:; \
.regstk _n_args_, 0, 0, 0 \
MCOUNT
#define NESTED_NOPROFILE(_name_,_n_args_,_n_locals_,_n_outputs_, \
_pfs_reg_,_rp_reg_) \
.globl _name_; \
.proc _name_; \
_name_:; \
alloc _pfs_reg_=ar.pfs,_n_args_,_n_locals_,_n_outputs_,0;; \
mov _rp_reg_=rp
#define NESTED_NOPROFILE(_name_,_n_args_) \
.globl _name_; \
.proc _name_; \
_name_:; \
.regstk _n_args_, 0, 0, 0
/*
* STATIC_NESTED
* Declare a local nested function.
*/
#define STATIC_NESTED(_name_,_n_args_,_n_locals_,_n_outputs_, \
_pfs_reg_,_rp_reg_) \
.proc _name_; \
_name_:; \
alloc _pfs_reg_=ar.pfs,_n_args_,_n_locals_,_n_outputs_,0;; \
mov _rp_reg_=rp;; \
#define STATIC_NESTED(_name_,_n_args_) \
.proc _name_; \
_name_:; \
.regstk _n_args_, 0, 0, 0 \
MCOUNT
/*

View File

@ -186,13 +186,36 @@ ia64_tpa(u_int64_t va)
* Read the value of ar.itc.
*/
static __inline u_int64_t
ia64_read_itc(void)
ia64_get_itc(void)
{
u_int64_t result;
__asm __volatile("mov %0=ar.itc" : "=r" (result));
return result;
}
/*
* Read the value of ar.itm.
*/
static __inline u_int64_t
ia64_get_itm(void)
{
u_int64_t result;
__asm __volatile("mov %0=cr.itm" : "=r" (result));
return result;
}
/*
* Write the value of ar.itm.
*/
static __inline void
ia64_set_itm(u_int64_t v)
{
__asm __volatile("mov cr.itm=%0" :: "r" (v));
}
/*
* Write a region register.
*/
static __inline void
ia64_set_rr(u_int64_t rrbase, u_int64_t v)
{

View File

@ -43,6 +43,13 @@ struct pcb {
struct ia64_fpreg pcb_f4;
struct ia64_fpreg pcb_f5;
u_int64_t pcb_b0; /* really restart address */
u_int64_t pcb_b1;
u_int64_t pcb_b2;
u_int64_t pcb_b3;
u_int64_t pcb_b4;
u_int64_t pcb_b5;
u_int64_t pcb_old_unat; /* caller's ar.unat */
u_int64_t pcb_sp;
u_int64_t pcb_pfs;
@ -51,10 +58,9 @@ struct pcb {
u_int64_t pcb_unat; /* ar.unat for r4..r7 */
u_int64_t pcb_rnat;
u_int64_t pcb_pr; /* predicates */
u_int64_t pcb_iip; /* address to restart */
unsigned long pcb_onfault; /* for copy faults */
unsigned long pcb_accessaddr; /* for [fs]uswintr */
u_int64_t pcb_onfault; /* for copy faults */
u_int64_t pcb_accessaddr; /* for [fs]uswintr */
};
/*

View File

@ -38,7 +38,6 @@
struct mdproc {
u_long md_flags;
struct trapframe *md_tf; /* trap/syscall registers */
struct pcb *md_pcbpaddr; /* phys addr of the pcb */
};
#define MDP_FPUSED 0x0001 /* Process used the FPU */