xref: /f-stack/freebsd/mips/mips/vm_machdep.c (revision 22ce4aff)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1982, 1986 The Regents of the University of California.
5  * Copyright (c) 1989, 1990 William Jolitz
6  * Copyright (c) 1994 John Dyson
7  * All rights reserved.
8  *
9  * This code is derived from software contributed to Berkeley by
10  * the Systems Programming Group of the University of Utah Computer
11  * Science Department, and William Jolitz.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  *	from: @(#)vm_machdep.c	7.3 (Berkeley) 5/13/91
38  *	Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$
39  *	from: src/sys/i386/i386/vm_machdep.c,v 1.132.2.2 2000/08/26 04:19:26 yokota
40  *	JNPR: vm_machdep.c,v 1.8.2.2 2007/08/16 15:59:17 girish
41  */
42 
43 #include <sys/cdefs.h>
44 __FBSDID("$FreeBSD$");
45 
46 #include "opt_ddb.h"
47 
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/malloc.h>
51 #include <sys/proc.h>
52 #include <sys/syscall.h>
53 #include <sys/sysent.h>
54 #include <sys/buf.h>
55 #include <sys/vnode.h>
56 #include <sys/vmmeter.h>
57 #include <sys/kernel.h>
58 #include <sys/sysctl.h>
59 #include <sys/unistd.h>
60 
61 #include <machine/abi.h>
62 #include <machine/cache.h>
63 #include <machine/clock.h>
64 #include <machine/cpu.h>
65 #include <machine/cpufunc.h>
66 #include <machine/cpuinfo.h>
67 #include <machine/md_var.h>
68 #include <machine/pcb.h>
69 #include <machine/tls.h>
70 
71 #include <vm/vm.h>
72 #include <vm/vm_extern.h>
73 #include <vm/pmap.h>
74 #include <vm/vm_kern.h>
75 #include <vm/vm_map.h>
76 #include <vm/vm_page.h>
77 #include <vm/vm_pageout.h>
78 #include <vm/vm_param.h>
79 #include <vm/uma.h>
80 #include <vm/uma_int.h>
81 
82 #include <sys/user.h>
83 #include <sys/mbuf.h>
84 
85 /*
86  * Finish a fork operation, with process p2 nearly set up.
87  * Copy and update the pcb, set up the stack so that the child
88  * ready to run and return to user mode.
89  */
90 void
cpu_fork(struct thread * td1,struct proc * p2,struct thread * td2,int flags)91 cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
92 {
93 	struct pcb *pcb2;
94 
95 	if ((flags & RFPROC) == 0)
96 		return;
97 	/* It is assumed that the vm_thread_alloc called
98 	 * cpu_thread_alloc() before cpu_fork is called.
99 	 */
100 
101 	/* Point the pcb to the top of the stack */
102 	pcb2 = td2->td_pcb;
103 
104 	/* Copy td1's pcb, note that in this case
105 	 * our pcb also includes the td_frame being copied
106 	 * too. The older mips2 code did an additional copy
107 	 * of the td_frame, for us that's not needed any
108 	 * longer (this copy does them both)
109 	 */
110 	bcopy(td1->td_pcb, pcb2, sizeof(*pcb2));
111 
112 	/* Point mdproc and then copy over td1's contents
113 	 * md_proc is empty for MIPS
114 	 */
115 	td2->td_md.md_flags = td1->td_md.md_flags & MDTD_FPUSED;
116 
117 	/*
118 	 * Set up return-value registers as fork() libc stub expects.
119 	 */
120 	td2->td_frame->v0 = 0;
121 	td2->td_frame->v1 = 1;
122 	td2->td_frame->a3 = 0;
123 
124 	if (td1 == PCPU_GET(fpcurthread))
125 		MipsSaveCurFPState(td1);
126 
127 	pcb2->pcb_context[PCB_REG_RA] = (register_t)(intptr_t)fork_trampoline;
128 	/* Make sp 64-bit aligned */
129 	pcb2->pcb_context[PCB_REG_SP] = (register_t)(((vm_offset_t)td2->td_pcb &
130 	    ~(sizeof(__int64_t) - 1)) - CALLFRAME_SIZ);
131 	pcb2->pcb_context[PCB_REG_S0] = (register_t)(intptr_t)fork_return;
132 	pcb2->pcb_context[PCB_REG_S1] = (register_t)(intptr_t)td2;
133 	pcb2->pcb_context[PCB_REG_S2] = (register_t)(intptr_t)td2->td_frame;
134 	pcb2->pcb_context[PCB_REG_SR] = mips_rd_status() &
135 	    (MIPS_SR_KX | MIPS_SR_UX | MIPS_SR_INT_MASK);
136 	/*
137 	 * FREEBSD_DEVELOPERS_FIXME:
138 	 * Setup any other CPU-Specific registers (Not MIPS Standard)
139 	 * and/or bits in other standard MIPS registers (if CPU-Specific)
140 	 *  that are needed.
141 	 */
142 
143 	td2->td_md.md_tls = td1->td_md.md_tls;
144 	p2->p_md.md_tls_tcb_offset = td1->td_proc->p_md.md_tls_tcb_offset;
145 	td2->td_md.md_saved_intr = MIPS_SR_INT_IE;
146 	td2->td_md.md_spinlock_count = 1;
147 #ifdef CPU_CNMIPS
148 	if (td1->td_md.md_flags & MDTD_COP2USED) {
149 		if (td1->td_md.md_cop2owner == COP2_OWNER_USERLAND) {
150 			if (td1->td_md.md_ucop2)
151 				octeon_cop2_save(td1->td_md.md_ucop2);
152 			else
153 				panic("cpu_fork: ucop2 is NULL but COP2 is enabled");
154 		}
155 		else {
156 			if (td1->td_md.md_cop2)
157 				octeon_cop2_save(td1->td_md.md_cop2);
158 			else
159 				panic("cpu_fork: cop2 is NULL but COP2 is enabled");
160 		}
161 	}
162 
163 	if (td1->td_md.md_cop2) {
164 		td2->td_md.md_cop2 = octeon_cop2_alloc_ctx();
165 		memcpy(td2->td_md.md_cop2, td1->td_md.md_cop2,
166 			sizeof(*td1->td_md.md_cop2));
167 	}
168 	if (td1->td_md.md_ucop2) {
169 		td2->td_md.md_ucop2 = octeon_cop2_alloc_ctx();
170 		memcpy(td2->td_md.md_ucop2, td1->td_md.md_ucop2,
171 			sizeof(*td1->td_md.md_ucop2));
172 	}
173 	td2->td_md.md_cop2owner = td1->td_md.md_cop2owner;
174 	pcb2->pcb_context[PCB_REG_SR] |= MIPS_SR_PX | MIPS_SR_UX | MIPS_SR_KX | MIPS_SR_SX;
175 	/* Clear COP2 bits for userland & kernel */
176 	td2->td_frame->sr &= ~MIPS_SR_COP_2_BIT;
177 	pcb2->pcb_context[PCB_REG_SR] &= ~MIPS_SR_COP_2_BIT;
178 #endif
179 }
180 
181 /*
182  * Intercept the return address from a freshly forked process that has NOT
183  * been scheduled yet.
184  *
185  * This is needed to make kernel threads stay in kernel mode.
186  */
187 void
cpu_fork_kthread_handler(struct thread * td,void (* func)(void *),void * arg)188 cpu_fork_kthread_handler(struct thread *td, void (*func)(void *), void *arg)
189 {
190 	/*
191 	 * Note that the trap frame follows the args, so the function
192 	 * is really called like this:	func(arg, frame);
193 	 */
194 	td->td_pcb->pcb_context[PCB_REG_S0] = (register_t)(intptr_t)func;
195 	td->td_pcb->pcb_context[PCB_REG_S1] = (register_t)(intptr_t)arg;
196 }
197 
198 void
cpu_exit(struct thread * td)199 cpu_exit(struct thread *td)
200 {
201 }
202 
203 void
cpu_thread_exit(struct thread * td)204 cpu_thread_exit(struct thread *td)
205 {
206 
207 	if (PCPU_GET(fpcurthread) == td)
208 		PCPU_GET(fpcurthread) = (struct thread *)0;
209 #ifdef  CPU_CNMIPS
210 	if (td->td_md.md_cop2)
211 		memset(td->td_md.md_cop2, 0,
212 			sizeof(*td->td_md.md_cop2));
213 	if (td->td_md.md_ucop2)
214 		memset(td->td_md.md_ucop2, 0,
215 			sizeof(*td->td_md.md_ucop2));
216 #endif
217 }
218 
219 void
cpu_thread_free(struct thread * td)220 cpu_thread_free(struct thread *td)
221 {
222 #ifdef  CPU_CNMIPS
223 	if (td->td_md.md_cop2)
224 		octeon_cop2_free_ctx(td->td_md.md_cop2);
225 	if (td->td_md.md_ucop2)
226 		octeon_cop2_free_ctx(td->td_md.md_ucop2);
227 	td->td_md.md_cop2 = NULL;
228 	td->td_md.md_ucop2 = NULL;
229 #endif
230 }
231 
232 void
cpu_thread_clean(struct thread * td)233 cpu_thread_clean(struct thread *td)
234 {
235 }
236 
237 void
cpu_thread_swapin(struct thread * td)238 cpu_thread_swapin(struct thread *td)
239 {
240 	pt_entry_t *pte;
241 	int i;
242 
243 	/*
244 	 * The kstack may be at a different physical address now.
245 	 * Cache the PTEs for the Kernel stack in the machine dependent
246 	 * part of the thread struct so cpu_switch() can quickly map in
247 	 * the pcb struct and kernel stack.
248 	 */
249 	for (i = 0; i < KSTACK_PAGES; i++) {
250 		pte = pmap_pte(kernel_pmap, td->td_kstack + i * PAGE_SIZE);
251 		td->td_md.md_upte[i] = *pte & ~TLBLO_SWBITS_MASK;
252 	}
253 }
254 
255 void
cpu_thread_swapout(struct thread * td)256 cpu_thread_swapout(struct thread *td)
257 {
258 }
259 
260 void
cpu_thread_alloc(struct thread * td)261 cpu_thread_alloc(struct thread *td)
262 {
263 	pt_entry_t *pte;
264 	int i;
265 
266 	KASSERT((td->td_kstack & (1 << PAGE_SHIFT)) == 0, ("kernel stack must be aligned."));
267 	td->td_pcb = (struct pcb *)(td->td_kstack +
268 	    td->td_kstack_pages * PAGE_SIZE) - 1;
269 	td->td_frame = &td->td_pcb->pcb_regs;
270 
271 	for (i = 0; i < KSTACK_PAGES; i++) {
272 		pte = pmap_pte(kernel_pmap, td->td_kstack + i * PAGE_SIZE);
273 		td->td_md.md_upte[i] = *pte & ~TLBLO_SWBITS_MASK;
274 	}
275 }
276 
277 void
cpu_set_syscall_retval(struct thread * td,int error)278 cpu_set_syscall_retval(struct thread *td, int error)
279 {
280 	struct trapframe *locr0 = td->td_frame;
281 	unsigned int code;
282 	int quad_syscall;
283 
284 	code = locr0->v0;
285 	quad_syscall = 0;
286 #if defined(__mips_n32) || defined(__mips_n64)
287 #ifdef COMPAT_FREEBSD32
288 	if (code == SYS___syscall && SV_PROC_FLAG(td->td_proc, SV_ILP32))
289 		quad_syscall = 1;
290 #endif
291 #else
292 	if (code == SYS___syscall)
293 		quad_syscall = 1;
294 #endif
295 
296 	if (code == SYS_syscall)
297 		code = locr0->a0;
298 	else if (code == SYS___syscall) {
299 		if (quad_syscall)
300 			code = _QUAD_LOWWORD ? locr0->a1 : locr0->a0;
301 		else
302 			code = locr0->a0;
303 	}
304 
305 	switch (error) {
306 	case 0:
307 		if (quad_syscall && code != SYS_lseek) {
308 			/*
309 			 * System call invoked through the
310 			 * SYS___syscall interface but the
311 			 * return value is really just 32
312 			 * bits.
313 			 */
314 			locr0->v0 = td->td_retval[0];
315 			if (_QUAD_LOWWORD)
316 				locr0->v1 = td->td_retval[0];
317 			locr0->a3 = 0;
318 		} else {
319 			locr0->v0 = td->td_retval[0];
320 			locr0->v1 = td->td_retval[1];
321 			locr0->a3 = 0;
322 		}
323 		break;
324 
325 	case ERESTART:
326 		locr0->pc = td->td_pcb->pcb_tpc;
327 		break;
328 
329 	case EJUSTRETURN:
330 		break;	/* nothing to do */
331 
332 	default:
333 		if (quad_syscall && code != SYS_lseek) {
334 			locr0->v0 = error;
335 			if (_QUAD_LOWWORD)
336 				locr0->v1 = error;
337 			locr0->a3 = 1;
338 		} else {
339 			locr0->v0 = error;
340 			locr0->a3 = 1;
341 		}
342 	}
343 }
344 
345 /*
346  * Initialize machine state, mostly pcb and trap frame for a new
347  * thread, about to return to userspace.  Put enough state in the new
348  * thread's PCB to get it to go back to the fork_return(), which
349  * finalizes the thread state and handles peculiarities of the first
350  * return to userspace for the new thread.
351  */
352 void
cpu_copy_thread(struct thread * td,struct thread * td0)353 cpu_copy_thread(struct thread *td, struct thread *td0)
354 {
355 	struct pcb *pcb2;
356 
357 	/* Point the pcb to the top of the stack. */
358 	pcb2 = td->td_pcb;
359 
360 	/*
361 	 * Copy the upcall pcb.  This loads kernel regs.
362 	 * Those not loaded individually below get their default
363 	 * values here.
364 	 *
365 	 * XXXKSE It might be a good idea to simply skip this as
366 	 * the values of the other registers may be unimportant.
367 	 * This would remove any requirement for knowing the KSE
368 	 * at this time (see the matching comment below for
369 	 * more analysis) (need a good safe default).
370 	 * In MIPS, the trapframe is the first element of the PCB
371 	 * and gets copied when we copy the PCB. No separate copy
372 	 * is needed.
373 	 */
374 	bcopy(td0->td_pcb, pcb2, sizeof(*pcb2));
375 
376 	/*
377 	 * Set registers for trampoline to user mode.
378 	 */
379 
380 	pcb2->pcb_context[PCB_REG_RA] = (register_t)(intptr_t)fork_trampoline;
381 	/* Make sp 64-bit aligned */
382 	pcb2->pcb_context[PCB_REG_SP] = (register_t)(((vm_offset_t)td->td_pcb &
383 	    ~(sizeof(__int64_t) - 1)) - CALLFRAME_SIZ);
384 	pcb2->pcb_context[PCB_REG_S0] = (register_t)(intptr_t)fork_return;
385 	pcb2->pcb_context[PCB_REG_S1] = (register_t)(intptr_t)td;
386 	pcb2->pcb_context[PCB_REG_S2] = (register_t)(intptr_t)td->td_frame;
387 	/* Dont set IE bit in SR. sched lock release will take care of it */
388 	pcb2->pcb_context[PCB_REG_SR] = mips_rd_status() &
389 	    (MIPS_SR_PX | MIPS_SR_KX | MIPS_SR_UX | MIPS_SR_INT_MASK);
390 
391 	/*
392 	 * FREEBSD_DEVELOPERS_FIXME:
393 	 * Setup any other CPU-Specific registers (Not MIPS Standard)
394 	 * that are needed.
395 	 */
396 
397 	/* Setup to release spin count in in fork_exit(). */
398 	td->td_md.md_spinlock_count = 1;
399 	td->td_md.md_saved_intr = MIPS_SR_INT_IE;
400 #if 0
401 	    /* Maybe we need to fix this? */
402 	td->td_md.md_saved_sr = ( (MIPS_SR_COP_2_BIT | MIPS_SR_COP_0_BIT) |
403 	                          (MIPS_SR_PX | MIPS_SR_UX | MIPS_SR_KX | MIPS_SR_SX) |
404 	                          (MIPS_SR_INT_IE | MIPS_HARD_INT_MASK));
405 #endif
406 	td->td_md.md_tls = NULL;
407 }
408 
409 /*
410  * Set that machine state for performing an upcall that starts
411  * the entry function with the given argument.
412  */
413 void
cpu_set_upcall(struct thread * td,void (* entry)(void *),void * arg,stack_t * stack)414 cpu_set_upcall(struct thread *td, void (*entry)(void *), void *arg,
415     stack_t *stack)
416 {
417 	struct trapframe *tf;
418 	register_t sp, sr;
419 
420 	sp = (((intptr_t)stack->ss_sp + stack->ss_size) & ~(STACK_ALIGN - 1)) -
421 	    CALLFRAME_SIZ;
422 
423 	/*
424 	 * Set the trap frame to point at the beginning of the uts
425 	 * function.
426 	 */
427 	tf = td->td_frame;
428 	sr = tf->sr;
429 	bzero(tf, sizeof(struct trapframe));
430 	tf->sp = sp;
431 	tf->sr = sr;
432 	tf->pc = (register_t)(intptr_t)entry;
433 	/*
434 	 * MIPS ABI requires T9 to be the same as PC
435 	 * in subroutine entry point
436 	 */
437 	tf->t9 = (register_t)(intptr_t)entry;
438 	tf->a0 = (register_t)(intptr_t)arg;
439 
440 	/*
441 	 * FREEBSD_DEVELOPERS_FIXME:
442 	 * Setup any other CPU-Specific registers (Not MIPS Standard)
443 	 * that are needed.
444 	 */
445 }
446 
447 bool
cpu_exec_vmspace_reuse(struct proc * p __unused,vm_map_t map __unused)448 cpu_exec_vmspace_reuse(struct proc *p __unused, vm_map_t map __unused)
449 {
450 
451 	return (true);
452 }
453 
454 int
cpu_procctl(struct thread * td __unused,int idtype __unused,id_t id __unused,int com __unused,void * data __unused)455 cpu_procctl(struct thread *td __unused, int idtype __unused, id_t id __unused,
456     int com __unused, void *data __unused)
457 {
458 
459 	return (EINVAL);
460 }
461 
462 /*
463  * Software interrupt handler for queued VM system processing.
464  */
465 void
swi_vm(void * dummy)466 swi_vm(void *dummy)
467 {
468 
469 	if (busdma_swi_pending)
470 		busdma_swi();
471 }
472 
473 int
cpu_set_user_tls(struct thread * td,void * tls_base)474 cpu_set_user_tls(struct thread *td, void *tls_base)
475 {
476 
477 	td->td_md.md_tls = (char*)tls_base;
478 	if (td == curthread && cpuinfo.userlocal_reg == true) {
479 		mips_wr_userlocal((unsigned long)tls_base +
480 		    td->td_proc->p_md.md_tls_tcb_offset);
481 	}
482 
483 	return (0);
484 }
485 
486 #ifdef DDB
487 #include <ddb/ddb.h>
488 
489 #define DB_PRINT_REG(ptr, regname)			\
490 	db_printf("  %-12s %p\n", #regname, (void *)(intptr_t)((ptr)->regname))
491 
492 #define DB_PRINT_REG_ARRAY(ptr, arrname, regname)	\
493 	db_printf("  %-12s %p\n", #regname, (void *)(intptr_t)((ptr)->arrname[regname]))
494 
495 static void
dump_trapframe(struct trapframe * trapframe)496 dump_trapframe(struct trapframe *trapframe)
497 {
498 
499 	db_printf("Trapframe at %p\n", trapframe);
500 
501 	DB_PRINT_REG(trapframe, zero);
502 	DB_PRINT_REG(trapframe, ast);
503 	DB_PRINT_REG(trapframe, v0);
504 	DB_PRINT_REG(trapframe, v1);
505 	DB_PRINT_REG(trapframe, a0);
506 	DB_PRINT_REG(trapframe, a1);
507 	DB_PRINT_REG(trapframe, a2);
508 	DB_PRINT_REG(trapframe, a3);
509 #if defined(__mips_n32) || defined(__mips_n64)
510 	DB_PRINT_REG(trapframe, a4);
511 	DB_PRINT_REG(trapframe, a5);
512 	DB_PRINT_REG(trapframe, a6);
513 	DB_PRINT_REG(trapframe, a7);
514 	DB_PRINT_REG(trapframe, t0);
515 	DB_PRINT_REG(trapframe, t1);
516 	DB_PRINT_REG(trapframe, t2);
517 	DB_PRINT_REG(trapframe, t3);
518 #else
519 	DB_PRINT_REG(trapframe, t0);
520 	DB_PRINT_REG(trapframe, t1);
521 	DB_PRINT_REG(trapframe, t2);
522 	DB_PRINT_REG(trapframe, t3);
523 	DB_PRINT_REG(trapframe, t4);
524 	DB_PRINT_REG(trapframe, t5);
525 	DB_PRINT_REG(trapframe, t6);
526 	DB_PRINT_REG(trapframe, t7);
527 #endif
528 	DB_PRINT_REG(trapframe, s0);
529 	DB_PRINT_REG(trapframe, s1);
530 	DB_PRINT_REG(trapframe, s2);
531 	DB_PRINT_REG(trapframe, s3);
532 	DB_PRINT_REG(trapframe, s4);
533 	DB_PRINT_REG(trapframe, s5);
534 	DB_PRINT_REG(trapframe, s6);
535 	DB_PRINT_REG(trapframe, s7);
536 	DB_PRINT_REG(trapframe, t8);
537 	DB_PRINT_REG(trapframe, t9);
538 	DB_PRINT_REG(trapframe, k0);
539 	DB_PRINT_REG(trapframe, k1);
540 	DB_PRINT_REG(trapframe, gp);
541 	DB_PRINT_REG(trapframe, sp);
542 	DB_PRINT_REG(trapframe, s8);
543 	DB_PRINT_REG(trapframe, ra);
544 	DB_PRINT_REG(trapframe, sr);
545 	DB_PRINT_REG(trapframe, mullo);
546 	DB_PRINT_REG(trapframe, mulhi);
547 	DB_PRINT_REG(trapframe, badvaddr);
548 	DB_PRINT_REG(trapframe, cause);
549 	DB_PRINT_REG(trapframe, pc);
550 }
551 
DB_SHOW_COMMAND(pcb,ddb_dump_pcb)552 DB_SHOW_COMMAND(pcb, ddb_dump_pcb)
553 {
554 	struct thread *td;
555 	struct pcb *pcb;
556 	struct trapframe *trapframe;
557 
558 	/* Determine which thread to examine. */
559 	if (have_addr)
560 		td = db_lookup_thread(addr, true);
561 	else
562 		td = curthread;
563 
564 	pcb = td->td_pcb;
565 
566 	db_printf("Thread %d at %p\n", td->td_tid, td);
567 
568 	db_printf("PCB at %p\n", pcb);
569 
570 	trapframe = &pcb->pcb_regs;
571 	dump_trapframe(trapframe);
572 
573 	db_printf("PCB Context:\n");
574 	DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S0);
575 	DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S1);
576 	DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S2);
577 	DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S3);
578 	DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S4);
579 	DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S5);
580 	DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S6);
581 	DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S7);
582 	DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_SP);
583 	DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S8);
584 	DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_RA);
585 	DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_SR);
586 	DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_GP);
587 	DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_PC);
588 
589 	db_printf("PCB onfault = %p\n", pcb->pcb_onfault);
590 	db_printf("md_saved_intr = 0x%0lx\n", (long)td->td_md.md_saved_intr);
591 	db_printf("md_spinlock_count = %d\n", td->td_md.md_spinlock_count);
592 
593 	if (td->td_frame != trapframe) {
594 		db_printf("td->td_frame %p is not the same as pcb_regs %p\n",
595 			  td->td_frame, trapframe);
596 	}
597 }
598 
599 /*
600  * Dump the trapframe beginning at address specified by first argument.
601  */
DB_SHOW_COMMAND(trapframe,ddb_dump_trapframe)602 DB_SHOW_COMMAND(trapframe, ddb_dump_trapframe)
603 {
604 
605 	if (!have_addr)
606 		return;
607 
608 	dump_trapframe((struct trapframe *)addr);
609 }
610 
611 #endif	/* DDB */
612