subr.S revision 1.43 1 1.43 kalvisd /* $NetBSD: subr.S,v 1.43 2023/12/18 22:40:01 kalvisd Exp $ */
2 1.1 matt
3 1.1 matt /*
4 1.1 matt * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
5 1.1 matt * All rights reserved.
6 1.1 matt *
7 1.1 matt * Redistribution and use in source and binary forms, with or without
8 1.1 matt * modification, are permitted provided that the following conditions
9 1.1 matt * are met:
10 1.1 matt * 1. Redistributions of source code must retain the above copyright
11 1.1 matt * notice, this list of conditions and the following disclaimer.
12 1.1 matt * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 matt * notice, this list of conditions and the following disclaimer in the
14 1.1 matt * documentation and/or other materials provided with the distribution.
15 1.1 matt *
16 1.1 matt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 1.1 matt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 1.1 matt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 1.1 matt * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 1.1 matt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 1.1 matt * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 1.1 matt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 1.1 matt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 1.1 matt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 1.1 matt * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 1.1 matt */
27 1.1 matt
28 1.1 matt #include <machine/asm.h>
29 1.1 matt
30 1.1 matt #include "assym.h"
31 1.1 matt #include "opt_ddb.h"
32 1.1 matt #include "opt_multiprocessor.h"
33 1.1 matt #include "opt_lockdebug.h"
34 1.1 matt #include "opt_compat_netbsd.h"
35 1.1 matt #include "opt_compat_ultrix.h"
36 1.1 matt #ifdef COMPAT_ULTRIX
37 1.1 matt #include <compat/ultrix/ultrix_syscall.h>
38 1.1 matt #endif
39 1.1 matt
40 1.1 matt #define JSBENTRY(x) .globl x ; .align 2 ; x :
41 1.21 matt #define SCBENTRY(name) \
42 1.21 matt .text ; \
43 1.21 matt .align 2 ; \
44 1.21 matt .globl __CONCAT(X,name) ; \
45 1.21 matt __CONCAT(X,name):
46 1.1 matt
47 1.1 matt .text
48 1.1 matt
49 1.1 matt #ifdef KERNEL_LOADABLE_BY_MOP
50 1.1 matt /*
51 1.1 matt * This is a little tricky. The kernel is not loaded at the correct
52 1.1 matt * address, so the kernel must first be relocated, then copied, then
53 1.1 matt * jump back to the correct address.
54 1.1 matt */
55 1.1 matt /* Copy routine */
56 1.1 matt cps:
57 1.2 matt 2: movb (%r0)+,(%r1)+
58 1.2 matt cmpl %r0,%r7
59 1.1 matt bneq 2b
60 1.1 matt
61 1.2 matt 3: clrb (%r1)+
62 1.2 matt incl %r0
63 1.2 matt cmpl %r0,%r6
64 1.1 matt bneq 3b
65 1.2 matt clrl -(%sp)
66 1.2 matt movl %sp,%ap
67 1.2 matt movl $_cca,%r7
68 1.2 matt movl %r8,(%r7)
69 1.2 matt movpsl -(%sp)
70 1.2 matt pushl %r2
71 1.1 matt rei
72 1.1 matt cpe:
73 1.1 matt
74 1.1 matt /* Copy the copy routine */
75 1.2 matt 1: movab cps,%r0
76 1.2 matt movab cpe,%r1
77 1.2 matt movl $0x300000,%sp
78 1.2 matt movl %sp,%r3
79 1.2 matt 4: movb (%r0)+,(%r3)+
80 1.2 matt cmpl %r0,%r1
81 1.1 matt bneq 4b
82 1.2 matt movl %r7,%r8
83 1.1 matt /* Ok, copy routine copied, set registers and rei */
84 1.2 matt movab _edata,%r7
85 1.2 matt movab _end,%r6
86 1.2 matt movl $0x80000000,%r1
87 1.2 matt movl $0x80000200,%r0
88 1.2 matt subl3 $0x200,%r6,%r9
89 1.2 matt movab 2f,%r2
90 1.2 matt subl2 $0x200,%r2
91 1.2 matt movpsl -(%sp)
92 1.2 matt pushab 4(%sp)
93 1.1 matt rei
94 1.1 matt
95 1.1 matt /*
96 1.1 matt * First entry routine from boot. This should be in a file called locore.
97 1.1 matt */
98 1.1 matt JSBENTRY(start)
99 1.1 matt brb 1b # Netbooted starts here
100 1.1 matt #else
101 1.1 matt ASENTRY(start, 0)
102 1.1 matt #endif
103 1.2 matt 2: bisl3 $0x80000000,%r9,_C_LABEL(esym) # End of loaded code
104 1.1 matt pushl $0x1f0000 # Push a nice PSL
105 1.1 matt pushl $to # Address to jump to
106 1.1 matt rei # change to kernel stack
107 1.1 matt to: movw $0xfff,_C_LABEL(panic) # Save all regs in panic
108 1.3 matt cmpb (%ap),$3 # symbols info present?
109 1.1 matt blssu 3f # nope, skip
110 1.2 matt bisl3 $0x80000000,8(%ap),_C_LABEL(symtab_start)
111 1.1 matt # save start of symtab
112 1.2 matt movl 12(%ap),_C_LABEL(symtab_nsyms) # save number of symtab
113 1.3 matt bisl3 $0x80000000,%r9,_C_LABEL(symtab_end)
114 1.2 matt # save end of symtab
115 1.2 matt 3: addl3 _C_LABEL(esym),$0x3ff,%r0 # Round symbol table end
116 1.27 matt bicl3 $0x3ff,%r0,%r1 #
117 1.28 rmind movl %r1,_C_LABEL(lwp0)+L_PCB # lwp0 pcb, XXXuvm_lwp_getuarea
118 1.29 martin bicl3 $0x80000000,%r1,%r0 # get phys lwp0 uarea addr
119 1.2 matt mtpr %r0,$PR_PCBB # Save in IPR PCBB
120 1.27 matt addl3 $USPACE,%r1,%r0 # Get kernel stack top
121 1.2 matt mtpr %r0,$PR_KSP # put in IPR KSP
122 1.2 matt movl %r0,_C_LABEL(Sysmap) # SPT start addr after KSP
123 1.28 rmind movl _C_LABEL(lwp0)+L_PCB,%r0 # get PCB virtual address
124 1.21 matt mfpr $PR_PCBB,PCB_PADDR(%r0) # save PCB physical address
125 1.30 chs movab PCB_ONFAULT(%r0),ESP(%r0) # Save trap address in ESP
126 1.2 matt mtpr 4(%r0),$PR_ESP # Put it in ESP also
127 1.1 matt
128 1.1 matt # Set some registers in known state
129 1.28 rmind movl %r1,%r0 # get lwp0 pcb
130 1.2 matt clrl P0LR(%r0)
131 1.2 matt clrl P1LR(%r0)
132 1.1 matt mtpr $0,$PR_P0LR
133 1.1 matt mtpr $0,$PR_P1LR
134 1.2 matt movl $0x80000000,%r1
135 1.2 matt movl %r1,P0BR(%r0)
136 1.2 matt movl %r1,P1BR(%r0)
137 1.2 matt mtpr %r1,$PR_P0BR
138 1.2 matt mtpr %r1,$PR_P1BR
139 1.30 chs clrl PCB_ONFAULT(%r0)
140 1.1 matt mtpr $0,$PR_SCBB
141 1.1 matt
142 1.1 matt # Copy the RPB to its new position
143 1.1 matt #if defined(COMPAT_14)
144 1.2 matt tstl (%ap) # Any arguments?
145 1.1 matt bneq 1f # Yes, called from new boot
146 1.2 matt movl %r11,_C_LABEL(boothowto) # Howto boot (single etc...)
147 1.2 matt # movl %r10,_C_LABEL(bootdev) # uninteresting, will complain
148 1.2 matt movl %r8,_C_LABEL(avail_end) # Usable memory (from VMB)
149 1.2 matt clrl -(%sp) # Have no RPB
150 1.1 matt brb 2f
151 1.1 matt #endif
152 1.1 matt
153 1.2 matt 1: pushl 4(%ap) # Address of old rpb
154 1.1 matt 2: calls $1,_C_LABEL(_start) # Jump away.
155 1.1 matt /* NOTREACHED */
156 1.1 matt
157 1.1 matt
158 1.1 matt /*
159 1.1 matt * Signal handler code.
160 1.1 matt */
161 1.1 matt
162 1.1 matt .align 2
163 1.11 matt .globl _C_LABEL(sigcode),_C_LABEL(esigcode)
164 1.1 matt _C_LABEL(sigcode):
165 1.1 matt pushr $0x3f
166 1.2 matt subl2 $0xc,%sp
167 1.2 matt movl 0x24(%sp),%r0
168 1.2 matt calls $3,(%r0)
169 1.1 matt popr $0x3f
170 1.8 matt chmk $SYS_compat_16___sigreturn14
171 1.1 matt chmk $SYS_exit
172 1.1 matt halt
173 1.1 matt _C_LABEL(esigcode):
174 1.1 matt
175 1.1 matt #ifdef COMPAT_ULTRIX
176 1.1 matt .align 2
177 1.1 matt .globl _C_LABEL(ultrix_sigcode),_C_LABEL(ultrix_esigcode)
178 1.1 matt _C_LABEL(ultrix_sigcode):
179 1.1 matt pushr $0x3f
180 1.2 matt subl2 $0xc,%sp
181 1.2 matt movl 0x24(%sp),%r0
182 1.2 matt calls $3,(%r0)
183 1.1 matt popr $0x3f
184 1.1 matt chmk $ULTRIX_SYS_sigreturn
185 1.1 matt chmk $SYS_exit
186 1.1 matt halt
187 1.1 matt _C_LABEL(ultrix_esigcode):
188 1.1 matt #endif
189 1.1 matt
190 1.1 matt .align 2
191 1.1 matt .globl _C_LABEL(idsptch), _C_LABEL(eidsptch)
192 1.16 matt _C_LABEL(idsptch):
193 1.16 matt pushr $0x3f
194 1.1 matt .word 0x9f16 # jsb to absolute address
195 1.1 matt .long _C_LABEL(cmn_idsptch) # the absolute address
196 1.1 matt .long 0 # the callback interrupt routine
197 1.1 matt .long 0 # its argument
198 1.1 matt .long 0 # ptr to correspond evcnt struct
199 1.1 matt _C_LABEL(eidsptch):
200 1.1 matt
201 1.1 matt _C_LABEL(cmn_idsptch):
202 1.16 matt #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
203 1.16 matt calls $0,_C_LABEL(krnlock)
204 1.16 matt #endif
205 1.2 matt movl (%sp)+,%r0 # get pointer to idspvec
206 1.20 matt mtpr $IPL_VM,$PR_IPL # Make sure we are at IPL_VM
207 1.2 matt movl 8(%r0),%r1 # get evcnt pointer
208 1.1 matt beql 1f # no ptr, skip increment
209 1.2 matt incl EV_COUNT(%r1) # increment low longword
210 1.2 matt adwc $0,EV_COUNT+4(%r1) # add any carry to hi longword
211 1.33 matt 1: mfpr $PR_SSP, %r2 # get curlwp
212 1.33 matt movl L_CPU(%r2), %r2 # get curcpu
213 1.33 matt incl CI_NINTR(%r2) # increment ci_data.cpu_nintr
214 1.33 matt adwc $0,(CI_NINTR+4)(%r2)
215 1.16 matt #if 0
216 1.16 matt pushl %r0
217 1.16 matt movq (%r0),-(%sp)
218 1.16 matt pushab 2f
219 1.16 matt calls $3,_C_LABEL(printf)
220 1.16 matt movl (%sp)+,%r0
221 1.16 matt #endif
222 1.6 ragge pushl 4(%r0) # push argument
223 1.2 matt calls $1,*(%r0) # call interrupt routine
224 1.16 matt #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
225 1.16 matt calls $0,_C_LABEL(krnunlock)
226 1.16 matt #endif
227 1.1 matt popr $0x3f # pop registers
228 1.41 andvar rei # return from interrupt
229 1.16 matt #if 0
230 1.16 matt 2: .asciz "intr %p(%p)\n"
231 1.16 matt #endif
232 1.1 matt
233 1.1 matt ENTRY(badaddr,0) # Called with addr,b/w/l
234 1.2 matt mfpr $PR_IPL,%r0 # splhigh()
235 1.1 matt mtpr $IPL_HIGH,$PR_IPL
236 1.2 matt movl 4(%ap),%r2 # First argument, the address
237 1.2 matt movl 8(%ap),%r1 # Sec arg, b,w,l
238 1.2 matt pushl %r0 # Save old IPL
239 1.2 matt clrl %r3
240 1.1 matt movab 4f,_C_LABEL(memtest) # Set the return address
241 1.1 matt
242 1.2 matt caseb %r1,$1,$4 # What is the size
243 1.1 matt 1: .word 1f-1b
244 1.1 matt .word 2f-1b
245 1.1 matt .word 3f-1b # This is unused
246 1.1 matt .word 3f-1b
247 1.1 matt
248 1.2 matt 1: movb (%r2),%r1 # Test a byte
249 1.1 matt brb 5f
250 1.1 matt
251 1.2 matt 2: movw (%r2),%r1 # Test a word
252 1.1 matt brb 5f
253 1.1 matt
254 1.2 matt 3: movl (%r2),%r1 # Test a long
255 1.1 matt brb 5f
256 1.1 matt
257 1.2 matt 4: incl %r3 # Got machine chk => addr bad
258 1.2 matt 5: mtpr (%sp)+,$PR_IPL
259 1.2 matt movl %r3,%r0
260 1.1 matt ret
261 1.1 matt
262 1.1 matt #ifdef DDB
263 1.1 matt /*
264 1.1 matt * DDB is the only routine that uses setjmp/longjmp.
265 1.1 matt */
266 1.1 matt .globl _C_LABEL(setjmp), _C_LABEL(longjmp)
267 1.1 matt _C_LABEL(setjmp):.word 0
268 1.2 matt movl 4(%ap), %r0
269 1.2 matt movl 8(%fp), (%r0)
270 1.2 matt movl 12(%fp), 4(%r0)
271 1.2 matt movl 16(%fp), 8(%r0)
272 1.2 matt moval 28(%fp),12(%r0)
273 1.2 matt clrl %r0
274 1.1 matt ret
275 1.1 matt
276 1.1 matt _C_LABEL(longjmp):.word 0
277 1.2 matt movl 4(%ap), %r1
278 1.2 matt movl 8(%ap), %r0
279 1.2 matt movl (%r1), %ap
280 1.2 matt movl 4(%r1), %fp
281 1.2 matt movl 12(%r1), %sp
282 1.2 matt jmp *8(%r1)
283 1.1 matt #endif
284 1.1 matt
285 1.1 matt #if defined(MULTIPROCESSOR)
286 1.1 matt .align 2
287 1.12 he .globl _C_LABEL(vax_mp_tramp) # used to kick off multiprocessor systems.
288 1.12 he _C_LABEL(vax_mp_tramp):
289 1.1 matt ldpctx
290 1.1 matt rei
291 1.1 matt #endif
292 1.5 thorpej
293 1.22 matt .globl softint_cleanup,softint_exit,softint_process
294 1.22 matt .type softint_cleanup@function
295 1.22 matt .type softint_exit@function
296 1.22 matt .type softint_process@function
297 1.21 matt softint_cleanup:
298 1.24 matt movl L_CPU(%r0),%r1 /* get cpu_info */
299 1.21 matt incl CI_MTX_COUNT(%r1) /* increment mutex count */
300 1.28 rmind movl L_PCB(%r0),%r1 /* get PCB of softint LWP */
301 1.21 matt softint_exit:
302 1.21 matt popr $0x3 /* restore r0 and r1 */
303 1.21 matt rei /* return from interrupt */
304 1.21 matt
305 1.21 matt softint_process:
306 1.21 matt /*
307 1.21 matt * R6 contains pinned LWP
308 1.21 matt * R7 contains ipl to dispatch with
309 1.21 matt */
310 1.21 matt movq %r6,-(%sp) /* push old lwp and ipl onto stack */
311 1.21 matt calls $2,_C_LABEL(softint_dispatch) /* dispatch it */
312 1.21 matt
313 1.21 matt /* We can use any register because ldpctx will overwrite them */
314 1.28 rmind movl L_PCB(%r6),%r3 /* get pcb */
315 1.21 matt movab softint_exit,PCB_PC(%r3)/* do a quick exit */
316 1.24 matt #ifdef MULTIPROCESSOR
317 1.24 matt movl L_CPU(%r6),%r8
318 1.42 riastrad /* XXX store-before-store barrier -- see cpu_switchto */
319 1.24 matt movl %r6,CI_CURLWP(%r8)
320 1.42 riastrad /* XXX store-before-load barrier -- see cpu_switchto */
321 1.24 matt #endif
322 1.43 kalvisd /* copy AST level from current LWP to pinned LWP, reset
323 1.43 kalvisd current AST level */
324 1.43 kalvisd mfpr $PR_SSP,%r4 /* current LWP */
325 1.43 kalvisd movl L_PCB(%r4),%r4 /* PCB address */
326 1.43 kalvisd movl P0LR(%r4),%r0 /* LR and ASTLVL field, current PCB */
327 1.43 kalvisd movl P0LR(%r3),%r1 /* same, pinned LWP */
328 1.43 kalvisd cmpl %r0,%r1
329 1.43 kalvisd bgtru 1f /* AST(current) >= AST(pinned) */
330 1.43 kalvisd extv $24,$3,%r0,%r0 /* ASTLVL field for current LWP */
331 1.43 kalvisd insv %r0,$24,$3,P0LR(%r3) /* copy to pinned LWP */
332 1.43 kalvisd insv $4,$24,$3,P0LR(%r4) /* reset AST for current LWP */
333 1.43 kalvisd 1:
334 1.21 matt mtpr PCB_PADDR(%r3),$PR_PCBB /* restore PA of interrupted pcb */
335 1.40 msaitoh ldpctx /* implicitly updates curlwp */
336 1.21 matt rei
337 1.21 matt
338 1.21 matt
339 1.21 matt softint_common:
340 1.21 matt mfpr $PR_IPL,%r1
341 1.21 matt mtpr $IPL_HIGH,$PR_IPL /* we need to be at IPL_HIGH */
342 1.21 matt movpsl -(%sp) /* add cleanup hook */
343 1.21 matt pushab softint_cleanup
344 1.21 matt svpctx
345 1.21 matt
346 1.21 matt /* We can use any register because ldpctx will overwrite them */
347 1.24 matt mfpr $PR_SSP,%r6 /* Get curlwp */
348 1.24 matt movl L_CPU(%r6),%r8 /* get cpu_info */
349 1.21 matt movl CI_SOFTLWPS(%r8)[%r0],%r2 /* get softlwp to switch to */
350 1.28 rmind movl L_PCB(%r2),%r3 /* Get pointer to its pcb. */
351 1.24 matt movl %r6,PCB_R6(%r3) /* move old lwp into new pcb */
352 1.21 matt movl %r1,PCB_R7(%r3) /* move IPL into new pcb */
353 1.24 matt #ifdef MULTIPROCESSOR
354 1.42 riastrad /* XXX store-before-store barrier -- see cpu_switchto */
355 1.21 matt movl %r2,CI_CURLWP(%r8) /* update ci_curlwp */
356 1.42 riastrad /* XXX store-before-load barrier -- see cpu_switchto */
357 1.24 matt #endif
358 1.23 matt
359 1.23 matt /*
360 1.23 matt * Now reset the PCB since we no idea what state it was last in
361 1.23 matt */
362 1.23 matt movab (USPACE-TRAPFRAMELEN-CALLSFRAMELEN)(%r3),%r0
363 1.23 matt /* calculate where KSP should be */
364 1.23 matt movl %r0,KSP(%r3) /* save it as SP */
365 1.23 matt movl %r0,PCB_FP(%r3) /* and as the FP too */
366 1.23 matt movab CA_ARGNO(%r0),PCB_AP(%r3) /* update the AP as well */
367 1.23 matt movab softint_process,PCB_PC(%r3) /* and where we will start */
368 1.32 snj movl $PSL_HIGHIPL,PCB_PSL(%r3) /* Needs to be running at IPL_HIGH */
369 1.23 matt
370 1.21 matt mtpr PCB_PADDR(%r3),$PR_PCBB /* set PA of new pcb */
371 1.21 matt ldpctx /* load it */
372 1.21 matt rei /* get off interrupt stack */
373 1.21 matt
374 1.21 matt SCBENTRY(softclock)
375 1.21 matt pushr $0x3 /* save r0 and r1 */
376 1.21 matt movl $SOFTINT_CLOCK,%r0
377 1.21 matt brb softint_common
378 1.21 matt
379 1.21 matt SCBENTRY(softbio)
380 1.21 matt pushr $0x3 /* save r0 and r1 */
381 1.21 matt movl $SOFTINT_BIO,%r0
382 1.21 matt brb softint_common
383 1.21 matt
384 1.21 matt SCBENTRY(softnet)
385 1.21 matt pushr $0x3 /* save r0 and r1 */
386 1.21 matt movl $SOFTINT_NET,%r0
387 1.21 matt brb softint_common
388 1.21 matt
389 1.21 matt SCBENTRY(softserial)
390 1.21 matt pushr $0x3 /* save r0 and r1 */
391 1.21 matt movl $SOFTINT_SERIAL,%r0
392 1.21 matt brb softint_common
393 1.21 matt
394 1.17 yamt /*
395 1.17 yamt * Helper routine for cpu_lwp_fork. It get invoked by Swtchto.
396 1.17 yamt * It let's the kernel know the lwp is alive and then calls func(arg)
397 1.17 yamt * and possibly returns to sret.
398 1.17 yamt */
399 1.17 yamt ENTRY(cpu_lwp_bootstrap, 0)
400 1.17 yamt movq %r2,-(%sp) /* save func & arg */
401 1.17 yamt movq %r0,-(%sp) /* push oldl/newl */
402 1.17 yamt calls $2,_C_LABEL(lwp_startup) /* startup the lwp */
403 1.17 yamt movl (%sp)+,%r0 /* grab func */
404 1.17 yamt calls $1,(%r0) /* call it with arg */
405 1.17 yamt ret
406 1.17 yamt
407 1.17 yamt /*
408 1.17 yamt * r1 = newlwp
409 1.17 yamt * r0 = oldlwp
410 1.17 yamt */
411 1.5 thorpej JSBENTRY(Swtchto)
412 1.17 yamt /* this pops the pc and psw from the stack and puts them in the pcb. */
413 1.5 thorpej svpctx # Now on interrupt stack
414 1.5 thorpej
415 1.17 yamt /* We can know use any register because ldpctx will overwrite them */
416 1.17 yamt /* New LWP already in %r1 */
417 1.28 rmind movl L_PCB(%r1),%r3 # Get pointer to new pcb.
418 1.17 yamt movl %r0,PCB_R0(%r3) # move r0 into new pcb (return value)
419 1.21 matt #ifdef MULTIPROCESSOR
420 1.24 matt movl L_CPU(%r0), %r8 /* get cpu_info of old lwp */
421 1.24 matt movl %r8, L_CPU(%r1) /* update cpu_info of new lwp */
422 1.42 riastrad /*
423 1.42 riastrad * Issue barriers to coordinate mutex_exit on this CPU with
424 1.42 riastrad * mutex_vector_enter on another CPU.
425 1.42 riastrad *
426 1.42 riastrad * 1. Any prior mutex_exit by oldlwp must be visible to other
427 1.42 riastrad * CPUs before we set ci_curlwp := newlwp on this one,
428 1.42 riastrad * requiring a store-before-store barrier.
429 1.42 riastrad *
430 1.42 riastrad * 2. ci_curlwp := newlwp must be visible on all other CPUs
431 1.42 riastrad * before any subsequent mutex_exit by newlwp can even test
432 1.42 riastrad * whether there might be waiters, requiring a
433 1.42 riastrad * store-before-load barrier.
434 1.42 riastrad *
435 1.42 riastrad * See kern_mutex.c for details -- this is necessary for
436 1.42 riastrad * adaptive mutexes to detect whether the lwp is on the CPU in
437 1.42 riastrad * order to safely block without requiring atomic r/m/w in
438 1.42 riastrad * mutex_exit.
439 1.42 riastrad *
440 1.42 riastrad * XXX I'm fuzzy on the memory model of VAX. I would guess
441 1.42 riastrad * it's TSO like x86 but I can't find a store-before-load
442 1.42 riastrad * barrier, which is the only one TSO requires explicitly.
443 1.42 riastrad */
444 1.42 riastrad /* XXX store-before-store barrier */
445 1.24 matt movl %r1,CI_CURLWP(%r8) /* update ci_curlwp */
446 1.42 riastrad /* XXX store-before-load barrier */
447 1.21 matt #endif
448 1.17 yamt
449 1.21 matt mtpr PCB_PADDR(%r3),$PR_PCBB # set PA of new pcb
450 1.21 matt mtpr $IPL_HIGH,$PR_IPL /* we need to be at IPL_HIGH */
451 1.17 yamt ldpctx # load it
452 1.17 yamt /* r0 already has previous lwp */
453 1.17 yamt /* r1 already has this lwp */
454 1.17 yamt /* r2/r3 and r4/r5 restored */
455 1.17 yamt rei /* get off interrupt stack */
456 1.1 matt
457 1.1 matt #
458 1.1 matt # copy/fetch/store routines.
459 1.1 matt #
460 1.1 matt
461 1.1 matt ENTRY(copyout, 0)
462 1.26 tsutsui movl 8(%ap),%r3
463 1.1 matt blss 3f # kernel space
464 1.2 matt movl 4(%ap),%r1
465 1.1 matt brb 2f
466 1.1 matt
467 1.1 matt ENTRY(copyin, 0)
468 1.2 matt movl 4(%ap),%r1
469 1.1 matt blss 3f # kernel space
470 1.26 tsutsui movl 8(%ap),%r3
471 1.26 tsutsui 2: mfpr $PR_ESP,%r2
472 1.30 chs movab 1f,(%r2) # set pcb_onfault
473 1.26 tsutsui 4: tstw 14(%ap) # check if >= 64K
474 1.26 tsutsui bneq 5f
475 1.26 tsutsui movc3 12(%ap),(%r1),(%r3)
476 1.30 chs clrl %r0
477 1.26 tsutsui 1: mfpr $PR_ESP,%r2
478 1.30 chs clrl (%r2) # clear pcb_onfault
479 1.1 matt ret
480 1.26 tsutsui 5: movc3 $0xfffc,(%r1),(%r3)
481 1.26 tsutsui subl2 $0xfffc,12(%ap)
482 1.26 tsutsui brb 4b
483 1.1 matt
484 1.30 chs 3: movl $EFAULT,%r0
485 1.1 matt ret
486 1.1 matt
487 1.1 matt ENTRY(kcopy,0)
488 1.2 matt mfpr $PR_ESP,%r3
489 1.30 chs movl (%r3),-(%sp) # save current pcb_onfault
490 1.30 chs movab 1f,(%r3) # set pcb_onfault
491 1.2 matt movl 4(%ap),%r1
492 1.2 matt movl 8(%ap),%r2
493 1.2 matt movc3 12(%ap),(%r1), (%r2)
494 1.30 chs clrl %r0
495 1.2 matt 1: mfpr $PR_ESP,%r3
496 1.30 chs movl (%sp)+,(%r3) # restore pcb_onfault
497 1.1 matt ret
498 1.1 matt
499 1.1 matt /*
500 1.1 matt * copy{in,out}str() copies data from/to user space to/from kernel space.
501 1.1 matt * Security checks:
502 1.1 matt * 1) user space address must be < KERNBASE
503 1.1 matt * 2) the VM system will do the checks while copying
504 1.1 matt */
505 1.1 matt ENTRY(copyinstr, 0)
506 1.2 matt tstl 4(%ap) # kernel address?
507 1.1 matt bgeq 8f # no, continue
508 1.2 matt 6: movl $EFAULT,%r0
509 1.2 matt movl 16(%ap),%r2
510 1.1 matt beql 7f
511 1.2 matt clrl (%r2)
512 1.1 matt 7: ret
513 1.1 matt
514 1.1 matt ENTRY(copyoutstr, 0)
515 1.2 matt tstl 8(%ap) # kernel address?
516 1.1 matt bgeq 8f # no, continue
517 1.1 matt brb 6b # yes, return EFAULT
518 1.1 matt
519 1.2 matt 8: movl 4(%ap),%r5 # from
520 1.2 matt movl 8(%ap),%r4 # to
521 1.2 matt movl 12(%ap),%r3 # len
522 1.2 matt movl 16(%ap),%r2 # copied
523 1.2 matt clrl %r0
524 1.2 matt mfpr $PR_ESP,%r1
525 1.30 chs movab 2f,(%r1) # set pcb_onfault
526 1.1 matt
527 1.2 matt tstl %r3 # any chars to copy?
528 1.1 matt bneq 1f # yes, jump for more
529 1.2 matt 0: tstl %r2 # save copied len?
530 1.1 matt beql 2f # no
531 1.2 matt subl3 4(%ap),%r5,(%r2) # save copied len
532 1.30 chs 2: mfpr $PR_ESP,%r1
533 1.30 chs clrl (%r1) # clear pcb_onfault
534 1.30 chs ret
535 1.1 matt
536 1.2 matt 1: movb (%r5)+,(%r4)+ # copy one char
537 1.1 matt beql 0b # jmp if last char
538 1.2 matt sobgtr %r3,1b # copy one more
539 1.2 matt movl $ENAMETOOLONG,%r0 # inform about too long string
540 1.1 matt brb 0b # out of chars
541 1.1 matt
542 1.36 thorpej /**************************************************************************/
543 1.1 matt
544 1.36 thorpej .align 2
545 1.1 matt
546 1.36 thorpej #define UFETCHSTORE_PROLOGUE \
547 1.39 andvar tstl 4(%ap) /* uaddr in userspace? */ ;\
548 1.36 thorpej blss 1f /* nope, fault */ ;\
549 1.36 thorpej mfpr $PR_ESP,%r1 /* &pcb_onfault is in ESP */ ;\
550 1.36 thorpej movab 2f,(%r1) /* set pcb_onfault */
551 1.36 thorpej
552 1.36 thorpej #define UFETCHSTORE_EPILOGUE \
553 1.36 thorpej mfpr $PR_ESP,%r1 /* &pcb_onfault is in ESP */ ;\
554 1.36 thorpej clrl (%r1) /* pcb_onfault = NULL */
555 1.36 thorpej
556 1.36 thorpej #define UFETCHSTORE_RETURN \
557 1.36 thorpej clrl %r0 /* return success */ ;\
558 1.36 thorpej ret ;\
559 1.36 thorpej 1: movl $EFAULT,%r0 ;\
560 1.36 thorpej ret /* return EFAULT */ ;\
561 1.36 thorpej 2: UFETCHSTORE_EPILOGUE ;\
562 1.36 thorpej ret /* error already in %r0 */
563 1.36 thorpej
564 1.36 thorpej /* LINTSTUB: int _ufetch_8(const uint8_t *uaddr, uint8_t *valp); */
565 1.36 thorpej ENTRY(_ufetch_8,0)
566 1.36 thorpej UFETCHSTORE_PROLOGUE
567 1.36 thorpej movb *4(%ap),*8(%ap) # *valp = *uaddr
568 1.36 thorpej UFETCHSTORE_EPILOGUE
569 1.36 thorpej UFETCHSTORE_RETURN
570 1.36 thorpej
571 1.36 thorpej /* LINTSTUB: int _ufetch_16(const uint16_t *uaddr, uint16_t *valp); */
572 1.36 thorpej ENTRY(_ufetch_16,0)
573 1.36 thorpej UFETCHSTORE_PROLOGUE
574 1.36 thorpej movw *4(%ap),*8(%ap) # *valp = *uaddr
575 1.36 thorpej UFETCHSTORE_EPILOGUE
576 1.36 thorpej UFETCHSTORE_RETURN
577 1.36 thorpej
578 1.36 thorpej /* LINTSTUB: int _ufetch_32(const uint32_t *uaddr, uint32_t *valp); */
579 1.36 thorpej ENTRY(_ufetch_32,0)
580 1.36 thorpej UFETCHSTORE_PROLOGUE
581 1.36 thorpej movl *4(%ap),*8(%ap) # *valp = *uaddr
582 1.36 thorpej UFETCHSTORE_EPILOGUE
583 1.36 thorpej UFETCHSTORE_RETURN
584 1.36 thorpej
585 1.36 thorpej /* LINTSTUB: int _ustore_8(uint8_t *uaddr, uint8_t val); */
586 1.36 thorpej ENTRY(_ustore_8,0)
587 1.36 thorpej UFETCHSTORE_PROLOGUE
588 1.36 thorpej movb 8(%ap),*4(%ap) # *uaddr = val
589 1.36 thorpej UFETCHSTORE_EPILOGUE
590 1.36 thorpej UFETCHSTORE_RETURN
591 1.36 thorpej
592 1.36 thorpej /* LINTSTUB: int _ustore_16(uint16_t *uaddr, uint16_t val); */
593 1.36 thorpej ENTRY(_ustore_16,0)
594 1.36 thorpej UFETCHSTORE_PROLOGUE
595 1.36 thorpej movw 8(%ap),*4(%ap) # *uaddr = val
596 1.36 thorpej UFETCHSTORE_EPILOGUE
597 1.36 thorpej UFETCHSTORE_RETURN
598 1.36 thorpej
599 1.36 thorpej /* LINTSTUB: int _ustore_32(uint32_t *uaddr, uint32_t val); */
600 1.36 thorpej ENTRY(_ustore_32,0)
601 1.36 thorpej UFETCHSTORE_PROLOGUE
602 1.36 thorpej movl 8(%ap),*4(%ap) # *uaddr = val
603 1.36 thorpej UFETCHSTORE_EPILOGUE
604 1.36 thorpej UFETCHSTORE_RETURN
605 1.1 matt
606 1.36 thorpej /**************************************************************************/
607 1.1 matt
608 1.1 matt .align 2
609 1.1 matt
610 1.1 matt JSBENTRY(Slock)
611 1.2 matt 1: bbssi $0,(%r1),1b
612 1.1 matt rsb
613 1.1 matt
614 1.1 matt JSBENTRY(Slocktry)
615 1.2 matt clrl %r0
616 1.2 matt bbssi $0,(%r1),1f
617 1.2 matt incl %r0
618 1.1 matt 1: rsb
619 1.1 matt
620 1.1 matt JSBENTRY(Sunlock)
621 1.2 matt bbcci $0,(%r1),1f
622 1.1 matt 1: rsb
623 1.1 matt
624 1.1 matt #
625 1.1 matt # data department
626 1.1 matt #
627 1.1 matt .data
628 1.1 matt
629 1.1 matt .globl _C_LABEL(memtest)
630 1.1 matt _C_LABEL(memtest): # memory test in progress
631 1.1 matt .long 0
632