home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / ddjmag / ddj9103.zip / 386BSD.MAR next >
Text File  |  1991-02-15  |  36KB  |  1,218 lines

  1. _PORTING UNIX TO THE 386: THE STANDALONE SYSTEM_
  2. by William Frederick Jolitz and Lynne Greer Jolitz
  3.  
  4.  
  5. [LISTING ONE]
  6.  
  7.  
  8. # hi.s:    Simplest protected mode program providing some kind of output.
  9.     .text
  10. start:    movl    $0x0e690e48, 0x0b8800    # put "hi" mid screen on display
  11.     hlt
  12.  
  13.  
  14. [LISTING TWO]
  15.  
  16. # hello.s: Minimal test of GNU GAS assembler, handles CGA & strings.
  17.     .text
  18. start:
  19.     movl    $0xA0000,%esp
  20.  
  21.     pushl    $str
  22.     call    _puts
  23.     pop    %eax
  24.     hlt
  25. str:    .asciz    "\n\rHello world from GAS\r\n"
  26. _puts:
  27.     push    %ebx
  28.     movl    8(%esp),%ebx
  29. 1:    cmpb    $0,(%ebx)    # until we see a null
  30.     je    2f
  31.  
  32.     movzbl    (%ebx),%eax
  33.     pushl    %eax
  34.     call    _putchar    # put out characters
  35.     popl    %eax
  36.  
  37.     incl    %ebx
  38.     jmp    1b
  39. 2:    popl    %ebx
  40.     ret
  41. crtat:    .long    0xb8000        # address of CGA video RAM
  42. row:    .long     0
  43.  
  44. _putchar:
  45.     movzbl    4(%esp),%eax
  46.     push    %ebx
  47.     push    %ecx
  48.     movl    crtat,%ebx
  49.     cmpl    $0xb8000+80*25*2,%ebx  # continous output off screen edge & bot
  50.     jl    1f
  51.     movl    $0,row
  52.     movl    $0xb8000+80*(25-1)*2,%ebx
  53. 1:    cmpb    $0xd,%al        # cr
  54.     jne    1f
  55.     movl    $80,%ecx        # clear rest of line
  56.     subl    row,%ecx
  57.     movl    %ebx,%edi
  58.     movw    $0xfff,%ax
  59.     cld
  60.     rep
  61.     stosw
  62.     subl    row,%ebx
  63.     subl    row,%ebx
  64.     movl    $0,row
  65.     jmp    9f
  66. 1:    cmpb    $0xa,%al        # nl
  67.     jne    2f
  68.     cmpl    $0xb8000+80*(25-1)*2,%ebx    # scroll?
  69.     jl    1f
  70.     movl    $0xb8000,%edi        # scroll page
  71.     movl    $0xb8000+80*2,%esi
  72.     movl    $80*(25-1),%ecx
  73.     cld
  74.     rep
  75.     movsw
  76.     movl    $80,%ecx        # clear new bottom line
  77.     movl    $0xb8000+80*(25-1)*2,%edi
  78.     movw    $0,%ax
  79.     rep
  80.     stosw
  81.     sub    $80*2,%ebx        # position cursor before lf
  82. 1:    add    $80*2,%ebx
  83.     jmp    9f
  84. 2:    orw    $0x0e00,%ax        # attribute
  85.     movw    %ax,(%ebx)
  86.     addl    $2,%ebx
  87.     incl    row
  88. 9:    movl    %ebx,crtat
  89.     pop    %ecx
  90.     pop    %ebx
  91.     ret
  92.  
  93.  
  94. [LISTING THREE]
  95.  
  96. /* [Excerpted from srt.s] */
  97.  
  98.  ...
  99. entry:    .globl    entry
  100.     jmp    1f
  101.     .space    0x500        /* skip over BIOS data area */
  102. 1:    cli            /* no interrupts yet */
  103.  
  104.     movl    $0xA0000,%esp
  105.  
  106.     movl    %esp,%edx
  107.     movl    $_edata,%eax
  108.     subl    %eax,%edx    /* clear stack and heap store */
  109.     pushl    %edx
  110.     pushl    %eax
  111.     call    _bzero
  112.     popl    %eax
  113.     popl    %eax
  114.  
  115.     call    _main
  116.  ...
  117.  
  118. /* hello.c */
  119. main() {    printf("Hello, world!\n");    }
  120.  
  121.  
  122. [LISTING FOUR]
  123.  
  124. /* kbd.c: Copyright (c) 1989, 1990 William Jolitz. All rights reserved.
  125.  * Written by William Jolitz 9/89
  126.  * Redistribution and use in source and binary forms are freely permitted
  127.  * provided that the above copyright notice and attribution and date of work
  128.  * and this paragraph are duplicated in all such forms.
  129.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  130.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  131.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  132.  * Standalone driver for IBM PC keyboards. 
  133.  */
  134.  
  135. #define    L        0x001    /* locking function */
  136. #define    SHF        0x002    /* keyboard shift */
  137. #define    ALT        0x004    /* alternate shift -- alternate chars */
  138. #define    NUM        0x008    /* numeric shift  cursors vs. numeric */
  139. #define    CTL        0x010    /* control shift  -- allows ctl function */
  140. #define    CPS        0x020    /* caps shift -- swaps case of letter */
  141. #define    ASCII        0x040    /* ascii code for this key */
  142. #define    STP        0x080    /* stop output */
  143. #define    BREAK        0x100    /* key breaking contact */
  144.  
  145. typedef unsigned char u_char;
  146.  
  147. u_char inb();
  148.  
  149. u_char action[] = {
  150. 0,     ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,     /* scan  0- 7 */
  151. ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,     /* scan  8-15 */
  152. ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,     /* scan 16-23 */
  153. ASCII, ASCII, ASCII, ASCII, ASCII,   CTL, ASCII, ASCII,     /* scan 24-31 */
  154. ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,     /* scan 32-39 */
  155. ASCII, ASCII, SHF  , ASCII, ASCII, ASCII, ASCII, ASCII,     /* scan 40-47 */
  156. ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,  SHF,  ASCII,     /* scan 48-55 */
  157.   ALT, ASCII, CPS|L,     0,     0, ASCII,     0,     0,     /* scan 56-63 */
  158.     0,     0,     0,     0,     0, NUM|L, STP|L, ASCII,     /* scan 64-71 */
  159. ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,     /* scan 72-79 */
  160. ASCII, ASCII, ASCII, ASCII,     0,     0,     0,     0,     /* scan 80-87 */
  161. 0,0,0,0,0,0,0,0,
  162. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  163. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,    } ;
  164.  
  165. u_char unshift[] = {    /* no shift */
  166. 0,     033  , '1'  , '2'  , '3'  , '4'  , '5'  , '6'  ,     /* scan  0- 7 */
  167. '7'  , '8'  , '9'  , '0'  , '-'  , '='  , 0177 ,'\t'  ,     /* scan  8-15 */
  168.  
  169. 'q'  , 'w'  , 'e'  , 'r'  , 't'  , 'y'  , 'u'  , 'i'  ,     /* scan 16-23 */
  170. 'o'  , 'p'  , '['  , ']'  , '\r' , CTL  , 'a'  , 's'  ,     /* scan 24-31 */
  171.  
  172. 'd'  , 'f'  , 'g'  , 'h'  , 'j'  , 'k'  , 'l'  , ';'  ,  /* scan 32-39 */
  173. '\'' , '`'  , SHF  , '\\' , 'z'  , 'x'  , 'c'  , 'v'  ,     /* scan 40-47 */
  174.  
  175. 'b'  , 'n'  , 'm'  , ','  , '.'  , '/'  , SHF  ,   '*',     /* scan 48-55 */
  176. ALT  , ' '  , CPS|L,     0,     0, ' '  ,     0,     0,     /* scan 56-63 */
  177.  
  178.     0,     0,     0,     0,     0, NUM|L, STP|L,   '7',     /* scan 64-71 */
  179.   '8',   '9',   '-',   '4',   '5',   '6',   '+',   '1',     /* scan 72-79 */
  180.  
  181.   '2',   '3',   '0',   '.',     0,     0,     0,     0,     /* scan 80-87 */
  182. 0,0,0,0,0,0,0,0,
  183. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  184. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,    } ;
  185.  
  186. u_char shift[] = {    /* shift shift */
  187. 0,     033  , '!'  , '@'  , '#'  , '$'  , '%'  , '^'  ,     /* scan  0- 7 */
  188. '&'  , '*'  , '('  , ')'  , '_'  , '+'  , 0177 ,'\t'  ,     /* scan  8-15 */
  189. 'Q'  , 'W'  , 'E'  , 'R'  , 'T'  , 'Y'  , 'U'  , 'I'  ,     /* scan 16-23 */
  190. 'O'  , 'P'  , '['  , ']'  , '\r' , CTL  , 'A'  , 'S'  ,     /* scan 24-31 */
  191. 'D'  , 'F'  , 'G'  , 'H'  , 'J'  , 'K'  , 'L'  , ':'  ,     /* scan 32-39 */
  192. '"'  , '~'  , SHF  , '|'  , 'Z'  , 'X'  , 'C'  , 'V'  ,     /* scan 40-47 */
  193. 'B'  , 'N'  , 'M'  , '<'  , '>'  , '?'  , SHF  ,   '*',     /* scan 48-55 */
  194. ALT  , ' '  , CPS|L,     0,     0, ' '  ,     0,     0,     /* scan 56-63 */
  195.     0,     0,     0,     0,     0, NUM|L, STP|L,   '7',     /* scan 64-71 */
  196.   '8',   '9',   '-',   '4',   '5',   '6',   '+',   '1',     /* scan 72-79 */
  197.   '2',   '3',   '0',   '.',     0,     0,     0,     0,     /* scan 80-87 */
  198. 0,0,0,0,0,0,0,0,
  199. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  200. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,    } ;
  201.  
  202. u_char ctl[] = {    /* CTL shift */
  203. 0,     033  , '!'  , 000  , '#'  , '$'  , '%'  , 036  ,     /* scan  0- 7 */
  204. '&'  , '*'  , '('  , ')'  , 037  , '+'  , 034  ,'\177',     /* scan  8-15 */
  205. 021  , 027  , 005  , 022  , 024  , 031  , 025  , 011  ,     /* scan 16-23 */
  206. 017  , 020  , 033  , 035  , '\r' , CTL  , 001  , 013  ,     /* scan 24-31 */
  207. 004  , 006  , 007  , 010  , 012  , 013  , 014  , ';'  ,     /* scan 32-39 */
  208. '\'' , '`'  , SHF  , 034  , 032  , 030  , 003  , 026  ,     /* scan 40-47 */
  209. 002  , 016  , 015  , '<'  , '>'  , '?'  , SHF  ,   '*',     /* scan 48-55 */
  210. ALT  , ' '  , CPS|L,     0,     0, ' '  ,     0,     0,     /* scan 56-63 */
  211. CPS|L,     0,     0,     0,     0,     0,     0,     0,     /* scan 64-71 */
  212.     0,     0,     0,     0,     0,     0,     0,     0,     /* scan 72-79 */
  213.     0,     0,     0,     0,     0,     0,     0,     0,     /* scan 80-87 */
  214.     0,     0,   033, '7'  , '4'  , '1'  ,     0, NUM|L,     /* scan 88-95 */
  215. '8'  , '5'  , '2'  ,     0, STP|L, '9'  , '6'  , '3'  ,     /*scan  96-103*/
  216. '.'  ,     0, '*'  , '-'  , '+'  ,     0,     0,     0,     /*scan 104-111*/
  217. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,    } ;
  218.  
  219. #define    KBSTATP        0x64        /* kbd status port */
  220. #define    KBS_RDY        0x02        /* kbd char ready */
  221. #define    KBDATAP        0x60        /* kbd data port */
  222. #define    KBSTATUSPORT    0x61        /* kbd status */
  223. #define    KBD_BRK    0x80 /* key is breaking contact, not making contact */
  224. #define    KBD_KEY(s)    ((s) & 0x7f)    /* key that has changed */
  225.  
  226. /* Return an ASCII character from the keyboard.  */
  227. u_char kbd() {
  228.     u_char dt, act;
  229.     static u_char odt, shfts, ctls, alts, caps, num, stp;
  230.     
  231.     do {
  232.         do {
  233.             while (inb(KBSTATP)&KBS_RDY) ;
  234.             dt = inb(KBDATAP);
  235.         } while (dt == odt);
  236.  
  237.         odt = dt;
  238.         dt = KBD_KEY(dt);
  239.         act = action[dt];
  240.         if (odt & KBD_BRK) act |= BREAK;
  241.  
  242.         /* kinds of shift keys */
  243.         if (act&SHF) actl (act, &shfts);
  244.         if (act&ALT) actl (act, &alts);
  245.         if (act&NUM) actl (act, &num);
  246.         if (act&CTL) actl (act, &ctls);
  247.         if (act&CPS) actl (act, &caps);
  248.         if (act&STP) actl (act, &stp);
  249.  
  250.         if (act&(ASCII|BREAK) == ASCII) {
  251.             u_char chr;
  252.  
  253.             if (shfts)
  254.                  chr = shift[dt] ;
  255.             else {
  256.                 if (ctls) chr = ctl[dt] ;
  257.                 else chr = unshift[dt] ;
  258.             }
  259.             if (caps && (chr >= 'a' && chr <= 'z'))
  260.                 chr -= 'a' - 'A' ;
  261.             return(chr);
  262.         }
  263.     } while (1);
  264. }
  265.  
  266. /* Handle shift key actions */
  267. actl(act, v, brk) char *v; {
  268.  
  269.     /* are we locking ... */
  270.     if (act&L) {
  271.         if((act&BREAK) == 0) *v ^= 1;
  272.  
  273.     /* ... or single - action ? */
  274.     } else
  275.         if(act&BREAK) *v = 0; else *v = 1;
  276. }
  277.  
  278.  
  279. [LISTING FIVE]
  280.  
  281. /* cga.c: Copyright (c) 1989, 1990 William Jolitz. All rights reserved.
  282.  * Written by William Jolitz 9/89
  283.  * Redistribution and use in source and binary forms are freely permitted
  284.  * provided that the above copyright notice and attribution and date of work
  285.  * and this paragraph are duplicated in all such forms.
  286.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  287.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  288.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  289.  * Standalone driver for IBM PC Displays like CGA.
  290.  */
  291.  
  292. typedef unsigned short u_short;
  293. typedef unsigned char u_char;
  294.  
  295. #define    CRT_TXTADDR    Crtat
  296. #define    COL        80
  297. #define    ROW        25
  298. #define    CHR        2
  299.  
  300. u_short *Crtat = ((u_short *)0xb8000); /* 0xb0000 for monochrome */
  301. u_short    *crtat;
  302. u_char    color = 0xe ;
  303. int row;
  304.  
  305. sput(c) u_char c; {
  306.  
  307.     if (crtat == 0) {
  308.         crtat = CRT_TXTADDR; bzero (crtat,COL*ROW*CHR);
  309.     }
  310.     if (crtat >= (CRT_TXTADDR+COL*ROW*CHR)) {
  311.         crtat = CRT_TXTADDR+COL*(ROW-1); row = 0;
  312.     }
  313.     switch(c) {
  314.  
  315.     case '\t':
  316.         do {
  317.             *crtat++ = (color<<8)| ' '; row++ ;
  318.         } while (row %8);
  319.         break;
  320.     case '\010':
  321.         crtat--; row--;
  322.         break;
  323.     case '\r':
  324.         bzero (crtat,(COL-row)*CHR) ; crtat -= row ; row = 0;
  325.         break;
  326.     case '\n':
  327.         if (crtat >= CRT_TXTADDR+COL*(ROW-1)) { /* scroll */
  328.             bcopy(CRT_TXTADDR+COL, CRT_TXTADDR,COL*(ROW-1)*CHR);
  329.             bzero (CRT_TXTADDR+COL*(ROW-1),COL*CHR) ;
  330.             crtat -= COL ;
  331.         }
  332.         crtat += COL ;
  333.         break;
  334.     default:
  335.         *crtat++ = (color<<8)| c; row++ ;
  336.         break ;
  337.     }
  338. }
  339.  
  340.  
  341.  
  342. [LISTING SIX]
  343.  
  344. /* [excerpted from i386.c] */
  345.  ...
  346. /* Descriptor Tables  */
  347.  
  348.     /* Global Descriptor Table */
  349. #define    GNULL_SEL    0    /* Null Descriptor - obligatory */
  350. #define    GCODE_SEL    1    /* Kernel Code Descriptor */
  351. #define    GDATA_SEL    2    /* Kernel Data Descriptor */
  352. #define    GLDT_SEL    3    /* LDT - eventually one per process */
  353. #define    GTGATE_SEL    4    /* Process task switch gate */
  354. #define    GPANIC_SEL    5    /* Task state to consider panic from */
  355. #define    GPROC0_SEL    6    /* Task state process slot zero and up */
  356. union descriptor gdt[GPROC0_SEL+NPROC];
  357.  
  358. /* interrupt descriptor table */
  359. struct gate_descriptor idt[NEXECPT+NINTR];
  360.  
  361. /* local descriptor table */
  362. #define    LSYS5CALLS_SEL    0    /* SVID/BCS 386 system call gate */
  363. #define    LSYS5SIGR_SEL    1    /* SVID/BCS 386 sigreturn() */
  364. #define    LBSDCALLS_SEL    2    /* BSD experimental system calls */
  365. #define    LUCODE_SEL    3    /* user process code descriptor */
  366. #define    LUDATA_SEL    4    /* user process data descriptor */
  367. union descriptor ldt[LUDATA_SEL+1];
  368.  
  369. /* Task State Structures (TSS) for hardware context switch */
  370. struct    i386tss    tss[NPROC], ptss;
  371.  
  372. /* software prototypes -- in more palitable form */
  373. struct soft_segment_descriptor gdt_segs[GPROC0_SEL+NPROC] = {
  374.     /* Null Descriptor */
  375. {    0x0,            /* segment base address  */
  376.     0x0,            /* length - all address space */
  377.     0,            /* segment type */
  378.     0,            /* segment descriptor priority level */
  379.     0,            /* segment descriptor present */
  380.     0,0,
  381.     0,            /* default 32 vs 16 bit size */
  382.     0              /* limit granularity (byte/page units)*/ },
  383.     /* Code Descriptor for kernel */
  384. {    0x0,            /* segment base address  */
  385.     0xfffff,        /* length - all address space */
  386.     SDT_MEMERA,        /* segment type */
  387.     0,            /* segment descriptor priority level */
  388.     1,            /* segment descriptor present */
  389.     0,0,
  390.     1,            /* default 32 vs 16 bit size */
  391.     1              /* limit granularity (byte/page units)*/ },
  392.     /* Data Descriptor for kernel */
  393. {    0x0,            /* segment base address  */
  394.     0xfffff,        /* length - all address space */
  395.     SDT_MEMRWA,        /* segment type */
  396.     0,            /* segment descriptor priority level */
  397.     1,            /* segment descriptor present */
  398.     0,0,
  399.     1,            /* default 32 vs 16 bit size */
  400.     1              /* limit granularity (byte/page units)*/ },
  401.     /* LDT Descriptor */
  402. {    (int) ldt,            /* segment base address  */
  403.     sizeof(ldt)-1,        /* length - all address space */
  404.     SDT_SYSLDT,        /* segment type */
  405.     0,            /* segment descriptor priority level */
  406.     1,            /* segment descriptor present */
  407.     0,0,
  408.     0,            /* unused - default 32 vs 16 bit size */
  409.     0              /* limit granularity (byte/page units)*/ },
  410.     /* Null Descriptor - Placeholder */
  411. {    0x0,            /* segment base address  */
  412.     0x0,            /* length - all address space */
  413.     0,            /* segment type */
  414.     0,            /* segment descriptor priority level */
  415.     0,            /* segment descriptor present */
  416.     0,0,
  417.     0,            /* default 32 vs 16 bit size */
  418.     0              /* limit granularity (byte/page units)*/ },
  419.     /* Panic Tss Descriptor */
  420. {    (int) &ptss,            /* segment base address  */
  421.     sizeof(tss)-1,        /* length - all address space */
  422.     SDT_SYS386TSS,        /* segment type */
  423.     0,            /* segment descriptor priority level */
  424.     1,            /* segment descriptor present */
  425.     0,0,
  426.     0,            /* unused - default 32 vs 16 bit size */
  427.     0              /* limit granularity (byte/page units)*/ },
  428.     /* Process 0 Tss Descriptor */
  429. {    (int) &tss[0],        /* segment base address  */
  430.     sizeof(tss)-1,        /* length - all address space */
  431.     SDT_SYS386TSS,        /* segment type */
  432.     0,            /* segment descriptor priority level */
  433.     1,            /* segment descriptor present */
  434.     0,0,
  435.     0,            /* unused - default 32 vs 16 bit size */
  436.     0              /* limit granularity (byte/page units)*/ } };
  437.  
  438. struct soft_segment_descriptor ldt_segs[] = {
  439.     /* Null Descriptor - overwritten by call gate */
  440. {    0x0,            /* segment base address  */
  441.     0x0,            /* length - all address space */
  442.     0,            /* segment type */
  443.     0,            /* segment descriptor priority level */
  444.     0,            /* segment descriptor present */
  445.     0,0,
  446.     0,            /* default 32 vs 16 bit size */
  447.     0              /* limit granularity (byte/page units)*/ },
  448.     /* Null Descriptor - overwritten by call gate */
  449. {    0x0,            /* segment base address  */
  450.     0x0,            /* length - all address space */
  451.     0,            /* segment type */
  452.     0,            /* segment descriptor priority level */
  453.     0,            /* segment descriptor present */
  454.     0,0,
  455.     0,            /* default 32 vs 16 bit size */
  456.     0              /* limit granularity (byte/page units)*/ },
  457.     /* Null Descriptor - overwritten by call gate */
  458. {    0x0,            /* segment base address  */
  459.     0x0,            /* length - all address space */
  460.     0,            /* segment type */
  461.     0,            /* segment descriptor priority level */
  462.     0,            /* segment descriptor present */
  463.     0,0,
  464.     0,            /* default 32 vs 16 bit size */
  465.     0              /* limit granularity (byte/page units)*/ },
  466.     /* Code Descriptor for user */
  467. {    0x0,            /* segment base address  */
  468.     0xfffff,        /* length - all address space */
  469.     SDT_MEMERA,        /* segment type */
  470.     SEL_UPL,        /* segment descriptor priority level */
  471.     1,            /* segment descriptor present */
  472.     0,0,
  473.     1,            /* default 32 vs 16 bit size */
  474.     1              /* limit granularity (byte/page units)*/ },
  475.     /* Data Descriptor for user */
  476. {    0x0,            /* segment base address  */
  477.     0xfffff,        /* length - all address space */
  478.     SDT_MEMRWA,        /* segment type */
  479.     SEL_UPL,        /* segment descriptor priority level */
  480.     1,            /* segment descriptor present */
  481.     0,0,
  482.     1,            /* default 32 vs 16 bit size */
  483.     1              /* limit granularity (byte/page units)*/ } };
  484.  ...
  485. extern ssdtosd(), lgdt(), lidt(), lldt(), usercode(), touser();
  486.  
  487. init386() {
  488.  ...
  489.     /* make gdt memory segments */
  490.     for (x=0; x < sizeof gdt / sizeof gdt[0] ; x++)
  491.             ssdtosd(gdt_segs+x, gdt+x);
  492.     printf("lgdt\n"); getchar();
  493.     lgdt(gdt, sizeof(gdt)-1);
  494.  
  495.     /* make ldt memory segments */
  496.     for (x=0; x < sizeof ldt / sizeof ldt[0] ; x++)
  497.         ssdtosd(ldt_segs+x, ldt+x);
  498.  
  499.     /* make a call gate to reenter kernel with */
  500.     setgate(&ldt[LSYS5CALLS_SEL].gd, &IDTVEC(syscall), SDT_SYS386CGT,
  501.         SEL_UPL);
  502.     printf("lldt\n"); getchar();
  503.     lldt(GSEL(GLDT_SEL, SEL_KPL));
  504.  ...
  505. /* [excerpted from srt.s] */
  506.  ...
  507.     /* lgdt(*gdt, ngdt) */
  508.     .globl    _lgdt
  509. gdesc:    .word 0
  510.     .long 0
  511. _lgdt:
  512.     movl    4(%esp),%eax
  513.     movl    %eax,gdesc+2
  514.     movl    8(%esp),%eax
  515.     movw    %ax,gdesc
  516.     lgdt    gdesc
  517.     jmp    1f        /* flush instruction prefetch q */
  518.     nop
  519. 1:    movw    $0x10,%ax    /* reload other "well known" descriptors */
  520.     movw    %ax,%ds
  521.     movw    %ax,%es
  522.     movw    %ax,%ss
  523.     movl    0(%esp),%eax
  524.     pushl    %eax
  525.     movl    $8,4(%esp)    /* including the ever popular CS */
  526.     lret
  527.  ...
  528.     /* lldt(sel) */
  529.     .globl    _lldt
  530. _lldt:
  531.     lldt    4(%esp)
  532.     ret
  533.  ...
  534.  
  535.  
  536.  
  537. [LISTING SEVEN]
  538.  
  539. /* segments.h: Copyright (c) 1989, 1990 William Jolitz. All rights reserved.
  540.  * Written by William Jolitz 6/20/1989
  541.  * Redistribution and use in source and binary forms are freely permitted
  542.  * provided that the above copyright notice and attribution and date of work
  543.  * and this paragraph are duplicated in all such forms.
  544.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  545.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  546.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  547.  * 386 Segmentation Data Structures and definitions
  548.  */
  549.  
  550. /* Selectors  */
  551. #define    ISPL(s)    ((s)&3)        /* what is the priority level of a selector */
  552. #define     SEL_KPL    0    /* kernel priority level */    
  553. #define     SEL_UPL    3    /* user priority level */    
  554. #define    ISLDT(s) ((s)&SEL_LDT)    /* is it local or global */
  555. #define     SEL_LDT    4    /* local descriptor table */    
  556. #define    IDXSEL(s) (((s)>>3) & 0x1fff)    /* index of selector */
  557. #define    LSEL(s,r) (((s)<<3) | SEL_LDT | r) /* a local selector */
  558. #define    GSEL(s,r) (((s)<<3) | r) /* a global selector */
  559.  
  560. /* Memory and System segment descriptors  */
  561. struct    segment_descriptor    {
  562.     unsigned sd_lolimit:16 ;     /* segment extent (lsb) */
  563.     unsigned sd_lobase:24 ;         /* segment base address (lsb) */
  564.     unsigned sd_type:5 ;         /* segment type */
  565.     unsigned sd_dpl:2 ;         /* segment descriptor priority level */
  566.     unsigned sd_p:1 ;         /* segment descriptor present */
  567.     unsigned sd_hilimit:4 ;         /* segment extent (msb) */
  568.     unsigned sd_xx:2 ;         /* unused */
  569.     unsigned sd_def32:1 ;         /* default 32 vs 16 bit size */
  570.     unsigned sd_gran:1 ;         /* limit granularity (byte/page units)*/
  571.     unsigned sd_hibase:8 ;         /* segment base address  (msb) */
  572. } ;
  573.  
  574. /* Gate descriptors (e.g. indirect descriptors)  */
  575. struct    gate_descriptor    {
  576.     unsigned gd_looffset:16 ;    /* gate offset (lsb) */
  577.     unsigned gd_selector:16 ;    /* gate segment selector */
  578.     unsigned gd_stkcpy:5 ;        /* number of stack wds to cpy */
  579.     unsigned gd_xx:3 ;        /* unused */
  580.     unsigned gd_type:5 ;        /* segment type */
  581.     unsigned gd_dpl:2 ;        /* segment descriptor priority level */
  582.     unsigned gd_p:1 ;        /* segment descriptor present */
  583.     unsigned gd_hioffset:16 ;    /* gate offset (msb) */
  584. } ;
  585.  
  586. /* Generic descriptor  */
  587. union    descriptor    {
  588.     struct    segment_descriptor sd;
  589.     struct    gate_descriptor gd;
  590. };
  591. #define    d_type    gd.gd_type
  592.  
  593.     /* system segments and gate types */
  594. #define    SDT_SYSNULL     0    /* system null */
  595. #define    SDT_SYS286TSS     1    /* system 286 TSS available */
  596. #define    SDT_SYSLDT     2    /* system local descriptor table */
  597. #define    SDT_SYS286BSY     3    /* system 286 TSS busy */
  598. #define    SDT_SYS286CGT     4    /* system 286 call gate */
  599. #define    SDT_SYSTASKGT     5    /* system task gate */
  600. #define    SDT_SYS286IGT     6    /* system 286 interrupt gate */
  601. #define    SDT_SYS286TGT     7    /* system 286 trap gate */
  602. #define    SDT_SYSNULL2     8    /* system null again */
  603. #define    SDT_SYS386TSS     9    /* system 386 TSS available */
  604. #define    SDT_SYSNULL3    10    /* system null again */
  605. #define    SDT_SYS386BSY    11    /* system 386 TSS busy */
  606. #define    SDT_SYS386CGT    12    /* system 386 call gate */
  607. #define    SDT_SYSNULL4    13    /* system null again */
  608. #define    SDT_SYS386IGT    14    /* system 386 interrupt gate */
  609. #define    SDT_SYS386TGT    15    /* system 386 trap gate */
  610.  
  611.     /* memory segment types */
  612. #define    SDT_MEMRO    16    /* memory read only */
  613. #define    SDT_MEMROA    17    /* memory read only accessed */
  614. #define    SDT_MEMRW    18    /* memory read write */
  615. #define    SDT_MEMRWA    19    /* memory read write accessed */
  616. #define    SDT_MEMROD    20    /* memory read only expand dwn limit */
  617. #define    SDT_MEMRODA    21    /* memory read only expand dwn limit accessed */
  618. #define    SDT_MEMRWD    22    /* memory read write expand dwn limit */
  619. #define    SDT_MEMRWDA    23    /* memory r/w expand dwn limit acessed */
  620. #define    SDT_MEME    24    /* memory execute only */
  621. #define    SDT_MEMEA    25    /* memory execute only accessed */
  622. #define    SDT_MEMER    26    /* memory execute read */
  623. #define    SDT_MEMERA    27    /* memory execute read accessed */
  624. #define    SDT_MEMEC    28    /* memory execute only conforming */
  625. #define    SDT_MEMEAC    29    /* memory execute only accessed conforming */
  626. #define    SDT_MEMERC    30    /* memory execute read conforming */
  627. #define    SDT_MEMERAC    31    /* memory execute read accessed conforming */
  628.  
  629. /* is memory segment descriptor pointer ? */
  630. #define ISMEMSDP(s)   ((s->d_type) >= SDT_MEMRO && (s->d_type) <= SDT_MEMERAC)
  631.  
  632. /* is 286 gate descriptor pointer ? */
  633. #define IS286GDP(s)    (((s->d_type) >= SDT_SYS286CGT \
  634.                  && (s->d_type) < SDT_SYS286TGT))
  635. /* is 386 gate descriptor pointer ? */
  636. #define IS386GDP(s)    (((s->d_type) >= SDT_SYS386CGT \
  637.                 && (s->d_type) < SDT_SYS386TGT))
  638. /* is gate descriptor pointer ? */
  639. #define ISGDP(s)    (IS286GDP(s) || IS386GDP(s))
  640.  
  641. /* is segment descriptor pointer ? */
  642. #define ISSDP(s)    (ISMEMSDP(s) || !ISGDP(s))
  643.  
  644. /* is system segment descriptor pointer ? */
  645. #define ISSYSSDP(s)    (!ISMEMSDP(s) && !ISGDP(s))
  646.  
  647. /* Software definitions are in this convenient format; translated into 
  648.  * inconvenient segment descriptors when needed to be used by 386 hardware  */
  649. struct    soft_segment_descriptor    {
  650.     unsigned ssd_base ;        /* segment base address  */
  651.     unsigned ssd_limit ;        /* segment extent */
  652.     unsigned ssd_type:5 ;        /* segment type */
  653.     unsigned ssd_dpl:2 ;        /* segment descriptor priority level */
  654.     unsigned ssd_p:1 ;        /* segment descriptor present */
  655.     unsigned ssd_xx:4 ;        /* unused */
  656.     unsigned ssd_xx1:2 ;        /* unused */
  657.     unsigned ssd_def32:1 ;        /* default 32 vs 16 bit size */
  658.     unsigned ssd_gran:1 ;           /* limit granularity (byte/page units)*/
  659. };
  660.  
  661. extern ssdtosd() ;    /* to decode a ssd */
  662. extern sdtossd() ;    /* to encode a sd */
  663.  
  664. /* region descriptors, used to load gdt/idt tables before segments yet exist */
  665. struct region_descriptor {
  666.     unsigned rd_limit:16 ;        /* segment extent */
  667.     char *rd_base;            /* base address  */
  668. };
  669.  
  670. /* Segment Protection Exception code bits  */
  671. #define    SEGEX_EXT    0x01    /* recursive or externally induced */
  672. #define    SEGEX_IDT    0x02    /* interrupt descriptor table */
  673. #define    SEGEX_TI    0x04    /* local descriptor table */
  674.                 /* other bits are affected descriptor index */
  675. #define SEGEX_IDX(s)    ((s)>>3)&0x1fff)
  676.  
  677.  
  678.  
  679. [LISTING EIGHT]
  680.  
  681. /* [excerpted from i386.c] */
  682.  ...
  683. /* Assemble a gate descriptor  */
  684. setgate(gp, func, typ, dpl) char *func; struct gate_descriptor *gp; {
  685.     gp->gd_looffset = (int)func;
  686.     gp->gd_selector = GSEL(GCODE_SEL,SEL_KPL);
  687.     gp->gd_stkcpy = 0;
  688.     gp->gd_xx = 0;
  689.     gp->gd_type = typ;
  690.     gp->gd_dpl = dpl;
  691.     gp->gd_p = 1;        /* definitely present */
  692.     gp->gd_hioffset = ((int)func)>>16 ;
  693. }
  694.  
  695. /* ASM entry points to exception/trap/interrupt entry stub code. */
  696. #define    IDTVEC(name)    X##name
  697. extern
  698.     IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
  699.     IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm),
  700.     IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot), IDTVEC(page),
  701.     IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(rsvd0), IDTVEC(rsvd1), IDTVEC(rsvd2),
  702.     IDTVEC(rsvd3), IDTVEC(rsvd4), IDTVEC(rsvd5), IDTVEC(rsvd6),
  703.     IDTVEC(rsvd7), IDTVEC(rsvd8), IDTVEC(rsvd9), IDTVEC(rsvd10),
  704.     IDTVEC(rsvd11), IDTVEC(rsvd12), IDTVEC(rsvd13), IDTVEC(rsvd14),
  705.     IDTVEC(rsvd14), IDTVEC(intr0), IDTVEC(intr1), IDTVEC(intr2),
  706.     IDTVEC(intr3), IDTVEC(intr4), IDTVEC(intr5), IDTVEC(intr6),
  707.     IDTVEC(intr7), IDTVEC(intr8), IDTVEC(intr9), IDTVEC(intr10),
  708.     IDTVEC(intr11), IDTVEC(intr12), IDTVEC(intr13), IDTVEC(intr14),
  709.     IDTVEC(intr15), IDTVEC(syscall);
  710. init386() {
  711.  ...
  712.     /* exceptions */
  713.     setgate(idt+0, &IDTVEC(div),  SDT_SYS386TGT, SEL_KPL);
  714.     setgate(idt+1, &IDTVEC(dbg),  SDT_SYS386TGT, SEL_KPL);
  715.     setgate(idt+2, &IDTVEC(nmi),  SDT_SYS386TGT, SEL_KPL);
  716.     setgate(idt+3, &IDTVEC(bpt),  SDT_SYS386TGT, SEL_KPL);
  717.     setgate(idt+4, &IDTVEC(ofl),  SDT_SYS386TGT, SEL_KPL);
  718.     setgate(idt+5, &IDTVEC(bnd),  SDT_SYS386TGT, SEL_KPL);
  719.     setgate(idt+6, &IDTVEC(ill),  SDT_SYS386TGT, SEL_KPL);
  720.     setgate(idt+7, &IDTVEC(dna),  SDT_SYS386TGT, SEL_KPL);
  721.     setgate(idt+8, &IDTVEC(dble),  SDT_SYS386TGT, SEL_KPL);
  722.     setgate(idt+9, &IDTVEC(fpusegm),  SDT_SYS386TGT, SEL_KPL);
  723.     setgate(idt+10, &IDTVEC(tss),  SDT_SYS386TGT, SEL_KPL);
  724.     setgate(idt+11, &IDTVEC(missing),  SDT_SYS386TGT, SEL_KPL);
  725.     setgate(idt+12, &IDTVEC(stk),  SDT_SYS386TGT, SEL_KPL);
  726.     setgate(idt+13, &IDTVEC(prot),  SDT_SYS386TGT, SEL_KPL);
  727.     setgate(idt+14, &IDTVEC(page),  SDT_SYS386TGT, SEL_KPL);
  728.     setgate(idt+15, &IDTVEC(rsvd),  SDT_SYS386TGT, SEL_KPL);
  729.     setgate(idt+16, &IDTVEC(fpu),  SDT_SYS386TGT, SEL_KPL);
  730.     setgate(idt+17, &IDTVEC(rsvd0),  SDT_SYS386TGT, SEL_KPL);
  731.     setgate(idt+18, &IDTVEC(rsvd1),  SDT_SYS386TGT, SEL_KPL);
  732.     setgate(idt+19, &IDTVEC(rsvd2),  SDT_SYS386TGT, SEL_KPL);
  733.     setgate(idt+20, &IDTVEC(rsvd3),  SDT_SYS386TGT, SEL_KPL);
  734.     setgate(idt+21, &IDTVEC(rsvd4),  SDT_SYS386TGT, SEL_KPL);
  735.     setgate(idt+22, &IDTVEC(rsvd5),  SDT_SYS386TGT, SEL_KPL);
  736.     setgate(idt+23, &IDTVEC(rsvd6),  SDT_SYS386TGT, SEL_KPL);
  737.     setgate(idt+24, &IDTVEC(rsvd7),  SDT_SYS386TGT, SEL_KPL);
  738.     setgate(idt+25, &IDTVEC(rsvd8),  SDT_SYS386TGT, SEL_KPL);
  739.     setgate(idt+26, &IDTVEC(rsvd9),  SDT_SYS386TGT, SEL_KPL);
  740.     setgate(idt+27, &IDTVEC(rsvd10),  SDT_SYS386TGT, SEL_KPL);
  741.     setgate(idt+28, &IDTVEC(rsvd11),  SDT_SYS386TGT, SEL_KPL);
  742.     setgate(idt+29, &IDTVEC(rsvd12),  SDT_SYS386TGT, SEL_KPL);
  743.     setgate(idt+30, &IDTVEC(rsvd13),  SDT_SYS386TGT, SEL_KPL);
  744.     setgate(idt+31, &IDTVEC(rsvd14),  SDT_SYS386TGT, SEL_KPL);
  745.  
  746.     /* first icu */
  747.     setgate(idt+32, &IDTVEC(intr0),  SDT_SYS386IGT, SEL_KPL);
  748.     setgate(idt+33, &IDTVEC(intr1),  SDT_SYS386IGT, SEL_KPL);
  749.     setgate(idt+34, &IDTVEC(intr2),  SDT_SYS386IGT, SEL_KPL);
  750.     setgate(idt+35, &IDTVEC(intr3),  SDT_SYS386IGT, SEL_KPL);
  751.     setgate(idt+36, &IDTVEC(intr4),  SDT_SYS386IGT, SEL_KPL);
  752.     setgate(idt+37, &IDTVEC(intr5),  SDT_SYS386IGT, SEL_KPL);
  753.     setgate(idt+38, &IDTVEC(intr6),  SDT_SYS386IGT, SEL_KPL);
  754.     setgate(idt+39, &IDTVEC(intr7),  SDT_SYS386IGT, SEL_KPL);
  755.  
  756.     /* second icu */
  757.     setgate(idt+40, &IDTVEC(intr8),  SDT_SYS386IGT, SEL_KPL);
  758.     setgate(idt+41, &IDTVEC(intr9),  SDT_SYS386IGT, SEL_KPL);
  759.     setgate(idt+42, &IDTVEC(intr10),  SDT_SYS386IGT, SEL_KPL);
  760.     setgate(idt+43, &IDTVEC(intr11),  SDT_SYS386IGT, SEL_KPL);
  761.     setgate(idt+44, &IDTVEC(intr12),  SDT_SYS386IGT, SEL_KPL);
  762.     setgate(idt+45, &IDTVEC(intr13),  SDT_SYS386IGT, SEL_KPL);
  763.     setgate(idt+46, &IDTVEC(intr14),  SDT_SYS386IGT, SEL_KPL);
  764.     setgate(idt+47, &IDTVEC(intr15),  SDT_SYS386IGT, SEL_KPL);
  765.  
  766.     printf("lidt\n"); getchar();
  767.     lidt(idt, sizeof(idt)-1);
  768.  ...
  769.  /* [excerpted from srt.s] */
  770.  
  771.     /* lidt(*idt, nidt) */
  772.     .globl    _lidt
  773. idesc:    .word    0
  774.     .long    0
  775. _lidt:
  776.     movl    4(%esp),%eax
  777.     movl    %eax,idesc+2
  778.     movl    8(%esp),%eax
  779.     movw    %ax,idesc
  780.     lidt    idesc
  781.     ret
  782.  
  783.  
  784.  
  785.  
  786. [LISTING NINE]
  787.  
  788. /* [excerpted from i386.c] */
  789.  ...
  790. #define    NBPG        4096        /* number of bytes per page */
  791. #define    PG_V        0x00000001    /* mark this page as valid */
  792. #define    PG_UW        0x00000006    /* user and supervisor writable */
  793.  
  794. int lcr0(), lcr3();
  795.  ...
  796. init386() {
  797.     /* bag of bytes to put page table, page directory in */
  798.     static char bag[(1+1+1)*NBPG];    
  799.     int *ppte, *pptd, *cr3, x;
  800.  
  801.     /* make page table & directory aligned to NBPG */
  802.     ppte = (int *) (((int) bag + NBPG-1) & ~(NBPG-1));
  803.     cr3 = pptd = ppte + 1024;
  804.  
  805.     /* page table directory only has lowest 4MB entry mapped */
  806.     *pptd++ = (int) ppte + (PG_V|PG_UW);
  807.     for (x = 1; x < 1024 ; x++,pptd++) *pptd =  0;
  808.  
  809.     /* page table, all entrys virtual == real, user/supervisor r/w */
  810.     for (x = 0; x < 1024 ; x++,ppte++) *ppte =  x*NBPG + (PG_V|PG_UW) ;
  811.  
  812.     /* turn on paging */
  813.     lcr3(cr3);
  814.     printf("paging"); getchar();
  815.     lcr0(0x80000001);
  816.  ...
  817.  
  818. /* [excerpted from srt.s] */
  819.  
  820.     /*
  821.      * lcr3(cr3)
  822.      */
  823.     .globl    _lcr3
  824. _lcr3:
  825.     movl    4(%esp),%eax
  826.     movl    %eax,%cr3
  827.     ret
  828.  
  829.     /* lcr0(cr0) */
  830.     .globl    _lcr0
  831. _lcr0:
  832.     movl    4(%esp),%eax
  833.     movl    %eax,%cr0
  834.     ret
  835.  
  836.  
  837. [LISTING TEN]
  838.  
  839. /* [excerpted from i386.c] */
  840.  ...
  841. init386(){
  842.  ...
  843.     /* make a initial tss so 386 can get interrupt stack on syscall! */
  844.     tss[0].tss_esp0 = (int) &x - 4096; 
  845.     tss[0].tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
  846.     tss[0].tss_cr3 = (int) cr3;
  847.     printf("ltr "); getchar();
  848.     ltr(GSEL(GPROC0_SEL, SEL_KPL));
  849.  
  850.     printf("resume() "); getchar();
  851.     /* set busy type to avail */
  852.     gdt[GPROC0_SEL].sd.sd_type = SDT_SYS386TSS;
  853.     /* jump to self to fill out tss, like BSD resume() */
  854.     jmptss(GSEL(GPROC0_SEL, SEL_KPL));
  855.  ...
  856. # excerpted from srt.s
  857.  ...
  858. /* jmptss(sel)-- Jump to TSS so that we can load/unload context  */
  859.     .globl _jmptss        /* similar to BSD swtch()/resume() */
  860. _jmptss:
  861.     ljmp    0(%esp)        /* ljmp tss */
  862.                 /* saved pc points here */
  863.     ret
  864.  
  865.  
  866.  
  867.  
  868. [LISTING ELEVEN]
  869.  
  870. /* [excerpted from i386.c] */
  871.  ...
  872. test386(){
  873.  ...
  874.     /* test handling exceptions */
  875.     printf("breakpoint "); getchar();
  876.     asm (" int $3 ");
  877.  ...
  878. /* Trap exception processing code  */
  879. trap(es, ds, edi, esi, ebp, dummy, ebx, edx, ecx, eax,
  880.     fault, ec, eip, cs, eflags, esp, ss) {
  881.  
  882.     printf("pc:%x cs:%x ds:%x eflags:%x ec %x fault %x cr0 %x cr2 %x \n",
  883.         eip, cs, ds, eflags, ec, fault, rcr0(), rcr2());
  884.     printf("edi %x esi %x ebp %x ebx %x edx %x ecx %x eax %x\n",
  885.         edi, esi, ebp, ebx, edx, ecx, eax);
  886.     eip++;    /* simple way to 'jump' over fault */
  887.     getchar();
  888. }
  889.  
  890.  ...
  891. # excerpted from srt.s
  892.  ...
  893. #include <machine/i386/trap.h>
  894.  
  895. #define    IDTVEC(name)    .align 4; .globl _X##name; _X##name:
  896.  ...
  897. /* Trap and fault vector routines  */ 
  898. #define    TRAP(a)    pushl $##a ; jmp alltraps
  899.  
  900. IDTVEC(div)
  901.     pushl $0; TRAP(T_DIVIDE)
  902. IDTVEC(dbg)
  903.     pushl $0; TRAP(T_DEBUG)
  904. IDTVEC(nmi)
  905.     pushl $0; TRAP(T_NMI)
  906. IDTVEC(bpt)
  907.     pushl $0; TRAP(T_BPTFLT)
  908. IDTVEC(ofl)
  909.     pushl $0; TRAP(T_OFLOW)
  910. IDTVEC(bnd)
  911.     pushl $0; TRAP(T_BOUND)
  912. IDTVEC(ill)
  913.     pushl $0; TRAP(T_PRIVINFLT)
  914. IDTVEC(dna)
  915.     pushl $0; TRAP(T_DNA)
  916. IDTVEC(dble)
  917.     TRAP(T_DOUBLEFLT)
  918. IDTVEC(fpusegm)
  919.     pushl $0; TRAP(T_FPOPFLT)
  920. IDTVEC(tss)
  921.     TRAP(T_TSSFLT)
  922. IDTVEC(missing)
  923.     TRAP(T_SEGNPFLT)
  924. IDTVEC(stk)
  925.     TRAP(T_STKFLT)
  926. IDTVEC(prot)
  927.     TRAP(T_PROTFLT)
  928. IDTVEC(page)
  929.     TRAP(T_PAGEFLT)
  930. IDTVEC(rsvd)
  931.     pushl $0; TRAP(T_RESERVED)
  932. IDTVEC(fpu)
  933.     pushl $0; TRAP(T_ARITHTRAP)
  934.     /* 17 - 31 reserved for future exp */
  935. IDTVEC(rsvd0)
  936.     pushl $0; TRAP(17)
  937. IDTVEC(rsvd1)
  938.     pushl $0; TRAP(18)
  939. IDTVEC(rsvd2)
  940.     pushl $0; TRAP(19)
  941. IDTVEC(rsvd3)
  942.     pushl $0; TRAP(20)
  943. IDTVEC(rsvd4)
  944.     pushl $0; TRAP(21)
  945. IDTVEC(rsvd5)
  946.     pushl $0; TRAP(22)
  947. IDTVEC(rsvd6)
  948.     pushl $0; TRAP(23)
  949. IDTVEC(rsvd7)
  950.     pushl $0; TRAP(24)
  951. IDTVEC(rsvd8)
  952.     pushl $0; TRAP(25)
  953. IDTVEC(rsvd9)
  954.     pushl $0; TRAP(26)
  955. IDTVEC(rsvd10)
  956.     pushl $0; TRAP(27)
  957. IDTVEC(rsvd11)
  958.     pushl $0; TRAP(28)
  959. IDTVEC(rsvd12)
  960.     pushl $0; TRAP(29)
  961. IDTVEC(rsvd13)
  962.     pushl $0; TRAP(30)
  963. IDTVEC(rsvd14)
  964.     pushl $0; TRAP(31)
  965.  
  966. alltraps:
  967.     pushal
  968.     push %ds            # save old selector's we will use
  969.     push %es
  970.     movw    $0x10,%ax        # load them with kernel global data sel
  971.     movw    %ax,%ds
  972.     movw    %ax,%es
  973.     call    _trap
  974.     pop %es
  975.     pop %ds
  976.     popal
  977.     addl    $8,%esp            # pop type, code
  978.     iret
  979.  
  980.  
  981.  
  982.  
  983. [LISTING TWELVE]
  984.  
  985. /* [excerpted from i386.c] */
  986.  ...
  987. init386() {
  988.  ...
  989.     outb(0xf1,0);    /* clear coprocessor to cover all bases */
  990.  
  991.     /* initialize 8259 ICU's in preperation for device interrupts */
  992.  
  993.     outb(ICU1,0x11);    /* reset the unit */
  994.     outb(ICU1+1,32);    /* start with idt 32 */
  995.     outb(ICU1+1,4);        /* master please */
  996.     outb(ICU1+1,1);
  997.     outb(ICU1+1,0xff);    /* all disabled */
  998.  
  999.     outb(ICU2,0x11);
  1000.     outb(ICU2+1,40);    /* start with idt 40 */
  1001.     outb(ICU2+1,2);        /* just a slave */
  1002.     outb(ICU2+1,1);
  1003.     outb(ICU2+1,0xff);    /* all disabled */
  1004.  
  1005.     /* initialize 8253 timer on interrupt #0 */
  1006.  
  1007.     outb (0x43, 0x36);
  1008.     outb (0x40, 193182/60);
  1009.     outb (0x40, (193182/60)/256);
  1010. }
  1011. test386(){
  1012.  ...
  1013.     /* test interrupts for a while */
  1014.     printf("inton"); getchar();
  1015.     outb(ICU1+1,0);    /* unmask all interrupts */
  1016.     outb(ICU2+1,0);
  1017.     inton();
  1018.  
  1019.     timeout = 0x8000000;
  1020.     do nothing(); while (timeout-- );
  1021.  
  1022.     intoff();
  1023.  ...
  1024.  
  1025. # excerpted from srt.s
  1026.  ...
  1027. #define    INTR(a) \
  1028.     pushal ; \
  1029.     push %ds ; \
  1030.     push %es ; \
  1031.     movw $0x10, %ax ; \
  1032.     movw %ax, %ds ; \
  1033.     movw %ax,%es ; \
  1034.     pushl $##a ; \
  1035.     call _intr ; \
  1036.     pop %eax ; \
  1037.     pop %es ; \
  1038.     pop %ds ; \
  1039.     popal ; \
  1040.     iret
  1041.  
  1042.     /* hardware 32 - 47 */
  1043. IDTVEC(intr0)
  1044.     INTR(0)
  1045. IDTVEC(intr1)
  1046.     INTR(1)
  1047. IDTVEC(intr2)
  1048.     INTR(2)
  1049. IDTVEC(intr3)
  1050.     INTR(3)
  1051. IDTVEC(intr4)
  1052.     INTR(4)
  1053. IDTVEC(intr5)
  1054.     INTR(5)
  1055. IDTVEC(intr6)
  1056.     INTR(6)
  1057. IDTVEC(intr7)
  1058.     INTR(7)
  1059. IDTVEC(intr8)
  1060.     INTR(8)
  1061. IDTVEC(intr9)
  1062.     INTR(9)
  1063. IDTVEC(intr10)
  1064.     INTR(10)
  1065. IDTVEC(intr11)
  1066.     INTR(11)
  1067. IDTVEC(intr12)
  1068.     INTR(12)
  1069. IDTVEC(intr13)
  1070.     INTR(13)
  1071. IDTVEC(intr14)
  1072.     INTR(14)
  1073. IDTVEC(intr15)
  1074.     INTR(15)
  1075.  
  1076.     .globl    _inton
  1077. _inton:
  1078.     sti
  1079.     ret
  1080.  
  1081.     .globl    _intoff
  1082. _intoff:
  1083.     cli
  1084.     ret
  1085.  ...
  1086.  
  1087. /* back to i386.c */
  1088.  ...
  1089. /* Interrupt vector processing code  */
  1090. intr(ivec) {
  1091.     static clk;
  1092.     int omsk1, omsk2;
  1093.     
  1094.     /* mask off interrupt being serviced, save old mask */
  1095.     if (ivec > 7) {
  1096.         omsk2 = inb(ICU2+1);
  1097.         outb(ICU2+1, 1<<(ivec-8));
  1098.     } else {
  1099.         omsk1 = inb(ICU1+1);
  1100.         outb(ICU1+1, 1<<ivec);
  1101.     }
  1102.  
  1103.     /* re-enable processor's interrupts, allowing others in */
  1104.     inton();
  1105.  
  1106.     /* if we are the clock, count clock tick */
  1107.     if (ivec == 0) clk++;
  1108.     /* if we are the keyboard, show data incoming */
  1109.     else if (ivec == 1) printf("kbd data %x, clk %d\n", inb(0x60), clk);
  1110.     /* otherwise print message stating source and time */
  1111.     else {
  1112.         printf("intr %d, clk %d \n", ivec, clk);
  1113.         getchar();
  1114.     }
  1115.  
  1116.     /* turn off interrupts, re-enable old mask, do interrupt acknowledge */
  1117.     intoff();
  1118.     if (ivec > 7) {
  1119.         outb(ICU2+1,omsk2);
  1120.         outb(ICU2,0x20);
  1121.     } else
  1122.         outb(ICU1+1,omsk1);
  1123.     outb(ICU1,0x20);
  1124.     /* return to interrupt stub */
  1125. }
  1126.  ...
  1127.  
  1128.  
  1129.  
  1130. [LISTING THIRTEEN]
  1131.  
  1132. test386(){
  1133.  ...
  1134.        /* transfer to user mode to test system call */
  1135.        printf("touser "); getchar();
  1136.        touser (LSEL(LUCODE_SEL,SEL_UPL), LSEL(LUDATA_SEL, SEL_UPL), &usercode);
  1137.  ...
  1138. # [excerpted from srt.s]
  1139.  
  1140.     /* touser (cs,ds,func) */
  1141.     .globl    _touser
  1142. _touser:
  1143.     pushal
  1144.     movl    %esp,_myspback
  1145.     movl    32+4(%esp),%eax
  1146.     movl    32+8(%esp),%edx
  1147.     movl    32+12(%esp),%ecx
  1148.     # build outer stack frame
  1149.     pushl    %edx        # user ss
  1150.     pushl    %esp        # user esp
  1151.     pushl    %eax        # cs
  1152.     pushl    %ecx        # ip
  1153.     movw    %dx,%ds
  1154.     movw    %dx,%es
  1155.     lret    # goto user!
  1156.  
  1157. /* code to execute in user mode */
  1158.     .globl    _usercode
  1159. #define    LCALL(x,y)    .byte 0x9a ; .long y; .word x
  1160. _usercode:
  1161.     LCALL(0x7,0x0)    /* would be lcall $0x7,0x0 except for assembler bug */
  1162. IDTVEC(syscall)
  1163.     pushal         
  1164.     movw    $0x10,%ax
  1165.     movw    %ax,%ds
  1166.     movw    %ax,%es
  1167.     call    _syscall
  1168.     movl    _myspback,%esp    /* non-local goto touser() exit */
  1169.     popal
  1170.     ret
  1171. /* back to i386.c */
  1172.  ...
  1173. /* System call processing */
  1174. syscall() {
  1175.     printf("syscall\n");
  1176. }
  1177.  
  1178.  
  1179. [LISTING FOURTEEN]
  1180.  
  1181. /* trap.h: i386 trap type index     [as they intersect with other BSD systems] */
  1182.  
  1183. #define    T_PRIVINFLT    1    /* privileged instruction */
  1184. #define    T_BPTFLT    3    /* breakpoint instruction */
  1185. #define    T_ARITHTRAP    6    /* arithmetic trap */
  1186. #define    T_PROTFLT    9    /* protection fault */
  1187. #define    T_PAGEFLT    12    /* page fault */
  1188.  
  1189. #define    T_DIVIDE    18    /* integer divide fault */
  1190. #define    T_NMI        19    /* non-maskable trap */
  1191. #define    T_OFLOW        20    /* overflow trap */
  1192. #define    T_BOUND        21    /* bound instruction fault */
  1193. #define    T_DNA        22    /* device not available fault */
  1194. #define    T_DOUBLEFLT    23    /* double fault */
  1195. #define    T_FPOPFLT    24    /* fp coprocessor operand fetch fault */
  1196. #define    T_TSSFLT    25    /* invalid tss fault */
  1197. #define    T_SEGNPFLT    26    /* segment not present fault */
  1198. #define    T_STKFLT    27    /* stack fault */
  1199. #define    T_RESERVED    28    /* reserved fault base */
  1200.  
  1201.  
  1202.  
  1203. [LISTING FIFTEEN]
  1204.  
  1205. /* [excerpted from i386.c] */
  1206.  ...
  1207. test386(){
  1208.     int x, *pi, timeout; 
  1209.  ...
  1210.     /* generate a page fault exception */
  1211.     printf("dopagflt\n"); getchar();
  1212.     pi =  (int *) 0x800000;    /* above 4MB */
  1213.     x = *pi;        /* will fault invalid read */
  1214.     *pi = ++x ;        /* will fault invalid write */
  1215.  ...
  1216.  
  1217.  
  1218.