Skip to content

Commit b109691

Browse files
committed
Lesson 23, section 6
1 parent c473761 commit b109691

File tree

8 files changed

+44
-51
lines changed

8 files changed

+44
-51
lines changed

23-fixes/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ OBJ = ${C_SOURCES:.c=.o cpu/interrupt.o}
77
CC = /usr/local/i386elfgcc/bin/i386-elf-gcc
88
GDB = /usr/local/i386elfgcc/bin/i386-elf-gdb
99
# -g: Use debugging symbols in gcc
10-
CFLAGS = -g -ffreestanding -Wall -Wextra -fno-exceptions
10+
CFLAGS = -g -ffreestanding -Wall -Wextra -fno-exceptions -m32
1111

1212
# First rule is run by default
1313
os-image.bin: boot/bootsect.bin kernel.bin
@@ -33,7 +33,7 @@ debug: os-image.bin kernel.elf
3333
# Generic rules for wildcards
3434
# To make an object, always compile from its .c
3535
%.o: %.c ${HEADERS}
36-
${CC} ${CFLAGS} -ffreestanding -c $< -o $@
36+
${CC} ${CFLAGS} -c $< -o $@
3737

3838
%.o: %.asm
3939
nasm $< -f elf -o $@

23-fixes/README.md

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*Concepts you may want to Google beforehand: XX*
1+
*Concepts you may want to Google beforehand: freestanding, uint32_t, size_t,*
22

33
**Goal: Fix miscellaneous issues with our code**
44

