| .. | ||
| boot | ||
| cpu | ||
| drivers | ||
| kernel | ||
| libc | ||
| Makefile | ||
| README.md | ||
Concepts you may want to Google beforehand: freestanding, uint32_t, size_t
Goal: Fix miscellaneous issues with our code
The OSDev wiki has a section which describes some issues with JamesM's tutorial. Since we followed his tutorial for lessons 18-22 (interrupts through malloc), we'll need to make sure we fix any of the issues before moving on.
- Wrong CFLAGS
We add  -ffreestanding when compiling .o files, which includes kernel_entry.o and thus
kernel.bin and os-image.bin.
Before, we disabled libgcc (not libc) through the use of -nostdlib and we didn't re-enable
it for linking. Since this is tricky, we'll delete -nostdlib
-nostdinc was also passed to gcc, but we will need it for step 3, so let's delete it.
- kernel.c main()function
Modify kernel/kernel.c and change main() to kernel_main() since gcc recognizes "main" as
a special keyword and we don't want to mess with that.
Change boot/kernel_entry.asm to point to the new name accordingly.
To fix the i386-elf-ld: warning: cannot find entry symbol _start; defaulting to 0000000000001000
warning message, add a global _start; and define the _start: label in boot/kernel_entry.asm.
- Reinvented datatypes
It looks like it was a bad idea to define non-standard data types like u32 and such, since
C99 introduces standard fixed-width data types like uint32_t
We need to include <stdint.h> which works even in -ffreestanding (but requires stdlibs)
and use those data types instead of our own, then delete them on type.h
We also delete the underscores around __asm__ and __volatile__ since they aren't needed.
- Improperly aligned kmalloc
First, since kmalloc uses a size parameter, we'll use the correct data type size_t instead
of u32int_t. size_t should be used for all parameters which "count" stuff and cannot be
negative. Include <stddef.h>.
We will fix our kmalloc in the future, making it a proper memory manager and aligning data types.
For now, it will always return a new page-aligned memory block.
- Missing functions
We will implement the missing mem* functions in following lessons
- Interrupt handlers
cli is redundant, since we already established on the IDT entries if interrupts
are enabled within a handler using the idt_gate_t flags.
sti is also redundant, as iret loads the eflags value from the stack, which contains a
bit telling whether interrupts are on or off.
In other words the interrupt handler automatically restores interrupts whether or not
interrupts were enabled before this interrupt
On cpu/isr.h, struct registers_t has a couple issues.
First, the alleged esp is renamed to useless.
The value is useless because it has to do with the current stack context, not what was interrupted.
Then, we rename useresp to esp
We add cld just before call isr_handler on cpu/interrupt.asm as suggested
by the osdev wiki.
There is a final, important issue with cpu/interrupt.asm. The common stubs create an instance
of struct registers on the stack and then call the C handler. But that breaks the ABI, since
the stack belongs to the called function and they may change them as they please. It is needed
to pass the struct as a pointer.
To achieve this, edit cpu/isr.h and cpu/isr.c and change registers_t r into registers_t *t,
then, instead of accessing the fields of the struct via ., access the fields of the pointer via ->.
Finally, in cpu/interrupt.asm, and add a push esp before calling both isr_handler and
irq_handler -- remember to also pop eax to clear the pointer afterwards.
Both current callbacks, the timer and the keyboard, also need to be changed to use a pointer to
registers_t.