Skip to content

Commit

Permalink
Update doc for IRQ, PIT, and paging. Add customized divisor for syste…
Browse files Browse the repository at this point in the history
…m timer
  • Loading branch information
Yanhui Zhao committed Oct 30, 2019
1 parent 9ebfbd2 commit 20c7354
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 8 deletions.
70 changes: 69 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ gdb kernel.debug
(gdb) target remote :1234
```
### Register handlers
*
* time
* keyboard

## Operating System Notes (To be categorized)

Expand Down Expand Up @@ -92,6 +93,73 @@ The special, CPU-dedicated interrupts are shown below.
* 18 - Machine check exception
* 19-31 - Reserved

```c
struct idt_entry
{
unsigned short base_lo; // The lower 16 bits of the address to jump to when the interrupt fires
unsigned short sel; // Kernel segment selector
unsigned char always0; // Always zero
unsigned char flags;
unsigned short base_hi; // The upper 16 bits of the address to jump to
}
```

Flags byte format:
00110 (bit 0:4): always 00110 (decimal 10)
DPL (bit 5:6): privilege level
P (bit 7): An entry to handle interrupt is present. Any descriptor with this bit clear will cause a "Interrupt Not Handled" exception

Interrupt Requests (IRQs)

Two methods for os to communicate with external devices
* Polling: Spin in a loop, occasionally checking if the device is ready
* Interrupts: Causing a CPU interrupt when device is ready, and interrupt handler will run

All devices that are interrupt-capable have line connecting them to the PIC. The PIC is the only device that is directly connected to the CPU's interrupt pin. Two PICs (master and slave) are in modern PC, serving a total of 15 interruptable devices (one line is sued to signal the slave PIC)

PIC mappings can be remapped, default mappings are:
* IRQ 0:7 - INT 0x8:0xF
* IRQ 8:15 - INT 0x70:0x77

To avoid conflict with CPU signal exceptions, IRQs 0:15 usually gets remapped to ISRs 32:47

Communicating with PICs:
* Master: control port (0x20), data port (0x21)
* Slave: control port (0xA0), data port (0xA1)

Programmable Interval Timer (PIT) is a chip connected to IRQ0. It can interrupt the CPU at a user-defined rate (18.2HZ and 1.1931MHZ). The PIT is the primary method used for implementing a system clock. Internal clock oscillates at around 1.1931MHz, and is fed with frequency divider to module the final output frequency.

Three channels:
* Channel 0: Output is connected to IRQ0
* Channel 1: Used to control refresh rates for DRAM (no longer implemented)
* Channel 2: Controls the PC speaker

Communicating with PIT:
control port (0x43), channel 0 data port (0x40), channel 1 data port (0x41), channel 2 data port (0x42)

Paging is used for memory protection and virtual memory. Virtual address space is usually split into 4K (0x1000) blocks called pages. Pages can be mapped on to frames of same block size to physical memory.

Page table entry format:
P: (bit 0): Set if the page is present in memory
R/W: (bit 1): Set if the page is writeable, unset if the page is read-only. Not applied when code is running in kernel-mode
U/S (bit 2): Set if the page is in user-mode, unset if the page is in supervisor(kernel)-mode. User-mode code can not write to or read from kernel-mode pages
Reserved (bit 3:4): Used by CPU internally
A (bit 5): Set if the page has been accessed (set by the CPU)
D (bit 6): Set if the page has been written to (become dirty)
Reserved (bit 7:8): Used by CPU internally
AVAIL (bit 9:11): Unused and available for kernel-use
Page frame address (bit 12:31): The high 20 bits of the frame address in physical memory

Enabling paging:
1. Copy the location of the page directory into the CR3 register
2. Set the PG bit in the CR0 register

Page faults can be caused:
* Reading from or writing to an area of memory that is not mapped ('present' flag is not set)
* The process is in user-mode and tries to write to a read-only page
* The process is in user-mode and tries to access a kernel-only page
* The page table entry is corrupted (the reserved bits have been overwritten)

## References and Further Reading
* http://www.osdever.net/bkerndev/index.php
* http://www.jamesmolloy.co.uk/tutorial_html/
Expand Down
2 changes: 1 addition & 1 deletion include/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ void irq_install_handler(int irq, void (*handler)(struct regs *r));
void irq_uninstall_handler(int irq);
void irq_install();

void timer_install();
void timer_install(unsigned int frequency);

void keyborad_install();

Expand Down
8 changes: 5 additions & 3 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,14 @@ void main()
idt_install();
isrs_install();
irq_install();
timer_install();
timer_install(10);
keyborad_install();
init_video();
__asm__ __volatile__("sti");
puts("System Start!\n");
//int i = 8 / 0;
//puts(i);
// int i = 8 / 0;
// puts(i);
// asm volatile ("int $0x3");
// asm volatile ("int $0x4");
for(;;);
}
2 changes: 1 addition & 1 deletion start.asm
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ gdt_flush:
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:flush2 ; 0x08 is the offset to the code segment, jmp to flush2 in the code segment (0x08 offset) and set the current cs with target cs
jmp 0x08:flush2 ; 0x08 is the offset to the code segment, jmp to flush2 in the code segment (0x08 offset) and set the current cs with target
flush2:
ret

Expand Down
13 changes: 11 additions & 2 deletions timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,22 @@ void timer_handler(struct regs *r)
timer_ticks++;
if (timer_ticks % 18 == 0)
{
puts("One second has passed!\n");
puts("One system second has passed!\n");
}
}

void timer_install()
void timer_install(unsigned int frequency)
{
irq_install_handler(0, timer_handler);

unsigned int divisor = 1193180 / frequency;
outportb(0x43, 0x36);
unsigned char l = (unsigned char)(divisor & 0xFF);
unsigned char h = (unsigned char)((divisor >> 8) & 0xFF);

outportb(0x40, l);
outportb(0x40, h);

}

void timer_wait(int ticks)
Expand Down

0 comments on commit 20c7354

Please sign in to comment.