root/arch/i386/stand/libsa/gidt.S

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _rtt
  2. bootbuf

    1 /*      $OpenBSD: gidt.S,v 1.32 2006/12/26 19:30:44 tom Exp $   */
    2 
    3 /*
    4  * Copyright (c) 1997 Michael Shalayeff
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
   17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
   18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  *
   28  */
   29 
   30         .file "gidt.S"
   31 
   32 #include <machine/asm.h>
   33 #define _LOCORE
   34 #include <machine/trap.h>
   35 #include <debug_md.h>
   36 #undef _LOCORE
   37 #include <assym.h>
   38 
   39 #include "gidt.h"
   40 
   41 #ifdef GIDT_DEBUG
   42 #define gidt_debug0             ; \
   43         mov     $0xb8000, %eax  ; \
   44         mov     $0x47314730, (%eax)
   45 #define gidt_debug1             ; \
   46         mov     $(0xb8000 - LINKADDR), %eax     ; \
   47         mov     $0x4f314f30, (%eax)
   48 #define gidt_debug2             ; \
   49         mov     $0xb8004, %eax  ; \
   50         mov     $0x47334732, (%eax)
   51 #define gidt_debug3             ; \
   52         mov     $0xb8004, %eax  ; \
   53         mov     $0x4f334f32, (%eax)
   54 #define gidt_debug4             ; \
   55         movl    $0xb8008, %eax  ; \
   56         movl    $0x47344733, (%eax)
   57 #else
   58 #define gidt_debug0 /* gidt_debug0 */
   59 #define gidt_debug1 /* gidt_debug1 */
   60 #define gidt_debug2 /* gidt_debug2 */
   61 #define gidt_debug3 /* gidt_debug3 */
   62 #define gidt_debug4 /* gidt_debug4 */
   63 #endif
   64 
   65 #define prot2real                                               \
   66         gidt_debug0;                                            \
   67                                                                 \
   68         ljmp    $S16TEXT, $1f - LINKADDR;                       \
   69 1:                                                              \
   70         .code16;                                                \
   71         movw    $S16DATA, %ax;                                  \
   72         movw    %ax, %ds;                                       \
   73         movw    %ax, %es;                                       \
   74         gidt_debug1;                                            \
   75                                                                 \
   76         movl    %cr0, %eax;     /* disable pmmm */              \
   77         andl    $~CR0_PE, %eax;                                 \
   78         movl    %eax, %cr0;                                     \
   79                                                                 \
   80         /* reload real cs:ip */                                 \
   81         data32 ljmp     $(LINKADDR >> 4), $1f - LINKADDR;       \
   82 1:                                                              \
   83         movw    %cs, %ax;       /* setup: %ds, %es, %ss = %cs */ \
   84         movw    %ax, %ds;                                       \
   85         movw    %ax, %es;                                       \
   86         xorw    %ax, %ax;                                       \
   87         movw    %ax, %ss;                                       \
   88                                                                 \
   89         gidt_debug2;                                            \
   90                                                                 \
   91         data32 addr32 lidt (Idtr_real - LINKADDR); /* load idtr for real mode */
   92 
   93 #define real2prot                                               \
   94         gidt_debug3;                                            \
   95                                                                 \
   96         movw    $LINKADDR >> 4, %ax;                            \
   97         movw    %ax, %ds;                                       \
   98         data32 addr32 lgdt (Gdtr - LINKADDR);   /* load the gdtr */     \
   99                                                                 \
  100         movl    %cr0, %eax;     /* enable pmmm */               \
  101         orl     $CR0_PE, %eax;                                  \
  102         movl    %eax, %cr0;                                     \
  103                                                                 \
  104         data32 ljmp     $S32TEXT, $1f;   /* reload %cs,flush pipeline */\
  105 1:                                                              \
  106         .code32;                                                \
  107         /* reload 32bit %ds, %ss, %es */                        \
  108         mov     $S32DATA, %eax;                                 \
  109         mov     %ax, %ds;                                       \
  110         mov     %ax, %ss;                                       \
  111         mov     %ax, %es;                                       \
  112                                                                 \
  113         gidt_debug4;                                            \
  114                                                                 \
  115         /* load idtr for debugger and DOS/BIOS iface */         \
  116         lidt    Idtr;
  117 
  118 
  119         .globl  _C_LABEL(BIOS_regs)
  120 
  121         .text
  122         .code32
  123         .globl  _ASM_LABEL(pmm_init)
  124         .globl  _C_LABEL(_rtt)
  125 
  126 ENTRY(_rtt)
  127 #ifdef GIDT_DEBUG
  128         movl    $0xb8000, %ebx
  129         movl    $0x4f514f51, (%ebx)
  130 #endif
  131         movw    $0x1234, %ax
  132         movw    %ax, 0x472      /* warm boot */
  133 
  134         /* Try to use the KBD to reboot system */
  135         movb    $0xfe, %al
  136         outb    %al, $0x64
  137 
  138         movl    $0x5000, %ecx
  139 1:      inb     $0x84, %al
  140         loop    1b
  141 
  142         movb    $0xfe, %al
  143         outb    %al, $0x64
  144 
  145 #ifdef GIDT_DEBUG
  146         movl    $0xb8000, %ebx
  147         movl    $0x07310731, (%ebx)
  148 #endif
  149 
  150         /* Try to cause a triple fault... */
  151         lidt    Idtr_reset
  152         xorl    %eax, %eax
  153         divl    %eax, %eax
  154 
  155         /* Again... */
  156         int $0x8
  157 
  158         /* Again... */
  159         movl    $0, %esp        /* segment violation */
  160         ret
  161 
  162         .align  8, 0x90
  163 pmm_init:
  164         /* load idtr for interrupts */
  165         lidt    Idtr
  166         ret
  167 
  168 
  169 #ifdef __STDC__
  170 #define IPROC(n)        X##n
  171 #define IEMU(n)         IPROC(emu##n)
  172 #else
  173 #define IPROC(n)        X/**/n
  174 #define IEMU(n)         IPROC(emu/**/n)
  175 #endif
  176         .align 8, 0x90
  177 idt:
  178 #define idte(e) \
  179         .short  IPROC(e); .short (S32TEXT); \
  180         .short  ((0x80|SDT_SYS386TGT) << 8); .short (LINKADDR >> 16)
  181 /* internal (0-31) */
  182         idte(de); idte(db); idte(nmi); idte(bp); idte(of); idte(br)
  183         idte(ud); idte(nm); idte(df);  idte(fo); idte(ts); idte(np)
  184         idte(ss); idte(gp); idte(pf);  idte(xx); idte(mf); idte(ac)
  185         idte(mc)
  186         idte(xx); idte(xx); idte(xx);  idte(xx); idte(xx); idte(xx)
  187         idte(xx); idte(xx); idte(xx);  idte(xx); idte(xx); idte(xx)
  188         idte(xx) 
  189                 /* Maskable interrupts (32-255) */
  190                 /* BIOS entry points (32-63) */
  191                 /* DOS entry points (64-80) */
  192 #ifdef __STDC__
  193 #define idtb(b) idte(emu##b)
  194 #else
  195 #define idtb(b) idte(emu/**/b)
  196 #endif
  197         idtb(0);  idtb(1);  idtb(2);  idtb(3);  idtb(4);  idtb(5)
  198         idtb(6);  idtb(7);  idtb(8);  idtb(9);  idtb(10); idtb(11)
  199         idtb(12); idtb(13); idtb(14); idtb(15); idtb(16); idtb(17)
  200         idtb(18); idtb(19); idtb(20); idtb(21); idtb(22); idtb(23)
  201         idtb(24); idtb(25); idtb(26); idtb(27); idtb(28); idtb(29)
  202         idtb(30); idtb(31); idtb(32); idtb(33); idtb(34); idtb(35)
  203         idtb(36); idtb(37); idtb(38); idtb(39); idtb(40); idtb(41)
  204         idtb(42); idtb(43); idtb(44); idtb(45); idtb(46); idtb(47)
  205 #undef idte
  206         .globl  Idtr
  207 Idtr:   .word   . - idt - 1
  208         .long   idt
  209         .word   0
  210 
  211         .align  8
  212         .globl  Idtr_real
  213 Idtr_real:      .word   1023
  214                 .long   0
  215                 .word   0
  216 
  217         .align  8
  218 Idtr_reset:     .long   0, 0
  219 
  220         .align  8
  221 gdt:
  222                 /* 0x00 : null */
  223         .space  8
  224                 /* 0x08 : flat code */
  225         .word   0xFFFF                  # lolimit
  226         .word   0                       # lobase
  227         .byte   0                       # midbase
  228         .byte   SDT_MEMERAC | 0 | 0x80  # RXAC, dpl = 0, present
  229         .byte   0xf | 0 | 0x40 | 0x80   # hilimit, xx, 32bit, 4k granularity
  230         .byte   0                       # hibase
  231                 /* 0x10 : flat data */
  232         .word   0xFFFF                  # lolimit
  233         .word   0                       # lobase
  234         .byte   0                       # midbase
  235         .byte   SDT_MEMRWA | 0 | 0x80   # RWA, dpl = 0, present
  236         .byte   0xf | 0 | 0x40 | 0x80   # hilimit, xx, 32bit, 4k granularity
  237         .byte   0                       # hibase
  238                 /* 0x18 : 16 bit code */
  239         .word   0xFFFF                  # lolimit
  240         .word   (LINKADDR & 0xffff)     # lobase
  241         .byte   (LINKADDR >> 16) & 0xff # midbase
  242         .byte   SDT_MEMERAC | 0 | 0x80  # RXAC, dpl = 0, present
  243         .byte   0x0 | 0 | 0 | 0         # hilimit, xx, 16bit, byte granularity
  244         .byte   (LINKADDR >> 20) & 0xff # hibase
  245                 /* 0x20 : 16 bit data */
  246         .word   0xFFFF                  # lolimit
  247         .word   (LINKADDR & 0xffff)     # lobase
  248         .byte   (LINKADDR >> 16) & 0xff # midbase
  249         .byte   SDT_MEMRWA | 0 | 0x80   # RWA, dpl = 0, present
  250         .byte   0x0 | 0 | 0 | 0         # hilimit, xx, 16bit, byte granularity
  251         .byte   (LINKADDR >> 20) & 0xff # hibase
  252 
  253 .globl Gdtr
  254 Gdtr:   .word   . - gdt - 1
  255         .long   gdt
  256         .word   0
  257 
  258 #define IENTRY(name,type) \
  259 IPROC(name): \
  260         pushl   $type ; \
  261         jmp     1f
  262 #define IENTRY_ERR(name,err,type) \
  263 IPROC(name): \
  264         pushl   $err ; \
  265         pushl   $type ; \
  266         jmp     1f
  267 
  268 IPROC(xx):
  269         pushl   $1
  270         pushl   $T_RESERVED
  271         jmp     1f
  272 
  273 IENTRY_ERR(de,0,T_DIVIDE)       /* #DE divide by zero */
  274 IENTRY_ERR(db,0,T_TRCTRAP)      /* #DB debug */
  275 IENTRY_ERR(nmi,0,T_NMI)         /* NMI */
  276 IENTRY_ERR(bp,0,T_BPTFLT)       /* #BP breakpoint */
  277 IENTRY_ERR(of,0,T_OFLOW)        /* #OF overflow */
  278 IENTRY_ERR(br,0,T_BOUND)        /* #BR BOUND range exceeded */
  279 IENTRY_ERR(ud,0,T_PRIVINFLT)    /* #UD invalid opcode */
  280 IENTRY_ERR(nm,0,T_DNA)          /* #NM device not available */
  281 IENTRY(df,T_DOUBLEFLT)          /* #DF double fault */
  282 IENTRY_ERR(fo,0,T_FPOPFLT)      /* #FO coprocessor segment overrun */
  283 IENTRY(ts,T_TSSFLT)             /* #TS invalid TSS */
  284 IENTRY(np,T_SEGNPFLT)           /* #NP segment not present */
  285 IENTRY(ss,T_STKFLT)             /* #SS stack fault */
  286 IENTRY(gp,T_PROTFLT)            /* #GP general protection */
  287 IENTRY(pf,T_PAGEFLT)            /* #PF page fault */
  288 IENTRY_ERR(mf,0,T_ARITHTRAP)    /* #MF floating point error */
  289 IENTRY(ac,T_ALIGNFLT)           /* #AC alignment check */
  290 IENTRY(mc,T_MACHK)              /* #MC machine check */
  291 
  292         .globl  alltraps
  293 1:      /* save on jumps */
  294         jmp     alltraps
  295 
  296 #define IEMUENT(n)      IEMU(n): pushl $n; jmp 1f
  297 
  298 IEMUENT(0);  IEMUENT(1);  IEMUENT(2);  IEMUENT(3)
  299 IEMUENT(4);  IEMUENT(5);  IEMUENT(6);  IEMUENT(7)
  300 IEMUENT(8);  IEMUENT(9);  IEMUENT(10); IEMUENT(11)
  301 IEMUENT(12); IEMUENT(13); IEMUENT(14); IEMUENT(15)
  302 IEMUENT(16); IEMUENT(17); IEMUENT(18); IEMUENT(19)
  303 IEMUENT(20); IEMUENT(21); IEMUENT(22); IEMUENT(23)
  304 IEMUENT(24); IEMUENT(25); IEMUENT(26); IEMUENT(27)
  305 IEMUENT(28); IEMUENT(29); IEMUENT(30); IEMUENT(31)
  306 1:      jmp     EMUh    /* redirect for short jumps */
  307 IEMUENT(32); IEMUENT(33); IEMUENT(34); IEMUENT(35)
  308 IEMUENT(36); IEMUENT(37); IEMUENT(38); IEMUENT(39)
  309 IEMUENT(40); IEMUENT(41); IEMUENT(42); IEMUENT(43)
  310 IEMUENT(44); IEMUENT(45); IEMUENT(46); IEMUENT(47)
  311 1:      jmp     EMUh
  312 
  313 /*
  314  * entry point for BIOS real-mode interface
  315  * all the magic for real-prot mode switching is here
  316  *
  317  * Call:        %eax, %ecx, %edx, %ebx, %ebp, %esi, %edi, %es, %ds
  318  * Return:      %eax, %edx, %ecx, %eflags (as returned from BIOS)
  319  *
  320  */
  321         .globl  EMUh
  322         .align  8, 0x90
  323 EMUh:
  324         /* save %eax */
  325         mov     %eax, 3f
  326         pop     %eax
  327 
  328         pusha
  329         push    %ds
  330         push    %es
  331         push    %fs
  332         push    %gs
  333 
  334         /* save BIOS int vector */
  335         mov     %al, intno
  336 
  337         prot2real
  338 
  339         push    %ds
  340 
  341         addr32  movw (_C_LABEL(BIOS_regs)+(BIOSR_ES) - LINKADDR), %ax
  342         movw    %ax, %es
  343         addr32  movw (_C_LABEL(BIOS_regs)+(BIOSR_DS) - LINKADDR), %ax
  344         movw    %ax, %ds
  345 
  346         # data32 movl $Leax, %eax
  347         .byte   0x66, 0xb8
  348 3:      .long   0x90909090
  349 
  350         ;sti
  351         int     $0
  352 intno   = . - 1
  353         ;cli
  354 
  355         pop     %ds
  356 
  357         addr32 movl %ebx, (_C_LABEL(BIOS_regs)+(BIOSR_BX) - LINKADDR)
  358         movw    %es, %bx
  359         addr32 movw %bx, (_C_LABEL(BIOS_regs)+(BIOSR_ES) - LINKADDR)
  360         movb    %ah, %bh
  361         lahf
  362         xchgb   %ah, %bh
  363 
  364         addr32 movl %eax, (2f - LINKADDR)
  365 
  366         real2prot
  367 
  368         # movl $Leax, %eax
  369         .byte 0xb8
  370 2:      .long 0x90909090
  371 
  372         /* pass BIOS return values back to caller */
  373         movl    %eax, 0xb*4(%esp)
  374         movl    %ecx, 0xa*4(%esp)
  375         movl    %edx, 0x9*4(%esp)
  376         movb    %bh , 0xe*4(%esp)
  377 
  378         /* clear NT flag in eflags */
  379         /* Martin Fredriksson <martin@gbg.netman.se> */
  380         pushf
  381         pop     %eax
  382         and     $0xffffbfff, %eax
  383         push    %eax
  384         popf
  385 
  386         /* save registers into save area */
  387         movl    %eax, _C_LABEL(BIOS_regs)+BIOSR_AX
  388         movl    %ecx, _C_LABEL(BIOS_regs)+BIOSR_CX
  389         movl    %edx, _C_LABEL(BIOS_regs)+BIOSR_DX
  390         movl    %ebp, _C_LABEL(BIOS_regs)+BIOSR_BP
  391         movl    %esi, _C_LABEL(BIOS_regs)+BIOSR_SI
  392         movl    %edi, _C_LABEL(BIOS_regs)+BIOSR_DI
  393 
  394         pop     %gs
  395         pop     %fs
  396         pop     %es
  397         pop     %ds
  398         popa
  399         iret
  400 
  401 /* Call buffer at 07c0:0000 in real mode to simulate a BIOS boot */
  402 ENTRY(bootbuf)
  403         pop     %eax            /* Don't need return address */
  404         pop     %esi            /* Buffer */
  405         pop     %edx            /* Device */
  406         prot2real               /* Switch */
  407 
  408         /* Set up stack */
  409         cli
  410         xor     %ax, %ax
  411         mov     %ax, %ss
  412         mov     $0xfffc, %esp
  413         sti
  414 
  415         /* Jump to buffer */
  416         ljmp $0x0, $0x7c00
  417 
  418         .end

/* [<][>][^][v][top][bottom][index][help] */