ZNFS - ZeX/OS Network Filesystem added; virtual block device support added; added...
[ZeXOS.git] / kernel / arch / i386 / int.asm
blobbac21fbeb2b4770ae11efff28bcd0d5ff9b9af63
1 ; ZeX/OS
2 ; Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
4 ; This program is free software: you can redistribute it and/or modify
5 ; it under the terms of the GNU General Public License as published by
6 ; the Free Software Foundation, either version 3 of the License, or
7 ; (at your option) any later version.
9 ; This program is distributed in the hope that it will be useful,
10 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 ; GNU General Public License for more details.
14 ; You should have received a copy of the GNU General Public License
15 ; along with this program. If not, see <http://www.gnu.org/licenses/>.
18 %macro IMP 1
19 %ifdef UNDERBARS
20 EXTERN _%1
21 %define %1 _%1
22 %else
23 EXTERN %1
24 %endif
25 %endmacro
27 %macro EXP 1
28 GLOBAL $_%1
29 $_%1:
30 GLOBAL $%1
31 $%1:
32 %endmacro
34 ; IMPORTS
35 ; from KRNL.LD
36 IMP bss
37 IMP end
39 ; from MAIN.C
40 IMP g_curr_thread
41 IMP fault
42 IMP main
44 [BITS 32]
45 SECTION .text
46 ; This will set up our new segment registers. We need to do
47 ; something special in order to set CS. We do what is called a
48 ; far jump. A jump that includes a segment as well as an offset.
49 ; This is declared in C as 'extern void gdt_flush();'
51 EXP gdt_flush
52 IMP gp ; Says that '_gp' is in another file
53 ;_gdt_flush:
54 lgdt [gp] ; Load the GDT with our '_gp' which is a special pointer
55 mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment
56 mov ds, ax
57 mov es, ax
58 mov fs, ax
59 mov gs, ax
60 jmp 0x08:flush2 ; 0x08 is the offset to our code segment: Far jump!
61 flush2:
62 ret ; Returns back to the C code!
64 EXP gdt_smp
65 IMP gp
66 lgdt [gp] ; Load the GDT with our '_gp' which is a special pointer
67 jmp 0x08:ccode ; 0x08 is the offset to our code segment: Far jump!
68 ccode:
69 ret
72 ; Loads the IDT defined in '_idtp' into the processor.
73 ; This is declared in C as 'extern void idt_load();'
74 EXP idt_load
75 IMP idtp
76 lidt [idtp]
77 ret
79 ; 0: Divide By Zero Exception
80 EXP isr0
81 cli
82 push byte 0
83 push byte 0
84 jmp isr_common_stub
86 ; 1: Debug Exception
87 EXP isr1
88 cli
89 push byte 0
90 push byte 1
91 jmp isr_common_stub
93 ; 2: Non Maskable Interrupt Exception
94 EXP isr2
95 cli
96 push byte 0
97 push byte 2
98 jmp isr_common_stub
100 ; 3: Int 3 Exception
101 EXP isr3
103 push byte 0
104 push byte 3
105 jmp isr_common_stub
107 ; 4: INTO Exception
108 EXP isr4
110 push byte 0
111 push byte 4
112 jmp isr_common_stub
114 ; 5: Out of Bounds Exception
115 EXP isr5
117 push byte 0
118 push byte 5
119 jmp isr_common_stub
121 ; 6: Invalid Opcode Exception
122 EXP isr6
123 cli
124 push byte 0
125 push byte 6
126 jmp isr_common_stub
128 ; 7: Coprocessor Not Available Exception
129 EXP isr7
131 push byte 0
132 push byte 7
133 jmp isr_common_stub
135 ; 8: Double Fault Exception (With Error Code!)
136 EXP isr8
138 push byte 8
139 jmp isr_common_stub
141 ; 9: Coprocessor Segment Overrun Exception
142 EXP isr9
144 push byte 0
145 push byte 9
146 jmp isr_common_stub
148 ; 10: Bad TSS Exception (With Error Code!)
149 EXP isr10
151 push byte 10
152 jmp isr_common_stub
154 ; 11: Segment Not Present Exception (With Error Code!)
155 EXP isr11
157 push byte 11
158 jmp isr_common_stub
160 ; 12: Stack Fault Exception (With Error Code!)
161 EXP isr12
163 push byte 12
164 jmp isr_common_stub
166 ; 13: General Protection Fault Exception (With Error Code!)
167 EXP isr13
169 push byte 13
170 jmp isr_common_stub
172 ; 14: Page Fault Exception (With Error Code!)
173 EXP isr14
175 push byte 14
176 jmp isr_common_stub
178 ; 15: Reserved Exception
179 EXP isr15
181 push byte 0
182 push byte 15
183 jmp isr_common_stub
185 ; 16: Floating Point Exception
186 EXP isr16
188 push byte 0
189 push byte 16
190 jmp isr_common_stub
192 ; 17: Alignment Check Exception
193 EXP isr17
195 push byte 0
196 push byte 17
197 jmp isr_common_stub
199 ; 18: Machine Check Exception
200 EXP isr18
202 push byte 0
203 push byte 18
204 jmp isr_common_stub
206 ; 19: Reserved
207 EXP isr19
209 push byte 0
210 push byte 19
211 jmp isr_common_stub
213 ; 20: Reserved
214 EXP isr20
216 push byte 0
217 push byte 20
218 jmp isr_common_stub
220 ; 21: Reserved
221 EXP isr21
223 push byte 0
224 push byte 21
225 jmp isr_common_stub
227 ; 22: Reserved
228 EXP isr22
230 push byte 0
231 push byte 22
232 jmp isr_common_stub
234 ; 23: Reserved
235 EXP isr23
237 push byte 0
238 push byte 23
239 jmp isr_common_stub
241 ; 24: Reserved
242 EXP isr24
244 push byte 0
245 push byte 24
246 jmp isr_common_stub
248 ; 25: Reserved
249 EXP isr25
251 push byte 0
252 push byte 25
253 jmp isr_common_stub
255 ; 26: Reserved
256 EXP isr26
258 push byte 0
259 push byte 26
260 jmp isr_common_stub
262 ; 27: Reserved
263 EXP isr27
265 push byte 0
266 push byte 27
267 jmp isr_common_stub
269 ; 28: Reserved
270 EXP isr28
272 push byte 0
273 push byte 28
274 jmp isr_common_stub
276 ; 29: Reserved
277 EXP isr29
279 push byte 0
280 push byte 29
281 jmp isr_common_stub
283 ; 30: Reserved
284 EXP isr30
286 push byte 0
287 push byte 30
288 jmp isr_common_stub
290 ; 31: Reserved
291 EXP isr31
293 push byte 0
294 push byte 31
295 jmp isr_common_stub
298 ; We call a C function in here. We need to let the assembler know
299 ; that '_fault_handler' exists in another file
302 ; This is our common ISR stub. It saves the processor state, sets
303 ; up for kernel mode segments, calls the C-level fault handler,
304 ; and finally restores the stack frame.
305 isr_common_stub:
306 IMP fault_handler
307 pusha
308 push ds
309 push es
310 push fs
311 push gs
312 mov ax, 0x10
313 mov ds, ax
314 mov es, ax
315 mov fs, ax
316 mov gs, ax
317 mov eax, esp
318 push eax
319 mov eax, fault_handler
320 call eax
321 pop eax
322 pop gs
323 pop fs
324 pop es
325 pop ds
326 popa
327 add esp, 8
328 iret
330 ;global _irq0
331 ;global _irq1
332 ;global _irq2
333 ;global _irq3
334 ;global _irq4
335 ;global _irq5
336 ;global _irq6
337 ;global _irq7
338 ;global _irq8
339 ;global _irq9
340 ;global _irq10
341 ;global _irq11
342 ;global _irq12
343 ;global _irq13
344 ;global _irq14
345 ;global _irq15
347 ; 32: IRQ0
348 EXP irq0
350 push byte 0
351 push byte 32
352 jmp irq_common_stub
354 ; 33: IRQ1
355 EXP irq1
357 push byte 0
358 push byte 33
359 jmp irq_common_stub
361 ; 34: IRQ2
362 EXP irq2
364 push byte 0
365 push byte 34
366 jmp irq_common_stub
368 ; 35: IRQ3
369 EXP irq3
371 push byte 0
372 push byte 35
373 jmp irq_common_stub
375 ; 36: IRQ4
376 EXP irq4
378 push byte 0
379 push byte 36
380 jmp irq_common_stub
382 ; 37: IRQ5
383 EXP irq5
385 push byte 0
386 push byte 37
387 jmp irq_common_stub
389 ; 38: IRQ6
390 EXP irq6
392 push byte 0
393 push byte 38
394 jmp irq_common_stub
396 ; 39: IRQ7
397 EXP irq7
399 push byte 0
400 push byte 39
401 jmp irq_common_stub
403 ; 40: IRQ8
404 EXP irq8
406 push byte 0
407 push byte 40
408 jmp irq_common_stub
410 ; 41: IRQ9
411 EXP irq9
413 push byte 0
414 push byte 41
415 jmp irq_common_stub
417 ; 42: IRQ10
418 EXP irq10
420 push byte 0
421 push byte 42
422 jmp irq_common_stub
424 ; 43: IRQ11
425 EXP irq11
427 push byte 0
428 push byte 43
429 jmp irq_common_stub
431 ; 44: IRQ12
432 EXP irq12
434 push byte 0
435 push byte 44
436 jmp irq_common_stub
438 ; 45: IRQ13
439 EXP irq13
441 push byte 0
442 push byte 45
443 jmp irq_common_stub
445 ; 46: IRQ14
446 EXP irq14
448 push byte 0
449 push byte 46
450 jmp irq_common_stub
452 ; 47: IRQ15
453 EXP irq15
455 push byte 0
456 push byte 47
457 jmp irq_common_stub
459 IMP irq_handler
461 irq_common_stub:
462 pusha
463 push ds
464 push es
465 push fs
466 push gs
468 mov ax, 0x10
469 mov ds, ax
470 mov es, ax
471 mov fs, ax
472 mov gs, ax
473 mov eax, esp
475 push eax
476 mov eax, irq_handler
477 call eax
478 pop eax
480 pop gs
481 pop fs
482 pop es
483 pop ds
484 popa
485 add esp, 8
486 iret
488 ;extern testf
489 ;global testf_c
491 ;testf_c:
492 ; mov ecx, testf
493 ; jmp syscall0
495 ; syscall with 0 args
497 ;IMP syscall_handler
498 ;EXP system_call
499 ; push ds ; switch to kernel space
500 ; push es
501 ; mov eax, 0x10
502 ; mov ds, eax
503 ; mov es, eax
505 ; call syscall_handler ; make call
507 ; pop es ; back to userland
508 ; pop ds
509 ; retf 0
510 ; iret
512 IMP syscall_handler
513 EXP system_call
514 pusha
515 push ds
516 push es
517 push fs
518 push gs
520 mov ax, 0x10
521 mov ds, ax
522 mov es, ax
523 mov fs, ax
524 mov gs, ax
526 ; mov eax, esp
528 ; push edx
529 ; push ecx
530 ; push ebx
531 push esp
533 call syscall_handler ; make call
535 add esp, 4
536 ; pop eax
537 ; pop ebx
538 ; pop ecx
539 ; pop edx
541 pop gs
542 pop fs
543 pop es
544 pop ds
546 popa
548 iret
551 ;IMP syscall_handler
552 ;EXP system_call
553 ; pusha
554 ; push ds
555 ; push es
556 ; push fs
557 ; push gs
558 ; push edx
559 ; push ecx
560 ; push ebx
562 ; mov ax, 0x10
563 ; mov ds, ax
564 ; mov es, ax
565 ; mov fs, ax
566 ; mov gs, ax
567 ; mov eax, esp
569 ; push eax
570 ; mov eax, syscall_handler
571 ; call eax
573 ; pop eax
574 ; pop ebx
575 ; pop ecx
576 ; pop edx
577 ; pop gs
578 ; pop fs
579 ; pop es
580 ; pop ds
581 ; popa
582 ;add esp, 8
583 ; iret
585 EXP prot_to_real
586 IMP gp
587 pmode32: mov ax,[gp] ; now we are in protected mode
588 mov ds,ax ; set all selector limits to 4 GB
589 mov es,ax
590 mov fs,ax
591 mov gs,ax
593 mov eax,cr0 ; restore real mode
594 and al,0feh
595 mov cr0,eax
597 ;db 0eah ; far jump to rmode label
598 ;dw offset rmode
599 ;dw Code
600 ;jmp far [rmode_ip]
605 ;rmode: clc ; now we are back in real mode, zero carry
606 ; sti ; to indicate ok and enable interrupts
608 ;leave4gb:
609 ; ret
611 ;rmode_ip:
612 ; dw rmode
613 ;rmode_cs:
614 ; dw 0
616 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
617 ; return to real mode procedure, modified from section 14.5 of 386INTEL.TXT
618 ; (...continued from below...)
619 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
621 ; 4. load SS with selector to descriptor that is "appropriate for real mode":
622 ; Limit = 64K (FFFFh) Byte-granular (G=0)
623 ; Expand-up (E=0) Writable (W=1)
624 ; Present (P=1) Base address = any value
625 ; You may leave the other data segment registers with limits >64K if you
626 ; want 'unreal mode', otherwise load them with a similar selector.
628 pmode16:
629 mov ax,_16BIT_DATA_SEL
630 mov ss,ax
631 mov ds,ax
632 mov es,ax
633 mov fs,ax
634 mov gs,ax
636 ; 5. Clear the PE bit in register CR0
637 mov eax,cr0
638 and al,0FEh
639 mov cr0,eax
641 ; 6. Jump to a 16:16 real-mode far address
642 jmp far [_real_ip]
643 real:
645 ; 7. Load all other segment registers (SS, DS, ES, FS, GS)
646 mov ax,cs
647 mov ss,ax
648 mov ds,ax
649 mov es,ax
650 mov fs,ax
651 mov gs,ax
653 ; 8. Use the LIDT instruction to load an IDT appropriate for real mode,
654 ; with base address = 0 and limit = 3FFh. Use the 32-bit operand size
655 ; override prefix so all 32 bits of the IDT base are set (otherwise,
656 ; only the bottom 24 bits will be set).
657 o32 lidt [_real_idt]
659 ; 9. Zero the high 16 bits of 32-bit registers. If the register value is
660 ; not important, just zero the entire 32-bit register, otherwise use 'movzx'
661 xor eax,eax
662 xor ebx,ebx
663 xor ecx,ecx
664 xor edx,edx
665 xor esi,esi
666 xor edi,edi
667 movzx ebp,bp
668 movzx esp,sp
670 ; 10. Enable interrupts
672 jmp $
674 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
675 ; pmode
676 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
678 ALIGN 512 ; so NDISASM knows where the 32-bit code starts
680 BITS 32
681 GLOBAL pmode ; so "objdump --source ..." can find it
682 pmode:
683 mov ax,KRNL_DATA_SEL
684 mov ds,ax
685 mov ss,ax
686 mov es,ax
687 mov fs,ax
688 mov gs,ax
690 ; LTR is illegal in real mode, so do it now
691 mov ax,TSS_SEL
692 ltr ax
694 ; zero the kernel BSS
695 xor eax,eax
696 mov edi,bss ; BSS starts here
697 mov ecx,end
698 sub ecx,edi ; BSS size is (g_end - g_bss) bytes
700 rep stosb
702 ; call C code
703 call main
705 ; return to real mode procedure, modified from section 14.5 of 386INTEL.TXT
706 ; 1. Disable interrupts (already done)
707 ; 2. If paging is enabled... (it isn't)
708 ; 3. Jump to a segment with limit 64K-1. CS must have this limit
709 ; before you return to real mode.
711 jmp _16BIT_CODE_SEL:pmode16
714 EXP start_v86
716 ; save registers used by C: EBP, EBX, ESI, EDI
717 ; Actually, just use PUSHA to save them all
718 pusha
720 ; copy V86 mode registers to top of stack
721 sub esp,92
722 mov esi,[esp + 128] ; (uregs_t *regs)
723 mov edi,esp
724 mov ecx,92 ; sizeof(uregs_t)
726 rep movsb
727 jmp short to_user
729 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
730 ; name: all_ints
731 ; action: unified IRQ/interrupt/exception handler
732 ; in: IRET frame, error code, and exception number
733 ; all pushed on stack
734 ; out: (nothing)
735 ; modifies: (nothing)
736 ; notes: prototype for C-language interrupt handler:
737 ; int fault(uregs_t *regs);
739 ; *** WARNING: The order in which registers are pushed and popped here
740 ; must agree with the layout of the uregs_t structure in the C code.
741 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
743 all_ints:
744 push gs ; push segment registers
745 push fs
746 push ds
747 push es
748 pusha ; push EDI...EAX (7 regs; 8 dwords)
749 mov ax,KRNL_DATA_SEL
750 mov ds,eax ; put known-good values in segment registers
751 mov es,eax
752 mov fs,eax
753 mov gs,eax
754 push esp ; push pointer to stacked registers
755 call fault
756 add esp,4
757 or eax,eax
758 jne end_v86
760 ; *** FALL-THROUGH to to_user ***
762 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
763 ; name: to_user
764 ; action: kernel exit code
765 ; in: uregs_t frame on kernel stack
766 ; out: (nothing)
767 ; modifies: (nothing)
768 ; notes:
769 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
771 to_user:
773 ; IRET to Ring 3 pmode will pop these values
774 ; 8 GP regs, 4 seg regs, int_num/err_code, EIP/CS/EFLAGS/ESP/SS
775 ; making the kernel stack 76 bytes smaller
776 lea eax,[esp + 76]
777 ; IRET to V86 mode...
778 ;test dword [esp + 64],20000h ; test VM bit in stacked EFLAGS
779 test byte [esp + 66],2
780 je set_tss_esp0
782 ; ...will pop these values
783 ; 8 GP regs, 4 seg regs, int_num/err_code, EIP/CS/EFLAGS/ESP/SS/ES/DS/FS/GS
784 ; making the kernel stack 92 bytes smaller
785 lea eax,[esp + 92]
787 ; For IRET to Ring 0 pmode, _tss_esp0 is not used,
788 ; so this value doesn't matter
789 set_tss_esp0:
790 mov [_tss_esp0],eax
792 popa ; pop EAX...EDI (7 regs; 8 dwords)
793 pop es ; pop segment registers
794 pop ds
795 pop fs
796 pop gs
798 add esp,byte 8 ; drop int_num and err_code
800 iret ; pop EIP...GS (9 regs)
802 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
803 ; name: end_v86
804 ; action: cleans up after virtual 8086 mode session;
805 ; returns to pmode kernel
806 ; in: (see start_v86, above)
807 ; out: registers in uregs_t may be modified
808 ; modifies: registers in uregs_t may be modified
809 ; notes:
810 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
812 end_v86:
814 ; get modified V86 mode registers
815 mov esi,esp
816 mov edi,[esp + 128]
817 mov ecx,92
819 rep movsb
821 ; remove V86 registers from stack
822 add esp,92
824 ; restore C registers and return to pmode kernel
825 popa
830 ; We need it for halt pc
831 EXP halt
836 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
837 ; data
838 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
840 SECTION .data
842 _cpu_msg:
843 db "32-bit CPU required", 10, 13, 0
845 _v86_msg:
846 db "CPU already in Virtual-8086 mode "
847 db "(Windows DOS box or EMM386 loaded?)"
848 db 10, 13, 0
850 _real_idt:
851 dw 1023
852 dd 0
853 _dos:
854 db 0
856 ; 16:16 far address for return to real mode. Don't change the order
857 ; of '_real_ip' and '_real_cs', and don't put anything between them,
858 ; because these two values are the operand of a far JMP
859 _real_ip:
860 ;dw real
861 _real_cs:
862 dw 0
864 EXP g_kvirt_to_phys
865 dd 0
867 ;;;;;;;;;;;;;
868 ;;;; TSS ;;;;
869 ;;;;;;;;;;;;;
871 ALIGN 4
873 ; most of the TSS is unused
874 ; I need only ESP0, SS0, and the I/O permission bitmap
875 _tss:
876 dw 0, 0 ; back link
877 _tss_esp0:
878 dd 0 ; ESP0
879 dw KRNL_DATA_SEL, 0 ; SS0, reserved
881 dd 0 ; ESP1
882 dw 0, 0 ; SS1, reserved
884 dd 0 ; ESP2
885 dw 0, 0 ; SS2, reserved
887 dd 0 ; CR3
888 dd 0, 0 ; EIP, EFLAGS
889 dd 0, 0, 0, 0 ; EAX, ECX, EDX, EBX
890 dd 0, 0, 0, 0 ; ESP, EBP, ESI, EDI
891 dw 0, 0 ; ES, reserved
892 dw 0, 0 ; CS, reserved
893 dw 0, 0 ; SS, reserved
894 dw 0, 0 ; DS, reserved
895 dw 0, 0 ; FS, reserved
896 dw 0, 0 ; GS, reserved
897 dw 0, 0 ; LDT, reserved
898 dw 0, g_tss_iopb - _tss ; debug, IO permission bitmap base
899 EXP g_tss_iopb
901 ; no I/O permitted
902 times 8192 db 0FFh
904 ; The TSS notes in section 12.5.2 of volume 1 of
905 ; "IA-32 Intel Architecture Software Developer's Manual"
906 ; are confusing as hell. I think they mean simply that the IOPB
907 ; must contain an even number of bytes; so pad here if necessary.
908 ;dw 0FFFFh
909 EXP g_tss_end
911 ;;;;;;;;;;;;;
912 ;;;; GDT ;;;;
913 ;;;;;;;;;;;;;
915 _gdt:
916 dd 0
917 dd 0
919 TSS_SEL EQU ($ - _gdt)
920 _gdt_tss:
921 dw g_tss_end - _tss - 1
922 dw 0
923 db 0
924 db 89h ; ring 0 available 32-bit TSS
925 db 0
926 db 0
928 KRNL_DATA_SEL EQU ($ - _gdt)
929 _gdt_krnl_ds:
930 dw 0FFFFh
931 dw 0 ; base; gets set above
932 db 0
933 db 92h ; present, ring 0, data, expand-up, writable
934 db 0CFh
935 db 0
937 KRNL_CODE_SEL EQU ($ - _gdt)
938 _gdt_krnl_cs:
939 dw 0FFFFh
940 dw 0 ; base; gets set above
941 db 0
942 db 9Ah ; present, ring 0, code, non-conforming, readable
943 db 0CFh ; 32-bit
944 db 0
946 USER_DATA_SEL EQU (($ - _gdt) | 3) ; RPL=3 (ring 3)
947 _gdt_user_ds:
948 dw 0FFFFh
949 dw 0 ; base
950 db 0
951 db 0F2h ; present, ring 3, data, expand-up, writable
952 db 0CFh
953 db 0
955 USER_CODE_SEL EQU (($ - _gdt) | 3)
956 _gdt_user_cs:
957 dw 0FFFFh
958 dw 0 ; base; gets set above
959 db 0
960 db 0FAh ; present, ring 3, code, non-conforming, readable
961 db 0CFh ; 32-bit
962 db 0
964 LINEAR_DATA_SEL EQU ($ - _gdt)
965 dw 0FFFFh
966 dw 0
967 db 0
968 db 92h ; present, ring 0, data, expand-up, writable
969 db 0CFh
970 db 0
972 LINEAR_CODE_SEL EQU ($ - _gdt)
973 dw 0FFFFh
974 dw 0
975 db 0
976 db 9Ah ; present, ring 0, code, non-conforming, readable
977 db 0CFh
978 db 0
980 _16BIT_DATA_SEL EQU ($ - _gdt)
981 _gdt_16bit_ds:
982 dw 0FFFFh
983 dw 0 ; base; gets set above
984 db 0
985 db 92h ; present, ring 0, data, expand-up, writable
986 db 0
987 db 0
989 _16BIT_CODE_SEL EQU ($ - _gdt)
990 _gdt_16bit_cs:
991 dw 0FFFFh
992 dw 0 ; base; gets set above
993 db 0
994 db 9Ah ; present, ring 0, code, non-conforming, readable
995 db 0 ; 16-bit
996 db 0
997 _gdt_end:
999 _gdt_ptr:
1000 dw _gdt_end - _gdt - 1 ; GDT limit
1001 dd _gdt ; linear adr of GDT; gets set above
1003 ;;;;;;;;;;;;;
1004 ;;;; IDT ;;;;
1005 ;;;;;;;;;;;;;
1007 _idt:
1008 ; 48 ring 0 interrupt gates
1009 times 48 dw 0, KRNL_CODE_SEL, 8E00h, 0
1011 ; one ring 3 interrupt gate for syscalls (INT 30h)
1012 dw 0 ; offset 15:0
1013 dw KRNL_CODE_SEL ; selector
1014 db 0 ; (always 0 for interrupt gates)
1015 db 0EEh ; present, ring 3, '386 interrupt gate
1016 dw 0 ; offset 31:16
1017 _idt_end:
1019 _idt_ptr:
1020 dw _idt_end - _idt - 1 ; IDT limit
1021 dd _idt ; linear, physical address of IDT (patched)