@@ -16,7 +16,8 @@ We add `-ffreestanding` when compiling `.o` files, which includes `kernel_entry
1616
Before, we disabled libgcc (not libc) through the use of `-nostdlib` and we didn't re-enable
1717
it for linking. Since this is tricky, we'll delete `-nostdlib`
1818

19-
`-nostdinc` was also pased to gcc, but we will need it for step 3.
19+
`-nostdinc` was also pased to gcc, but we will need it for step 3, so let's delete it.
20+
2021

2122
2. kernel.c `main()` function
2223
-----------------------------
@@ -69,11 +70,23 @@ bit telling whether interrupts are on or off.
6970
In other words the interrupt handler automatically restores interrupts whether or not
7071
interrupts were enabled before this interrupt
7172

72-
7373
On `cpu/isr.h`, `struct registers_t` has a couple issues.
7474
First, the alleged `esp` is renamed to `useless`.
7575
The value is useless because it has to do with the current stack context, not what was interrupted.
7676
Then, we rename `useresp` to `esp`
7777

78-
Finally, we add `cld` just before `call isr_handler` on `cpu/interrupt.asm`
78+
We add `cld` just before `call isr_handler` on `cpu/interrupt.asm` as suggested
79+
by the osdev wiki.
80+
81+
There is a final, important issue with `cpu/interrupt.asm`. The common stubs create an instance
82+
of `struct registers` on the stack and then call the C handler. But that breaks the ABI, since
83+
the stack belongs to the called function and they may change them as they please. It is needed
84+
to pass the struct as a pointer.
85+
86+
To achieve this, edit `cpu/isr.h` and `cpu/isr.c` and change `registers_t r` into `registers_t *t`,
87+
then, instead of accessing the fields of the struct via `.`, access the fields of the pointer via `->`.
88+
Finally, in `cpu/interrupt.asm`, and add a `push esp` before calling both `isr_handler` and
89+
`irq_handler` -- remember to also `pop eax` to clear the pointer afterwards.
7990

91+
Both current callbacks, the timer and the keyboard, also need to be changed to use a pointer to
92+
`registers_t`.

23-fixes/cpu/interrupt.asm

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@ isr_common_stub:
1313
mov es, ax
1414
mov fs, ax
1515
mov gs, ax
16-
16+
push esp ; registers_t *r
1717
; 2. Call C handler
1818
cld ; C code following the sysV ABI requires DF to be clear on function entry
1919
call isr_handler
2020
2121
; 3. Restore state
2222
pop eax
23+
pop eax
2324
mov ds, ax
2425
mov es, ax
2526
mov fs, ax
@@ -39,9 +40,11 @@ irq_common_stub:
3940
mov es, ax
4041
mov fs, ax
4142
mov gs, ax
43+
push esp
4244
cld
4345
call irq_handler ; Different than the ISR code
4446
pop ebx ; Different than the ISR code
47+
pop ebx
4548
mov ds, bx
4649
mov es, bx
4750
mov fs, bx
@@ -110,218 +113,186 @@ global irq15
110113

111114
; 0: Divide By Zero Exception
112115
isr0:
113-
cli
114116
push byte 0
115117
push byte 0
116118
jmp isr_common_stub
117119

118120
; 1: Debug Exception
119121
isr1:
120-
cli
121122
push byte 0
122123
push byte 1
123124
jmp isr_common_stub
124125

125126
; 2: Non Maskable Interrupt Exception
126127
isr2:
127-
cli
128128
push byte 0
129129
push byte 2
130130
jmp isr_common_stub
131131

132132
; 3: Int 3 Exception
133133
isr3:
134-
cli
135134
push byte 0
136135
push byte 3
137136
jmp isr_common_stub
138137

139138
; 4: INTO Exception
140139
isr4:
141-
cli
142140
push byte 0
143141
push byte 4
144142
jmp isr_common_stub
145143

146144
; 5: Out of Bounds Exception
147145
isr5:
148-
cli
149146
push byte 0
150147
push byte 5
151148
jmp isr_common_stub
152149

153150
; 6: Invalid Opcode Exception
154151
isr6:
155-
cli
156152
push byte 0
157153
push byte 6
158154
jmp isr_common_stub
159155

160156
; 7: Coprocessor Not Available Exception
161157
isr7:
162-
cli
163158
push byte 0
164159
push byte 7
165160
jmp isr_common_stub
166161

167162
; 8: Double Fault Exception (With Error Code!)
168163
isr8:
169-
cli
170164
push byte 8
171165
jmp isr_common_stub
172166

173167
; 9: Coprocessor Segment Overrun Exception
174168
isr9:
175-
cli
176169
push byte 0
177170
push byte 9
178171
jmp isr_common_stub
179172

180173
; 10: Bad TSS Exception (With Error Code!)
181174
isr10:
182-
cli
183175
push byte 10
184176
jmp isr_common_stub
185177

186178
; 11: Segment Not Present Exception (With Error Code!)
187179
isr11:
188-
cli
189180
push byte 11
190181
jmp isr_common_stub
191182

192183
; 12: Stack Fault Exception (With Error Code!)
193184
isr12:
194-
cli
195185
push byte 12
196186
jmp isr_common_stub
197187

198188
; 13: General Protection Fault Exception (With Error Code!)
199189
isr13:
200-
cli
201190
push byte 13
202191
jmp isr_common_stub
203192

204193
; 14: Page Fault Exception (With Error Code!)
205194
isr14:
206-
cli
207195
push byte 14
208196
jmp isr_common_stub
209197

210198
; 15: Reserved Exception
211199
isr15:
212-
cli
213200
push byte 0
214201
push byte 15
215202
jmp isr_common_stub
216203

217204
; 16: Floating Point Exception
218205
isr16:
219-
cli
220206
push byte 0
221207
push byte 16
222208
jmp isr_common_stub
223209

224210
; 17: Alignment Check Exception
225211
isr17:
226-
cli
227212
push byte 0
228213
push byte 17
229214
jmp isr_common_stub
230215

231216
; 18: Machine Check Exception
232217
isr18:
233-
cli
234218
push byte 0
235219
push byte 18
236220
jmp isr_common_stub
237221

238222
; 19: Reserved
239223
isr19:
240-
cli
241224
push byte 0
242225
push byte 19
243226
jmp isr_common_stub
244227

245228
; 20: Reserved
246229
isr20:
247-
cli
248230
push byte 0
249231
push byte 20
250232
jmp isr_common_stub
251233

252234
; 21: Reserved
253235
isr21:
254-
cli
255236
push byte 0
256237
push byte 21
257238
jmp isr_common_stub
258239

259240
; 22: Reserved
260241
isr22:
261-
cli
262242
push byte 0
263243
push byte 22
264244
jmp isr_common_stub
265245

266246
; 23: Reserved
267247
isr23:
268-
cli
269248
push byte 0
270249
push byte 23
271250
jmp isr_common_stub
272251

273252
; 24: Reserved
274253
isr24:
275-
cli
276254
push byte 0
277255
push byte 24
278256
jmp isr_common_stub
279257

280258
; 25: Reserved
281259
isr25:
282-
cli
283260
push byte 0
284261
push byte 25
285262
jmp isr_common_stub
286263

287264
; 26: Reserved
288265
isr26:
289-
cli
290266
push byte 0
291267
push byte 26
292268
jmp isr_common_stub
293269

294270
; 27: Reserved
295271
isr27:
296-
cli
297272
push byte 0
298273
push byte 27
299274
jmp isr_common_stub
300275

301276
; 28: Reserved
302277
isr28:
303-
cli
304278
push byte 0
305279
push byte 28
306280
jmp isr_common_stub
307281

308282
; 29: Reserved
309283
isr29:
310-
cli
311284
push byte 0
312285
push byte 29
313286
jmp isr_common_stub
314287

315288
; 30: Reserved
316289
isr30:
317-
cli
318290
push byte 0
319291
push byte 30
320292
jmp isr_common_stub
321293

322294
; 31: Reserved
323295
isr31:
324-
cli
325296
push byte 0
326297
push byte 31
327298
jmp isr_common_stub

23-fixes/cpu/isr.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,29 +116,29 @@ char *exception_messages[] = {
116116
"Reserved"
117117
};
118118

119-
void isr_handler(registers_t r) {
119+
void isr_handler(registers_t *r) {
120120
kprint("received interrupt: ");
121121
char s[3];
122-
int_to_ascii(r.int_no, s);
122+
int_to_ascii(r->int_no, s);
123123
kprint(s);
124124
kprint("\n");
125-
kprint(exception_messages[r.int_no]);
125+
kprint(exception_messages[r->int_no]);
126126
kprint("\n");
127127
}
128128

129129
void register_interrupt_handler(uint8_t n, isr_t handler) {
130130
interrupt_handlers[n] = handler;
131131
}
132132

133-
void irq_handler(registers_t r) {
133+
void irq_handler(registers_t *r) {
134134
/* After every interrupt we need to send an EOI to the PICs
135135
* or they will not send another interrupt again */
136-
if (r.int_no >= 40) port_byte_out(0xA0, 0x20); /* slave */
136+
if (r->int_no >= 40) port_byte_out(0xA0, 0x20); /* slave */
137137
port_byte_out(0x20, 0x20); /* master */
138138

139139
/* Handle the interrupt in a more modular way */
140-
if (interrupt_handlers[r.int_no] != 0) {
141-
isr_t handler = interrupt_handlers[r.int_no];
140+
if (interrupt_handlers[r->int_no] != 0) {
141+
isr_t handler = interrupt_handlers[r->int_no];
142142
handler(r);
143143
}
144144
}

23-fixes/cpu/isr.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,13 @@ extern void irq15();
7171
#define IRQ14 46
7272
#define IRQ15 47
7373

74-
/* Struct which aggregates many registers */
74+
/* Struct which aggregates many registers.
75+
* It matches exactly the pushes on interrupt.asm. From the bottom:
76+
* - Pushed by the processor automatically
77+
* - `push byte`s on the isr-specific code: error code, then int number
78+
* - All the registers by pusha
79+
* - `push eax` whose lower 16-bits contain DS
80+
*/
7581
typedef struct {
7682
uint32_t ds; /* Data segment selector */
7783
uint32_t edi, esi, ebp, useless, ebx, edx, ecx, eax; /* Pushed by pusha. */
@@ -80,10 +86,10 @@ typedef struct {
8086
} registers_t;
8187

8288
void isr_install();
83-
void isr_handler(registers_t r);
89+
void isr_handler(registers_t *r);
8490
void irq_install();
8591

86-
typedef void (*isr_t)(registers_t);
92+
typedef void (*isr_t)(registers_t*);
8793
void register_interrupt_handler(uint8_t n, isr_t handler);
8894

8995
#endif

23-fixes/cpu/timer.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
uint32_t tick = 0;
77

8-
static void timer_callback(registers_t regs) {
8+
static void timer_callback(registers_t *regs) {
99
tick++;
1010
UNUSED(regs);
1111
}

23-fixes/drivers/keyboard.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const char sc_ascii[] = { '?', '?', '1', '2', '3', '4', '5', '6',
2525
'H', 'J', 'K', 'L', ';', '\'', '`', '?', '\\', 'Z', 'X', 'C', 'V',
2626
'B', 'N', 'M', ',', '.', '/', '?', '?', '?', ' '};
2727

28-
static void keyboard_callback(registers_t regs) {
28+
static void keyboard_callback(registers_t *regs) {
2929
/* The PIC leaves us the scancode in port 0x60 */
3030
uint8_t scancode = port_byte_in(0x60);
3131

23-fixes/kernel/kernel.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ void kernel_main() {
99
isr_install();
1010
irq_install();
1111

12+
asm("int $2");
13+
asm("int $3");
14+
1215
kprint("Type something, it will go through the kernel\n"
1316
"Type END to halt the CPU or PAGE to request a kmalloc()\n> ");
1417
}

0 commit comments

Comments
 (0)