Skip to content

Latest commit

 

History

History

Vi OS

We using GNU Assembly (GAS), it sucks a lil bit but will switch to NASM or something in the future.

GNU Asm Syntax: https://en.wikibooks.org/wiki/X86_Assembly/GNU_assembly_syntax
GNU Asm Ref: https://sourceware.org/binutils/docs/as/
Intel IA-32 manual: https://pdos.csail.mit.edu/archive/6.097/readings/intelv2.pdf
VGA Ref: http://www.osdever.net/FreeVGA/home.htm


Back to GDT (Global Descriptor Table)

resources
https://wiki.osdev.org/GDT_Tutorial http://www.osdever.net/bkerndev/Docs/gdt.htm
https://youtu.be/5LbXClJhxcs?t=408
https://stackoverflow.com/questions/23978486/far-jump-in-gdt-in-bootloader
https://stackoverflow.com/questions/52490438/why-cant-mov-set-cs-the-code-segment-register-even-though-it-can-set-others

Segmentation is a must
GDT handles segmentation, and this cannot be disabled, even if you want to use paging.

Segment Selectors= Segment Registers i.e. CS, DS, SS, ...
Every segment selector is 16 bit sized.

[   Index (13 bits)  ][T I][RPL]
15                   3  2  1   0

Request Privilege Level(0-1): 00 Highest, 11 Lowest
Table Indicator(2)          : 0 GDT, 1 LDT
Segment Index(3-15)

GDT must contain:

  • Entry 0 in the DT, called the Null Descriptor, is never referenced by the processor and should always contain no data. (its 8 bytes wide)
  • DPL 0 CS (Code Segment) Descriptor (for kernel)
  • DS Descriptor
  • Task State Segment descriptor
  • Room for more segments, if needed.

  • The CPU doesn't care where the GDT is (in memory)
  • Can sit in the kernel's data section (global var in src code)
  • To verify GDT loaded: use -monitor stdio flag w/ qemu and in terminal type: info registers and then check the DS/SS/CS and GDT registers

The Story of GDT
At the time of booting, loader (linker.ld) will load the kernel-elf into the memory as specified by linker.ld. CPU doesn't care where the GDT lives. It wants a contiguous memory containing specific bits in order. So, we declare a global var (this lives in the data section of kernel binary, loaded into RAM by bootloader) array of gdt_entries, each of which will live as long as the kernel is in memory. We encode the gdt entries at the memory location of array, and now we need to tell the cpu that GDT is located at this address in memory.

Altho, mov can set the sections like DS, SS, ES etc. the CS is read only for mov. Thus we have to long jump setting 0x08 to CS and Instruction Pointer to the next label. This is important because the bootloader has its own GDT at the time of booting, and if CS is not changed, we would still be using the bootloader's GDT henceforth.

(IntelManual#629)

The POP instruction cannot pop a value into the CS register. To load the CS register from the
stack, use the RET instruction.

Time to implement IDT

resources
http://www.osdever.net/bkerndev/Docs/idt.htm
https://wiki.osdev.org/Interrupt_Descriptor_Table
https://wiki.jwo.cz/wiki/x86_protected_mode_interrupts

The IDT entries are called gates. It can contain Interrupt Gates, Task Gates and Trap Gates.

  • On 32-bit processors, the entries in the IDT are 8 bytes long

Gate Types:
two kinds of interrupts:

  • ones that occur when code execution has encountered an Exception due to bad code,
    • save the address of the currently executing instruction so that it can be retried, these are called Traps.
  • or ones that occur to handle events unrelated to currently executing code
    • save the address of the next instruction so that execution can be resumed where it left off
    • caused by an IRQ(interrupt request) or other hardware event, or by use of the INT instruction
  • with Traps, new interrupts might occur during the service routine, but when the CPU is serving an IRQ, further interrupts are masked until an End of Interrupt signal is sent.
  • If the processor finds that a program is trying to access a piece of memory that it shouldn't, it will cause a General Protection Fault
  • The first 32 entries in the IDT correspond to Exceptions that can possibly be generated by the processor, and therefore need to be handled. Some exceptions will push another value onto the stack: an Error Code value which is specific to the exception caused.
Exception # Description Error Code?
0 Division By Zero Exception No
1 Debug Exception No
2 Non Maskable Interrupt Exception No
3 Breakpoint Exception No
4 Into Detected Overflow Exception No
5 Out of Bounds Exception No
6 Invalid Opcode Exception No
7 No Coprocessor Exception No
8 Double Fault Exception Yes
9 Coprocessor Segment Overrun Exception No
10 Bad TSS Exception Yes
11 Segment Not Present Exception Yes
12 Stack Fault Exception Yes
13 General Protection Fault Exception Yes
14 Page Fault Exception Yes
15 Unknown Interrupt Exception No
16 Coprocessor Fault Exception No
17 Alignment Check Exception (486+) No
18 Machine Check Exception (Pentium/586+) No
19 to 31 Reserved Exceptions No
Implementing PS/2 Keyboard (finally)

refs:
http://www.osdever.net/bkerndev/Docs/keyboard.htm

  • A scancode is simply a key number. The keyboard assigns a number to each key on the keyboard; this is your scancode
  • use a lookup table (an array of values) and use the scancode as the index into this table
    • The lookup table is called a keymap, and will be used to translate scancodes into ASCII values
  • if bit 7 is set (test with 'scancode & 0x80'), then this is the keyboard's way of telling us that a key was just released
  • The keyboard is attached to the computer through a special microcontroller chip on your mainboard. This keyboard controller chip has 2 channels: one for the keyboard, and one for the mouse.
  • The keyboard controller has 2 main registers: a Data register at 0x60, and a Control register at 0x64.
    • Anything that the keyboard wants to send the computer is stored into the Data register
    • keyboard will raise IRQ1 whenever it has data for us to read

http://www.osdever.net/bkerndev/Docs/keyboard.htm

    0,  27, '1', '2', '3', '4', '5', '6', '7', '8',	/* 9 */
  '9', '0', '-', '=', '\b',	/* Backspace */
  '\t',			/* Tab */
  'q', 'w', 'e', 'r',	/* 19 */
  't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',	/* Enter key */
    0,			/* 29   - Control */
  'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',	/* 39 */
 '\'', '`',   0,		/* Left shift */
 '\\', 'z', 'x', 'c', 'v', 'b', 'n',			/* 49 */
  'm', ',', '.', '/',   0,				/* Right shift */
  '*',
    0,	/* Alt */
  ' ',	/* Space bar */
    0,	/* Caps lock */
    0,	/* 59 - F1 key ... > */
    0,   0,   0,   0,   0,   0,   0,   0,
    0,	/* < ... F10 */
    0,	/* 69 - Num lock*/
    0,	/* Scroll Lock */
    0,	/* Home key */
    0,	/* Up Arrow */
    0,	/* Page Up */
  '-',
    0,	/* Left Arrow */
    0,
    0,	/* Right Arrow */
  '+',
    0,	/* 79 - End key*/
    0,	/* Down Arrow */
    0,	/* Page Down */
    0,	/* Insert Key */
    0,	/* Delete Key */
    0,   0,   0,
    0,	/* F11 Key */
    0,	/* F12 Key */
    0,	/* All other keys are undefined */