1/*- 2 * Copyright (c) 1982, 1986 The Regents of the University of California. 3 * Copyright (c) 1989, 1990 William Jolitz 4 * Copyright (c) 1994 John Dyson 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * the Systems Programming Group of the University of Utah Computer 9 * Science Department, and William Jolitz. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * from: @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 36 * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$ 37 * from: src/sys/i386/i386/vm_machdep.c,v 1.132.2.2 2000/08/26 04:19:26 yokota 38 * JNPR: vm_machdep.c,v 1.8.2.2 2007/08/16 15:59:17 girish 39 */ 40 41#include <sys/cdefs.h> 42__FBSDID("$FreeBSD$"); 43 44#include "opt_compat.h" 45#include "opt_ddb.h" 46 47#include <sys/param.h> 48#include <sys/systm.h> 49#include <sys/malloc.h> 50#include <sys/proc.h> 51#include <sys/syscall.h> 52#include <sys/sysent.h> 53#include <sys/buf.h> 54#include <sys/vnode.h> 55#include <sys/vmmeter.h> 56#include <sys/kernel.h> 57#include <sys/sysctl.h> 58#include <sys/unistd.h> 59 60#include <machine/cache.h> 61#include <machine/clock.h> 62#include <machine/cpu.h> 63#include <machine/md_var.h> 64#include <machine/pcb.h> 65 66#include <vm/vm.h> 67#include <vm/vm_extern.h> 68#include <vm/pmap.h> 69#include <vm/vm_kern.h> 70#include <vm/vm_map.h> 71#include <vm/vm_page.h> 72#include <vm/vm_pageout.h> 73#include <vm/vm_param.h> 74#include <vm/uma.h> 75#include <vm/uma_int.h> 76 77#include <sys/user.h> 78#include <sys/mbuf.h> 79#ifndef __mips_n64 80#include <sys/sf_buf.h> 81#endif 82 83/* Duplicated from asm.h */ 84#if defined(__mips_o32) 85#define SZREG 4 86#else 87#define SZREG 8 88#endif 89#if defined(__mips_o32) || defined(__mips_o64) 90#define CALLFRAME_SIZ (SZREG * (4 + 2)) 91#elif defined(__mips_n32) || defined(__mips_n64) 92#define CALLFRAME_SIZ (SZREG * 4) 93#endif 94 95#ifndef __mips_n64 96 97#ifndef NSFBUFS 98#define NSFBUFS (512 + maxusers * 16) 99#endif 100 101static int nsfbufs; 102static int nsfbufspeak; 103static int nsfbufsused; 104 105SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufs, CTLFLAG_RDTUN, &nsfbufs, 0, 106 "Maximum number of sendfile(2) sf_bufs available"); 107SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufspeak, CTLFLAG_RD, &nsfbufspeak, 0, 108 "Number of sendfile(2) sf_bufs at peak usage"); 109SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufsused, CTLFLAG_RD, &nsfbufsused, 0, 110 "Number of sendfile(2) sf_bufs in use"); 111 112static void sf_buf_init(void *arg); 113SYSINIT(sock_sf, SI_SUB_MBUF, SI_ORDER_ANY, sf_buf_init, NULL); 114 115/* 116 * Expanded sf_freelist head. Really an SLIST_HEAD() in disguise, with the 117 * sf_freelist head with the sf_lock mutex. 118 */ 119static struct { 120 SLIST_HEAD(, sf_buf) sf_head; 121 struct mtx sf_lock; 122} sf_freelist; 123 124static u_int sf_buf_alloc_want; 125#endif /* !__mips_n64 */ 126 127/* 128 * Finish a fork operation, with process p2 nearly set up. 129 * Copy and update the pcb, set up the stack so that the child 130 * ready to run and return to user mode. 131 */ 132void 133cpu_fork(register struct thread *td1,register struct proc *p2, 134 struct thread *td2,int flags) 135{ 136 register struct proc *p1; 137 struct pcb *pcb2; 138 139 p1 = td1->td_proc; 140 if ((flags & RFPROC) == 0) 141 return; 142 /* It is assumed that the vm_thread_alloc called 143 * cpu_thread_alloc() before cpu_fork is called. 144 */ 145 146 /* Point the pcb to the top of the stack */ 147 pcb2 = td2->td_pcb; 148 149 /* Copy p1's pcb, note that in this case 150 * our pcb also includes the td_frame being copied 151 * too. The older mips2 code did an additional copy 152 * of the td_frame, for us that's not needed any 153 * longer (this copy does them both) 154 */ 155 bcopy(td1->td_pcb, pcb2, sizeof(*pcb2)); 156 157 /* Point mdproc and then copy over td1's contents 158 * md_proc is empty for MIPS 159 */ 160 td2->td_md.md_flags = td1->td_md.md_flags & MDTD_FPUSED; 161 162 /* 163 * Set up return-value registers as fork() libc stub expects. 164 */ 165 td2->td_frame->v0 = 0; 166 td2->td_frame->v1 = 1; 167 td2->td_frame->a3 = 0; 168 169 if (td1 == PCPU_GET(fpcurthread)) 170 MipsSaveCurFPState(td1); 171 172 pcb2->pcb_context[PCB_REG_RA] = (register_t)(intptr_t)fork_trampoline; 173 /* Make sp 64-bit aligned */ 174 pcb2->pcb_context[PCB_REG_SP] = (register_t)(((vm_offset_t)td2->td_pcb & 175 ~(sizeof(__int64_t) - 1)) - CALLFRAME_SIZ); 176 pcb2->pcb_context[PCB_REG_S0] = (register_t)(intptr_t)fork_return; 177 pcb2->pcb_context[PCB_REG_S1] = (register_t)(intptr_t)td2; 178 pcb2->pcb_context[PCB_REG_S2] = (register_t)(intptr_t)td2->td_frame; 179 pcb2->pcb_context[PCB_REG_SR] = mips_rd_status() & 180 (MIPS_SR_KX | MIPS_SR_UX | MIPS_SR_INT_MASK); 181 /* 182 * FREEBSD_DEVELOPERS_FIXME: 183 * Setup any other CPU-Specific registers (Not MIPS Standard) 184 * and/or bits in other standard MIPS registers (if CPU-Specific) 185 * that are needed. 186 */ 187 188 td2->td_md.md_tls = td1->td_md.md_tls; 189 td2->td_md.md_saved_intr = MIPS_SR_INT_IE; 190 td2->td_md.md_spinlock_count = 1; 191#ifdef CPU_CNMIPS 192 if (td1->td_md.md_flags & MDTD_COP2USED) { 193 if (td1->td_md.md_cop2owner == COP2_OWNER_USERLAND) { 194 if (td1->td_md.md_ucop2) 195 octeon_cop2_save(td1->td_md.md_ucop2); 196 else 197 panic("cpu_fork: ucop2 is NULL but COP2 is enabled"); 198 } 199 else { 200 if (td1->td_md.md_cop2) 201 octeon_cop2_save(td1->td_md.md_cop2); 202 else 203 panic("cpu_fork: cop2 is NULL but COP2 is enabled"); 204 } 205 } 206 207 if (td1->td_md.md_cop2) { 208 td2->td_md.md_cop2 = octeon_cop2_alloc_ctx(); 209 memcpy(td2->td_md.md_cop2, td1->td_md.md_cop2, 210 sizeof(*td1->td_md.md_cop2)); 211 } 212 if (td1->td_md.md_ucop2) { 213 td2->td_md.md_ucop2 = octeon_cop2_alloc_ctx(); 214 memcpy(td2->td_md.md_ucop2, td1->td_md.md_ucop2, 215 sizeof(*td1->td_md.md_ucop2)); 216 } 217 td2->td_md.md_cop2owner = td1->td_md.md_cop2owner; 218 pcb2->pcb_context[PCB_REG_SR] |= MIPS_SR_PX | MIPS_SR_UX | MIPS_SR_KX | MIPS_SR_SX; 219 /* Clear COP2 bits for userland & kernel */ 220 td2->td_frame->sr &= ~MIPS_SR_COP_2_BIT; 221 pcb2->pcb_context[PCB_REG_SR] &= ~MIPS_SR_COP_2_BIT; 222#endif 223} 224 225/* 226 * Intercept the return address from a freshly forked process that has NOT 227 * been scheduled yet. 228 * 229 * This is needed to make kernel threads stay in kernel mode. 230 */ 231void 232cpu_set_fork_handler(struct thread *td, void (*func) __P((void *)), void *arg) 233{ 234 /* 235 * Note that the trap frame follows the args, so the function 236 * is really called like this: func(arg, frame); 237 */ 238 td->td_pcb->pcb_context[PCB_REG_S0] = (register_t)(intptr_t)func; 239 td->td_pcb->pcb_context[PCB_REG_S1] = (register_t)(intptr_t)arg; 240} 241 242void 243cpu_exit(struct thread *td) 244{ 245} 246 247void 248cpu_thread_exit(struct thread *td) 249{ 250 251 if (PCPU_GET(fpcurthread) == td) 252 PCPU_GET(fpcurthread) = (struct thread *)0; 253#ifdef CPU_CNMIPS 254 if (td->td_md.md_cop2) 255 memset(td->td_md.md_cop2, 0, 256 sizeof(*td->td_md.md_cop2)); 257 if (td->td_md.md_ucop2) 258 memset(td->td_md.md_ucop2, 0, 259 sizeof(*td->td_md.md_ucop2)); 260#endif 261} 262 263void 264cpu_thread_free(struct thread *td) 265{ 266#ifdef CPU_CNMIPS 267 if (td->td_md.md_cop2) 268 octeon_cop2_free_ctx(td->td_md.md_cop2); 269 if (td->td_md.md_ucop2) 270 octeon_cop2_free_ctx(td->td_md.md_ucop2); 271 td->td_md.md_cop2 = NULL; 272 td->td_md.md_ucop2 = NULL; 273#endif 274} 275 276void 277cpu_thread_clean(struct thread *td) 278{ 279} 280 281void 282cpu_thread_swapin(struct thread *td) 283{ 284 pt_entry_t *pte; 285 int i; 286 287 /* 288 * The kstack may be at a different physical address now. 289 * Cache the PTEs for the Kernel stack in the machine dependent 290 * part of the thread struct so cpu_switch() can quickly map in 291 * the pcb struct and kernel stack. 292 */ 293 for (i = 0; i < KSTACK_PAGES; i++) { 294 pte = pmap_pte(kernel_pmap, td->td_kstack + i * PAGE_SIZE); 295 td->td_md.md_upte[i] = *pte & ~TLBLO_SWBITS_MASK; 296 } 297} 298 299void 300cpu_thread_swapout(struct thread *td) 301{ 302} 303 304void 305cpu_thread_alloc(struct thread *td) 306{ 307 pt_entry_t *pte; 308 int i; 309 310 KASSERT((td->td_kstack & (1 << PAGE_SHIFT)) == 0, ("kernel stack must be aligned.")); 311 td->td_pcb = (struct pcb *)(td->td_kstack + 312 td->td_kstack_pages * PAGE_SIZE) - 1; 313 td->td_frame = &td->td_pcb->pcb_regs; 314 315 for (i = 0; i < KSTACK_PAGES; i++) { 316 pte = pmap_pte(kernel_pmap, td->td_kstack + i * PAGE_SIZE); 317 td->td_md.md_upte[i] = *pte & ~TLBLO_SWBITS_MASK; 318 } 319} 320 321void 322cpu_set_syscall_retval(struct thread *td, int error) 323{ 324 struct trapframe *locr0 = td->td_frame; 325 unsigned int code; 326 int quad_syscall; 327 328 code = locr0->v0; 329 quad_syscall = 0; 330#if defined(__mips_n32) || defined(__mips_n64) 331#ifdef COMPAT_FREEBSD32 332 if (code == SYS___syscall && SV_PROC_FLAG(td->td_proc, SV_ILP32)) 333 quad_syscall = 1; 334#endif 335#else 336 if (code == SYS___syscall) 337 quad_syscall = 1; 338#endif 339 340 if (code == SYS_syscall) 341 code = locr0->a0; 342 else if (code == SYS___syscall) { 343 if (quad_syscall) 344 code = _QUAD_LOWWORD ? locr0->a1 : locr0->a0; 345 else 346 code = locr0->a0; 347 } 348 349 switch (error) { 350 case 0: 351 if (quad_syscall && code != SYS_lseek) { 352 /* 353 * System call invoked through the 354 * SYS___syscall interface but the 355 * return value is really just 32 356 * bits. 357 */ 358 locr0->v0 = td->td_retval[0]; 359 if (_QUAD_LOWWORD) 360 locr0->v1 = td->td_retval[0]; 361 locr0->a3 = 0; 362 } else { 363 locr0->v0 = td->td_retval[0]; 364 locr0->v1 = td->td_retval[1]; 365 locr0->a3 = 0; 366 } 367 break; 368 369 case ERESTART: 370 locr0->pc = td->td_pcb->pcb_tpc; 371 break; 372 373 case EJUSTRETURN: 374 break; /* nothing to do */ 375 376 default: 377 if (quad_syscall && code != SYS_lseek) { 378 locr0->v0 = error; 379 if (_QUAD_LOWWORD) 380 locr0->v1 = error; 381 locr0->a3 = 1; 382 } else { 383 locr0->v0 = error; 384 locr0->a3 = 1; 385 } 386 } 387} 388 389/* 390 * Initialize machine state (pcb and trap frame) for a new thread about to 391 * upcall. Put enough state in the new thread's PCB to get it to go back 392 * userret(), where we can intercept it again to set the return (upcall) 393 * Address and stack, along with those from upcalls that are from other sources 394 * such as those generated in thread_userret() itself. 395 */ 396void 397cpu_set_upcall(struct thread *td, struct thread *td0) 398{ 399 struct pcb *pcb2; 400 401 /* Point the pcb to the top of the stack. */ 402 pcb2 = td->td_pcb; 403 404 /* 405 * Copy the upcall pcb. This loads kernel regs. 406 * Those not loaded individually below get their default 407 * values here. 408 * 409 * XXXKSE It might be a good idea to simply skip this as 410 * the values of the other registers may be unimportant. 411 * This would remove any requirement for knowing the KSE 412 * at this time (see the matching comment below for 413 * more analysis) (need a good safe default). 414 * In MIPS, the trapframe is the first element of the PCB 415 * and gets copied when we copy the PCB. No separate copy 416 * is needed. 417 */ 418 bcopy(td0->td_pcb, pcb2, sizeof(*pcb2)); 419 420 /* 421 * Set registers for trampoline to user mode. 422 */ 423 424 pcb2->pcb_context[PCB_REG_RA] = (register_t)(intptr_t)fork_trampoline; 425 /* Make sp 64-bit aligned */ 426 pcb2->pcb_context[PCB_REG_SP] = (register_t)(((vm_offset_t)td->td_pcb & 427 ~(sizeof(__int64_t) - 1)) - CALLFRAME_SIZ); 428 pcb2->pcb_context[PCB_REG_S0] = (register_t)(intptr_t)fork_return; 429 pcb2->pcb_context[PCB_REG_S1] = (register_t)(intptr_t)td; 430 pcb2->pcb_context[PCB_REG_S2] = (register_t)(intptr_t)td->td_frame; 431 /* Dont set IE bit in SR. sched lock release will take care of it */ 432 pcb2->pcb_context[PCB_REG_SR] = mips_rd_status() & 433 (MIPS_SR_PX | MIPS_SR_KX | MIPS_SR_UX | MIPS_SR_INT_MASK); 434 435 /* 436 * FREEBSD_DEVELOPERS_FIXME: 437 * Setup any other CPU-Specific registers (Not MIPS Standard) 438 * that are needed. 439 */ 440 441 /* SMP Setup to release sched_lock in fork_exit(). */ 442 td->td_md.md_spinlock_count = 1; 443 td->td_md.md_saved_intr = MIPS_SR_INT_IE; 444#if 0 445 /* Maybe we need to fix this? */ 446 td->td_md.md_saved_sr = ( (MIPS_SR_COP_2_BIT | MIPS_SR_COP_0_BIT) | 447 (MIPS_SR_PX | MIPS_SR_UX | MIPS_SR_KX | MIPS_SR_SX) | 448 (MIPS_SR_INT_IE | MIPS_HARD_INT_MASK)); 449#endif 450} 451 452/* 453 * Set that machine state for performing an upcall that has to 454 * be done in thread_userret() so that those upcalls generated 455 * in thread_userret() itself can be done as well. 456 */ 457void 458cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg, 459 stack_t *stack) 460{ 461 struct trapframe *tf; 462 register_t sp; 463 464 /* 465 * At the point where a function is called, sp must be 8 466 * byte aligned[for compatibility with 64-bit CPUs] 467 * in ``See MIPS Run'' by D. Sweetman, p. 269 468 * align stack 469 */ 470 sp = ((register_t)(intptr_t)(stack->ss_sp + stack->ss_size) & ~0x7) - 471 CALLFRAME_SIZ; 472 473 /* 474 * Set the trap frame to point at the beginning of the uts 475 * function. 476 */ 477 tf = td->td_frame; 478 bzero(tf, sizeof(struct trapframe)); 479 tf->sp = sp; 480 tf->pc = (register_t)(intptr_t)entry; 481 /* 482 * MIPS ABI requires T9 to be the same as PC 483 * in subroutine entry point 484 */ 485 tf->t9 = (register_t)(intptr_t)entry; 486 tf->a0 = (register_t)(intptr_t)arg; 487 488 /* 489 * Keep interrupt mask 490 */ 491 td->td_frame->sr = MIPS_SR_KSU_USER | MIPS_SR_EXL | MIPS_SR_INT_IE | 492 (mips_rd_status() & MIPS_SR_INT_MASK); 493#if defined(__mips_n32) 494 td->td_frame->sr |= MIPS_SR_PX; 495#elif defined(__mips_n64) 496 td->td_frame->sr |= MIPS_SR_PX | MIPS_SR_UX | MIPS_SR_KX; 497#endif 498/* tf->sr |= (ALL_INT_MASK & idle_mask) | SR_INT_ENAB; */ 499 /**XXX the above may now be wrong -- mips2 implements this as panic */ 500 /* 501 * FREEBSD_DEVELOPERS_FIXME: 502 * Setup any other CPU-Specific registers (Not MIPS Standard) 503 * that are needed. 504 */ 505} 506 507/* 508 * Implement the pre-zeroed page mechanism. 509 * This routine is called from the idle loop. 510 */ 511 512#define ZIDLE_LO(v) ((v) * 2 / 3) 513#define ZIDLE_HI(v) ((v) * 4 / 5) 514 515/* 516 * Allocate a pool of sf_bufs (sendfile(2) or "super-fast" if you prefer. :-)) 517 */ 518#ifndef __mips_n64 519static void 520sf_buf_init(void *arg) 521{ 522 struct sf_buf *sf_bufs; 523 vm_offset_t sf_base; 524 int i; 525 526 nsfbufs = NSFBUFS; 527 TUNABLE_INT_FETCH("kern.ipc.nsfbufs", &nsfbufs); 528 529 mtx_init(&sf_freelist.sf_lock, "sf_bufs list lock", NULL, MTX_DEF); 530 SLIST_INIT(&sf_freelist.sf_head); 531 sf_base = kva_alloc(nsfbufs * PAGE_SIZE); 532 sf_bufs = malloc(nsfbufs * sizeof(struct sf_buf), M_TEMP, 533 M_NOWAIT | M_ZERO); 534 for (i = 0; i < nsfbufs; i++) { 535 sf_bufs[i].kva = sf_base + i * PAGE_SIZE; 536 SLIST_INSERT_HEAD(&sf_freelist.sf_head, &sf_bufs[i], free_list); 537 } 538 sf_buf_alloc_want = 0; 539} 540 541/* 542 * Get an sf_buf from the freelist. Will block if none are available. 543 */ 544struct sf_buf * 545sf_buf_alloc(struct vm_page *m, int flags) 546{ 547 struct sf_buf *sf; 548 int error; 549 550 mtx_lock(&sf_freelist.sf_lock); 551 while ((sf = SLIST_FIRST(&sf_freelist.sf_head)) == NULL) { 552 if (flags & SFB_NOWAIT) 553 break; 554 sf_buf_alloc_want++; 555 SFSTAT_INC(sf_allocwait); 556 error = msleep(&sf_freelist, &sf_freelist.sf_lock, 557 (flags & SFB_CATCH) ? PCATCH | PVM : PVM, "sfbufa", 0); 558 sf_buf_alloc_want--; 559 560 /* 561 * If we got a signal, don't risk going back to sleep. 562 */ 563 if (error) 564 break; 565 } 566 if (sf != NULL) { 567 SLIST_REMOVE_HEAD(&sf_freelist.sf_head, free_list); 568 sf->m = m; 569 nsfbufsused++; 570 nsfbufspeak = imax(nsfbufspeak, nsfbufsused); 571 pmap_qenter(sf->kva, &sf->m, 1); 572 } 573 mtx_unlock(&sf_freelist.sf_lock); 574 return (sf); 575} 576 577/* 578 * Release resources back to the system. 579 */ 580void 581sf_buf_free(struct sf_buf *sf) 582{ 583 pmap_qremove(sf->kva, 1); 584 mtx_lock(&sf_freelist.sf_lock); 585 SLIST_INSERT_HEAD(&sf_freelist.sf_head, sf, free_list); 586 nsfbufsused--; 587 if (sf_buf_alloc_want > 0) 588 wakeup(&sf_freelist); 589 mtx_unlock(&sf_freelist.sf_lock); 590} 591#endif /* !__mips_n64 */ 592 593/* 594 * Software interrupt handler for queued VM system processing. 595 */ 596void 597swi_vm(void *dummy) 598{ 599 600 if (busdma_swi_pending) 601 busdma_swi(); 602} 603 604int 605cpu_set_user_tls(struct thread *td, void *tls_base) 606{ 607 608 td->td_md.md_tls = (char*)tls_base; 609 610 return (0); 611} 612 613#ifdef DDB 614#include <ddb/ddb.h> 615 616#define DB_PRINT_REG(ptr, regname) \ 617 db_printf(" %-12s %p\n", #regname, (void *)(intptr_t)((ptr)->regname)) 618 619#define DB_PRINT_REG_ARRAY(ptr, arrname, regname) \ 620 db_printf(" %-12s %p\n", #regname, (void *)(intptr_t)((ptr)->arrname[regname])) 621 622static void 623dump_trapframe(struct trapframe *trapframe) 624{ 625 626 db_printf("Trapframe at %p\n", trapframe); 627 628 DB_PRINT_REG(trapframe, zero); 629 DB_PRINT_REG(trapframe, ast); 630 DB_PRINT_REG(trapframe, v0); 631 DB_PRINT_REG(trapframe, v1); 632 DB_PRINT_REG(trapframe, a0); 633 DB_PRINT_REG(trapframe, a1); 634 DB_PRINT_REG(trapframe, a2); 635 DB_PRINT_REG(trapframe, a3); 636#if defined(__mips_n32) || defined(__mips_n64) 637 DB_PRINT_REG(trapframe, a4); 638 DB_PRINT_REG(trapframe, a5); 639 DB_PRINT_REG(trapframe, a6); 640 DB_PRINT_REG(trapframe, a7); 641 DB_PRINT_REG(trapframe, t0); 642 DB_PRINT_REG(trapframe, t1); 643 DB_PRINT_REG(trapframe, t2); 644 DB_PRINT_REG(trapframe, t3); 645#else 646 DB_PRINT_REG(trapframe, t0); 647 DB_PRINT_REG(trapframe, t1); 648 DB_PRINT_REG(trapframe, t2); 649 DB_PRINT_REG(trapframe, t3); 650 DB_PRINT_REG(trapframe, t4); 651 DB_PRINT_REG(trapframe, t5); 652 DB_PRINT_REG(trapframe, t6); 653 DB_PRINT_REG(trapframe, t7); 654#endif 655 DB_PRINT_REG(trapframe, s0); 656 DB_PRINT_REG(trapframe, s1); 657 DB_PRINT_REG(trapframe, s2); 658 DB_PRINT_REG(trapframe, s3); 659 DB_PRINT_REG(trapframe, s4); 660 DB_PRINT_REG(trapframe, s5); 661 DB_PRINT_REG(trapframe, s6); 662 DB_PRINT_REG(trapframe, s7); 663 DB_PRINT_REG(trapframe, t8); 664 DB_PRINT_REG(trapframe, t9); 665 DB_PRINT_REG(trapframe, k0); 666 DB_PRINT_REG(trapframe, k1); 667 DB_PRINT_REG(trapframe, gp); 668 DB_PRINT_REG(trapframe, sp); 669 DB_PRINT_REG(trapframe, s8); 670 DB_PRINT_REG(trapframe, ra); 671 DB_PRINT_REG(trapframe, sr); 672 DB_PRINT_REG(trapframe, mullo); 673 DB_PRINT_REG(trapframe, mulhi); 674 DB_PRINT_REG(trapframe, badvaddr); 675 DB_PRINT_REG(trapframe, cause); 676 DB_PRINT_REG(trapframe, pc); 677} 678 679DB_SHOW_COMMAND(pcb, ddb_dump_pcb) 680{ 681 struct thread *td; 682 struct pcb *pcb; 683 struct trapframe *trapframe; 684 685 /* Determine which thread to examine. */ 686 if (have_addr) 687 td = db_lookup_thread(addr, TRUE); 688 else 689 td = curthread; 690 691 pcb = td->td_pcb; 692 693 db_printf("Thread %d at %p\n", td->td_tid, td); 694 695 db_printf("PCB at %p\n", pcb); 696 697 trapframe = &pcb->pcb_regs; 698 dump_trapframe(trapframe); 699 700 db_printf("PCB Context:\n"); 701 DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S0); 702 DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S1); 703 DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S2); 704 DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S3); 705 DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S4); 706 DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S5); 707 DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S6); 708 DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S7); 709 DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_SP); 710 DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_S8); 711 DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_RA); 712 DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_SR); 713 DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_GP); 714 DB_PRINT_REG_ARRAY(pcb, pcb_context, PCB_REG_PC); 715 716 db_printf("PCB onfault = %p\n", pcb->pcb_onfault); 717 db_printf("md_saved_intr = 0x%0lx\n", (long)td->td_md.md_saved_intr); 718 db_printf("md_spinlock_count = %d\n", td->td_md.md_spinlock_count); 719 720 if (td->td_frame != trapframe) { 721 db_printf("td->td_frame %p is not the same as pcb_regs %p\n", 722 td->td_frame, trapframe); 723 } 724} 725 726/* 727 * Dump the trapframe beginning at address specified by first argument. 728 */ 729DB_SHOW_COMMAND(trapframe, ddb_dump_trapframe) 730{ 731 732 if (!have_addr) 733 return; 734 735 dump_trapframe((struct trapframe *)addr); 736} 737 738#endif /* DDB */ 739