Return to BSD News archive
Path: euryale.cc.adfa.oz.au!newshost.carno.net.au!harbinger.cc.monash.edu.au!news.rmit.EDU.AU!goanna.cs.rmit.edu.au!news.apana.org.au!cantor.edge.net.au!news.teragen.com.au!news.access.net.au!news.mel.connect.com.au!munnari.OZ.AU!news.ecn.uoknor.edu!feed1.news.erols.com!howland.erols.net!newsxfer3.itd.umich.edu!feeder.chicago.cic.net!news.sba.com!pacifier!deraadt
From: deraadt@theos.com (Theo de Raadt)
Newsgroups: comp.unix.bsd.netbsd.misc
Subject: Re: Why no addusr?
Date: 15 Feb 1997 22:50:22 GMT
Organization: Theo Ports Kernels For Fun And Profit
Lines: 1604
Message-ID: <DERAADT.97Feb15155022@zeus.pacifier.com>
References: <none-ya023480001912962244220001@news.infi.net>
<1997Feb14.090136@screwem.citi.umich.edu> <5e2sb7$62a@panix2.panix.com>
<DERAADT.97Feb14205132@zeus.pacifier.com> <5e52dj$c8p@news.bayarea.net>
NNTP-Posting-Host: zeus.theos.com
In-reply-to: thorpej@baygate.bayarea.net's message of 15 Feb 1997 19:22:27 GMT
Xref: euryale.cc.adfa.oz.au comp.unix.bsd.netbsd.misc:5417
In article <5e52dj$c8p@news.bayarea.net> thorpej@baygate.bayarea.net (Jason R. Thorpe) writes:
>Instead your project has developers that put #ifndef __OpenBSD__ into
>NetBSD source files so the FREE code, when merged into another system
>which happens to #define __OpenBSD__ will experience machine resets,
>right? (Hint to those who are curious, go get an alpha locore.S from
>January or so.)
Well, the only suggestion I can offer is that you are more careful when
integrating code in the future.
More careful, oh.
Here is the file.
The key is to search down to __OpenBSD__. I don't know much alpha
assembly either, but I think someone can guess that this might be
nasty.
Why would someone write code in such a way?
/* $NetBSD: locore.s,v 1.27 1996/12/03 19:54:16 cgd Exp $ */
/*
* Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
* All rights reserved.
*
* Author: Chris G. Demetriou
*
* Permission to use, copy, modify and distribute this software and
* its documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
#include <machine/asm.h>
#ifndef EVCNT_COUNTERS
#include <machine/intrcnt.h>
#endif
#include "assym.h"
/* don't reorder instructions; paranoia. */
.set noreorder
.text
/*
* This is for kvm_mkdb, and should be the address of the beginning
* of the kernel text segment (not necessarily the same as kernbase).
*/
EXPORT(kernel_text)
kernel_text:
/*
* bootstack: a temporary stack, for booting.
*
* Extends from 'start' down.
*/
bootstack:
/*
* __start: Kernel start.
*
* Arguments:
* a0 is the first free page frame number (PFN)
* a1 is the page table base register (PTBR)
*
* All arguments are passed to alpha_init().
*/
NESTED_NOPROFILE(__start,1,0,ra,0,0)
br pv,Lstart1
Lstart1: LDGP(pv)
/* Switch to the boot stack. */
lda sp,bootstack
/* 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 and a1.
*/
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)
call_pal PAL_OSF1_swpctx
ldiq a0, -2
call_pal PAL_OSF1_tbi
/*
* 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 /* main()'s arg is frame ptr */
CALL(main) /* go to main()! */
/*
* 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." */
END(__start)
/**************************************************************************/
/*
* Pull in the PROM interface routines; these are needed for
* prom printf (while bootstrapping), and for determining the
* boot device, etc.
*/
#include <alpha/alpha/prom_disp.s>
/**************************************************************************/
/*
* Pull in the PALcode function stubs.
*/
#include <alpha/alpha/pal.s>
/**************************************************************************/
.data
EXPORT(cold)
.long 1 /* cold start flag (.long -> _4_ bytes) */
.text
/**************************************************************************/
/*
* Signal "trampoline" code. Invoked from RTE setup by sendsig().
*
* On entry, stack & registers look like:
*
* a0 signal number
* a1 signal specific code
* a2 pointer to signal context frame (scp)
* a3 address of handler
* sp+0 saved hardware state
* .
* .
* scp+0 beginning of signal context frame
*/
NESTED(sigcode,0,0,ra,0,0)
lda sp, -16(sp) /* save the sigcontext pointer */
stq a2, 0(sp)
jsr ra, (t12) /* call the signal handler (t12==pv) */
ldq a0, 0(sp) /* get the sigcontext pointer */
lda sp, 16(sp)
CALLSYS_NOERROR(sigreturn) /* and call sigreturn() with it. */
mov v0, a0 /* if that failed, get error code */
CALLSYS_NOERROR(exit) /* and call exit() with it. */
XNESTED(esigcode,0)
END(sigcode)
/**************************************************************************/
/*
* exception_return: return from trap, exception, or syscall
*/
BSS(ssir, 8)
IMPORT(astpending, 8)
LEAF(exception_return, 1) /* XXX should be NESTED */
br pv, Ler1
Ler1: LDGP(pv)
ldq s1, (FRAME_PS * 8)(sp) /* get the saved PS */
and s1, ALPHA_PSL_IPL_MASK, t0 /* look at the saved IPL */
bne t0, Lrestoreregs /* != 0: can't do AST or SIR */
/* see if we can do an SIR */
ldq t1, ssir /* SIR pending? */
beq t1, Lchkast /* no, try an AST*/
/* We've got a SIR. */
CALL(do_sir) /* do the SIR; lowers IPL */
Lchkast:
ldiq a0, ALPHA_PSL_IPL_0 /* drop IPL to zero*/
call_pal PAL_OSF1_swpipl
and s1, ALPHA_PSL_USERMODE, t0 /* are we returning to user? */
beq t0, Lrestoreregs /* no: just return */
ldq t2, astpending /* AST pending? */
beq t2, Lsetfpenable /* no: return & deal with FP */
/* We've got an AST. Handle it. */
mov sp, a0 /* only arg is frame */
CALL(ast)
Lsetfpenable:
/* enable FPU based on whether the current proc is fpcurproc */
ldq t0, curproc
ldq t1, fpcurproc
cmpeq t0, t1, t0
mov zero, a0
cmovne t0, 1, a0
call_pal PAL_OSF1_wrfen
Lrestoreregs:
/* restore the registers, and return */
bsr ra, exception_restore_regs /* jmp/CALL trashes pv/t12 */
ldq ra,(FRAME_RA*8)(sp)
.set noat
ldq at_reg,(FRAME_AT*8)(sp)
lda sp,(FRAME_SW_SIZE*8)(sp)
call_pal PAL_OSF1_rti
.set at
END(exception_return)
LEAF(exception_save_regs, 0)
stq v0,(FRAME_V0*8)(sp)
stq a3,(FRAME_A3*8)(sp)
stq a4,(FRAME_A4*8)(sp)
stq a5,(FRAME_A5*8)(sp)
stq s0,(FRAME_S0*8)(sp)
stq s1,(FRAME_S1*8)(sp)
stq s2,(FRAME_S2*8)(sp)
stq s3,(FRAME_S3*8)(sp)
stq s4,(FRAME_S4*8)(sp)
stq s5,(FRAME_S5*8)(sp)
stq s6,(FRAME_S6*8)(sp)
stq t0,(FRAME_T0*8)(sp)
stq t1,(FRAME_T1*8)(sp)
stq t2,(FRAME_T2*8)(sp)
stq t3,(FRAME_T3*8)(sp)
stq t4,(FRAME_T4*8)(sp)
stq t5,(FRAME_T5*8)(sp)
stq t6,(FRAME_T6*8)(sp)
stq t7,(FRAME_T7*8)(sp)
stq t8,(FRAME_T8*8)(sp)
stq t9,(FRAME_T9*8)(sp)
stq t10,(FRAME_T10*8)(sp)
stq t11,(FRAME_T11*8)(sp)
stq t12,(FRAME_T12*8)(sp)
RET
END(exception_save_regs)
LEAF(exception_restore_regs, 0)
ldq v0,(FRAME_V0*8)(sp)
ldq a3,(FRAME_A3*8)(sp)
ldq a4,(FRAME_A4*8)(sp)
ldq a5,(FRAME_A5*8)(sp)
ldq s0,(FRAME_S0*8)(sp)
ldq s1,(FRAME_S1*8)(sp)
ldq s2,(FRAME_S2*8)(sp)
ldq s3,(FRAME_S3*8)(sp)
ldq s4,(FRAME_S4*8)(sp)
ldq s5,(FRAME_S5*8)(sp)
ldq s6,(FRAME_S6*8)(sp)
ldq t0,(FRAME_T0*8)(sp)
ldq t1,(FRAME_T1*8)(sp)
ldq t2,(FRAME_T2*8)(sp)
ldq t3,(FRAME_T3*8)(sp)
ldq t4,(FRAME_T4*8)(sp)
ldq t5,(FRAME_T5*8)(sp)
ldq t6,(FRAME_T6*8)(sp)
ldq t7,(FRAME_T7*8)(sp)
ldq t8,(FRAME_T8*8)(sp)
ldq t9,(FRAME_T9*8)(sp)
ldq t10,(FRAME_T10*8)(sp)
ldq t11,(FRAME_T11*8)(sp)
ldq t12,(FRAME_T12*8)(sp)
#ifndef __OpenBSD__
RET
#endif
END(exception_restore_regs)
/**************************************************************************/
/*
* XentArith:
* System arithmetic trap entry point.
*/
LEAF(XentArith, 2) /* XXX should be NESTED */
.set noat
lda sp,-(FRAME_SW_SIZE*8)(sp)
stq at_reg,(FRAME_AT*8)(sp)
.set at
stq ra,(FRAME_RA*8)(sp)
bsr ra, exception_save_regs /* jmp/CALL trashes pv/t12 */
/* a0, a1, & a2 already set up */
ldiq a3, ALPHA_KENTRY_ARITH
mov sp, a4
CALL(trap)
jmp zero, exception_return
END(XentArith)
/**************************************************************************/
/*
* XentIF:
* System instruction fault trap entry point.
*/
LEAF(XentIF, 1) /* XXX should be NESTED */
.set noat
lda sp,-(FRAME_SW_SIZE*8)(sp)
stq at_reg,(FRAME_AT*8)(sp)
.set at
stq ra,(FRAME_RA*8)(sp)
bsr ra, exception_save_regs /* jmp/CALL trashes pv/t12 */
/* a0, a1, & a2 already set up */
ldiq a3, ALPHA_KENTRY_IF
mov sp, a4
CALL(trap)
jmp zero, exception_return
END(XentIF)
/**************************************************************************/
/*
* XentInt:
* System interrupt entry point.
*/
LEAF(XentInt, 2) /* XXX should be NESTED */
.set noat
lda sp,-(FRAME_SW_SIZE*8)(sp)
stq at_reg,(FRAME_AT*8)(sp)
.set at
stq ra,(FRAME_RA*8)(sp)
bsr ra, exception_save_regs /* jmp/CALL trashes pv/t12 */
/* a0, a1, & a2 already set up */
mov sp, a3
CALL(interrupt)
jmp zero, exception_return
END(XentInt)
/**************************************************************************/
/*
* XentMM:
* System memory management fault entry point.
*/
LEAF(XentMM, 3) /* XXX should be NESTED */
.set noat
lda sp,-(FRAME_SW_SIZE*8)(sp)
stq at_reg,(FRAME_AT*8)(sp)
.set at
stq ra,(FRAME_RA*8)(sp)
bsr ra, exception_save_regs /* jmp/CALL trashes pv/t12 */
/* a0, a1, & a2 already set up */
ldiq a3, ALPHA_KENTRY_MM
mov sp, a4
CALL(trap)
jmp zero, exception_return
END(XentMM)
/**************************************************************************/
/*
* XentSys:
* System call entry point.
*/
LEAF(XentSys, 0) /* XXX should be NESTED */
lda sp,-(FRAME_SW_SIZE*8)(sp)
stq v0,(FRAME_V0*8)(sp) /* in case we need to restart */
stq s0,(FRAME_S0*8)(sp)
stq s1,(FRAME_S1*8)(sp)
stq s2,(FRAME_S2*8)(sp)
stq s3,(FRAME_S3*8)(sp)
stq s4,(FRAME_S4*8)(sp)
stq s5,(FRAME_S5*8)(sp)
stq s6,(FRAME_S6*8)(sp)
stq a0,(FRAME_A0*8)(sp)
stq a1,(FRAME_A1*8)(sp)
stq a2,(FRAME_A2*8)(sp)
stq a3,(FRAME_A3*8)(sp)
stq a4,(FRAME_A4*8)(sp)
stq a5,(FRAME_A5*8)(sp)
stq ra,(FRAME_RA*8)(sp)
/* syscall number, passed in v0, is first arg, frame pointer second */
mov v0,a0
mov sp,a1
CALL(syscall)
jmp zero, exception_return
END(XentSys)
/**************************************************************************/
/*
* XentUna:
* System unaligned access entry point.
*/
LEAF(XentUna, 3) /* XXX should be NESTED */
.set noat
lda sp,-(FRAME_SW_SIZE*8)(sp)
stq at_reg,(FRAME_AT*8)(sp)
.set at
stq ra,(FRAME_RA*8)(sp)
bsr ra, exception_save_regs /* jmp/CALL trashes pv/t12 */
/* a0, a1, & a2 already set up */
ldiq a3, ALPHA_KENTRY_UNA
mov sp, a4
CALL(trap)
jmp zero, exception_return
END(XentUna)
/**************************************************************************/
/*
* savefpstate: Save a process's floating point state.
*
* Arguments:
* a0 'struct fpstate *' to save into
*/
LEAF(savefpstate, 1)
LDGP(pv)
/* save all of the FP registers */
lda t1, FPREG_FPR_REGS(a0) /* get address of FP reg. save area */
stt $f0, (0 * 8)(t1) /* save first register, using hw name */
stt $f1, (1 * 8)(t1) /* etc. */
stt $f2, (2 * 8)(t1)
stt $f3, (3 * 8)(t1)
stt $f4, (4 * 8)(t1)
stt $f5, (5 * 8)(t1)
stt $f6, (6 * 8)(t1)
stt $f7, (7 * 8)(t1)
stt $f8, (8 * 8)(t1)
stt $f9, (9 * 8)(t1)
stt $f10, (10 * 8)(t1)
stt $f11, (11 * 8)(t1)
stt $f12, (12 * 8)(t1)
stt $f13, (13 * 8)(t1)
stt $f14, (14 * 8)(t1)
stt $f15, (15 * 8)(t1)
stt $f16, (16 * 8)(t1)
stt $f17, (17 * 8)(t1)
stt $f18, (18 * 8)(t1)
stt $f19, (19 * 8)(t1)
stt $f20, (20 * 8)(t1)
stt $f21, (21 * 8)(t1)
stt $f22, (22 * 8)(t1)
stt $f23, (23 * 8)(t1)
stt $f24, (24 * 8)(t1)
stt $f25, (25 * 8)(t1)
stt $f26, (26 * 8)(t1)
stt $f27, (27 * 8)(t1)
.set noat
stt $f28, (28 * 8)(t1)
.set at
stt $f29, (29 * 8)(t1)
stt $f30, (30 * 8)(t1)
/*
* Then save the FPCR; note that the necessary 'trapb's are taken
* care of on kernel entry and exit.
*/
mf_fpcr ft0
stt ft0, FPREG_FPR_CR(a0) /* store to FPCR save area */
RET
END(savefpstate)
/**************************************************************************/
/*
* restorefpstate: Restore a process's floating point state.
*
* Arguments:
* a0 'struct fpstate *' to restore from
*/
LEAF(restorefpstate, 1)
LDGP(pv)
/*
* Restore the FPCR; note that the necessary 'trapb's are taken care of
* on kernel entry and exit.
*/
ldt ft0, FPREG_FPR_CR(a0) /* load from FPCR save area */
mt_fpcr ft0
/* Restore all of the FP registers. */
lda t1, FPREG_FPR_REGS(a0) /* get address of FP reg. save area */
ldt $f0, (0 * 8)(t1) /* restore first reg., using hw name */
ldt $f1, (1 * 8)(t1) /* etc. */
ldt $f2, (2 * 8)(t1)
ldt $f3, (3 * 8)(t1)
ldt $f4, (4 * 8)(t1)
ldt $f5, (5 * 8)(t1)
ldt $f6, (6 * 8)(t1)
ldt $f7, (7 * 8)(t1)
ldt $f8, (8 * 8)(t1)
ldt $f9, (9 * 8)(t1)
ldt $f10, (10 * 8)(t1)
ldt $f11, (11 * 8)(t1)
ldt $f12, (12 * 8)(t1)
ldt $f13, (13 * 8)(t1)
ldt $f14, (14 * 8)(t1)
ldt $f15, (15 * 8)(t1)
ldt $f16, (16 * 8)(t1)
ldt $f17, (17 * 8)(t1)
ldt $f18, (18 * 8)(t1)
ldt $f19, (19 * 8)(t1)
ldt $f20, (20 * 8)(t1)
ldt $f21, (21 * 8)(t1)
ldt $f22, (22 * 8)(t1)
ldt $f23, (23 * 8)(t1)
ldt $f24, (24 * 8)(t1)
ldt $f25, (25 * 8)(t1)
ldt $f26, (26 * 8)(t1)
ldt $f27, (27 * 8)(t1)
ldt $f28, (28 * 8)(t1)
ldt $f29, (29 * 8)(t1)
ldt $f30, (30 * 8)(t1)
RET
END(restorefpstate)
/**************************************************************************/
/*
* savectx: save process context, i.e. callee-saved registers
*
* Note that savectx() only works for processes other than curproc,
* since cpu_switch will copy over the info saved here. (It _can_
* sanely be used for curproc iff cpu_switch won't be called again, e.g.
* from if called from boot().)
*
* Arguments:
* a0 'struct user *' of the process that needs its context saved
*
* Return:
* v0 0. (note that for child processes, it seems
* like savectx() returns 1, because the return address
* in the PCB is set to the return address from savectx().)
*/
LEAF(savectx, 1)
br pv, Lsavectx1
Lsavectx1: LDGP(pv)
stq sp, U_PCB_HWPCB_KSP(a0) /* store sp */
stq s0, U_PCB_CONTEXT+(0 * 8)(a0) /* store s0 - s6 */
stq s1, U_PCB_CONTEXT+(1 * 8)(a0)
stq s2, U_PCB_CONTEXT+(2 * 8)(a0)
stq s3, U_PCB_CONTEXT+(3 * 8)(a0)
stq s4, U_PCB_CONTEXT+(4 * 8)(a0)
stq s5, U_PCB_CONTEXT+(5 * 8)(a0)
stq s6, U_PCB_CONTEXT+(6 * 8)(a0)
stq ra, U_PCB_CONTEXT+(7 * 8)(a0) /* store ra */
call_pal PAL_OSF1_rdps /* NOTE: doesn't kill a0 */
stq v0, U_PCB_CONTEXT+(8 * 8)(a0) /* store ps, for ipl */
mov zero, v0
RET
END(savectx)
/**************************************************************************/
BSS(curpcb, 8)
IMPORT(whichqs, 4)
IMPORT(want_resched, 8)
IMPORT(Lev1map, 8)
/*
* When no processes are on the runq, cpu_switch branches to idle
* to wait for something to come ready.
* Note: this is really a part of cpu_switch() but defined here for kernel
* profiling.
*/
LEAF(idle, 0)
br pv, Lidle1
Lidle1: LDGP(pv)
stq zero, curproc /* curproc <- NULL for stats */
mov zero, a0 /* enable all interrupts */
call_pal PAL_OSF1_swpipl
Lidle2:
ldl t0, whichqs /* look for non-empty queue */
beq t0, Lidle2
ldiq a0, ALPHA_PSL_IPL_HIGH /* disable all interrupts */
call_pal PAL_OSF1_swpipl
jmp zero, sw1 /* jump back into the fray */
END(idle)
/*
* cpu_switch()
* Find the highest priority process and resume it.
* XXX should optimiize, and not do the switch if switching to curproc
*/
LEAF(cpu_switch, 0)
LDGP(pv)
/* do an inline savectx(), to save old context */
ldq a0, curproc
ldq a1, P_ADDR(a0)
/* NOTE: ksp is stored by the swpctx */
stq s0, U_PCB_CONTEXT+(0 * 8)(a1) /* store s0 - s6 */
stq s1, U_PCB_CONTEXT+(1 * 8)(a1)
stq s2, U_PCB_CONTEXT+(2 * 8)(a1)
stq s3, U_PCB_CONTEXT+(3 * 8)(a1)
stq s4, U_PCB_CONTEXT+(4 * 8)(a1)
stq s5, U_PCB_CONTEXT+(5 * 8)(a1)
stq s6, U_PCB_CONTEXT+(6 * 8)(a1)
stq ra, U_PCB_CONTEXT+(7 * 8)(a1) /* store ra */
call_pal PAL_OSF1_rdps /* NOTE: doesn't kill a0 */
stq v0, U_PCB_CONTEXT+(8 * 8)(a1) /* store ps, for ipl */
mov a0, s0 /* save old curproc */
mov a1, s1 /* save old U-area */
ldl t0, whichqs /* look for non-empty queue */
beq t0, idle /* and if none, go idle */
ldiq a0, ALPHA_PSL_IPL_HIGH /* disable all interrupts */
call_pal PAL_OSF1_swpipl
sw1:
br pv, Lcs1
Lcs1: LDGP(pv)
ldl t0, whichqs /* look for non-empty queue */
beq t0, idle /* and if none, go idle */
mov t0, t3 /* t3 = saved whichqs */
mov zero, t2 /* t2 = lowest bit set */
blbs t0, Lcs3 /* if low bit set, done! */
Lcs2: srl t0, 1, t0 /* try next bit */
addq t2, 1, t2
blbc t0, Lcs2 /* if clear, try again */
Lcs3:
/*
* Remove process from queue
*/
lda t1, qs /* get queues */
sll t2, 4, t0 /* queue head is 16 bytes */
addq t1, t0, t0 /* t0 = qp = &qs[firstbit] */
ldq t4, PH_LINK(t0) /* t4 = p = highest pri proc */
ldq t5, P_FORW(t4) /* t5 = p->p_forw */
bne t4, Lcs4 /* make sure p != NULL */
PANIC("cpu_switch",Lcpu_switch_pmsg) /* nothing in queue! */
Lcs4:
stq t5, PH_LINK(t0) /* qp->ph_link = p->p_forw */
stq t0, P_BACK(t5) /* p->p_forw->p_back = qp */
stq zero, P_BACK(t4) /* firewall: p->p_back = NULL */
cmpeq t0, t5, t0 /* see if queue is empty */
beq t0, Lcs5 /* nope, it's not! */
ldiq t0, 1 /* compute bit in whichqs */
sll t0, t2, t0
xor t3, t0, t3 /* clear bit in whichqs */
stl t3, whichqs
Lcs5:
/*
* Switch to the new context
*/
/* mark the new curproc, and other globals */
stq zero, want_resched /* we've rescheduled */
/* XXX should allocate an ASN, rather than just flushing */
stq t4, curproc /* curproc = p */
ldq t5, P_MD_PCBPADDR(t4) /* t5 = p->p_md.md_pcbpaddr */
stq t5, curpcb /* and store it in curpcb */
#ifndef NEW_PMAP
/*
* Do the context swap, and invalidate old TLB entries (XXX).
* XXX should do the ASN thing, and therefore not have to invalidate.
*/
ldq t2, P_VMSPACE(t4) /* t2 = p->p_vmspace */
ldq t2, VM_PMAP_STPTE(t2) /* = p_vmspace.vm_pmap.pm_ste */
ldq t3, Lev1map /* and store pte into Lev1map */
stq t2, USTP_OFFSET(t3)
mov t5, a0 /* swap the context */
call_pal PAL_OSF1_swpctx
ldiq a0, -1 /* & invalidate old TLB ents */
call_pal PAL_OSF1_tbi
/*
* Now running on the new u struct.
* Restore registers and return.
*/
ldq t0, curproc
ldq t0, P_ADDR(t0)
#else /* NEW_PMAP */
mov t4, s2 /* save new curproc */
mov t5, s3 /* save new pcbpaddr */
ldq s4, P_ADDR(t4) /* load/save new U-AREA */
ldq a0, P_VMSPACE(s2) /* p->p_vmspace */
lda a1, U_PCB_HWPCB(s4) /* &hardware PCB */
mov zero, a2
lda a0, VM_PMAP(a0) /* &p->p_vmspace->vm_pmap */
CALL(pmap_activate)
mov s3, a0 /* swap the context */
call_pal PAL_OSF1_swpctx
ldiq a0, -2 /* & invalidate old TLB ents */
call_pal PAL_OSF1_tbi
ldq a0, P_VMSPACE(s0)
lda a1, U_PCB_HWPCB(s1)
mov zero, a2
lda a0, VM_PMAP(a0)
CALL(pmap_deactivate)
/*
* Now running on the new u struct.
* Restore registers and return.
*/
mov s4, t0
#endif /* NEW_PMAP */
/* NOTE: ksp is restored by the swpctx */
ldq s0, U_PCB_CONTEXT+(0 * 8)(t0) /* restore s0 - s6 */
ldq s1, U_PCB_CONTEXT+(1 * 8)(t0)
ldq s2, U_PCB_CONTEXT+(2 * 8)(t0)
ldq s3, U_PCB_CONTEXT+(3 * 8)(t0)
ldq s4, U_PCB_CONTEXT+(4 * 8)(t0)
ldq s5, U_PCB_CONTEXT+(5 * 8)(t0)
ldq s6, U_PCB_CONTEXT+(6 * 8)(t0)
ldq ra, U_PCB_CONTEXT+(7 * 8)(t0) /* restore ra */
ldq a0, U_PCB_CONTEXT+(8 * 8)(t0) /* restore ipl */
and a0, ALPHA_PSL_IPL_MASK, a0
call_pal PAL_OSF1_swpipl
ldiq v0, 1 /* possible ret to savectx() */
RET
END(cpu_switch)
/*
* 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.
*/
LEAF(switch_trampoline, 0)
mov s0, pv
mov s1, ra
ldq a0, curproc
jmp zero, (pv)
END(switch_trampoline)
/*
* switch_exit(struct proc *p)
* Make a the named process exit. Partially switch to proc0, unmap
* the old proc's user struct, and jump into the middle of cpu_switch
* to switch into a few process. MUST BE CALLED AT SPLHIGH.
*/
LEAF(switch_exit, 1)
LDGP(pv)
/* save the exiting proc pointer */
mov a0, s2
/* Switch to proc0. */
lda t4, proc0 /* t4 = &proc0 */
ldq t5, P_MD_PCBPADDR(t4) /* t5 = p->p_md.md_pcbpaddr */
stq t5, curpcb /* and store it in curpcb */
#ifndef NEW_PMAP
mov t4, s0
ldq s1, P_ADDR(t4)
#endif
/*
* Do the context swap, and invalidate old TLB entries (XXX).
* XXX should do the ASN thing, and therefore not have to invalidate.
*/
#ifndef NEW_PMAP
ldq t2, P_VMSPACE(t4) /* t2 = p->p_vmspace */
ldq t2, VM_PMAP_STPTE(t2) /* = p_vmspace.vm_pmap.pm_ste */
ldq t3, Lev1map /* and store pte into Lev1map */
stq t2, USTP_OFFSET(t3)
#endif /* NEW_PMAP */
mov t5, a0 /* swap the context */
call_pal PAL_OSF1_swpctx
#ifndef NEW_PMAP
ldiq a0, -1 /* & invalidate old TLB ents */
call_pal PAL_OSF1_tbi
#endif /* NEW_PMAP */
/*
* Now running as proc0, except for the value of 'curproc' and
* the saved regs.
*/
/* blow away the old user struct */
ldq a0, kernel_map
ldq a1, P_ADDR(s2)
ldiq a2, (UPAGES * NBPG)
CALL(kmem_free)
/* and jump into the middle of cpu_switch. */
#ifdef NEW_PMAP
/* XXX XXX LOSE */
#endif
jmp zero, sw1
END(switch_exit)
/**************************************************************************/
/*
* Copy a null-terminated string within the kernel's address space.
* If lenp is not NULL, store the number of chars copied in *lenp
*
* int copystr(char *from, char *to, size_t len, size_t *lenp);
*/
LEAF(copystr, 4)
LDGP(pv)
mov a2, t0 /* t0 = i = len */
beq a2, Lcopystr2 /* if (len == 0), bail out */
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
END(copystr)
NESTED(copyinstr, 4, 16, ra, 0, 0)
LDGP(pv)
lda sp, -16(sp) /* set up stack frame */
stq ra, (16-8)(sp) /* save ra */
ldiq t0, VM_MAX_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 */
END(copyinstr)
NESTED(copyoutstr, 4, 16, ra, 0, 0)
LDGP(pv)
lda sp, -16(sp) /* set up stack frame */
stq ra, (16-8)(sp) /* save ra */
ldiq t0, VM_MAX_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 */
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);
*/
LEAF(bcopy,3)
XLEAF(ovbcopy,3)
/* Check for negative length */
ble a2,bcopy_done
/* Check for overlap */
subq a1,a0,t5
cmpult t5,a2,t5
bne t5,bcopy_overlap
/* a3 = end address */
addq a0,a2,a3
/* Get the first word */
ldq_u t2,0(a0)
/* Do they have the same alignment? */
xor a0,a1,t0
and t0,7,t0
and a1,7,t1
bne t0,bcopy_different_alignment
/* src & dst have same alignment */
beq t1,bcopy_all_aligned
ldq_u t3,0(a1)
addq a2,t1,a2
mskqh t2,a0,t2
mskql t3,a0,t3
or t2,t3,t2
/* Dst is 8-byte aligned */
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
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
bcopy_samealign_lp_end:
/* If we're done, exit */
bne a2,bcopy_small_left
stq_u t2,0(a1)
RET
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
bcopy_different_alignment:
/*
* this is the fun part
*/
addq a0,a2,a3
cmpule a2,8,t0
bne t0,bcopy_da_finish
beq t1,bcopy_da_noentry
/* 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)
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
END(bcopy)
NESTED(copyin, 3, 16, ra, 0, 0)
LDGP(pv)
lda sp, -16(sp) /* set up stack frame */
stq ra, (16-8)(sp) /* save ra */
ldiq t0, VM_MAX_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
END(copyin)
NESTED(copyout, 3, 16, ra, 0, 0)
LDGP(pv)
lda sp, -16(sp) /* set up stack frame */
stq ra, (16-8)(sp) /* save ra */
ldiq t0, VM_MAX_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
END(copyout)
LEAF(copyerr, 0)
LDGP(pv)
ldq ra, (16-8)(sp) /* restore ra. */
lda sp, 16(sp) /* kill stack frame. */
ldiq v0, EFAULT /* return EFAULT. */
RET
END(copyerr)
/**************************************************************************/
/*
* {fu,su},{ibyte,isword,iword}, fetch or store a byte, short or word to
* user text space.
* {fu,su},{byte,sword,word}, fetch or store a byte, short or word to
* user data space.
*/
#ifdef notdef
LEAF(fuword, 1)
XLEAF(fuiword, 1)
LDGP(pv)
ldiq t0, VM_MAX_ADDRESS /* make sure that addr */
cmpult a0, t0, t1 /* is in user space. */
beq t1, fswberr /* if it's not, error out. */
lda t0, fswberr
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq t0, U_PCB_ONFAULT(at_reg)
.set at
ldq v0, 0(a0)
zap v0, 0xf0, v0
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq zero, U_PCB_ONFAULT(at_reg)
.set at
RET
END(fuword)
LEAF(fusword, 1)
XLEAF(fuisword, 1)
LDGP(pv)
ldiq t0, VM_MAX_ADDRESS /* make sure that addr */
cmpult a0, t0, t1 /* is in user space. */
beq t1, fswberr /* if it's not, error out. */
lda t0, fswberr
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq t0, U_PCB_ONFAULT(at_reg)
.set at
/* XXX FETCH IT */
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq zero, U_PCB_ONFAULT(at_reg)
.set at
RET
END(fusword)
LEAF(fubyte, 1)
XLEAF(fuibyte, 1)
LDGP(pv)
ldiq t0, VM_MAX_ADDRESS /* make sure that addr */
cmpult a0, t0, t1 /* is in user space. */
beq t1, fswberr /* if it's not, error out. */
lda t0, fswberr
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq t0, U_PCB_ONFAULT(at_reg)
.set at
/* XXX FETCH IT */
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq zero, U_PCB_ONFAULT(at_reg)
.set at
RET
END(fubyte)
#endif /* notdef */
LEAF(suword, 2)
LDGP(pv)
ldiq t0, VM_MAX_ADDRESS /* make sure that addr */
cmpult a0, t0, t1 /* is in user space. */
beq t1, fswberr /* if it's not, error out. */
lda t0, fswberr
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq t0, U_PCB_ONFAULT(at_reg)
.set at
stq a1, 0(a0) /* do the wtore. */
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq zero, U_PCB_ONFAULT(at_reg)
.set at
mov zero, v0
RET
END(suword)
#ifdef notdef
LEAF(suiword, 2)
LDGP(pv)
ldiq t0, VM_MAX_ADDRESS /* make sure that addr */
cmpult a0, t0, t1 /* is in user space. */
beq t1, fswberr /* if it's not, error out. */
lda t0, fswberr
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq t0, U_PCB_ONFAULT(at_reg)
.set at
/* XXX STORE IT */
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq zero, U_PCB_ONFAULT(at_reg)
.set at
call_pal PAL_OSF1_imb /* sync instruction stream */
mov zero, v0
RET
END(suiword)
LEAF(susword, 2)
LDGP(pv)
ldiq t0, VM_MAX_ADDRESS /* make sure that addr */
cmpult a0, t0, t1 /* is in user space. */
beq t1, fswberr /* if it's not, error out. */
lda t0, fswberr
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq t0, U_PCB_ONFAULT(at_reg)
.set at
/* XXX STORE IT */
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq zero, U_PCB_ONFAULT(at_reg)
.set at
mov zero, v0
RET
END(susword)
LEAF(suisword, 2)
LDGP(pv)
ldiq t0, VM_MAX_ADDRESS /* make sure that addr */
cmpult a0, t0, t1 /* is in user space. */
beq t1, fswberr /* if it's not, error out. */
lda t0, fswberr
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq t0, U_PCB_ONFAULT(at_reg)
.set at
/* XXX STORE IT */
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq zero, U_PCB_ONFAULT(at_reg)
.set at
call_pal PAL_OSF1_imb /* sync instruction stream */
mov zero, v0
RET
END(suisword)
#endif /* notdef */
LEAF(subyte, 2)
LDGP(pv)
ldiq t0, VM_MAX_ADDRESS /* make sure that addr */
cmpult a0, t0, t1 /* is in user space. */
beq t1, fswberr /* if it's not, error out. */
lda t0, fswberr
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq t0, U_PCB_ONFAULT(at_reg)
.set at
zap a1, 0xfe, a1 /* kill arg's high bytes */
insbl a1, a0, a1 /* move it to the right byte */
ldq_u t0, 0(a0) /* load quad around byte */
mskbl t0, a0, t0 /* kill the target byte */
or t0, a1, a1 /* put the result together */
stq_u a1, 0(a0) /* and store it. */
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq zero, U_PCB_ONFAULT(at_reg)
.set at
mov zero, v0
RET
END(subyte)
LEAF(suibyte, 2)
LDGP(pv)
ldiq t0, VM_MAX_ADDRESS /* make sure that addr */
cmpult a0, t0, t1 /* is in user space. */
beq t1, fswberr /* if it's not, error out. */
lda t0, fswberr
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq t0, U_PCB_ONFAULT(at_reg)
.set at
zap a1, 0xfe, a1 /* kill arg's high bytes */
insbl a1, a0, a1 /* move it to the right byte */
ldq_u t0, 0(a0) /* load quad around byte */
mskbl t0, a0, t0 /* kill the target byte */
or t0, a1, a1 /* put the result together */
stq_u a1, 0(a0) /* and store it. */
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq zero, U_PCB_ONFAULT(at_reg)
.set at
call_pal PAL_OSF1_imb /* sync instruction stream */
mov zero, v0
RET
END(suibyte)
LEAF(fswberr, 0)
LDGP(pv)
ldiq v0, -1
RET
END(fswberr)
/**************************************************************************/
#ifdef notdef
/*
* fuswintr and suswintr are just like fusword and susword except that if
* the page is not in memory or would cause a trap, then we return an error.
* The important thing is to prevent sleep() and switch().
*/
LEAF(fuswintr, 2)
LDGP(pv)
ldiq t0, VM_MAX_ADDRESS /* make sure that addr */
cmpult a0, t0, t1 /* is in user space. */
beq t1, fswintrberr /* if it's not, error out. */
lda t0, fswintrberr
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq t0, U_PCB_ONFAULT(at_reg)
stq a0, U_PCB_ACCESSADDR(at_reg)
.set at
/* XXX FETCH IT */
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq zero, U_PCB_ONFAULT(at_reg)
.set at
RET
END(fuswintr)
LEAF(suswintr, 2)
LDGP(pv)
ldiq t0, VM_MAX_ADDRESS /* make sure that addr */
cmpult a0, t0, t1 /* is in user space. */
beq t1, fswintrberr /* if it's not, error out. */
lda t0, fswintrberr
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq t0, U_PCB_ONFAULT(at_reg)
stq a0, U_PCB_ACCESSADDR(at_reg)
.set at
/* XXX STORE IT */
.set noat
ldq at_reg, curproc
ldq at_reg, P_ADDR(at_reg)
stq zero, U_PCB_ONFAULT(at_reg)
.set at
mov zero, v0
RET
END(suswintr)
#endif
LEAF(fswintrberr, 0)
XLEAF(fuswintr, 2) /* XXX what is a 'word'? */
XLEAF(suswintr, 2) /* XXX what is a 'word'? */
LDGP(pv)
ldiq v0, -1
RET
END(fswberr)
/**************************************************************************/
/*
* Some bogus data, to keep vmstat happy, for now.
*/
.data
EXPORT(intrnames)
#ifndef EVCNT_COUNTERS
INTRNAMES_DEFINITION
#endif
EXPORT(eintrnames)
.align 3
EXPORT(intrcnt)
#ifndef EVCNT_COUNTERS
INTRCNT_DEFINITION
#endif
EXPORT(eintrcnt)
.text
/**************************************************************************/
/*
* Object:
* swpctxt EXPORTED function
*
* Change HW process context
*
* Arguments:
* pcb PHYSICAL struct pcb_hw *
* old_ksp VIRTUAL long *
*
* If old_ksp is non-zero it saves the current KSP in it.
* Execute the PAL call.
*/
LEAF(swpctxt,2)
beq a1,Lswpctxt1
stq sp,0(a1)
Lswpctxt1: call_pal PAL_OSF1_swpctx
RET
END(swpctxt)
/*
* console 'restart' routine to be placed in HWRPB.
*/
LEAF(XentRestart, 1) /* XXX should be NESTED */
.set noat
lda sp,-(FRAME_SIZE*8)(sp)
stq at_reg,(FRAME_AT*8)(sp)
.set at
stq v0,(FRAME_V0*8)(sp)
stq a3,(FRAME_A3*8)(sp)
stq a4,(FRAME_A4*8)(sp)
stq a5,(FRAME_A5*8)(sp)
stq s0,(FRAME_S0*8)(sp)
stq s1,(FRAME_S1*8)(sp)
stq s2,(FRAME_S2*8)(sp)
stq s3,(FRAME_S3*8)(sp)
stq s4,(FRAME_S4*8)(sp)
stq s5,(FRAME_S5*8)(sp)
stq s6,(FRAME_S6*8)(sp)
stq t0,(FRAME_T0*8)(sp)
stq t1,(FRAME_T1*8)(sp)
stq t2,(FRAME_T2*8)(sp)
stq t3,(FRAME_T3*8)(sp)
stq t4,(FRAME_T4*8)(sp)
stq t5,(FRAME_T5*8)(sp)
stq t6,(FRAME_T6*8)(sp)
stq t7,(FRAME_T7*8)(sp)
stq t8,(FRAME_T8*8)(sp)
stq t9,(FRAME_T9*8)(sp)
stq t10,(FRAME_T10*8)(sp)
stq t11,(FRAME_T11*8)(sp)
stq t12,(FRAME_T12*8)(sp)
stq ra,(FRAME_RA*8)(sp)
br pv,LXconsole_restart1
LXconsole_restart1: LDGP(pv)
ldq a0,(FRAME_RA*8)(sp) /* a0 = ra */
ldq a1,(FRAME_T11*8)(sp) /* a1 = ai */
ldq a2,(FRAME_T12*8)(sp) /* a2 = pv */
CALL(console_restart)
call_pal PAL_halt
END(XentRestart)
--
This space not left unintentionally unblank. deraadt@theos.com
www.OpenBSD.org -- We're fixing security problems so you can sleep at night.