其实在开学之前已经实现了简单的进程调度,实现了4个进程轮转。 不过一旦把进程栈调大,进程调度会不稳定,一直找不出原因,再加上代码文件弄的很乱,干脆重写一遍。
回到学校后就转用ubuntu做开发环境了。
目前的代码还是参考了《自》和部分minix的代码,不过《自》中引用的minix代码和《设计与实现》书中的代码不一样,尚不清楚是不是书的版本问题。我的内核实现上有部分细节与参考的代码略有不同,有些地方做了一下省略。目标只是做一个内核的雏形出来。
像minix一样,先贴出几个比较重要的全局头文件。
const.h
1
#ifndef _CONST_H
2 #define _CONST_H
3
4 #define PRIVILEGE_KERNEL (0)
5 #define PRIVILEGE_USER (3)
6
7 #endif
2 #define _CONST_H
3
4 #define PRIVILEGE_KERNEL (0)
5 #define PRIVILEGE_USER (3)
6
7 #endif
type.h
1
#ifndef _TYPE_H
2 #define _TYPE_H
3
4 #define PUBLIC
5 #define PRIVATE static
6
7 typedef signed char i8_t;
8 typedef signed short i16_t;
9 typedef signed long i32_t;
10 typedef signed long long i64_t;
11
12 typedef unsigned char u8_t;
13 typedef unsigned short u16_t;
14 typedef unsigned long u32_t;
15 typedef unsigned long long u64_t;
16
17 typedef u8_t byte_t;
18 typedef u16_t dbyte_t;
19 typedef u32_t qbyte_t;
20 typedef u64_t obyte_t;
21
22 typedef u32_t address_t;
23
24 #endif
2 #define _TYPE_H
3
4 #define PUBLIC
5 #define PRIVATE static
6
7 typedef signed char i8_t;
8 typedef signed short i16_t;
9 typedef signed long i32_t;
10 typedef signed long long i64_t;
11
12 typedef unsigned char u8_t;
13 typedef unsigned short u16_t;
14 typedef unsigned long u32_t;
15 typedef unsigned long long u64_t;
16
17 typedef u8_t byte_t;
18 typedef u16_t dbyte_t;
19 typedef u32_t qbyte_t;
20 typedef u64_t obyte_t;
21
22 typedef u32_t address_t;
23
24 #endif
上面两个文件比较简单,今后可以扩充。
接下来是内核用到的头文件。
kconst.h
1
#ifndef _KCONST_H
2 #define _KCONST_H
3
4 #define KCODE_SELECTOR 8
5 #define KDATA_SELECTOR 16
6 #define TSS_SELECTOR 24
7 #define UCODE_SELECTOR (32 + PRIVILEGE_USER)
8 #define UDATA_SELECTOR (40 + PRIVILEGE_USER)
9
10 /* vectors of exception */
11 #define VECTOR_DE 0
12 #define VECTOR_NMI 2
13 #define VECTOR_UD 6
14 #define VECTOR_TS 10
15 #define VECTOR_NP 11
16 #define VECTOR_SS 12
17 #define VECTOR_GP 13
18 #define VECTOR_PF 14
19
20 #define NO_ERROR_CODE 0xffffffff
21
22 /* vectors of hardware int */
23 #define VECTOR_IRQ0 0x20
24 #define VECTOR_IRQ8 0x28
25
26 /* port of 8259 */
27 #define INT_MASTER_CTL 0x20
28 #define INT_MASTER_MASK 0x21
29 #define INT_SLAVE_CTL 0xa0
30 #define INT_SLAVE_MASK 0xa1
31
32 #define NR_TASKS 4
33
34 #endif
2 #define _KCONST_H
3
4 #define KCODE_SELECTOR 8
5 #define KDATA_SELECTOR 16
6 #define TSS_SELECTOR 24
7 #define UCODE_SELECTOR (32 + PRIVILEGE_USER)
8 #define UDATA_SELECTOR (40 + PRIVILEGE_USER)
9
10 /* vectors of exception */
11 #define VECTOR_DE 0
12 #define VECTOR_NMI 2
13 #define VECTOR_UD 6
14 #define VECTOR_TS 10
15 #define VECTOR_NP 11
16 #define VECTOR_SS 12
17 #define VECTOR_GP 13
18 #define VECTOR_PF 14
19
20 #define NO_ERROR_CODE 0xffffffff
21
22 /* vectors of hardware int */
23 #define VECTOR_IRQ0 0x20
24 #define VECTOR_IRQ8 0x28
25
26 /* port of 8259 */
27 #define INT_MASTER_CTL 0x20
28 #define INT_MASTER_MASK 0x21
29 #define INT_SLAVE_CTL 0xa0
30 #define INT_SLAVE_MASK 0xa1
31
32 #define NR_TASKS 4
33
34 #endif
global.h
1
#ifndef _GLOBAL_H
2 #define _GLOBAL_H
3
4 #include < type.h >
5 #include " protect.h "
6 #include " process.h "
7
8 #ifdef _GLOBAL_
9 #define EXTERN PUBLIC
10 #else
11 #define EXTERN extern
12 #endif
13
14 EXTERN descriptor_t gdt[ 8 ], idt[ 256 ], ldt[ 8 ];
15
16 EXTERN u64_t gdtr, idtr;
17
18 EXTERN tss_t tss;
19
20 EXTERN byte_t kernel_entered;
21
22 EXTERN process_t proc_table[ 32 ];
23
24 EXTERN process_t * ptr_next_proc;
25
26 extern u32_t stack_user;
27
28 #endif
这个头文件要说一下,其中EXTERN宏的用法是学自minix,我这里利用一个测试宏来确定是声明还是定义。
2 #define _GLOBAL_H
3
4 #include < type.h >
5 #include " protect.h "
6 #include " process.h "
7
8 #ifdef _GLOBAL_
9 #define EXTERN PUBLIC
10 #else
11 #define EXTERN extern
12 #endif
13
14 EXTERN descriptor_t gdt[ 8 ], idt[ 256 ], ldt[ 8 ];
15
16 EXTERN u64_t gdtr, idtr;
17
18 EXTERN tss_t tss;
19
20 EXTERN byte_t kernel_entered;
21
22 EXTERN process_t proc_table[ 32 ];
23
24 EXTERN process_t * ptr_next_proc;
25
26 extern u32_t stack_user;
27
28 #endif
proto.h
1
#ifndef _PROTO_H
2 #define _PROTO_H
3
4 #include " protect.h "
5
6 /* init.c */
7 PUBLIC void init_kernel( void );
8 PUBLIC void init_hardware( void );
9 PUBLIC void fill_segdesc(descriptor_t * desc, address_t base , u32_t limit,
10 dbyte_t attrib, int dpl);
11 PUBLIC void fill_gatedesc(descriptor_t * desc, selector_t seg_selector, address_t offset,
12 byte_t attrib, int dpl);
13
14 /* kernel lib in klib.c & klib.asm */
15 PUBLIC void outportb( int port, byte_t value);
16 PUBLIC void intr_disable( void );
17 PUBLIC void intr_enabla( void );
18 PUBLIC void kputc( char c);
19 PUBLIC void kprintf( char * s, );
20
21 void default_isr( void );
22
23 /* exception int in kernel.asm */
24 void divide_error( void );
25 void nmi( void );
26 void invalid_opcode( void );
27 void invalid_tss( void );
28 void seg_not_present( void );
29 void stack_fault( void );
30 void general_protection( void );
31 void page_fault( void );
32
33 /* hardware int in kernel.asm */
34 void hwint00( void );
35 void hwint01( void );
36 void hwint02( void );
37 void hwint03( void );
38 void hwint04( void );
39 void hwint05( void );
40 void hwint06( void );
41 void hwint07( void );
42 void hwint08( void );
43 void hwint09( void );
44 void hwint10( void );
45 void hwint11( void );
46 void hwint12( void );
47 void hwint13( void );
48 void hwint14( void );
49 void hwint15( void );
50
51
52 void clock_handler( void );
53
54 #endif
2 #define _PROTO_H
3
4 #include " protect.h "
5
6 /* init.c */
7 PUBLIC void init_kernel( void );
8 PUBLIC void init_hardware( void );
9 PUBLIC void fill_segdesc(descriptor_t * desc, address_t base , u32_t limit,
10 dbyte_t attrib, int dpl);
11 PUBLIC void fill_gatedesc(descriptor_t * desc, selector_t seg_selector, address_t offset,
12 byte_t attrib, int dpl);
13
14 /* kernel lib in klib.c & klib.asm */
15 PUBLIC void outportb( int port, byte_t value);
16 PUBLIC void intr_disable( void );
17 PUBLIC void intr_enabla( void );
18 PUBLIC void kputc( char c);
19 PUBLIC void kprintf( char * s, );
20
21 void default_isr( void );
22
23 /* exception int in kernel.asm */
24 void divide_error( void );
25 void nmi( void );
26 void invalid_opcode( void );
27 void invalid_tss( void );
28 void seg_not_present( void );
29 void stack_fault( void );
30 void general_protection( void );
31 void page_fault( void );
32
33 /* hardware int in kernel.asm */
34 void hwint00( void );
35 void hwint01( void );
36 void hwint02( void );
37 void hwint03( void );
38 void hwint04( void );
39 void hwint05( void );
40 void hwint06( void );
41 void hwint07( void );
42 void hwint08( void );
43 void hwint09( void );
44 void hwint10( void );
45 void hwint11( void );
46 void hwint12( void );
47 void hwint13( void );
48 void hwint14( void );
49 void hwint15( void );
50
51
52 void clock_handler( void );
53
54 #endif
全局头文件的引用,以及这三个头文件的引用按顺序放在kernel.h中。这样写源文件时引用kernel.h即可。
1
#ifndef _KERNEL_H
2 #define _KERNEL_H
3
4 #include < ansi.h >
5 #include < type.h >
6 #include < const .h >
7
8 #include " kconst.h "
9 #include " global.h "
10 #include " proto.h "
11
12 #endif
2 #define _KERNEL_H
3
4 #include < ansi.h >
5 #include < type.h >
6 #include < const .h >
7
8 #include " kconst.h "
9 #include " global.h "
10 #include " proto.h "
11
12 #endif
接下来是两个比较重要的头文件,一个主要包含保护模式需要的类型和常量,另一个主要包含进程调度的类型和常量。
protect.h
1
#ifndef _PROTECT_H
2 #define _PROTECT_H
3
4 #include < type.h >
5
6 typedef u64_t descriptor_t;
7 typedef u16_t selector_t;
8
9 #define DA_CODE32 (0xc098)
10 #define DA_DATA32 (0xc092)
11 #define DA_TSS (0x89)
12 #define DA_LDT (0x82)
13
14 #define GA_INT32 (0x8e)
15
16 typedef struct tss_t {
17 u32_t backlink;
18 u32_t esp0;
19 u32_t ss0;
20 u32_t esp1;
21 u32_t ss1;
22 u32_t esp2;
23 u32_t ss2;
24 u32_t ecr3;
25 u32_t eip;
26 u32_t eflags;
27 u32_t eax;
28 u32_t ecx;
29 u32_t edx;
30 u32_t ebx;
31 u32_t esp;
32 u32_t ebp;
33 u32_t esi;
34 u32_t edi;
35 u32_t es;
36 u32_t cs;
37 u32_t ss;
38 u32_t ds;
39 u32_t fs;
40 u32_t gs;
41 u32_t ldt;
42 u32_t trap;
43 u32_t iobase;
44 } tss_t;
45
46 #endif
东西不多,但都是精心构造好的。
2 #define _PROTECT_H
3
4 #include < type.h >
5
6 typedef u64_t descriptor_t;
7 typedef u16_t selector_t;
8
9 #define DA_CODE32 (0xc098)
10 #define DA_DATA32 (0xc092)
11 #define DA_TSS (0x89)
12 #define DA_LDT (0x82)
13
14 #define GA_INT32 (0x8e)
15
16 typedef struct tss_t {
17 u32_t backlink;
18 u32_t esp0;
19 u32_t ss0;
20 u32_t esp1;
21 u32_t ss1;
22 u32_t esp2;
23 u32_t ss2;
24 u32_t ecr3;
25 u32_t eip;
26 u32_t eflags;
27 u32_t eax;
28 u32_t ecx;
29 u32_t edx;
30 u32_t ebx;
31 u32_t esp;
32 u32_t ebp;
33 u32_t esi;
34 u32_t edi;
35 u32_t es;
36 u32_t cs;
37 u32_t ss;
38 u32_t ds;
39 u32_t fs;
40 u32_t gs;
41 u32_t ldt;
42 u32_t trap;
43 u32_t iobase;
44 } tss_t;
45
46 #endif
process.h
1
#ifndef _PROCESS_H
2 #define _PROCESS_H
3
4 #include < type.h >
5
6 typedef struct process_t {
7 u32_t gs;
8 u32_t fs;
9 u32_t es;
10 u32_t ds;
11 u32_t edi;
12 u32_t esi;
13 u32_t ebp;
14 u32_t kernel_esp;
15 u32_t ebx;
16 u32_t edx;
17 u32_t ecx;
18 u32_t eax;
19 u32_t ret;
20 u32_t eip;
21 u32_t cs;
22 u32_t eflags;
23 u32_t esp;
24 u32_t ss;
25 u32_t pid;
26 } process_t;
27
28 typedef struct task_t {
29 address_t entry;
30 // u32_t stack_size;
31 // char name[16];
32 } task_t;
33
34 #endif
其中的process_t是进程表项的类型,其中元素的顺序是精心安排好的。ret元素可以说是minix中的一个不错的trick,借助他可以实现不用ret的调用返回。
2 #define _PROCESS_H
3
4 #include < type.h >
5
6 typedef struct process_t {
7 u32_t gs;
8 u32_t fs;
9 u32_t es;
10 u32_t ds;
11 u32_t edi;
12 u32_t esi;
13 u32_t ebp;
14 u32_t kernel_esp;
15 u32_t ebx;
16 u32_t edx;
17 u32_t ecx;
18 u32_t eax;
19 u32_t ret;
20 u32_t eip;
21 u32_t cs;
22 u32_t eflags;
23 u32_t esp;
24 u32_t ss;
25 u32_t pid;
26 } process_t;
27
28 typedef struct task_t {
29 address_t entry;
30 // u32_t stack_size;
31 // char name[16];
32 } task_t;
33
34 #endif
最后一个头文件是kconst.inc,其中的部分内容要于kconst.h和process.h中的内容同步。
1
%ifndef _KCONST_INC
2 %define _KCONST_INC
3
4
5 %define KCODE_SELECTOR 8
6 %define KDATA_SELECTOR 16
7 %define TSS_SELECTOR 24
8
9 ;vectors of exception
10 %define VECTOR_DE 0
11 %define VECTOR_NMI 2
12 %define VECTOR_UD 6
13 %define VECTOR_TS 10
14 %define VECTOR_NP 11
15 %define VECTOR_SS 12
16 %define VECTOR_GP 13
17 %define VECTOR_PF 14
18
19 %define NO_ERROR_CODE 0xffffffff
20
21 ;vectors of hardware int
22 %define VECTOR_IRQ0 0x20
23 %define VECTOR_IRQ8 0x28
24
25 ;port of 8259
26 %define INT_MASTER_CTL 0x20
27 %define INT_MASTER_MASK 0x21
28 %define INT_SLAVE_CTL 0xa0
29 %define INT_SLAVE_MASK 0xa1
30
31 %define END_OF_INT 0x20
32
33
34 ;process.h
35 PT_GS EQU 0
36 PT_FS EQU PT_GS +4
37 PT_ES EQU PT_FS +4
38 PT_DS EQU PT_ES +4
39 PT_EDI EQU PT_DS +4
40 PT_ESI EQU PT_EDI +4
41 PT_EBP EQU PT_ESI +4
42 PT_KESP EQU PT_EBP +4
43 PT_EBX EQU PT_KESP +4
44 PT_EDX EQU PT_EBX +4
45 PT_ECX EQU PT_EDX +4
46 PT_EAX EQU PT_ECX +4
47 PT_RET EQU PT_EAX +4
48 PT_EIP EQU PT_RET +4
49 PT_CS EQU PT_EIP +4
50 PT_EFLAGS EQU PT_CS +4
51 PT_ESP EQU PT_EFLAGS +4
52 PT_SS EQU PT_ESP +4
53
54 PT_STACK_TOP EQU PT_SS+4
55 TSS_ESP0 EQU 4
56
57 %endif
2 %define _KCONST_INC
3
4
5 %define KCODE_SELECTOR 8
6 %define KDATA_SELECTOR 16
7 %define TSS_SELECTOR 24
8
9 ;vectors of exception
10 %define VECTOR_DE 0
11 %define VECTOR_NMI 2
12 %define VECTOR_UD 6
13 %define VECTOR_TS 10
14 %define VECTOR_NP 11
15 %define VECTOR_SS 12
16 %define VECTOR_GP 13
17 %define VECTOR_PF 14
18
19 %define NO_ERROR_CODE 0xffffffff
20
21 ;vectors of hardware int
22 %define VECTOR_IRQ0 0x20
23 %define VECTOR_IRQ8 0x28
24
25 ;port of 8259
26 %define INT_MASTER_CTL 0x20
27 %define INT_MASTER_MASK 0x21
28 %define INT_SLAVE_CTL 0xa0
29 %define INT_SLAVE_MASK 0xa1
30
31 %define END_OF_INT 0x20
32
33
34 ;process.h
35 PT_GS EQU 0
36 PT_FS EQU PT_GS +4
37 PT_ES EQU PT_FS +4
38 PT_DS EQU PT_ES +4
39 PT_EDI EQU PT_DS +4
40 PT_ESI EQU PT_EDI +4
41 PT_EBP EQU PT_ESI +4
42 PT_KESP EQU PT_EBP +4
43 PT_EBX EQU PT_KESP +4
44 PT_EDX EQU PT_EBX +4
45 PT_ECX EQU PT_EDX +4
46 PT_EAX EQU PT_ECX +4
47 PT_RET EQU PT_EAX +4
48 PT_EIP EQU PT_RET +4
49 PT_CS EQU PT_EIP +4
50 PT_EFLAGS EQU PT_CS +4
51 PT_ESP EQU PT_EFLAGS +4
52 PT_SS EQU PT_ESP +4
53
54 PT_STACK_TOP EQU PT_SS+4
55 TSS_ESP0 EQU 4
56
57 %endif
引用的头文件告一段落,可以看到可执行代码了。现从kernel的入口点开始。
kernel.asm
1
%include "kconst.inc"
2
3 ;=====================================================================
4 ; kernel stack
5 ;=====================================================================
6
7 SECTION .bss
8
9 resb 4 * 1024 ;4KB
10 stack_kernel:
11
12 global stack_user
13 resb 10 * 1024 ;10KB
14 stack_user:
15
16 ;=====================================================================
17 ; kernel
18 ;=====================================================================
19
20 SECTION .text
21
22 extern init_kernel, init_hardware, main
23 extern gdtr, idtr
24 global _start
25 _start:
26 cli
27 mov esp, stack_kernel
28
29 call init_kernel
30 call init_hardware
31
32 cli
33 lgdt [gdtr]
34 lidt [idtr]
35
36 jmp KCODE_SELECTOR:.1
37 .1:
38 mov ax, KDATA_SELECTOR
39 mov ds, ax
40 mov es, ax
41 mov fs, ax
42 mov gs, ax
43 mov ss, ax
44 push 0
45 popf
46
47 mov ax, TSS_SELECTOR
48 ltr ax
49
50 mov al, 0xfe
51 out 0x21, al
52 nop
53 nop
54
55 jmp main
56
57 ;=====================================================================
58 ; default isr
59 ;=====================================================================
60
61 ALIGN 16
62 global default_isr
63 default_isr:
64 cli
65 call save
66 sti
67 call default_handler
68 cli
69 ret
70
71 ;=====================================================================
72 ; exception
73 ;=====================================================================
74
75 ;+++++++++++++++++++++++++++++++++++++++++++++++++
76 ; EH_ERR label, vector, error
77 ;+++++++++++++++++++++++++++++++++++++++++++++++++
78
79 %macro EH_ERR 2
80 ALIGN 16
81 global %1
82 %1:
83 push %2
84 jmp exception
85 %endmacro
86
87 ;+++++++++++++++++++++++++++++++++++++++++++++++++
88 ; EH_NOERR lable, vector
89 ;+++++++++++++++++++++++++++++++++++++++++++++++++
90
91 %macro EH_NOERR 2
92 ALIGN 16
93 global %1
94 %1:
95 push NO_ERROR_CODE
96 push %2
97 jmp exception
98 %endmacro
99
100 ;+++++++++++++++++++++++++++++++++++++++++++++++++
101 ;+++++++++++++++++++++++++++++++++++++++++++++++++
102
103 EH_NOERR divide_error, VECTOR_DE
104 EH_NOERR nmi, VECTOR_NMI
105 EH_NOERR invalid_opcode, VECTOR_UD
106 EH_ERR invalid_tss, VECTOR_TS
107 EH_ERR seg_not_present, VECTOR_NP
108 EH_ERR stack_fault, VECTOR_SS
109 EH_ERR general_protection, VECTOR_GP
110 EH_ERR page_fault, VECTOR_PF
111
112 ALIGN 16
113 exception:
114 extern exception_handler
115 call exception_handler
116 add esp, 8
117 hlt
118 jmp $
119 iretd
120
121 ;%unmacro EH_NOERR 2
122 ;%unmacro EH_ERR 2
123
124
125 ;=====================================================================
126 ; hardware int
127 ;=====================================================================
128
129 ;+++++++++++++++++++++++++++++++++++++++++++++++++
130 ; HWINT_MASTER label, irq, handler
131 ;+++++++++++++++++++++++++++++++++++++++++++++++++
132
133 %macro HWINT_MASTER 3
134 ALIGN 16
135 global %1
136 %1:
137 call save
138 in al, INT_MASTER_MASK
139 or al, (1 < < %2 )
140 out INT_MASTER_MASK, al
141 mov al, END_OF_INT
142 out INT_MASTER_CTL, al
143 sti
144 call %3
145 cli
146 in al, INT_MASTER_MASK
147 and al, ~(1 << %2)
148 out INT_MASTER_MASK, al
149 ret
150 %endmacro
151
152 ;+++++++++++++++++++++++++++++++++++++++++++++++++
153 ; HWINT_SLAVE label, irq, handler
154 ;+++++++++++++++++++++++++++++++++++++++++++++++++
155
156 %macro HWINT_SLAVE 3
157 ALIGN 16
158 global %1
159 %1:
160 call save
161 in al, INT_SLAVE_MASK
162 or al, (1 << (%2 - 8))
163 out INT_SLAVE_MASK, al
164 mov al, END_OF_INT
165 out INT_SLAVE_CTL, al
166 sti
167 call %3
168 cli
169 in al, INT_SLAVE_MASK
170 and al, ~(1 << (%2 - 8))
171 out INT_SLAVE_MASK, al
172 ret
173 %endmacro
174
175 ;+++++++++++++++++++++++++++++++++++++++++++++++++
176 ;+++++++++++++++++++++++++++++++++++++++++++++++++
177
178 extern clock_handler
179
180 HWINT_MASTER hwint00, 0, clock_handler
181 HWINT_MASTER hwint01, 1, default_handler
182 HWINT_MASTER hwint02, 2, default_handler
183 HWINT_MASTER hwint03, 3, default_handler
184 HWINT_MASTER hwint04, 4, default_handler
185 HWINT_MASTER hwint05, 5, default_handler
186 HWINT_MASTER hwint06, 6, default_handler
187 HWINT_MASTER hwint07, 7, default_handler
188
189 HWINT_SLAVE hwint08, 8, default_handler
190 HWINT_SLAVE hwint09, 9, default_handler
191 HWINT_SLAVE hwint10, 10, default_handler
192 HWINT_SLAVE hwint11, 11, default_handler
193 HWINT_SLAVE hwint12, 12, default_handler
194 HWINT_SLAVE hwint13, 13, default_handler
195 HWINT_SLAVE hwint14, 14, default_handler
196 HWINT_SLAVE hwint15, 15, default_handler
197
198
199 ; =====================================================================
200 ; save
201 ; =====================================================================
202
203 ALIGN 16
204 extern kernel_entered
205 save:
206 pushad
207 push ds
208 push es
209 push fs
210 push gs
211 mov ebp, esp
212 cmp byte [kernel_entered], 0
213 jne .reenter
214 inc byte [kernel_entered]
215 mov esp, stack_kernel
216 push restart
217 inc byte [0xb8002]
218 jmp [ebp + PT_RET]
219 ALIGN 16
220 .reenter:
221 push restart.1
222 inc byte [0xb8004]
223 jmp [ebp + PT_RET]
224
225 ; =====================================================================
226 ; restart
227 ; =====================================================================
228
229 ALIGN 16
230 extern ptr_next_proc, tss
231 global restart:
232 restart:
233 mov esp, dword [ptr_next_proc]
234 lea eax, [esp + PT_STACK_TOP]
235 mov dword [tss + TSS_ESP0], eax
236 dec byte [kernel_entered]
237 .1:
238 pop gs
239 pop fs
240 pop es
241 pop ds
242 popad
243 add esp, 4
244 iretd
245
246
247
248
249 ALIGN 16
250 extern kprintf
251 default_handler:
252 push .msg
253 call kprintf
254 add esp, 4
255 hlt
256 jmp $
257 ret
258
259 ALIGN 4
260 .msg DB `int handler not completed yet!\n`, 0
261
事实上这个kernel还很粗糙,比如save为了调试而改变显存的值,以及那个default_handler。IRQ0打开的也很粗暴。好在架构已经成形,剩下的是细节部分的打磨。
2
3 ;=====================================================================
4 ; kernel stack
5 ;=====================================================================
6
7 SECTION .bss
8
9 resb 4 * 1024 ;4KB
10 stack_kernel:
11
12 global stack_user
13 resb 10 * 1024 ;10KB
14 stack_user:
15
16 ;=====================================================================
17 ; kernel
18 ;=====================================================================
19
20 SECTION .text
21
22 extern init_kernel, init_hardware, main
23 extern gdtr, idtr
24 global _start
25 _start:
26 cli
27 mov esp, stack_kernel
28
29 call init_kernel
30 call init_hardware
31
32 cli
33 lgdt [gdtr]
34 lidt [idtr]
35
36 jmp KCODE_SELECTOR:.1
37 .1:
38 mov ax, KDATA_SELECTOR
39 mov ds, ax
40 mov es, ax
41 mov fs, ax
42 mov gs, ax
43 mov ss, ax
44 push 0
45 popf
46
47 mov ax, TSS_SELECTOR
48 ltr ax
49
50 mov al, 0xfe
51 out 0x21, al
52 nop
53 nop
54
55 jmp main
56
57 ;=====================================================================
58 ; default isr
59 ;=====================================================================
60
61 ALIGN 16
62 global default_isr
63 default_isr:
64 cli
65 call save
66 sti
67 call default_handler
68 cli
69 ret
70
71 ;=====================================================================
72 ; exception
73 ;=====================================================================
74
75 ;+++++++++++++++++++++++++++++++++++++++++++++++++
76 ; EH_ERR label, vector, error
77 ;+++++++++++++++++++++++++++++++++++++++++++++++++
78
79 %macro EH_ERR 2
80 ALIGN 16
81 global %1
82 %1:
83 push %2
84 jmp exception
85 %endmacro
86
87 ;+++++++++++++++++++++++++++++++++++++++++++++++++
88 ; EH_NOERR lable, vector
89 ;+++++++++++++++++++++++++++++++++++++++++++++++++
90
91 %macro EH_NOERR 2
92 ALIGN 16
93 global %1
94 %1:
95 push NO_ERROR_CODE
96 push %2
97 jmp exception
98 %endmacro
99
100 ;+++++++++++++++++++++++++++++++++++++++++++++++++
101 ;+++++++++++++++++++++++++++++++++++++++++++++++++
102
103 EH_NOERR divide_error, VECTOR_DE
104 EH_NOERR nmi, VECTOR_NMI
105 EH_NOERR invalid_opcode, VECTOR_UD
106 EH_ERR invalid_tss, VECTOR_TS
107 EH_ERR seg_not_present, VECTOR_NP
108 EH_ERR stack_fault, VECTOR_SS
109 EH_ERR general_protection, VECTOR_GP
110 EH_ERR page_fault, VECTOR_PF
111
112 ALIGN 16
113 exception:
114 extern exception_handler
115 call exception_handler
116 add esp, 8
117 hlt
118 jmp $
119 iretd
120
121 ;%unmacro EH_NOERR 2
122 ;%unmacro EH_ERR 2
123
124
125 ;=====================================================================
126 ; hardware int
127 ;=====================================================================
128
129 ;+++++++++++++++++++++++++++++++++++++++++++++++++
130 ; HWINT_MASTER label, irq, handler
131 ;+++++++++++++++++++++++++++++++++++++++++++++++++
132
133 %macro HWINT_MASTER 3
134 ALIGN 16
135 global %1
136 %1:
137 call save
138 in al, INT_MASTER_MASK
139 or al, (1 < < %2 )
140 out INT_MASTER_MASK, al
141 mov al, END_OF_INT
142 out INT_MASTER_CTL, al
143 sti
144 call %3
145 cli
146 in al, INT_MASTER_MASK
147 and al, ~(1 << %2)
148 out INT_MASTER_MASK, al
149 ret
150 %endmacro
151
152 ;+++++++++++++++++++++++++++++++++++++++++++++++++
153 ; HWINT_SLAVE label, irq, handler
154 ;+++++++++++++++++++++++++++++++++++++++++++++++++
155
156 %macro HWINT_SLAVE 3
157 ALIGN 16
158 global %1
159 %1:
160 call save
161 in al, INT_SLAVE_MASK
162 or al, (1 << (%2 - 8))
163 out INT_SLAVE_MASK, al
164 mov al, END_OF_INT
165 out INT_SLAVE_CTL, al
166 sti
167 call %3
168 cli
169 in al, INT_SLAVE_MASK
170 and al, ~(1 << (%2 - 8))
171 out INT_SLAVE_MASK, al
172 ret
173 %endmacro
174
175 ;+++++++++++++++++++++++++++++++++++++++++++++++++
176 ;+++++++++++++++++++++++++++++++++++++++++++++++++
177
178 extern clock_handler
179
180 HWINT_MASTER hwint00, 0, clock_handler
181 HWINT_MASTER hwint01, 1, default_handler
182 HWINT_MASTER hwint02, 2, default_handler
183 HWINT_MASTER hwint03, 3, default_handler
184 HWINT_MASTER hwint04, 4, default_handler
185 HWINT_MASTER hwint05, 5, default_handler
186 HWINT_MASTER hwint06, 6, default_handler
187 HWINT_MASTER hwint07, 7, default_handler
188
189 HWINT_SLAVE hwint08, 8, default_handler
190 HWINT_SLAVE hwint09, 9, default_handler
191 HWINT_SLAVE hwint10, 10, default_handler
192 HWINT_SLAVE hwint11, 11, default_handler
193 HWINT_SLAVE hwint12, 12, default_handler
194 HWINT_SLAVE hwint13, 13, default_handler
195 HWINT_SLAVE hwint14, 14, default_handler
196 HWINT_SLAVE hwint15, 15, default_handler
197
198
199 ; =====================================================================
200 ; save
201 ; =====================================================================
202
203 ALIGN 16
204 extern kernel_entered
205 save:
206 pushad
207 push ds
208 push es
209 push fs
210 push gs
211 mov ebp, esp
212 cmp byte [kernel_entered], 0
213 jne .reenter
214 inc byte [kernel_entered]
215 mov esp, stack_kernel
216 push restart
217 inc byte [0xb8002]
218 jmp [ebp + PT_RET]
219 ALIGN 16
220 .reenter:
221 push restart.1
222 inc byte [0xb8004]
223 jmp [ebp + PT_RET]
224
225 ; =====================================================================
226 ; restart
227 ; =====================================================================
228
229 ALIGN 16
230 extern ptr_next_proc, tss
231 global restart:
232 restart:
233 mov esp, dword [ptr_next_proc]
234 lea eax, [esp + PT_STACK_TOP]
235 mov dword [tss + TSS_ESP0], eax
236 dec byte [kernel_entered]
237 .1:
238 pop gs
239 pop fs
240 pop es
241 pop ds
242 popad
243 add esp, 4
244 iretd
245
246
247
248
249 ALIGN 16
250 extern kprintf
251 default_handler:
252 push .msg
253 call kprintf
254 add esp, 4
255 hlt
256 jmp $
257 ret
258
259 ALIGN 4
260 .msg DB `int handler not completed yet!\n`, 0
261
global.c是全局变量的所在地。呵呵,真是脱了global.h的福。
1
#define
_GLOBAL_
2 #include " global.h "
2 #include " global.h "
再有就是一个简单的库,klib.c和klib.asm里面有个非常简陋的输出函数,主要拿来调试用的。
1
#include
"
kernel.h
"
2
3 PUBLIC void kputc( char c)
4 {
5 static int pos = 160 , row = 1 , col = 0 ;
6 int i;
7
8 if ( 24 == row) {
9
10 for (i = 0xb8000 ; i < 0xb8000 + 24 * 160 ; i += 2 ) {
11 * (dbyte_t * )i = * (dbyte_t * )(i + 160 );
12 }
13 -- row;
14 pos -= 160 ;
15 /*
16 --row;
17 start += 80;
18 outportb(0x3d4, 0xc);
19 outportb(0x3d5, (start >> 8) & 0xff);
20 outportb(0x3d4, 0xd);
21 outportb(0x3d5, start & 0xff);
22 */
23 }
24 switch (c) {
25 case ' \n ' :
26 ++ row;
27 col = 0 ;
28 pos = row * 160 ;
29 break ;
30 default :
31 * (dbyte_t * )( 0xb8000 + pos) = (dbyte_t) 0x700 | c;
32 pos += 2 ;
33 ++ col;
34 if ( 80 == col) {
35 ++ row;
36 col = 0 ;
37 }
38 }
39 i = (pos >> 1 );
40 outportb( 0x3d4 , 0xe );
41 outportb( 0x3d5 , (i >> 8 ) & 0xff );
42 outportb( 0x3d4 , 0xf );
43 outportb( 0x3d5 , i & 0xff );
44 return ;
45 }
46
47 PRIVATE void kprint_hex(unsigned int x);
48 PRIVATE void kprint_int( int x);
49
50 PUBLIC void kprintf( char * s, )
51 {
52 u32_t * ptr_arg = (u32_t * )( & s);
53
54 while ( * s) {
55 if ( ' % ' == * s) {
56 ++ s;
57 switch ( * s) {
58 case ' x ' :
59 ++ s;
60 ++ ptr_arg;
61 kputc( ' 0 ' );
62 kputc( ' x ' );
63 kprint_hex( * ptr_arg);
64 break ;
65 case ' d ' :
66 ++ s;
67 ++ ptr_arg;
68 kprint_int( * ptr_arg);
69 break ;
70 default :
71 kputc( ' % ' );
72 }
73 } else {
74 kputc( * s);
75 ++ s;
76 }
77 }
78 return ;
79 }
80
81 PRIVATE void kprint_hex(unsigned int x)
82 {
83 int i;
84
85 if ( 0 == x) {
86 kputc( ' 0 ' );
87 return ;
88 }
89 for (i = 4 ; i < 32 ; i += 4 ) {
90 if ((x >> i) == 0 ) {
91 break ;
92 }
93 }
94 for (i -= 4 ; i >= 0 ; i -= 4 ) {
95 kputc( " 0123456789abcdef " [(x >> i) & 0xf ]);
96 }
97 return ;
98 }
99
100 PRIVATE void _kprint_int( int x);
101
102 PRIVATE void kprint_int( int x)
103 {
104 if ( 0 == x) {
105 kputc( ' 0 ' );
106 } else if (x > 0 ) {
107 _kprint_int(x);
108 } else {
109 kputc( ' - ' );
110 _kprint_int( - x);
111 }
112 return ;
113 }
114
115 PRIVATE void _kprint_int( int x)
116 {
117 if (x) {
118 _kprint_int(x / 10 );
119 kputc( " 01234567890 " [x % 10 ]);
120 }
121 return ;
122 }
2
3 PUBLIC void kputc( char c)
4 {
5 static int pos = 160 , row = 1 , col = 0 ;
6 int i;
7
8 if ( 24 == row) {
9
10 for (i = 0xb8000 ; i < 0xb8000 + 24 * 160 ; i += 2 ) {
11 * (dbyte_t * )i = * (dbyte_t * )(i + 160 );
12 }
13 -- row;
14 pos -= 160 ;
15 /*
16 --row;
17 start += 80;
18 outportb(0x3d4, 0xc);
19 outportb(0x3d5, (start >> 8) & 0xff);
20 outportb(0x3d4, 0xd);
21 outportb(0x3d5, start & 0xff);
22 */
23 }
24 switch (c) {
25 case ' \n ' :
26 ++ row;
27 col = 0 ;
28 pos = row * 160 ;
29 break ;
30 default :
31 * (dbyte_t * )( 0xb8000 + pos) = (dbyte_t) 0x700 | c;
32 pos += 2 ;
33 ++ col;
34 if ( 80 == col) {
35 ++ row;
36 col = 0 ;
37 }
38 }
39 i = (pos >> 1 );
40 outportb( 0x3d4 , 0xe );
41 outportb( 0x3d5 , (i >> 8 ) & 0xff );
42 outportb( 0x3d4 , 0xf );
43 outportb( 0x3d5 , i & 0xff );
44 return ;
45 }
46
47 PRIVATE void kprint_hex(unsigned int x);
48 PRIVATE void kprint_int( int x);
49
50 PUBLIC void kprintf( char * s, )
51 {
52 u32_t * ptr_arg = (u32_t * )( & s);
53
54 while ( * s) {
55 if ( ' % ' == * s) {
56 ++ s;
57 switch ( * s) {
58 case ' x ' :
59 ++ s;
60 ++ ptr_arg;
61 kputc( ' 0 ' );
62 kputc( ' x ' );
63 kprint_hex( * ptr_arg);
64 break ;
65 case ' d ' :
66 ++ s;
67 ++ ptr_arg;
68 kprint_int( * ptr_arg);
69 break ;
70 default :
71 kputc( ' % ' );
72 }
73 } else {
74 kputc( * s);
75 ++ s;
76 }
77 }
78 return ;
79 }
80
81 PRIVATE void kprint_hex(unsigned int x)
82 {
83 int i;
84
85 if ( 0 == x) {
86 kputc( ' 0 ' );
87 return ;
88 }
89 for (i = 4 ; i < 32 ; i += 4 ) {
90 if ((x >> i) == 0 ) {
91 break ;
92 }
93 }
94 for (i -= 4 ; i >= 0 ; i -= 4 ) {
95 kputc( " 0123456789abcdef " [(x >> i) & 0xf ]);
96 }
97 return ;
98 }
99
100 PRIVATE void _kprint_int( int x);
101
102 PRIVATE void kprint_int( int x)
103 {
104 if ( 0 == x) {
105 kputc( ' 0 ' );
106 } else if (x > 0 ) {
107 _kprint_int(x);
108 } else {
109 kputc( ' - ' );
110 _kprint_int( - x);
111 }
112 return ;
113 }
114
115 PRIVATE void _kprint_int( int x)
116 {
117 if (x) {
118 _kprint_int(x / 10 );
119 kputc( " 01234567890 " [x % 10 ]);
120 }
121 return ;
122 }
1
SECTION .text
2
3 ;=====================================================================
4 ; void outportb(dbyte_t port, byte_t value)
5 ;=====================================================================
6
7 global outportb
8 outportb:
9 push edx
10
11 mov dx, word [esp + 8]
12 mov al, byte [esp + 12]
13 out dx, al
14 nop
15 nop
16
17 pop edx
18 ret
19
20 ;=====================================================================
21 ; void intr_disable(void)
22 ;=====================================================================
23
24 global intr_disable
25 intr_disable:
26 cli
27 ret
28
29 ;=====================================================================
30 ; void intr_enable(void)
31 ;=====================================================================
32
33 global intr_enable
34 intr_enable:
35 sti
36 ret
2
3 ;=====================================================================
4 ; void outportb(dbyte_t port, byte_t value)
5 ;=====================================================================
6
7 global outportb
8 outportb:
9 push edx
10
11 mov dx, word [esp + 8]
12 mov al, byte [esp + 12]
13 out dx, al
14 nop
15 nop
16
17 pop edx
18 ret
19
20 ;=====================================================================
21 ; void intr_disable(void)
22 ;=====================================================================
23
24 global intr_disable
25 intr_disable:
26 cli
27 ret
28
29 ;=====================================================================
30 ; void intr_enable(void)
31 ;=====================================================================
32
33 global intr_enable
34 intr_enable:
35 sti
36 ret
继续,下面是init.c。
1
#include
"
kernel.h
"
2 #include " protect.h "
3 #include " process.h "
4
5 /* ====================================================================*
6 * init_kernel *
7 *==================================================================== */
8
9 PUBLIC void init_kernel( void )
10 {
11 int i;
12
13 byte_t * p = (byte_t * )( & gdtr);
14 * (u16_t * )(p + 0 ) = (u16_t)( sizeof (gdt) - 1 );
15 * (u32_t * )(p + 2 ) = (u32_t)( & gdt);
16
17 p = (byte_t * )( & idtr);
18 * (u16_t * )(p + 0 ) = (u16_t)( sizeof (idt) - 1 );
19 * (u32_t * )(p + 2 ) = (u32_t)( & idt);
20
21 fill_segdesc( & gdt[KCODE_SELECTOR >> 3 ], 0 , 0xfffff , DA_CODE32, PRIVILEGE_KERNEL);
22 fill_segdesc( & gdt[KDATA_SELECTOR >> 3 ], 0 , 0xfffff , DA_DATA32, PRIVILEGE_KERNEL);
23 fill_segdesc( & gdt[UCODE_SELECTOR >> 3 ], 0 , 0xfffff , DA_CODE32, PRIVILEGE_USER);
24 fill_segdesc( & gdt[UDATA_SELECTOR >> 3 ], 0 , 0xfffff , DA_DATA32, PRIVILEGE_USER);
25
26 tss.ss0 = KDATA_SELECTOR;
27 tss.iobase = sizeof (tss);
28 fill_segdesc( & gdt[TSS_SELECTOR >> 3 ], (address_t)( & tss), sizeof (tss) - 1 ,
29 DA_TSS, PRIVILEGE_KERNEL);
30
31 struct isr_table_t {
32 address_t entry;
33 int privilege;
34 } isr_table[ 256 ];
35
36 #define ISR_TABLE(V,E,P) {isr_table[V].entry = (address_t)(E); \
37 isr_table[V].privilege = (P);}
38
39 for (i = 0 ; i < 256 ; ++ i) {
40 ISR_TABLE(i, default_isr, PRIVILEGE_USER);
41 }
42
43 ISR_TABLE(VECTOR_DE, divide_error, PRIVILEGE_KERNEL);
44 ISR_TABLE(VECTOR_NMI, nmi, PRIVILEGE_KERNEL);
45 ISR_TABLE(VECTOR_UD, invalid_opcode, PRIVILEGE_KERNEL);
46 ISR_TABLE(VECTOR_TS, invalid_tss, PRIVILEGE_KERNEL);
47 ISR_TABLE(VECTOR_NP, seg_not_present, PRIVILEGE_KERNEL);
48 ISR_TABLE(VECTOR_SS, stack_fault, PRIVILEGE_KERNEL);
49 ISR_TABLE(VECTOR_GP, general_protection, PRIVILEGE_KERNEL);
50 ISR_TABLE(VECTOR_PF, page_fault, PRIVILEGE_KERNEL);
51
52 ISR_TABLE(VECTOR_IRQ0, hwint00, PRIVILEGE_KERNEL);
53 ISR_TABLE(VECTOR_IRQ0 + 1 , hwint01, PRIVILEGE_KERNEL);
54 ISR_TABLE(VECTOR_IRQ0 + 2 , hwint02, PRIVILEGE_KERNEL);
55 ISR_TABLE(VECTOR_IRQ0 + 3 , hwint03, PRIVILEGE_KERNEL);
56 ISR_TABLE(VECTOR_IRQ0 + 4 , hwint04, PRIVILEGE_KERNEL);
57 ISR_TABLE(VECTOR_IRQ0 + 5 , hwint05, PRIVILEGE_KERNEL);
58 ISR_TABLE(VECTOR_IRQ0 + 6 , hwint06, PRIVILEGE_KERNEL);
59 ISR_TABLE(VECTOR_IRQ0 + 7 , hwint07, PRIVILEGE_KERNEL);
60 ISR_TABLE(VECTOR_IRQ8, hwint08, PRIVILEGE_KERNEL);
61 ISR_TABLE(VECTOR_IRQ8 + 1 , hwint09, PRIVILEGE_KERNEL);
62 ISR_TABLE(VECTOR_IRQ8 + 2 , hwint10, PRIVILEGE_KERNEL);
63 ISR_TABLE(VECTOR_IRQ8 + 3 , hwint11, PRIVILEGE_KERNEL);
64 ISR_TABLE(VECTOR_IRQ8 + 4 , hwint12, PRIVILEGE_KERNEL);
65 ISR_TABLE(VECTOR_IRQ8 + 5 , hwint13, PRIVILEGE_KERNEL);
66 ISR_TABLE(VECTOR_IRQ8 + 6 , hwint14, PRIVILEGE_KERNEL);
67 ISR_TABLE(VECTOR_IRQ8 + 7 , hwint15, PRIVILEGE_KERNEL);
68
69 for (i = 0 ; i < 256 ; ++ i) {
70 fill_gatedesc( & idt[i], KCODE_SELECTOR, isr_table[i].entry,
71 GA_INT32, isr_table[i].privilege);
72 }
73
74 return ;
75 }
76
77
78 /* ====================================================================*
79 * fill_segdesc *
80 *==================================================================== */
81
82 PUBLIC void fill_segdesc(descriptor_t * desc, address_t base , u32_t limit,
83 dbyte_t attrib, int dpl)
84 {
85 address_t p = (address_t)desc;
86
87 * (dbyte_t * )(p + 0 ) = limit & 0xffff ;
88 * (dbyte_t * )(p + 2 ) = base & 0xffff ;
89 * (byte_t * )(p + 4 ) = ( base >> 16 ) & 0xff ;
90 * (dbyte_t * )(p + 5 ) = attrib | ((limit >> 8 ) & 0xf00 ) | (dpl << 5 );
91 * (byte_t * )(p + 7 ) = ( base >> 24 ) & 0xff ;
92 return ;
93 }
94
95 /* ====================================================================*
96 * fill_gatedesc *
97 *==================================================================== */
98
99 PUBLIC void fill_gatedesc(descriptor_t * desc, selector_t seg_selector,
100 address_t offset, byte_t attrib, int dpl)
101 {
102 address_t p = (address_t)desc;
103
104 * (dbyte_t * )(p + 0 ) = offset & 0xffff ;
105 * (dbyte_t * )(p + 2 ) = seg_selector;
106 * (byte_t * )(p + 4 ) = 0 ;
107 * (byte_t * )(p + 5 ) = attrib | (dpl << 5 );
108 * (dbyte_t * )(p + 6 ) = (offset >> 16 ) & 0xffff ;
109 return ;
110 }
111
112 /* ====================================================================*
113 * init_hardware *
114 *==================================================================== */
115
116 PUBLIC void init_hardware( void )
117 {
118 // init_8253();
119 init_8259();
120 return ;
121 }
其中对8253的初始化尚未实现,留作下一个目标。
2 #include " protect.h "
3 #include " process.h "
4
5 /* ====================================================================*
6 * init_kernel *
7 *==================================================================== */
8
9 PUBLIC void init_kernel( void )
10 {
11 int i;
12
13 byte_t * p = (byte_t * )( & gdtr);
14 * (u16_t * )(p + 0 ) = (u16_t)( sizeof (gdt) - 1 );
15 * (u32_t * )(p + 2 ) = (u32_t)( & gdt);
16
17 p = (byte_t * )( & idtr);
18 * (u16_t * )(p + 0 ) = (u16_t)( sizeof (idt) - 1 );
19 * (u32_t * )(p + 2 ) = (u32_t)( & idt);
20
21 fill_segdesc( & gdt[KCODE_SELECTOR >> 3 ], 0 , 0xfffff , DA_CODE32, PRIVILEGE_KERNEL);
22 fill_segdesc( & gdt[KDATA_SELECTOR >> 3 ], 0 , 0xfffff , DA_DATA32, PRIVILEGE_KERNEL);
23 fill_segdesc( & gdt[UCODE_SELECTOR >> 3 ], 0 , 0xfffff , DA_CODE32, PRIVILEGE_USER);
24 fill_segdesc( & gdt[UDATA_SELECTOR >> 3 ], 0 , 0xfffff , DA_DATA32, PRIVILEGE_USER);
25
26 tss.ss0 = KDATA_SELECTOR;
27 tss.iobase = sizeof (tss);
28 fill_segdesc( & gdt[TSS_SELECTOR >> 3 ], (address_t)( & tss), sizeof (tss) - 1 ,
29 DA_TSS, PRIVILEGE_KERNEL);
30
31 struct isr_table_t {
32 address_t entry;
33 int privilege;
34 } isr_table[ 256 ];
35
36 #define ISR_TABLE(V,E,P) {isr_table[V].entry = (address_t)(E); \
37 isr_table[V].privilege = (P);}
38
39 for (i = 0 ; i < 256 ; ++ i) {
40 ISR_TABLE(i, default_isr, PRIVILEGE_USER);
41 }
42
43 ISR_TABLE(VECTOR_DE, divide_error, PRIVILEGE_KERNEL);
44 ISR_TABLE(VECTOR_NMI, nmi, PRIVILEGE_KERNEL);
45 ISR_TABLE(VECTOR_UD, invalid_opcode, PRIVILEGE_KERNEL);
46 ISR_TABLE(VECTOR_TS, invalid_tss, PRIVILEGE_KERNEL);
47 ISR_TABLE(VECTOR_NP, seg_not_present, PRIVILEGE_KERNEL);
48 ISR_TABLE(VECTOR_SS, stack_fault, PRIVILEGE_KERNEL);
49 ISR_TABLE(VECTOR_GP, general_protection, PRIVILEGE_KERNEL);
50 ISR_TABLE(VECTOR_PF, page_fault, PRIVILEGE_KERNEL);
51
52 ISR_TABLE(VECTOR_IRQ0, hwint00, PRIVILEGE_KERNEL);
53 ISR_TABLE(VECTOR_IRQ0 + 1 , hwint01, PRIVILEGE_KERNEL);
54 ISR_TABLE(VECTOR_IRQ0 + 2 , hwint02, PRIVILEGE_KERNEL);
55 ISR_TABLE(VECTOR_IRQ0 + 3 , hwint03, PRIVILEGE_KERNEL);
56 ISR_TABLE(VECTOR_IRQ0 + 4 , hwint04, PRIVILEGE_KERNEL);
57 ISR_TABLE(VECTOR_IRQ0 + 5 , hwint05, PRIVILEGE_KERNEL);
58 ISR_TABLE(VECTOR_IRQ0 + 6 , hwint06, PRIVILEGE_KERNEL);
59 ISR_TABLE(VECTOR_IRQ0 + 7 , hwint07, PRIVILEGE_KERNEL);
60 ISR_TABLE(VECTOR_IRQ8, hwint08, PRIVILEGE_KERNEL);
61 ISR_TABLE(VECTOR_IRQ8 + 1 , hwint09, PRIVILEGE_KERNEL);
62 ISR_TABLE(VECTOR_IRQ8 + 2 , hwint10, PRIVILEGE_KERNEL);
63 ISR_TABLE(VECTOR_IRQ8 + 3 , hwint11, PRIVILEGE_KERNEL);
64 ISR_TABLE(VECTOR_IRQ8 + 4 , hwint12, PRIVILEGE_KERNEL);
65 ISR_TABLE(VECTOR_IRQ8 + 5 , hwint13, PRIVILEGE_KERNEL);
66 ISR_TABLE(VECTOR_IRQ8 + 6 , hwint14, PRIVILEGE_KERNEL);
67 ISR_TABLE(VECTOR_IRQ8 + 7 , hwint15, PRIVILEGE_KERNEL);
68
69 for (i = 0 ; i < 256 ; ++ i) {
70 fill_gatedesc( & idt[i], KCODE_SELECTOR, isr_table[i].entry,
71 GA_INT32, isr_table[i].privilege);
72 }
73
74 return ;
75 }
76
77
78 /* ====================================================================*
79 * fill_segdesc *
80 *==================================================================== */
81
82 PUBLIC void fill_segdesc(descriptor_t * desc, address_t base , u32_t limit,
83 dbyte_t attrib, int dpl)
84 {
85 address_t p = (address_t)desc;
86
87 * (dbyte_t * )(p + 0 ) = limit & 0xffff ;
88 * (dbyte_t * )(p + 2 ) = base & 0xffff ;
89 * (byte_t * )(p + 4 ) = ( base >> 16 ) & 0xff ;
90 * (dbyte_t * )(p + 5 ) = attrib | ((limit >> 8 ) & 0xf00 ) | (dpl << 5 );
91 * (byte_t * )(p + 7 ) = ( base >> 24 ) & 0xff ;
92 return ;
93 }
94
95 /* ====================================================================*
96 * fill_gatedesc *
97 *==================================================================== */
98
99 PUBLIC void fill_gatedesc(descriptor_t * desc, selector_t seg_selector,
100 address_t offset, byte_t attrib, int dpl)
101 {
102 address_t p = (address_t)desc;
103
104 * (dbyte_t * )(p + 0 ) = offset & 0xffff ;
105 * (dbyte_t * )(p + 2 ) = seg_selector;
106 * (byte_t * )(p + 4 ) = 0 ;
107 * (byte_t * )(p + 5 ) = attrib | (dpl << 5 );
108 * (dbyte_t * )(p + 6 ) = (offset >> 16 ) & 0xffff ;
109 return ;
110 }
111
112 /* ====================================================================*
113 * init_hardware *
114 *==================================================================== */
115
116 PUBLIC void init_hardware( void )
117 {
118 // init_8253();
119 init_8259();
120 return ;
121 }
8259.c
1
#include
"
kernel.h
"
2
3 /* ====================================================================*
4 * init_8259 *
5 *==================================================================== */
6
7 PUBLIC void init_8259( void )
8 {
9 intr_disable();
10
11 /* master ICW1 */
12 outportb(INT_MASTER_CTL, 0x11 );
13
14 /* master ICW2 */
15 outportb(INT_MASTER_MASK, VECTOR_IRQ0);
16
17 /* master ICW3 */
18 outportb(INT_MASTER_MASK, ( 1 << 2 ));
19
20 /* master ICW4 */
21 outportb(INT_MASTER_MASK, 0x1 );
22
23 /* master OCW1 , IRQ0 ~ IRQ7 mask */
24 outportb(INT_MASTER_MASK, ~ ( 1 << 2 ));
25
26 /* slave ICW1 */
27 outportb(INT_SLAVE_CTL, 0x11 );
28
29 /* slave ICW2 */
30 outportb(INT_SLAVE_MASK, VECTOR_IRQ8);
31
32 /* slave ICW3 */
33 outportb(INT_SLAVE_MASK, 2 );
34
35 /* slave ICW4 */
36 outportb(INT_SLAVE_MASK, 0x1 );
37
38 /* slave OCW1 , IRQ8 ~ IRQ15 mask */
39 outportb(INT_SLAVE_MASK, ~ 0 );
40
41 return ;
42 }
2
3 /* ====================================================================*
4 * init_8259 *
5 *==================================================================== */
6
7 PUBLIC void init_8259( void )
8 {
9 intr_disable();
10
11 /* master ICW1 */
12 outportb(INT_MASTER_CTL, 0x11 );
13
14 /* master ICW2 */
15 outportb(INT_MASTER_MASK, VECTOR_IRQ0);
16
17 /* master ICW3 */
18 outportb(INT_MASTER_MASK, ( 1 << 2 ));
19
20 /* master ICW4 */
21 outportb(INT_MASTER_MASK, 0x1 );
22
23 /* master OCW1 , IRQ0 ~ IRQ7 mask */
24 outportb(INT_MASTER_MASK, ~ ( 1 << 2 ));
25
26 /* slave ICW1 */
27 outportb(INT_SLAVE_CTL, 0x11 );
28
29 /* slave ICW2 */
30 outportb(INT_SLAVE_MASK, VECTOR_IRQ8);
31
32 /* slave ICW3 */
33 outportb(INT_SLAVE_MASK, 2 );
34
35 /* slave ICW4 */
36 outportb(INT_SLAVE_MASK, 0x1 );
37
38 /* slave OCW1 , IRQ8 ~ IRQ15 mask */
39 outportb(INT_SLAVE_MASK, ~ 0 );
40
41 return ;
42 }
exception.c,异常处理函数
1
#include
"
kernel.h
"
2
3 void exception_handler( int vector, int err_code)
4 {
5 u32_t * p;
6
7 static char msg[ 20 ][ 50 ] = {
8 " Divide 0 " ,
9 "" ,
10 "" ,
11 "" ,
12 "" ,
13 "" ,
14 " Undefined Opcode " ,
15 "" ,
16 "" ,
17 "" ,
18 " Invalid TTS " ,
19 " Segment Not Present " ,
20 " Stack-Segment Fault " ,
21 " General Protection " ,
22 " Page Fault " ,
23 "" ,
24 "" ,
25 " Alignment Check " ,
26 };
27
28 kprintf( " \n\n====================================================\n\n " );
29 kprintf( " An exception here!\n " );
30 kprintf(msg[vector]);
31 kprintf( " , error code is %x\n " , err_code);
32
33 if (err_code & 0x2 ) {
34 p = (u32_t * )( & idt[(err_code & 0xffff ) >> 3 ]);
35 kprintf( " vector of this gate is %x\n " , (err_code & 0xffff ) >> 3 );
36 kprintf( " gate decriptor in ldt is %x(high) %x(low)\n\n " , * (p + 1 ), * p);
37 } else {
38 p = (u32_t * )( & gdt[(err_code & 0xffff ) >> 3 ]);
39 kprintf( " seg decriptor in gdt is %x(high) %x(low)\n\n " , * (p + 1 ), * p);
40 }
41 return ;
42 }
2
3 void exception_handler( int vector, int err_code)
4 {
5 u32_t * p;
6
7 static char msg[ 20 ][ 50 ] = {
8 " Divide 0 " ,
9 "" ,
10 "" ,
11 "" ,
12 "" ,
13 "" ,
14 " Undefined Opcode " ,
15 "" ,
16 "" ,
17 "" ,
18 " Invalid TTS " ,
19 " Segment Not Present " ,
20 " Stack-Segment Fault " ,
21 " General Protection " ,
22 " Page Fault " ,
23 "" ,
24 "" ,
25 " Alignment Check " ,
26 };
27
28 kprintf( " \n\n====================================================\n\n " );
29 kprintf( " An exception here!\n " );
30 kprintf(msg[vector]);
31 kprintf( " , error code is %x\n " , err_code);
32
33 if (err_code & 0x2 ) {
34 p = (u32_t * )( & idt[(err_code & 0xffff ) >> 3 ]);
35 kprintf( " vector of this gate is %x\n " , (err_code & 0xffff ) >> 3 );
36 kprintf( " gate decriptor in ldt is %x(high) %x(low)\n\n " , * (p + 1 ), * p);
37 } else {
38 p = (u32_t * )( & gdt[(err_code & 0xffff ) >> 3 ]);
39 kprintf( " seg decriptor in gdt is %x(high) %x(low)\n\n " , * (p + 1 ), * p);
40 }
41 return ;
42 }
clock.c,时钟任务,仅仅作轮转调度,有待扩充
1
#include
"
kernel.h
"
2
3 PUBLIC void clock_handler( void )
4 {
5 // ++(*(byte_t *)0xb8000);
6
7 ++ ptr_next_proc;
8 if (proc_table + NR_TASKS == ptr_next_proc) {
9 ptr_next_proc = & proc_table[ 0 ];
10 }
11 return ;
12 }
2
3 PUBLIC void clock_handler( void )
4 {
5 // ++(*(byte_t *)0xb8000);
6
7 ++ ptr_next_proc;
8 if (proc_table + NR_TASKS == ptr_next_proc) {
9 ptr_next_proc = & proc_table[ 0 ];
10 }
11 return ;
12 }
main.c,由内核级下降到用户级,启动第一个进程
1
#include
"
kernel.h
"
2
3 void TestA( void );
4 void TestB( void );
5 void TestC( void );
6 void TestD( void );
7
8 int main( void )
9 {
10 static task_t task_table[NR_TASKS] = {
11 { (address_t)TestA },
12 { (address_t)TestB },
13 { (address_t)TestC },
14 { (address_t)TestD },
15 };
16 address_t stack_top = (address_t) & stack_user;
17 process_t * p;
18 int i;
19
20 for (i = 0 ; i < NR_TASKS; ++ i) {
21 p = & proc_table[i];
22 p -> cs = UCODE_SELECTOR;
23 p -> ds =
24 p -> es =
25 p -> fs =
26 p -> gs =
27 p -> ss = UDATA_SELECTOR;
28 p -> esp = (u32_t)stack_top;
29 p -> eip = (u32_t)task_table[i].entry;
30 p -> eflags = 0x3202 ;
31
32 stack_top -= 2048 ;
33 }
34
35 kernel_entered = 1 ;
36 ptr_next_proc = & proc_table[ 0 ];
37 kprintf( " start first process\n " );
38 restart();
39 return 0 ;
40 }
41
2
3 void TestA( void );
4 void TestB( void );
5 void TestC( void );
6 void TestD( void );
7
8 int main( void )
9 {
10 static task_t task_table[NR_TASKS] = {
11 { (address_t)TestA },
12 { (address_t)TestB },
13 { (address_t)TestC },
14 { (address_t)TestD },
15 };
16 address_t stack_top = (address_t) & stack_user;
17 process_t * p;
18 int i;
19
20 for (i = 0 ; i < NR_TASKS; ++ i) {
21 p = & proc_table[i];
22 p -> cs = UCODE_SELECTOR;
23 p -> ds =
24 p -> es =
25 p -> fs =
26 p -> gs =
27 p -> ss = UDATA_SELECTOR;
28 p -> esp = (u32_t)stack_top;
29 p -> eip = (u32_t)task_table[i].entry;
30 p -> eflags = 0x3202 ;
31
32 stack_top -= 2048 ;
33 }
34
35 kernel_entered = 1 ;
36 ptr_next_proc = & proc_table[ 0 ];
37 kprintf( " start first process\n " );
38 restart();
39 return 0 ;
40 }
41
test.c,其中有四个测试进程
1
#include
"
kernel.h
"
2
3 PRIVATE void delay( void );
4
5 void TestA( void )
6 {
7 int i;
8
9 for (i = 0 ; 1 ; ++ i) {
10 kprintf( " A%d " , i);
11 delay();
12 }
13 return ;
14 }
15
16 void TestB( void )
17 {
18 int i;
19
20 for (i = 0 ; 1 ; ++ i) {
21 kprintf( " B%d " , i);
22 delay();
23 }
24 return ;
25 }
26
27 void TestC( void )
28 {
29 int i;
30
31 for (i = 0 ; 1 ; ++ i) {
32 kprintf( " C%d " , i);
33 delay();
34 }
35 return ;
36 }
37
38 void TestD( void )
39 {
40 int i;
41
42 for (i = 0 ; 1 ; ++ i) {
43 kprintf( " D%d " , i);
44 delay();
45 }
46 return ;
47 }
48
49 PRIVATE void delay( void )
50 {
51 int i, j;
52
53 for (i = 0 ; i < 1000000 ; ++ i) {
54 ++ j;
55 }
56 }
2
3 PRIVATE void delay( void );
4
5 void TestA( void )
6 {
7 int i;
8
9 for (i = 0 ; 1 ; ++ i) {
10 kprintf( " A%d " , i);
11 delay();
12 }
13 return ;
14 }
15
16 void TestB( void )
17 {
18 int i;
19
20 for (i = 0 ; 1 ; ++ i) {
21 kprintf( " B%d " , i);
22 delay();
23 }
24 return ;
25 }
26
27 void TestC( void )
28 {
29 int i;
30
31 for (i = 0 ; 1 ; ++ i) {
32 kprintf( " C%d " , i);
33 delay();
34 }
35 return ;
36 }
37
38 void TestD( void )
39 {
40 int i;
41
42 for (i = 0 ; 1 ; ++ i) {
43 kprintf( " D%d " , i);
44 delay();
45 }
46 return ;
47 }
48
49 PRIVATE void delay( void )
50 {
51 int i, j;
52
53 for (i = 0 ; i < 1000000 ; ++ i) {
54 ++ j;
55 }
56 }
好,最后贴上编译用的Makefile,编译后就可以在virtualbox上看到结果了。
1
ENTRYPOINT = 0x30400
2 HEADERS = kernel.h global.h kconst.h proto.h protect.h process.h
3
4 AS = nasm
5 ASFLAGS = -f elf
6 CC = gcc
7 CFLAGS = -c -I ../include
8 LD = ld
9 LDFLAGS = -s -Ttext $(ENTRYPOINT)
10
11 OBJS = kernel.o global.o init.o 8259.o main.o klib1.o klib2.o exception.o clock.o test.o
12
13 kernel.bin: $(OBJS)
14 $(LD) $(LDFLAGS) -o $@ $(OBJS)
15 rm -f $(OBJS)
16 sudo mount ../TINIX.IMG /mnt/TINIX -o loop
17 sudo cp -f $@ /mnt/TINIX
18 sudo umount /mnt/TINIX
19 rm $@
20
21 kernel.o: kernel.asm kconst.inc
22 $(AS) $(ASFLAGS) -o $@ $ <
23
24 global .o: global.c $(HEADERS)
25 $(CC) $(CFLAGS) -o $@ $<
26
27 init.o: init.c $(HEADERS)
28 $(CC) $(CFLAGS) -o $@ $<
29
30 8259.o: 8259.c $(HEADERS)
31 $(CC) $(CFLAGS) -o $@ $<
32
33 main.o: main.c $(HEADERS)
34 $(CC) $(CFLAGS) -o $@ $<
35
36 klib1.o: klib.c $(HEADERS)
37 $(CC) $(CFLAGS) -o $@ $<
38
39 klib2.o: klib.asm kconst.inc
40 $(AS) $(ASFLAGS) -o $@ $<
41
42 exception.o: exception.c $(HEADERS)
43 $(CC) $(CFLAGS) -o $@ $<
44
45 clock.o: clock.c $(HEADERS)
46 $(CC) $(CFLAGS) -o $@ $<
47
48 test.o: test.c $(HEADERS)
49 $(CC) $(CFLAGS) -o $@ $<
50
51 unmount:
52 sudo umount /mnt/TINIX
2 HEADERS = kernel.h global.h kconst.h proto.h protect.h process.h
3
4 AS = nasm
5 ASFLAGS = -f elf
6 CC = gcc
7 CFLAGS = -c -I ../include
8 LD = ld
9 LDFLAGS = -s -Ttext $(ENTRYPOINT)
10
11 OBJS = kernel.o global.o init.o 8259.o main.o klib1.o klib2.o exception.o clock.o test.o
12
13 kernel.bin: $(OBJS)
14 $(LD) $(LDFLAGS) -o $@ $(OBJS)
15 rm -f $(OBJS)
16 sudo mount ../TINIX.IMG /mnt/TINIX -o loop
17 sudo cp -f $@ /mnt/TINIX
18 sudo umount /mnt/TINIX
19 rm $@
20
21 kernel.o: kernel.asm kconst.inc
22 $(AS) $(ASFLAGS) -o $@ $ <
23
24 global .o: global.c $(HEADERS)
25 $(CC) $(CFLAGS) -o $@ $<
26
27 init.o: init.c $(HEADERS)
28 $(CC) $(CFLAGS) -o $@ $<
29
30 8259.o: 8259.c $(HEADERS)
31 $(CC) $(CFLAGS) -o $@ $<
32
33 main.o: main.c $(HEADERS)
34 $(CC) $(CFLAGS) -o $@ $<
35
36 klib1.o: klib.c $(HEADERS)
37 $(CC) $(CFLAGS) -o $@ $<
38
39 klib2.o: klib.asm kconst.inc
40 $(AS) $(ASFLAGS) -o $@ $<
41
42 exception.o: exception.c $(HEADERS)
43 $(CC) $(CFLAGS) -o $@ $<
44
45 clock.o: clock.c $(HEADERS)
46 $(CC) $(CFLAGS) -o $@ $<
47
48 test.o: test.c $(HEADERS)
49 $(CC) $(CFLAGS) -o $@ $<
50
51 unmount:
52 sudo umount /mnt/TINIX
show一下运行的结果:
自己感觉还不错。
目前的kernel仍然很简陋,硬件的初始化尚未完成。异常处理也很简陋,甚至没有考虑到栈的问题。硬件中断也没有完成。
进程调度也没有实现。这些都是下一步的目标。