The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/kttd_interface.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* 
    2  * Mach Operating System
    3  * Copyright (c) 1993,1992 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * The i386 machine specific Kernel TTD code.
   28  *
   29  * HISTORY:
   30  * $Log:        kttd_interface.c,v $
   31  * Revision 2.2  93/05/10  23:23:34  rvb
   32  *      Checkin for MK80 branch.
   33  *      [93/05/10  15:11:12  grm]
   34  * 
   35  * Revision 2.1.1.2  93/04/20  11:44:01  grm
   36  *      Changed for use with different asyncronous entry logic.
   37  * 
   38  * Revision 2.1.1.1  93/03/25  11:31:47  grm
   39  *      Moved here from ../i386at.
   40  * 
   41  *
   42  */
   43 #include <kern/thread.h>
   44 #include <kern/processor.h>
   45 #include <mach/thread_status.h>
   46 #include <mach/vm_param.h>
   47 #include <i386/eflags.h>
   48 #include <i386/seg.h>
   49 #include <sys/types.h>
   50 
   51 #include <ttd/ttd_types.h>
   52 #include <ttd/ttd_stub.h>
   53 #include <machine/kttd_machdep.h>
   54 
   55 /*
   56  * Shamelessly copied from the ddb sources:
   57  */
   58 struct   i386_saved_state *kttd_last_saved_statep;
   59 struct   i386_saved_state kttd_nested_saved_state;
   60 unsigned last_kttd_sp;
   61 
   62 struct i386_saved_state kttd_regs;      /* was ddb_regs */
   63 
   64 extern int              kttd_debug;
   65 extern boolean_t        kttd_enabled;
   66 extern vm_offset_t      virtual_end;
   67 
   68 #define I386_BREAKPOINT 0xcc
   69 
   70 /*
   71  *      kernel map
   72  */
   73 extern vm_map_t kernel_map;
   74 
   75 boolean_t kttd_console_init(void)
   76 {
   77         /*
   78          * Get local machine's IP address via bootp.
   79          */
   80         return(ttd_ip_bootp());
   81 }
   82 
   83 /*
   84  *      Execute a break instruction that will invoke ttd
   85  */
   86 void kttd_break(void)
   87 {
   88         if (!kttd_enabled)
   89                 return;
   90         asm("int3");
   91 }
   92 
   93 /*
   94  * Halt all processors on the 386at (not really applicable).
   95  */
   96 void kttd_halt_processors(void)
   97 {
   98         /* XXX Fix for Sequent!!! */
   99         /* Only one on AT386, so ignore for now... */
  100 }
  101 
  102 /*
  103  * Determine whether or not the ehternet device driver supports
  104  * ttd.
  105  */
  106 boolean_t kttd_supported(void)
  107 {
  108         return ((int)ttd_get_packet != NULL);
  109 }
  110 
  111 /*
  112  * Return the ttd machine type for the i386at
  113  */
  114 ttd_machine_type get_ttd_machine_type(void)
  115 {
  116         return TTD_AT386;
  117 }
  118 
  119 void kttd_machine_getregs(struct i386_gdb_register_state *ttd_state)
  120 {
  121         ttd_state->gs = kttd_regs.gs;
  122         ttd_state->fs = kttd_regs.fs;
  123         ttd_state->es = kttd_regs.es;
  124         ttd_state->ds = kttd_regs.ds;
  125         ttd_state->edi = kttd_regs.edi;
  126         ttd_state->esi = kttd_regs.esi;
  127         ttd_state->ebp = kttd_regs.ebp;
  128 
  129         /*
  130          * This is set up to point to the right place in
  131          * kttd_trap and .
  132          */
  133         ttd_state->esp = kttd_regs.uesp;
  134 
  135         ttd_state->ebx = kttd_regs.ebx;
  136         ttd_state->edx = kttd_regs.edx;
  137         ttd_state->ecx = kttd_regs.ecx;
  138         ttd_state->eax = kttd_regs.eax;
  139         ttd_state->eip = kttd_regs.eip;
  140         ttd_state->cs = kttd_regs.cs;
  141         ttd_state->efl = kttd_regs.efl;
  142         ttd_state->ss = kttd_regs.ss;
  143 }
  144 
  145 void kttd_machine_setregs(struct i386_gdb_register_state *ttd_state)
  146 {
  147         if (kttd_regs.gs != ttd_state->gs) {
  148                 if (kttd_debug)
  149                         printf("gs 0x%x:0x%x, ", kttd_regs.gs, ttd_state->gs);
  150                 kttd_regs.gs = ttd_state->gs;
  151         }
  152         if (kttd_regs.fs != ttd_state->fs) {
  153                 if (kttd_debug)
  154                         printf("fs 0x%x:0x%x, ", kttd_regs.fs, ttd_state->fs);
  155                 kttd_regs.fs = ttd_state->fs;
  156         }
  157         if (kttd_regs.es != ttd_state->es) {
  158                 if (kttd_debug)
  159                         printf("es 0x%x:0x%x, ", kttd_regs.es, ttd_state->es);
  160                 kttd_regs.es = ttd_state->es;
  161         }
  162         if (kttd_regs.ds != ttd_state->ds) {
  163                 if (kttd_debug)
  164                         printf("ds 0x%x:0x%x, ", kttd_regs.ds, ttd_state->ds);
  165                 kttd_regs.ds = ttd_state->ds;
  166         }
  167         if (kttd_regs.edi != ttd_state->edi) {
  168                 if (kttd_debug)
  169                         printf("edi 0x%x:0x%x, ", kttd_regs.edi, ttd_state->edi);
  170                 kttd_regs.edi = ttd_state->edi;
  171         }
  172         if (kttd_regs.esi != ttd_state->esi) {
  173                 if (kttd_debug)
  174                         printf("esi 0x%x:0x%x, ", kttd_regs.esi, ttd_state->esi);
  175                 kttd_regs.esi = ttd_state->esi;
  176         }
  177         if (kttd_regs.ebp != ttd_state->ebp) {
  178                 if (kttd_debug)
  179                         printf("ebp 0x%x:0x%x, ", kttd_regs.ebp, ttd_state->ebp);
  180                 kttd_regs.ebp = ttd_state->ebp;
  181         }
  182         if (kttd_regs.ebx != ttd_state->ebx) {
  183                 if (kttd_debug)
  184                         printf("ebx 0x%x:0x%x, ", kttd_regs.ebx, ttd_state->ebx);
  185                 kttd_regs.ebx = ttd_state->ebx;
  186         }
  187         if (kttd_regs.edx != ttd_state->edx) {
  188                 if (kttd_debug)
  189                         printf("edx 0x%x:0x%x, ", kttd_regs.edx, ttd_state->edx);
  190                 kttd_regs.edx = ttd_state->edx;
  191         }
  192         if (kttd_regs.ecx != ttd_state->ecx) {
  193                 if (kttd_debug) 
  194                         printf("ecx 0x%x:0x%x, ", kttd_regs.ecx, ttd_state->ecx);
  195                 kttd_regs.ecx = ttd_state->ecx;
  196         }
  197         if (kttd_regs.eax != ttd_state->eax) {
  198                 if (kttd_debug)
  199                         printf("eax 0x%x:0x%x, ", kttd_regs.eax, ttd_state->eax);
  200                 kttd_regs.eax = ttd_state->eax;
  201         }
  202         if (kttd_regs.eip != ttd_state->eip) {
  203                 if (kttd_debug)
  204                         printf("eip 0x%x:0x%x, ", kttd_regs.eip, ttd_state->eip);
  205                 kttd_regs.eip = ttd_state->eip;
  206         }
  207         if (kttd_regs.cs != ttd_state->cs) {
  208                 if (kttd_debug)
  209                         printf("cs 0x%x:0x%x, ", kttd_regs.cs, ttd_state->cs);
  210                 kttd_regs.cs = ttd_state->cs;
  211         }
  212         if (kttd_regs.efl != ttd_state->efl) {
  213                 if (kttd_debug)
  214                         printf("efl 0x%x:0x%x, ", kttd_regs.efl, ttd_state->efl);
  215                 kttd_regs.efl = ttd_state->efl;
  216         }
  217 #if     0
  218         /*
  219          * We probably shouldn't mess with the uesp or the ss? XXX
  220          */
  221         if (kttd_regs.ss != ttd_state->ss) {
  222                 if (kttd_debug)
  223                         printf("ss 0x%x:0x%x, ", kttd_regs.ss, ttd_state->ss);
  224                 kttd_regs.ss = ttd_state->ss;
  225         }
  226 #endif  0
  227 
  228 }
  229 
  230 /*
  231  *      Enable a page for access, faulting it in if necessary
  232  */
  233 boolean_t kttd_mem_access(vm_offset_t offset, vm_prot_t access)
  234 {
  235         kern_return_t   code;
  236 
  237         /*
  238          *      VM_MIN_KERNEL_ADDRESS if the beginning of equiv
  239          *      mapped kernel memory.  virtual_end is the end.
  240          *      If it's in between it's always accessible
  241          */
  242         if (offset >= VM_MIN_KERNEL_ADDRESS && offset < virtual_end)
  243                 return TRUE;
  244 
  245         if (offset >= virtual_end) {
  246                 /*
  247                  *      fault in the memory just to make sure we can access it
  248                  */
  249                 if (kttd_debug)
  250                         printf(">>>>>>>>>>Faulting in memory: 0x%x, 0x%x\n",
  251                                trunc_page(offset), access);
  252                 code = vm_fault(kernel_map, trunc_page(offset), access, FALSE, 
  253                                 FALSE, (void (*)()) 0);
  254         }else{
  255                 /*
  256                  * Check for user thread
  257                  */
  258 #if     1
  259                 if ((current_thread() != THREAD_NULL) && 
  260                     (current_thread()->task->map->pmap != kernel_pmap) &&
  261                     (current_thread()->task->map->pmap != PMAP_NULL)) {
  262                         code = vm_fault(current_thread()->task->map,
  263                                         trunc_page(offset), access, FALSE,
  264                                         FALSE, (void (*)()) 0);
  265                 }else{
  266                         /*
  267                          * Invalid kernel address (below VM_MIN_KERNEL_ADDRESS)
  268                          */
  269                         return FALSE;
  270                 }
  271 #else
  272                 if (kttd_debug)
  273                         printf("==========Would've tried to map in user area 0x%x\n",
  274                                trunc_page(offset));
  275                 return FALSE;
  276 #endif  /* 0 */
  277         }
  278 
  279         return (code == KERN_SUCCESS);
  280 }
  281 
  282 /*
  283  *      See if we modified the kernel text and if so flush the caches.
  284  *      This routine is never called with a range that crosses a page
  285  *      boundary.
  286  */
  287 void kttd_flush_cache(vm_offset_t offset, vm_size_t length)
  288 {
  289         /* 386 doesn't need this */
  290         return;
  291 }
  292 
  293 /*
  294  * Insert a breakpoint into memory.
  295  */
  296 boolean_t kttd_insert_breakpoint(vm_address_t address,
  297                                  ttd_saved_inst *saved_inst)
  298 {
  299         /*
  300          * Saved old memory data:
  301          */
  302         *saved_inst = *(unsigned char *)address;
  303 
  304         /*
  305          * Put in a Breakpoint:
  306          */
  307         *(unsigned char *)address = I386_BREAKPOINT;
  308 
  309         return TRUE;
  310 }
  311 
  312 /*
  313  * Remove breakpoint from memory.
  314  */
  315 boolean_t kttd_remove_breakpoint(vm_address_t address,
  316                                  ttd_saved_inst saved_inst)
  317 {
  318         /*
  319          * replace it:
  320          */
  321         *(unsigned char *)address = (saved_inst & 0xff);
  322 
  323         return TRUE;
  324 }
  325 
  326 /*
  327  * Set single stepping mode.  Assumes that program counter is set
  328  * to the location where single stepping is to begin.  The 386 is
  329  * an easy single stepping machine, ie. built into the processor.
  330  */
  331 boolean_t kttd_set_machine_single_step(void)
  332 {
  333         /* Turn on Single Stepping */
  334         kttd_regs.efl |= EFL_TF;
  335 
  336         return TRUE;
  337 }
  338 
  339 /*
  340  * Clear single stepping mode.
  341  */
  342 boolean_t kttd_clear_machine_single_step(void)
  343 {
  344         /* Turn off the trace flag */
  345         kttd_regs.efl &= ~EFL_TF;
  346 
  347         return TRUE;
  348 }
  349 
  350 
  351 /*
  352  * kttd_type_to_ttdtrap:
  353  *
  354  * Fills in the task and thread info structures with the reason
  355  * for entering the Teledebugger (bp, single step, pg flt, etc.)
  356  *
  357  */
  358 void kttd_type_to_ttdtrap(int type)
  359 {
  360         /* XXX Fill this in sometime for i386 */
  361 }
  362 
  363 /*
  364  * kttd_trap:
  365  *
  366  *  This routine is called from the trap or interrupt handler when a
  367  * breakpoint instruction is encountered or a single step operation
  368  * completes. The argument is a pointer to a machine dependent
  369  * saved_state structure that was built on the interrupt or kernel stack.
  370  *
  371  */
  372 boolean_t kttd_trap(int type, int code, struct i386_saved_state *regs)
  373 {
  374         int s;
  375 
  376         if (kttd_debug)
  377                 printf("kttd_TRAP, before splhigh()\n");
  378 
  379         /*
  380          * TTD isn't supported by the driver.
  381          *
  382          * Try to switch off to kdb if it is resident.
  383          * Otherwise just hang (this might be panic).
  384          *
  385          * Check to make sure that TTD is supported.
  386          * (Both by the machine's driver's, and bootp if using ether). 
  387          */
  388         if (!kttd_supported()) {
  389                 kttd_enabled = FALSE;
  390                 return FALSE;
  391         }
  392 
  393         s = splhigh();
  394 
  395         /*
  396          * We are already in TTD!
  397          */
  398         if (++kttd_active > MAX_KTTD_ACTIVE) {
  399                 printf("kttd_trap: RE-ENTERED!!!\n");
  400         }
  401 
  402         if (kttd_debug)
  403                 printf("kttd_TRAP, after splhigh()\n");
  404 
  405         /*  Should switch to kttd's own stack here. */
  406 
  407         kttd_regs = *regs;
  408 
  409         if ((regs->cs & 0x3) == 0) {
  410             /*
  411              * Kernel mode - esp and ss not saved
  412              */
  413             kttd_regs.uesp = (int)&regs->uesp;  /* kernel stack pointer */
  414             kttd_regs.ss   = KERNEL_DS;
  415         }
  416 
  417         /*
  418          * If this was not entered via an interrupt (type != -1)
  419          * then we've entered via a bpt, single, etc. and must
  420          * set the globals.
  421          *
  422          * Setup the kttd globals for entry....
  423          */
  424         if (type != -1) {
  425                 kttd_current_request = NULL;
  426                 kttd_current_length = 0;
  427                 kttd_current_kmsg = NULL;
  428                 kttd_run_status = FULL_STOP;
  429         }else{
  430                 /*
  431                  * We know that we can only get here if we did a kttd_intr
  432                  * since it's the way that we are called with type -1 (via
  433                  * the trampoline), so we don't have to worry about entering
  434                  * from Cntl-Alt-D like the mips does.
  435                  */
  436                 /*
  437                  * Perform sanity check!
  438                  */
  439                 if ((kttd_current_request == NULL) ||
  440                     (kttd_current_length == 0) ||
  441                     (kttd_current_kmsg == NULL) ||
  442                     (kttd_run_status != ONE_STOP)) {
  443 
  444                         printf("kttd_trap: INSANITY!!!\n");
  445                 }
  446         }
  447 
  448         kttd_task_trap(type, code, (regs->cs & 0x3) != 0);
  449 
  450         regs->eip    = kttd_regs.eip;
  451         regs->efl    = kttd_regs.efl;
  452         regs->eax    = kttd_regs.eax;
  453         regs->ecx    = kttd_regs.ecx;
  454         regs->edx    = kttd_regs.edx;
  455         regs->ebx    = kttd_regs.ebx;
  456         if (regs->cs & 0x3) {
  457             /*
  458              * user mode - saved esp and ss valid
  459              */
  460             regs->uesp = kttd_regs.uesp;                /* user stack pointer */
  461             regs->ss   = kttd_regs.ss & 0xffff; /* user stack segment */
  462         }
  463         regs->ebp    = kttd_regs.ebp;
  464         regs->esi    = kttd_regs.esi;
  465         regs->edi    = kttd_regs.edi;
  466         regs->es     = kttd_regs.es & 0xffff;
  467         regs->cs     = kttd_regs.cs & 0xffff;
  468         regs->ds     = kttd_regs.ds & 0xffff;
  469         regs->fs     = kttd_regs.fs & 0xffff;
  470         regs->gs     = kttd_regs.gs & 0xffff;
  471 
  472         if (--kttd_active < MIN_KTTD_ACTIVE)
  473                 printf("ttd_trap: kttd_active < 0\n");
  474 
  475         if (kttd_debug) {
  476                 printf("Leaving kttd_trap, kttd_active = %d\n", kttd_active);
  477         }
  478 
  479         /*
  480          * Only reset this if we entered kttd_trap via an async trampoline.
  481          */
  482         if (type == -1) {
  483                 if (kttd_run_status == RUNNING)
  484                         printf("kttd_trap: $$$$$ run_status already RUNNING! $$$$$\n");
  485                 kttd_run_status = RUNNING;
  486         }
  487 
  488         /* Is this right? XXX */
  489         kttd_run_status = RUNNING;
  490 
  491         (void) splx(s);
  492 
  493         /*
  494          * Return true, that yes we handled the trap.
  495          */
  496         return TRUE;
  497 }
  498 
  499 /*
  500  *      Enter KTTD through a network packet trap.
  501  *      We show the registers as of the network interrupt
  502  *      instead of those at its call to KDB.
  503  */
  504 struct int_regs {
  505         int     gs;
  506         int     fs;
  507         int     edi;
  508         int     esi;
  509         int     ebp;
  510         int     ebx;
  511         struct i386_interrupt_state *is;
  512 };
  513 
  514 void
  515 kttd_netentry(int_regs)
  516         struct int_regs *int_regs;
  517 {
  518         struct i386_interrupt_state *is = int_regs->is;
  519         int     s;
  520 
  521         if (kttd_debug)
  522                 printf("kttd_NETENTRY before slphigh()\n");
  523 
  524         s = splhigh();
  525 
  526         if (kttd_debug)
  527                 printf("kttd_NETENTRY after slphigh()\n");
  528 
  529         if (is->cs & 0x3) {
  530             /*
  531              * Interrupted from User Space
  532              */
  533             kttd_regs.uesp = ((int *)(is+1))[0];
  534             kttd_regs.ss   = ((int *)(is+1))[1];
  535         }
  536         else {
  537             /*
  538              * Interrupted from Kernel Space
  539              */
  540             kttd_regs.ss  = KERNEL_DS;
  541             kttd_regs.uesp= (int)(is+1);
  542         }
  543         kttd_regs.efl = is->efl;
  544         kttd_regs.cs  = is->cs;
  545         kttd_regs.eip = is->eip;
  546         kttd_regs.eax = is->eax;
  547         kttd_regs.ecx = is->ecx;
  548         kttd_regs.edx = is->edx;
  549         kttd_regs.ebx = int_regs->ebx;
  550         kttd_regs.ebp = int_regs->ebp;
  551         kttd_regs.esi = int_regs->esi;
  552         kttd_regs.edi = int_regs->edi;
  553         kttd_regs.ds  = is->ds;
  554         kttd_regs.es  = is->es;
  555         kttd_regs.fs  = int_regs->fs;
  556         kttd_regs.gs  = int_regs->gs;
  557 
  558         kttd_active++;
  559         kttd_task_trap(-1, 0, (kttd_regs.cs & 0x3) != 0);
  560         kttd_active--;
  561 
  562         if (kttd_regs.cs & 0x3) {
  563             ((int *)(is+1))[0] = kttd_regs.uesp;
  564             ((int *)(is+1))[1] = kttd_regs.ss & 0xffff;
  565         }
  566         is->efl = kttd_regs.efl;
  567         is->cs  = kttd_regs.cs & 0xffff;
  568         is->eip = kttd_regs.eip;
  569         is->eax = kttd_regs.eax;
  570         is->ecx = kttd_regs.ecx;
  571         is->edx = kttd_regs.edx;
  572         int_regs->ebx = kttd_regs.ebx;
  573         int_regs->ebp = kttd_regs.ebp;
  574         int_regs->esi = kttd_regs.esi;
  575         int_regs->edi = kttd_regs.edi;
  576         is->ds  = kttd_regs.ds & 0xffff;
  577         is->es  = kttd_regs.es & 0xffff;
  578         int_regs->fs = kttd_regs.fs & 0xffff;
  579         int_regs->gs = kttd_regs.gs & 0xffff;
  580 
  581         if (kttd_run_status == RUNNING)
  582                 printf("kttd_netentry: %%%%% run_status already RUNNING! %%%%%\n");
  583         kttd_run_status = RUNNING;
  584 
  585         (void) splx(s);
  586 }

Cache object: 20771ebfe5b4a09d2fc00ea0cb44ff5e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.