Annotation of sys/arch/i386/stand/libsa/gidt.S, Revision 1.1.1.1
1.1 nbrk 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
CVSweb