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:
parent
534f2a9dad
commit
431f3cb41d
@ -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
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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));
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
@ -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)
|
@ -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);
|
||||
}
|
||||
|
||||
/***************************************************
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
|
@ -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)
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
||||
/*
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user