Compare commits
13 Commits
03aecd514f
...
main
Author | SHA1 | Date | |
---|---|---|---|
3fd818395d | |||
8a18cf5633 | |||
88921f024e | |||
ed2c0a3568 | |||
2ec3e259d8 | |||
99a842df7e | |||
af596cd43a | |||
779680987f | |||
45c167568c | |||
a009462c72 | |||
7669ea32a4 | |||
98f8a0dc88 | |||
f216c32f22 |
3
TODO.md
3
TODO.md
@ -6,8 +6,9 @@
|
|||||||
lets implmeent some better testing functions aswell
|
lets implmeent some better testing functions aswell
|
||||||
- Paging & virtual memory
|
- Paging & virtual memory
|
||||||
- Get GRUB to show memory map - DONE
|
- Get GRUB to show memory map - DONE
|
||||||
- Write a page allocator - WIP
|
- Write a page allocator - DONE
|
||||||
- Setup paging
|
- Setup paging
|
||||||
|
- Setup virtual memory
|
||||||
- Setup higher half kernel
|
- Setup higher half kernel
|
||||||
- Heap allocator (malloc)
|
- Heap allocator (malloc)
|
||||||
- after this, implment some data structures? cleanup queue?
|
- after this, implment some data structures? cleanup queue?
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
gdtr DW 0 ; limit store
|
gdtr DW 0 ; limit store
|
||||||
DD 0 ; base storage
|
DD 0 ; base storage
|
||||||
|
|
||||||
global setGdt
|
global set_gdt
|
||||||
setGdt:
|
set_gdt:
|
||||||
mov ax, [esp + 4]
|
mov ax, [esp + 4]
|
||||||
mov [gdtr], ax
|
mov [gdtr], ax
|
||||||
mov eax, [esp + 8]
|
mov eax, [esp + 8]
|
||||||
@ -10,8 +10,8 @@ setGdt:
|
|||||||
lgdt [gdtr]
|
lgdt [gdtr]
|
||||||
ret
|
ret
|
||||||
|
|
||||||
global reloadSegments
|
global reload_segments
|
||||||
reloadSegments:
|
reload_segments:
|
||||||
jmp 0x08:.reload_CS ; 0x08 is a stand in for the code segment
|
jmp 0x08:.reload_CS ; 0x08 is a stand in for the code segment
|
||||||
.reload_CS:
|
.reload_CS:
|
||||||
mov ax, 0x10 ; stand in for the data segment
|
mov ax, 0x10 ; stand in for the data segment
|
||||||
|
@ -26,8 +26,58 @@
|
|||||||
* etc, by going through the CPU permission system (RING 0 - 3)
|
* etc, by going through the CPU permission system (RING 0 - 3)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define GDT_SIZE 5
|
||||||
|
|
||||||
|
// Each define here is for a specific flag in the descriptor.
|
||||||
|
// Refer to the intel documentation for a description of what each one does.
|
||||||
|
#define SEG_DESCTYPE(x) ((x) << 0x04) // Descriptor type (0 for system, 1 for code/data)
|
||||||
|
#define SEG_PRES(x) ((x) << 0x07) // Present
|
||||||
|
#define SEG_SAVL(x) ((x) << 0x0C) // Available for system use
|
||||||
|
#define SEG_LONG(x) ((x) << 0x0D) // Long mode
|
||||||
|
#define SEG_SIZE(x) ((x) << 0x0E) // Size (0 for 16-bit, 1 for 32)
|
||||||
|
#define SEG_GRAN(x) ((x) << 0x0F) // Granularity (0 for 1B - 1MB, 1 for 4KB - 4GB)
|
||||||
|
#define SEG_PRIV(x) (((x) & 0x03) << 0x05) // Set privilege level (0 - 3)
|
||||||
|
|
||||||
|
#define SEG_DATA_RD 0x00 // Read-Only
|
||||||
|
#define SEG_DATA_RDA 0x01 // Read-Only, accessed
|
||||||
|
#define SEG_DATA_RDWR 0x02 // Read/Write
|
||||||
|
#define SEG_DATA_RDWRA 0x03 // Read/Write, accessed
|
||||||
|
#define SEG_DATA_RDEXPD 0x04 // Read-Only, expand-down
|
||||||
|
#define SEG_DATA_RDEXPDA 0x05 // Read-Only, expand-down, accessed
|
||||||
|
#define SEG_DATA_RDWREXPD 0x06 // Read/Write, expand-down
|
||||||
|
#define SEG_DATA_RDWREXPDA 0x07 // Read/Write, expand-down, accessed
|
||||||
|
#define SEG_CODE_EX 0x08 // Execute-Only
|
||||||
|
#define SEG_CODE_EXA 0x09 // Execute-Only, accessed
|
||||||
|
#define SEG_CODE_EXRD 0x0A // Execute/Read
|
||||||
|
#define SEG_CODE_EXRDA 0x0B // Execute/Read, accessed
|
||||||
|
#define SEG_CODE_EXC 0x0C // Execute-Only, conforming
|
||||||
|
#define SEG_CODE_EXCA 0x0D // Execute-Only, conforming, accessed
|
||||||
|
#define SEG_CODE_EXRDC 0x0E // Execute/Read, conforming
|
||||||
|
#define SEG_CODE_EXRDCA 0x0F // Execute/Read, conforming, accessed
|
||||||
|
|
||||||
|
#define GDT_CODE_PL0 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \
|
||||||
|
SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \
|
||||||
|
SEG_PRIV(0) | SEG_CODE_EXRD
|
||||||
|
|
||||||
|
#define GDT_DATA_PL0 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \
|
||||||
|
SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \
|
||||||
|
SEG_PRIV(0) | SEG_DATA_RDWR
|
||||||
|
|
||||||
|
#define GDT_CODE_PL3 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \
|
||||||
|
SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \
|
||||||
|
SEG_PRIV(3) | SEG_CODE_EXRD
|
||||||
|
|
||||||
|
#define GDT_DATA_PL3 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \
|
||||||
|
SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \
|
||||||
|
SEG_PRIV(3) | SEG_DATA_RDWR
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint64_t gdt[GDT_SIZE];
|
uint64_t gdt[GDT_SIZE];
|
||||||
|
|
||||||
|
void set_gdt(unsigned short limit, uint64_t* base);
|
||||||
|
void reload_segments(void);
|
||||||
|
|
||||||
uint64_t create_descriptor(uint32_t base, uint32_t limit, uint16_t flag)
|
uint64_t create_descriptor(uint32_t base, uint32_t limit, uint16_t flag)
|
||||||
{
|
{
|
||||||
uint64_t descriptor;
|
uint64_t descriptor;
|
||||||
@ -63,11 +113,11 @@ void gdt_init(void)
|
|||||||
gdt[0] = create_descriptor(0, 0, 0); // null
|
gdt[0] = create_descriptor(0, 0, 0); // null
|
||||||
gdt[1] = create_descriptor(0, 0x000FFFFF, (GDT_CODE_PL0)); // kernel code
|
gdt[1] = create_descriptor(0, 0x000FFFFF, (GDT_CODE_PL0)); // kernel code
|
||||||
gdt[2] = create_descriptor(0, 0x000FFFFF, (GDT_DATA_PL0)); // kernel data
|
gdt[2] = create_descriptor(0, 0x000FFFFF, (GDT_DATA_PL0)); // kernel data
|
||||||
//gdt[3] = create_descriptor(0, 0x000FFFFF, (GDT_CODE_PL3)); // user code
|
gdt[3] = create_descriptor(0, 0x000FFFFF, (GDT_CODE_PL3)); // user code
|
||||||
//gdt[4] = create_descriptor(0, 0x000FFFFF, (GDT_DATA_PL3)); // user data
|
gdt[4] = create_descriptor(0, 0x000FFFFF, (GDT_DATA_PL3)); // user data
|
||||||
|
|
||||||
setGdt((sizeof(uint64_t) * GDT_SIZE) - 1, &(gdt[0])); // limit, base
|
set_gdt((sizeof(uint64_t) * GDT_SIZE) - 1, &(gdt[0])); // limit, base
|
||||||
reloadSegments();
|
reload_segments();
|
||||||
#ifdef __TESTING__
|
#ifdef __TESTING__
|
||||||
kinfo("Initialized the GDT");
|
kinfo("Initialized the GDT");
|
||||||
#endif
|
#endif
|
||||||
@ -76,4 +126,31 @@ void gdt_init(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef SEG_DESCTYPE
|
||||||
|
#undef SEG_PRES
|
||||||
|
#undef SEG_SAVL
|
||||||
|
#undef SEG_LONG
|
||||||
|
#undef SEG_SIZE
|
||||||
|
#undef SEG_GRAN
|
||||||
|
#undef SEG_PRIV
|
||||||
|
#undef SEG_DATA_RD
|
||||||
|
#undef SEG_DATA_RDA
|
||||||
|
#undef SEG_DATA_RDWR
|
||||||
|
#undef SEG_DATA_RDWRA
|
||||||
|
#undef SEG_DATA_RDEXPD
|
||||||
|
#undef SEG_DATA_RDEXPDA
|
||||||
|
#undef SEG_DATA_RDWREXPD
|
||||||
|
#undef SEG_DATA_RDWREXPDA
|
||||||
|
#undef SEG_CODE_EX
|
||||||
|
#undef SEG_CODE_EXA
|
||||||
|
#undef SEG_CODE_EXRD
|
||||||
|
#undef SEG_CODE_EXRDA
|
||||||
|
#undef SEG_CODE_EXC
|
||||||
|
#undef SEG_CODE_EXCA
|
||||||
|
#undef SEG_CODE_EXRDC
|
||||||
|
#undef SEG_CODE_EXRDCA
|
||||||
|
#undef GDT_CODE_PL0
|
||||||
|
#undef GDT_DATA_PL0
|
||||||
|
#undef GDT_CODE_PL3
|
||||||
|
#undef GDT_DATA_PL3
|
||||||
|
#undef GDT_SIZE
|
||||||
|
@ -10,22 +10,35 @@
|
|||||||
#include <kernel/x86/io.h>
|
#include <kernel/x86/io.h>
|
||||||
#include <kernel/x86/keyb.h>
|
#include <kernel/x86/keyb.h>
|
||||||
|
|
||||||
|
#define IDT_MAX_DESCRIPTORS 48 // number of entries in the idt table
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t isr_low; // The lower 16 bits of the ISR's address
|
||||||
|
uint16_t kernel_cs; // The GDT segment selector that the CPU will load into CS before calling the ISR
|
||||||
|
uint8_t reserved; // set to zero
|
||||||
|
uint8_t attributes; // Type and attributes
|
||||||
|
uint16_t isr_high; // The higher 16 bits of the ISR's address
|
||||||
|
} __attribute__((packed)) idt_entry_t;
|
||||||
|
|
||||||
__attribute__((aligned(0x10)))
|
__attribute__((aligned(0x10)))
|
||||||
static idt_entry_t idt[256];
|
static idt_entry_t idt[256];
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t limit;
|
||||||
|
uint32_t base;
|
||||||
|
} __attribute__((packed)) idtr_t;
|
||||||
|
|
||||||
static idtr_t idtr;
|
static idtr_t idtr;
|
||||||
|
|
||||||
static bool vectors[IDT_MAX_DESCRIPTORS];
|
|
||||||
|
|
||||||
|
static bool vectors[IDT_MAX_DESCRIPTORS];
|
||||||
extern struct pit_state pit;
|
extern struct pit_state pit;
|
||||||
|
|
||||||
#define EXTERNAL_BIT (0x1)
|
#define EXTERNAL_BIT (0x1)
|
||||||
|
|
||||||
#define TBL_GDT (0x0)
|
#define TBL_GDT (0x0)
|
||||||
#define TBL_LDT (0x2)
|
#define TBL_LDT (0x2)
|
||||||
#define TBL_IDT (0x1)
|
#define TBL_IDT (0x1)
|
||||||
#define TBL_IDT_TWO (0x3)
|
#define TBL_IDT_TWO (0x3)
|
||||||
|
|
||||||
static void examine_selector(uint32_t selector)
|
static void examine_selector(uint32_t selector)
|
||||||
{
|
{
|
||||||
printf("The interrupt arised %s.\n", (selector & EXTERNAL_BIT) == EXTERNAL_BIT ? "externally" : "internally");
|
printf("The interrupt arised %s.\n", (selector & EXTERNAL_BIT) == EXTERNAL_BIT ? "externally" : "internally");
|
||||||
@ -44,11 +57,11 @@ static void examine_selector(uint32_t selector)
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef TBL_GDT
|
#undef TBL_GDT
|
||||||
#undef TBL_LDT
|
#undef TBL_LDT
|
||||||
#undef TBL_IDT
|
#undef TBL_IDT
|
||||||
#undef TBL_IDT_TWO
|
#undef TBL_IDT_TWO
|
||||||
|
#undef EXTERNAL_BIT
|
||||||
|
|
||||||
#define PF_P (1 << 0)
|
#define PF_P (1 << 0)
|
||||||
#define PF_W (1 << 1)
|
#define PF_W (1 << 1)
|
||||||
@ -119,7 +132,29 @@ static void dump_cpu_state(struct cpu_state cpu, struct stack_state stack)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define EXCEPTION_LOCATION() printf("Exception occurred at 0x%2\n", stack.eip)
|
#define EXCEPTION_LOCATION() printf("Exception occurred at 0x%2\n", stack.eip)
|
||||||
|
#define EXCEPT_DIV_ERR 0
|
||||||
|
#define EXCEPT_DEBUG 1
|
||||||
|
#define EXCEPT_NMI 2
|
||||||
|
#define EXCEPT_BREAKPOINT 3
|
||||||
|
#define EXCEPT_OVERFLOW 4
|
||||||
|
#define EXCEPT_BOUND_RANGE_EXCEEDED 5
|
||||||
|
#define EXCEPT_INVALID_OPCODE 6
|
||||||
|
#define EXCEPT_DEVICE_NOT_AVAILABLE 7
|
||||||
|
#define EXCEPT_DOUBLE_FAULT 8
|
||||||
|
#define EXCEPT_INVALID_TSS 10
|
||||||
|
#define EXCEPT_SEG_NOT_PRESENT 11
|
||||||
|
#define EXCEPT_STACK_SEG_FAULT 12
|
||||||
|
#define EXCEPT_GENERAL_PROTECTION 13
|
||||||
|
#define EXCEPT_PAGE_FAULT 14
|
||||||
|
#define EXCEPT_FLOATING_POINT_ERR_FPU 16
|
||||||
|
#define EXCEPT_ALIGNMENT_CHECK 17
|
||||||
|
#define EXCEPT_MACHINE_CHECK 18
|
||||||
|
#define EXCEPT_FLOATING_POINT_ERR_SIMD 19
|
||||||
|
#define EXCEPT_VIRT 20
|
||||||
|
#define EXCEPT_CTRL_PROT 21
|
||||||
|
#define EXCEPT_HYPERVISOR_INJECTION 28
|
||||||
|
#define EXCEPT_VMM_COMMUNICATION 29
|
||||||
|
#define EXCEPT_SECURITY_EXCEPTION 30
|
||||||
void exception_handler(struct cpu_state __attribute__((unused)) cpu, uint32_t interrupt, struct stack_state stack)
|
void exception_handler(struct cpu_state __attribute__((unused)) cpu, uint32_t interrupt, struct stack_state stack)
|
||||||
{
|
{
|
||||||
uint32_t inbyte;
|
uint32_t inbyte;
|
||||||
@ -157,8 +192,8 @@ void exception_handler(struct cpu_state __attribute__((unused)) cpu, uint32_t in
|
|||||||
break;
|
break;
|
||||||
case EXCEPT_DOUBLE_FAULT:
|
case EXCEPT_DOUBLE_FAULT:
|
||||||
kerror("EXCEPTION: DOUBLE FAULT");
|
kerror("EXCEPTION: DOUBLE FAULT");
|
||||||
__asm__ volatile ("cli; hlt"); // boned
|
__asm__ volatile ("cli; hlt"); // boned break;
|
||||||
break;
|
break; // don't need t his but -Werror lol
|
||||||
case EXCEPT_INVALID_TSS:
|
case EXCEPT_INVALID_TSS:
|
||||||
kerror("EXCEPTION: INVALID TSS");
|
kerror("EXCEPTION: INVALID TSS");
|
||||||
examine_selector(stack.error_code);
|
examine_selector(stack.error_code);
|
||||||
@ -249,6 +284,30 @@ void exception_handler(struct cpu_state __attribute__((unused)) cpu, uint32_t in
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#undef EXCEPT_DIV_ERR
|
||||||
|
#undef EXCEPT_DEBUG
|
||||||
|
#undef EXCEPT_NMI
|
||||||
|
#undef EXCEPT_BREAKPOINT
|
||||||
|
#undef EXCEPT_OVERFLOW
|
||||||
|
#undef EXCEPT_BOUND_RANGE_EXCEEDED
|
||||||
|
#undef EXCEPT_INVALID_OPCODE
|
||||||
|
#undef EXCEPT_DEVICE_NOT_AVAILABLE
|
||||||
|
#undef EXCEPT_DOUBLE_FAULT
|
||||||
|
#undef EXCEPT_INVALID_TSS
|
||||||
|
#undef EXCEPT_SEG_NOT_PRESENT
|
||||||
|
#undef EXCEPT_STACK_SEG_FAULT
|
||||||
|
#undef EXCEPT_GENERAL_PROTECTION
|
||||||
|
#undef EXCEPT_PAGE_FAULT
|
||||||
|
#undef EXCEPT_FLOATING_POINT_ERR_FPU
|
||||||
|
#undef EXCEPT_ALIGNMENT_CHECK
|
||||||
|
#undef EXCEPT_MACHINE_CHECK
|
||||||
|
#undef EXCEPT_FLOATING_POINT_ERR_SIMD
|
||||||
|
#undef EXCEPT_VIRT
|
||||||
|
#undef EXCEPT_CTRL_PROT
|
||||||
|
#undef EXCEPT_HYPERVISOR_INJECTION
|
||||||
|
#undef EXCEPT_VMM_COMMUNICATION
|
||||||
|
#undef EXCEPT_SECURITY_EXCEPTION
|
||||||
|
#undef EXCEPTION_LOCATION
|
||||||
|
|
||||||
void idt_set_descriptor(uint8_t vector, void *isr, uint8_t flags)
|
void idt_set_descriptor(uint8_t vector, void *isr, uint8_t flags)
|
||||||
{
|
{
|
||||||
@ -288,3 +347,5 @@ void idt_init(void)
|
|||||||
kinfo("Initialized the IDT");
|
kinfo("Initialized the IDT");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef IDT_MAX_DESCRIPTORS
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <kernel/paging.h>
|
|
||||||
|
|
||||||
//extern uint32_t endkernel; // found in link.ld
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The page table must be page aligned (aligned at 4KiB)
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* This is a temporary solution, as we want a page frame allocator, to properly get page frames.. but this works for now
|
|
||||||
*/
|
|
||||||
uint32_t page_directory[PAGE_DIRECTORY_ENTRIES] __attribute__((aligned(4096)));
|
|
||||||
|
|
||||||
uint32_t first_page_table[PAGE_TABLE_ENTRIES] __attribute__((aligned(4096)));
|
|
||||||
|
|
||||||
void setup_page_table(void)
|
|
||||||
{
|
|
||||||
uint32_t i;
|
|
||||||
for (i = 0; i < PAGE_TABLE_ENTRIES; i++) {
|
|
||||||
first_page_table[i] = (i * 0x1000) | 3; // supervisor, r/w, present
|
|
||||||
}
|
|
||||||
puts("test");
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup_page_dir(void)
|
|
||||||
{
|
|
||||||
setup_page_table();
|
|
||||||
/**
|
|
||||||
* Now that we have a page directory, we need to blank it.
|
|
||||||
*
|
|
||||||
* The page directory should have exactly 1024 entries. We will set each entry to not present, so that the if the
|
|
||||||
* MMU looks for that page table, it will see that it is not there yet.
|
|
||||||
*/
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < PAGE_DIRECTORY_ENTRIES; i++) {
|
|
||||||
// This sets the following flags to the pages:
|
|
||||||
// Supervisor: Only kernel-mode can access them
|
|
||||||
// Write Enabled: It can be both read from and written to
|
|
||||||
// Not Present: The page table is not present
|
|
||||||
page_directory[i] = 0x00000002;
|
|
||||||
}
|
|
||||||
|
|
||||||
page_directory[0] = ((uint32_t) first_page_table) | 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup_paging(void)
|
|
||||||
{
|
|
||||||
setup_page_dir();
|
|
||||||
|
|
||||||
load_page_directory(page_directory);
|
|
||||||
enable_paging();
|
|
||||||
}
|
|
86
kernel/arch/paging/paging.h
Normal file
86
kernel/arch/paging/paging.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/**
|
||||||
|
* The page direcotry and the page table have very specific
|
||||||
|
* entry formats.
|
||||||
|
*
|
||||||
|
* They will be defined here, and constants will be properly allocated.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page directory
|
||||||
|
* containes 1024 4 byte entries, making them 4KiB each.
|
||||||
|
*
|
||||||
|
* In the page directory, each entry points to a page table.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Page Directory Entry
|
||||||
|
*
|
||||||
|
* (this is following the page size of 0, or 4KiB)
|
||||||
|
* bits:
|
||||||
|
* 31 - 12 : Bits 31-12 of address
|
||||||
|
* 11 - 8 : AVL
|
||||||
|
* 7 : PS
|
||||||
|
* 6 : AVL
|
||||||
|
* 5 : A
|
||||||
|
* 4 : PCD
|
||||||
|
* 3 : PWT
|
||||||
|
* 2 : U/S
|
||||||
|
* 1 : R/W
|
||||||
|
* 0 : P
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* The address field represnets the physical address of the page table that manages the four megabytes at that point.
|
||||||
|
* It is very important that this address by 4KiB aligned. As the remainder of bytes are overwritten by access bits and such.
|
||||||
|
*
|
||||||
|
* P: Present
|
||||||
|
* If the bit is set, the page is actually in physical memory at the moment. For example, when a page is swapped out, it is not in physical memory and therefor not 'Present'.
|
||||||
|
* If a page is called, but not present, a page fault will occur, and the OS should handle it.
|
||||||
|
* R/W: Read/Write
|
||||||
|
* If the big is set, the page is read/write. Otherwise, it is read-only. The WP bit in CR0 determines if this is only applied to userland, always giving the kernel write access (the default)
|
||||||
|
* or both userland and the kernel. (see Intel Manuals 3A 2-20)
|
||||||
|
* U/S: User/Supervisor
|
||||||
|
* Controls access to the page based on privelege level. If the bit is set, then the page may be accessed by all; if the bit is not set, however,
|
||||||
|
* only the supervisor can access it. For ap age directory entry, the user bit controls access to all the pages referenced by the page directory entry.
|
||||||
|
* Therefore if you wish to make a page a user page, you must set the bit in the releveant page directory, as well as the page table entry.
|
||||||
|
* PWT: Write-through
|
||||||
|
* Controls Write-through abilities of the page. If the bit is set, write-through caching is enabled.
|
||||||
|
* If not, then write-back is enabled instead.
|
||||||
|
* PCD: Cache Disable
|
||||||
|
* Cache disable bit, if the bit is set, the page will not be cached. Otherwise, it will be.
|
||||||
|
* A: Accessed
|
||||||
|
* Accessed is used to discover whether a PDE or PTE was read during virtual address translation. If it has, then the bit is set, otherwise it is not.
|
||||||
|
* Note that, this bit will not be cleared by the CPU, so that burden falls on the OS (if its needed at all).
|
||||||
|
* D: Dirty
|
||||||
|
* Dirty is used to determine wether a page has been written to.
|
||||||
|
* PS: Page Size (always 0, since we're using 4KiB pages)
|
||||||
|
* Stores the page size for that specific entry. If the bit is set, then the PDE maps a page that is 4MiB in size. Otherwise, it maps to a 4KiB page table.
|
||||||
|
* AVL: Available
|
||||||
|
* These bits are unused and are free for the OS to use for accounting information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page Table
|
||||||
|
*
|
||||||
|
* In each page table, as it is, there are also 1024 entries. Each entry points to a 4KiB physical page frame.
|
||||||
|
*
|
||||||
|
* These are called page table entries, and are very similar to the entries described above.
|
||||||
|
*
|
||||||
|
* The first item is a 4KiB aligned physical address. However, these point to a 4KiB block of physical memory, which si then mapped to that location in the page table and driectory.
|
||||||
|
*
|
||||||
|
* 31 - 12 : Bits 31-12 of address
|
||||||
|
* 11 - 9 : AVL
|
||||||
|
* 8 : G
|
||||||
|
* 7 : PAT
|
||||||
|
* 6 : D
|
||||||
|
* 5 : A
|
||||||
|
* 4 : PCD
|
||||||
|
* 3 : PWT
|
||||||
|
* 2 : U/S
|
||||||
|
* 1 : R/W
|
||||||
|
* 0 : P
|
||||||
|
*
|
||||||
|
* G: Global
|
||||||
|
* Tells the processor not to invalidate the TLB entry corresponding to the page upon a MOV to CR3 instruction.
|
||||||
|
* Bit 7 (PGE) in CR4 must be set to enable global pages.
|
||||||
|
* PAT: Page Attribute Table
|
||||||
|
* If PAT is supported, then PAT along with PCD and PWT shall indicate the memory caching type. Otherwise, it is reserved and must be set to 0.
|
||||||
|
*/
|
@ -1,20 +0,0 @@
|
|||||||
global load_page_directory
|
|
||||||
load_page_directory:
|
|
||||||
push ebp
|
|
||||||
mov esp, ebp
|
|
||||||
mov eax, [esp + 4]
|
|
||||||
mov cr3, eax
|
|
||||||
mov esp, ebp
|
|
||||||
pop ebp
|
|
||||||
ret
|
|
||||||
|
|
||||||
global enable_paging
|
|
||||||
enable_paging:
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
mov eax, cr0
|
|
||||||
or eax, 0x80000000
|
|
||||||
mov cr0, eax
|
|
||||||
mov esp, ebp
|
|
||||||
pop ebp
|
|
||||||
ret
|
|
@ -5,6 +5,33 @@
|
|||||||
#include <kernel/x86/io.h>
|
#include <kernel/x86/io.h>
|
||||||
#include <kernel/x86/pic.h>
|
#include <kernel/x86/pic.h>
|
||||||
|
|
||||||
|
/** PIC I/O ports **/
|
||||||
|
#define PIC1 0x20 /** Master PIC **/
|
||||||
|
#define PIC2 0xA0 /** Slave PIC **/
|
||||||
|
|
||||||
|
/** PIC helper defines **/
|
||||||
|
#define PIC1_COMMAND (PIC1)
|
||||||
|
#define PIC1_DATA (PIC1 + 1)
|
||||||
|
#define PIC2_COMMAND (PIC2)
|
||||||
|
#define PIC2_DATA (PIC2 + 1)
|
||||||
|
|
||||||
|
/** PIC Commands **/
|
||||||
|
#define ICW1_ICW4 0x01 /** Indicates ICW4 will be present **/
|
||||||
|
#define ICW1_SINGLE 0x02 /** Single (cascade mode) **/
|
||||||
|
#define ICW1_INTERVAL4 0x04 /** Call address interval 4 (8) **/
|
||||||
|
#define ICW1_LEVEL 0x08 /** Level triggered (edge) mode **/
|
||||||
|
#define ICW1_INIT 0x10 /** Initialization **/
|
||||||
|
|
||||||
|
#define ICW4_8086 0x01 /** 8086/88 (MCS-80/85) mode **/
|
||||||
|
#define ICW4_AUTO 0x02 /** Auto (normal) EOI **/
|
||||||
|
#define ICW4_BUF_SLAVE 0x08 /** Buffered mode/slave **/
|
||||||
|
#define ICW4_BUF_MASTER 0x0C /** Buffered mode/master **/
|
||||||
|
#define ICW4_SFNM 0x10 /** Special fully nested (not) **/
|
||||||
|
|
||||||
|
#define PIC_EOI 0x20 /** End-of-interrupt command code **/
|
||||||
|
#define PIC_READ_IRR 0x0a /** OCW3 irq ready next CMD read **/
|
||||||
|
#define PIC_READ_ISR 0x0b /** OCW3 irq service next CMD read **/
|
||||||
|
|
||||||
void PIC_sendEOI(uint8_t irq)
|
void PIC_sendEOI(uint8_t irq)
|
||||||
{
|
{
|
||||||
if (irq >= 8) // if we're over the PIC1 limit
|
if (irq >= 8) // if we're over the PIC1 limit
|
||||||
@ -123,3 +150,22 @@ uint16_t pic_get_isr(void)
|
|||||||
return __pic_get_irq_reg(PIC_READ_ISR);
|
return __pic_get_irq_reg(PIC_READ_ISR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef PIC1
|
||||||
|
#undef PIC2
|
||||||
|
#undef PIC1_COMMAND
|
||||||
|
#undef PIC1_DATA
|
||||||
|
#undef PIC2_COMMAND
|
||||||
|
#undef PIC2_DATA
|
||||||
|
#undef ICW1_ICW4
|
||||||
|
#undef ICW1_SINGLE
|
||||||
|
#undef ICW1_INTERVAL4
|
||||||
|
#undef ICW1_LEVEL
|
||||||
|
#undef ICW1_INIT
|
||||||
|
#undef ICW4_8086
|
||||||
|
#undef ICW4_AUTO
|
||||||
|
#undef ICW4_BUF_SLAVE
|
||||||
|
#undef ICW4_BUF_MASTER
|
||||||
|
#undef ICW4_SFNM
|
||||||
|
#undef PIC_EOI
|
||||||
|
#undef PIC_READ_IRR
|
||||||
|
#undef PIC_READ_ISR
|
||||||
|
211
kernel/arch/pmm/pmm.c
Normal file
211
kernel/arch/pmm/pmm.c
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <kernel/_kernel.h>
|
||||||
|
#include <kernel/pmm.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* What i want to do is create a linked list of all the memory structures
|
||||||
|
*
|
||||||
|
* Theres one at the very start of the memory
|
||||||
|
*
|
||||||
|
* one at 1MB
|
||||||
|
*
|
||||||
|
* and then one provided by ram.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* So the idea is to create a way to access memory through this such that,
|
||||||
|
* when you give a bit block number, it'll go through the first item in the linked list, if the block is out of that range, it
|
||||||
|
* traverses to the next node, tries to find it there, and then continues until it either runs out of memory, or finds a location
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PMM_PAGE_SIZE 4096
|
||||||
|
#define PMM_BLOCKS_PER_BYTE 8
|
||||||
|
|
||||||
|
struct pmm_mem_info {
|
||||||
|
uint32_t startaddr;
|
||||||
|
uint32_t len; // in kb
|
||||||
|
uint32_t* bitmap;
|
||||||
|
|
||||||
|
uint32_t max_blocks;
|
||||||
|
uint32_t free_blocks;
|
||||||
|
uint32_t used_blocks;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PMM_GET_MEM_BLOCKS(x) x.len / PMM_PAGE_SIZE
|
||||||
|
|
||||||
|
struct pmm_mem_info main_mem;
|
||||||
|
|
||||||
|
void pmm_set(uint32_t bit);
|
||||||
|
void pmm_unset(uint32_t bit);
|
||||||
|
bool pmm_test(uint32_t bit);
|
||||||
|
int pmm_first_free(void);
|
||||||
|
void pmm_init(void);
|
||||||
|
void* pmm_alloc_block(void);
|
||||||
|
void pmm_free_block(void* p);
|
||||||
|
|
||||||
|
void pmm_panic(const char* str)
|
||||||
|
{
|
||||||
|
printf("PMM: ");
|
||||||
|
panic(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __pmm_set(uint32_t bit, struct pmm_mem_info* mem_block)
|
||||||
|
{
|
||||||
|
(mem_block->bitmap)[bit / 32] |= (1 << (bit % 32));
|
||||||
|
mem_block->used_blocks++;
|
||||||
|
mem_block->free_blocks--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __pmm_unset(uint32_t bit, struct pmm_mem_info* mem_block)
|
||||||
|
{
|
||||||
|
(mem_block->bitmap)[bit / 32] &= ~(1 << (bit % 32));
|
||||||
|
mem_block->used_blocks--;
|
||||||
|
mem_block->free_blocks++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __pmm_test(uint32_t bit, struct pmm_mem_info* mem_block)
|
||||||
|
{
|
||||||
|
return (mem_block->bitmap)[bit / 32] & (1 << (bit % 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
int __pmm_first_free(struct pmm_mem_info* mem_block)
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < PMM_GET_MEM_BLOCKS((*mem_block)) / 32; i++) {
|
||||||
|
if (mem_block->bitmap[i] == 0xFFFFFFFF) // this segment is full
|
||||||
|
continue;
|
||||||
|
for (int j = 0; j < 32; j++) {
|
||||||
|
if (mem_block->bitmap[i] & (1 << j))
|
||||||
|
continue; // this page is used
|
||||||
|
return (i * 32) + j; // i * 32 is the chunk of 32, plus j to get to the page in the chunk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __pmm_add_mem_block(uint32_t addr, int32_t len, struct pmm_mem_info* mem_block)
|
||||||
|
{
|
||||||
|
mem_block->startaddr = addr;
|
||||||
|
mem_block->len = len;
|
||||||
|
mem_block->bitmap = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __pmm_init(struct pmm_mem_info* mem_block)
|
||||||
|
{
|
||||||
|
// TODO same as above
|
||||||
|
mem_block->used_blocks = 0;
|
||||||
|
mem_block->max_blocks = PMM_GET_MEM_BLOCKS(main_mem);
|
||||||
|
mem_block->free_blocks = mem_block->max_blocks;
|
||||||
|
|
||||||
|
memset(mem_block->bitmap, 0x0, PMM_GET_MEM_BLOCKS((*mem_block)) / PMM_BLOCKS_PER_BYTE); // declare all memory available
|
||||||
|
|
||||||
|
#ifdef __TESTING__
|
||||||
|
printf("Initialized %1 blocks of memory (%1KiB available)\n", mem_block->max_blocks, mem_block->free_blocks * 4096);
|
||||||
|
#endif
|
||||||
|
__pmm_set(0, mem_block); // first block must always be set
|
||||||
|
}
|
||||||
|
|
||||||
|
void* __pmm_alloc_block(struct pmm_mem_info* mem_block)
|
||||||
|
{
|
||||||
|
if (mem_block->free_blocks == 0) {
|
||||||
|
kerror("OUT OF MEMORY");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int block_in_map = pmm_first_free();
|
||||||
|
if (block_in_map == -1) {
|
||||||
|
kerror("OUT OF MEMORY");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
__pmm_set(block_in_map, mem_block);
|
||||||
|
|
||||||
|
return (void*) (mem_block->startaddr + (block_in_map * PMM_PAGE_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
void __pmm_free_block(void* p, struct pmm_mem_info* mem_block)
|
||||||
|
{
|
||||||
|
uint64_t* addr = (uint64_t*) &p;
|
||||||
|
uint32_t idx = ((*addr) - mem_block->startaddr) / PMM_PAGE_SIZE;
|
||||||
|
|
||||||
|
// TODO this might still be a little flaky
|
||||||
|
// should we be able to free any pointer? or just ones that we've given out?
|
||||||
|
if (idx == 0)
|
||||||
|
pmm_panic("Trying to free reserved memory!");
|
||||||
|
|
||||||
|
if (pmm_test(idx) == 0)
|
||||||
|
pmm_panic("Trying to free a block that was already free!");
|
||||||
|
|
||||||
|
__pmm_unset(idx, mem_block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pmm_set(uint32_t bit)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Here we want to calculate if the bit is over the length
|
||||||
|
* subtract the length and bit amount so that we compensate for the bit map
|
||||||
|
*
|
||||||
|
* i.e. (length / 4096) == amount of blocks in that specific mem region
|
||||||
|
* if (bit > amt of blocks),
|
||||||
|
* go to next node, subtract amt of blocks from bit, and pass that
|
||||||
|
*
|
||||||
|
* below is merely a temporary solution
|
||||||
|
*/
|
||||||
|
__pmm_set(bit, &main_mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pmm_unset(uint32_t bit)
|
||||||
|
{
|
||||||
|
// TODO: same as above
|
||||||
|
__pmm_unset(bit, &main_mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pmm_test(uint32_t bit)
|
||||||
|
{
|
||||||
|
// TODO: same as above
|
||||||
|
return __pmm_test(bit, &main_mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pmm_first_free(void) //TODO implement a free_s where it finds a series of free pages
|
||||||
|
{
|
||||||
|
// TODO: same as above
|
||||||
|
int ret = __pmm_first_free(&main_mem);
|
||||||
|
if (ret == -1)
|
||||||
|
kerror("OUT OF MEMORY");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void pmm_init(void)
|
||||||
|
{
|
||||||
|
// TODO same as above
|
||||||
|
__pmm_init(&main_mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* pmm_alloc_block(void)
|
||||||
|
{
|
||||||
|
return __pmm_alloc_block(&main_mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pmm_free_block(void* p)
|
||||||
|
{
|
||||||
|
__pmm_free_block(p, &main_mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pmm_add_mem_block(uint32_t addr, uint32_t len)
|
||||||
|
{
|
||||||
|
// TODO: make this add to a linked list
|
||||||
|
__pmm_add_mem_block(addr, len, &main_mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __TESTING__
|
||||||
|
void print_main_mem()
|
||||||
|
{
|
||||||
|
printf("Available blocks: %1\nUsed blocks: %1\nMax blocks: %1\n",
|
||||||
|
main_mem.free_blocks, main_mem.used_blocks, main_mem.max_blocks);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -7,6 +7,5 @@ void kwarn(const char*);
|
|||||||
|
|
||||||
void kinfo(const char*);
|
void kinfo(const char*);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -3,14 +3,4 @@
|
|||||||
#ifndef ARCH_PAGING_H
|
#ifndef ARCH_PAGING_H
|
||||||
#define ARCH_PAGING_H
|
#define ARCH_PAGING_H
|
||||||
|
|
||||||
#define PAGE_TABLE_ENTRIES 1024
|
|
||||||
#define PAGE_DIRECTORY_ENTRIES 1024
|
|
||||||
|
|
||||||
void load_page_directory(uint32_t*);
|
|
||||||
|
|
||||||
void enable_paging();
|
|
||||||
|
|
||||||
|
|
||||||
void setup_paging(void);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
15
kernel/include/kernel/pmm.h
Normal file
15
kernel/include/kernel/pmm.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifndef ARCH_PMM_H
|
||||||
|
#define ARCH_PMM_H
|
||||||
|
|
||||||
|
void pmm_init(void);
|
||||||
|
void* pmm_alloc_block(void);
|
||||||
|
void pmm_free_block(void* p);
|
||||||
|
void pmm_add_mem_block(uint32_t addr, uint32_t len);
|
||||||
|
|
||||||
|
#ifdef __TESTING__
|
||||||
|
void print_main_mem();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -3,59 +3,6 @@
|
|||||||
#ifndef ARCH_I386_GDT_H
|
#ifndef ARCH_I386_GDT_H
|
||||||
#define ARCH_I386_GDT_H
|
#define ARCH_I386_GDT_H
|
||||||
|
|
||||||
// Each define here is for a specific flag in the descriptor.
|
|
||||||
// Refer to the intel documentation for a description of what each one does.
|
|
||||||
#define SEG_DESCTYPE(x) ((x) << 0x04) // Descriptor type (0 for system, 1 for code/data)
|
|
||||||
#define SEG_PRES(x) ((x) << 0x07) // Present
|
|
||||||
#define SEG_SAVL(x) ((x) << 0x0C) // Available for system use
|
|
||||||
#define SEG_LONG(x) ((x) << 0x0D) // Long mode
|
|
||||||
#define SEG_SIZE(x) ((x) << 0x0E) // Size (0 for 16-bit, 1 for 32)
|
|
||||||
#define SEG_GRAN(x) ((x) << 0x0F) // Granularity (0 for 1B - 1MB, 1 for 4KB - 4GB)
|
|
||||||
#define SEG_PRIV(x) (((x) & 0x03) << 0x05) // Set privilege level (0 - 3)
|
|
||||||
|
|
||||||
#define SEG_DATA_RD 0x00 // Read-Only
|
|
||||||
#define SEG_DATA_RDA 0x01 // Read-Only, accessed
|
|
||||||
#define SEG_DATA_RDWR 0x02 // Read/Write
|
|
||||||
#define SEG_DATA_RDWRA 0x03 // Read/Write, accessed
|
|
||||||
#define SEG_DATA_RDEXPD 0x04 // Read-Only, expand-down
|
|
||||||
#define SEG_DATA_RDEXPDA 0x05 // Read-Only, expand-down, accessed
|
|
||||||
#define SEG_DATA_RDWREXPD 0x06 // Read/Write, expand-down
|
|
||||||
#define SEG_DATA_RDWREXPDA 0x07 // Read/Write, expand-down, accessed
|
|
||||||
#define SEG_CODE_EX 0x08 // Execute-Only
|
|
||||||
#define SEG_CODE_EXA 0x09 // Execute-Only, accessed
|
|
||||||
#define SEG_CODE_EXRD 0x0A // Execute/Read
|
|
||||||
#define SEG_CODE_EXRDA 0x0B // Execute/Read, accessed
|
|
||||||
#define SEG_CODE_EXC 0x0C // Execute-Only, conforming
|
|
||||||
#define SEG_CODE_EXCA 0x0D // Execute-Only, conforming, accessed
|
|
||||||
#define SEG_CODE_EXRDC 0x0E // Execute/Read, conforming
|
|
||||||
#define SEG_CODE_EXRDCA 0x0F // Execute/Read, conforming, accessed
|
|
||||||
|
|
||||||
#define GDT_CODE_PL0 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \
|
|
||||||
SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \
|
|
||||||
SEG_PRIV(0) | SEG_CODE_EXRD
|
|
||||||
|
|
||||||
#define GDT_DATA_PL0 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \
|
|
||||||
SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \
|
|
||||||
SEG_PRIV(0) | SEG_DATA_RDWR
|
|
||||||
|
|
||||||
#define GDT_CODE_PL3 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \
|
|
||||||
SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \
|
|
||||||
SEG_PRIV(3) | SEG_CODE_EXRD
|
|
||||||
|
|
||||||
#define GDT_DATA_PL3 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \
|
|
||||||
SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \
|
|
||||||
SEG_PRIV(3) | SEG_DATA_RDWR
|
|
||||||
|
|
||||||
|
|
||||||
#define GDT_SIZE 3
|
|
||||||
|
|
||||||
|
|
||||||
void setGdt(unsigned short limit, uint64_t* base);
|
|
||||||
|
|
||||||
void reloadSegments();
|
|
||||||
|
|
||||||
uint64_t create_descriptor(uint32_t base, uint32_t limit, uint16_t flag);
|
|
||||||
|
|
||||||
void gdt_init(void);
|
void gdt_init(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -3,33 +3,6 @@
|
|||||||
#ifndef ARCH_IDT_H
|
#ifndef ARCH_IDT_H
|
||||||
#define ARCH_IDT_H
|
#define ARCH_IDT_H
|
||||||
|
|
||||||
#define IDT_MAX_DESCRIPTORS 48 // number of entries in the idt table
|
|
||||||
|
|
||||||
|
|
||||||
#define EXCEPT_DIV_ERR 0
|
|
||||||
#define EXCEPT_DEBUG 1
|
|
||||||
#define EXCEPT_NMI 2
|
|
||||||
#define EXCEPT_BREAKPOINT 3
|
|
||||||
#define EXCEPT_OVERFLOW 4
|
|
||||||
#define EXCEPT_BOUND_RANGE_EXCEEDED 5
|
|
||||||
#define EXCEPT_INVALID_OPCODE 6
|
|
||||||
#define EXCEPT_DEVICE_NOT_AVAILABLE 7
|
|
||||||
#define EXCEPT_DOUBLE_FAULT 8
|
|
||||||
#define EXCEPT_INVALID_TSS 10
|
|
||||||
#define EXCEPT_SEG_NOT_PRESENT 11
|
|
||||||
#define EXCEPT_STACK_SEG_FAULT 12
|
|
||||||
#define EXCEPT_GENERAL_PROTECTION 13
|
|
||||||
#define EXCEPT_PAGE_FAULT 14
|
|
||||||
#define EXCEPT_FLOATING_POINT_ERR_FPU 16
|
|
||||||
#define EXCEPT_ALIGNMENT_CHECK 17
|
|
||||||
#define EXCEPT_MACHINE_CHECK 18
|
|
||||||
#define EXCEPT_FLOATING_POINT_ERR_SIMD 19
|
|
||||||
#define EXCEPT_VIRT 20
|
|
||||||
#define EXCEPT_CTRL_PROT 21
|
|
||||||
#define EXCEPT_HYPERVISOR_INJECTION 28
|
|
||||||
#define EXCEPT_VMM_COMMUNICATION 29
|
|
||||||
#define EXCEPT_SECURITY_EXCEPTION 30
|
|
||||||
|
|
||||||
struct cpu_state {
|
struct cpu_state {
|
||||||
uint32_t eax;
|
uint32_t eax;
|
||||||
uint32_t ebx;
|
uint32_t ebx;
|
||||||
@ -49,20 +22,6 @@ struct stack_state {
|
|||||||
|
|
||||||
void exception_handler(struct cpu_state cpu, uint32_t interrupt, struct stack_state stack);
|
void exception_handler(struct cpu_state cpu, uint32_t interrupt, struct stack_state stack);
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint16_t isr_low; // The lower 16 bits of the ISR's address
|
|
||||||
uint16_t kernel_cs; // The GDT segment selector that the CPU will load into CS before calling the ISR
|
|
||||||
uint8_t reserved; // set to zero
|
|
||||||
uint8_t attributes; // Type and attributes
|
|
||||||
uint16_t isr_high; // The higher 16 bits of the ISR's address
|
|
||||||
} __attribute__((packed)) idt_entry_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint16_t limit;
|
|
||||||
uint32_t base;
|
|
||||||
} __attribute__((packed)) idtr_t;
|
|
||||||
|
|
||||||
void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags);
|
|
||||||
void idt_init(void);
|
void idt_init(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -3,34 +3,6 @@
|
|||||||
#ifndef ARCH_PIC_H
|
#ifndef ARCH_PIC_H
|
||||||
#define ARCH_PIC_H
|
#define ARCH_PIC_H
|
||||||
|
|
||||||
/** PIC I/O ports **/
|
|
||||||
#define PIC1 0x20 /** Master PIC **/
|
|
||||||
#define PIC2 0xA0 /** Slave PIC **/
|
|
||||||
|
|
||||||
/** PIC helper defines **/
|
|
||||||
#define PIC1_COMMAND (PIC1)
|
|
||||||
#define PIC1_DATA (PIC1 + 1)
|
|
||||||
#define PIC2_COMMAND (PIC2)
|
|
||||||
#define PIC2_DATA (PIC2 + 1)
|
|
||||||
|
|
||||||
/** PIC Commands **/
|
|
||||||
#define ICW1_ICW4 0x01 /** Indicates ICW4 will be present **/
|
|
||||||
#define ICW1_SINGLE 0x02 /** Single (cascade mode) **/
|
|
||||||
#define ICW1_INTERVAL4 0x04 /** Call address interval 4 (8) **/
|
|
||||||
#define ICW1_LEVEL 0x08 /** Level triggered (edge) mode **/
|
|
||||||
#define ICW1_INIT 0x10 /** Initialization **/
|
|
||||||
|
|
||||||
#define ICW4_8086 0x01 /** 8086/88 (MCS-80/85) mode **/
|
|
||||||
#define ICW4_AUTO 0x02 /** Auto (normal) EOI **/
|
|
||||||
#define ICW4_BUF_SLAVE 0x08 /** Buffered mode/slave **/
|
|
||||||
#define ICW4_BUF_MASTER 0x0C /** Buffered mode/master **/
|
|
||||||
#define ICW4_SFNM 0x10 /** Special fully nested (not) **/
|
|
||||||
|
|
||||||
#define PIC_EOI 0x20 /** End-of-interrupt command code **/
|
|
||||||
#define PIC_READ_IRR 0x0a /** OCW3 irq ready next CMD read **/
|
|
||||||
#define PIC_READ_ISR 0x0b /** OCW3 irq service next CMD read **/
|
|
||||||
|
|
||||||
|
|
||||||
#define PIC_PIT 32
|
#define PIC_PIT 32
|
||||||
#define PIC_KEYB 33
|
#define PIC_KEYB 33
|
||||||
#define PIC_CASCADE 34 // never raised
|
#define PIC_CASCADE 34 // never raised
|
||||||
@ -63,11 +35,6 @@ void pic_disable(void);
|
|||||||
void IRQ_set_mask(uint8_t IRQline);
|
void IRQ_set_mask(uint8_t IRQline);
|
||||||
void IRQ_clear_mask(uint8_t IRQline);
|
void IRQ_clear_mask(uint8_t IRQline);
|
||||||
|
|
||||||
/** Returns the combined value of the cascaded PICs irq request register **/
|
|
||||||
uint16_t pic_get_irr(void);
|
|
||||||
/** Returns the combined value of the cascaded PICs in-service register **/
|
|
||||||
uint16_t pic_get_isr(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: implement handling for Spurious IRQs
|
* TODO: implement handling for Spurious IRQs
|
||||||
* https://wiki.osdev.org/8259_PIC#Spurious_IRQs
|
* https://wiki.osdev.org/8259_PIC#Spurious_IRQs
|
||||||
|
@ -29,7 +29,7 @@ void klog(const char* buf, enum log_mode mode)
|
|||||||
serial_writestring(buf);
|
serial_writestring(buf);
|
||||||
terminal_writestring(buf);
|
terminal_writestring(buf);
|
||||||
|
|
||||||
serial_writestring("\n");
|
serial_writestring("\n\r");
|
||||||
terminal_writestring("\n");
|
terminal_writestring("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,51 +12,40 @@
|
|||||||
#include <kernel/x86/keyb.h>
|
#include <kernel/x86/keyb.h>
|
||||||
#include <kernel/x86/pit.h>
|
#include <kernel/x86/pit.h>
|
||||||
#include <kernel/x86/pci.h>
|
#include <kernel/x86/pci.h>
|
||||||
|
#include <kernel/pmm.h>
|
||||||
|
|
||||||
#include "multiboot.h"
|
#include "multiboot.h"
|
||||||
|
|
||||||
|
extern struct pmm_mem_info main_mem;
|
||||||
|
|
||||||
void verify_memmap(multiboot_info_t* mbd, uint32_t magic)
|
void verify_memmap(multiboot_info_t* mbd, uint32_t magic)
|
||||||
{
|
{
|
||||||
if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
|
if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
|
||||||
panic("Invalid magic number!");
|
panic("Invalid magic number!");
|
||||||
else
|
|
||||||
printf("%2\n", magic);
|
|
||||||
|
|
||||||
if (!(mbd->flags >> 6 & 0x1))
|
if (!(mbd->flags >> 6 & 0x1))
|
||||||
panic("Invalid memory map given by GRUB bootloader!");
|
panic("Invalid memory map given by GRUB bootloader!");
|
||||||
|
|
||||||
#ifdef __TESTING__
|
if (!(mbd->flags & (1 << 0)))
|
||||||
|
panic("Memory info not passed to kernel!");
|
||||||
|
|
||||||
puts("Printing available memory map...");
|
puts("Printing available memory map...");
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
for (i = 0; i < mbd->mmap_length; i += sizeof(multiboot_memory_map_t)) {
|
for (i = 0; i < mbd->mmap_length; i += sizeof(multiboot_memory_map_t)) {
|
||||||
multiboot_memory_map_t* mmmt = (multiboot_memory_map_t*) (mbd->mmap_addr + i);
|
multiboot_memory_map_t* mmmt = (multiboot_memory_map_t*) (mbd->mmap_addr + i);
|
||||||
|
|
||||||
printf("Start Addr: %4 | Length: %4 | Size: %2 | Type: ",
|
printf("Start Addr: %4 | Length: %4 | Size: %2 | Type: %d\n",
|
||||||
mmmt->addr, mmmt->len, mmmt->size);
|
mmmt->addr, mmmt->len, mmmt->size, mmmt->type);
|
||||||
switch (mmmt->type) {
|
|
||||||
case MULTIBOOT_MEMORY_AVAILABLE:
|
// This is pretty flaky, we want to actually create a linked list,
|
||||||
puts("Available");
|
// where each block of available memory gets its own mem_block
|
||||||
break;
|
// not just this main one
|
||||||
case MULTIBOOT_MEMORY_RESERVED:
|
// TODO
|
||||||
puts("Reserved");
|
if (mmmt->addr == 0x100000) {
|
||||||
break;
|
pmm_add_mem_block((uint32_t) mmmt->addr, (uint32_t) mmmt->len);
|
||||||
case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE:
|
|
||||||
puts("ACPI Reclaimable");
|
|
||||||
break;
|
|
||||||
case MULTIBOOT_MEMORY_NVS:
|
|
||||||
puts("NVS");
|
|
||||||
break;
|
|
||||||
case MULTIBOOT_MEMORY_BADRAM:
|
|
||||||
puts("Bad ram");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
puts("Unknown");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (mmmt->type == MULTIBOOT_MEMORY_AVAILABLE) -> DO SOMETHING
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _main(multiboot_info_t* mbd, uint32_t magic)
|
void _main(multiboot_info_t* mbd, uint32_t magic)
|
||||||
@ -65,7 +54,6 @@ void _main(multiboot_info_t* mbd, uint32_t magic)
|
|||||||
terminal_initialize();
|
terminal_initialize();
|
||||||
serial_initialize();
|
serial_initialize();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
verify_memmap(mbd, magic);
|
verify_memmap(mbd, magic);
|
||||||
|
|
||||||
gdt_init();
|
gdt_init();
|
||||||
@ -76,7 +64,9 @@ void _main(multiboot_info_t* mbd, uint32_t magic)
|
|||||||
serial_initialize();
|
serial_initialize();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
setup_paging();
|
pmm_init();
|
||||||
|
|
||||||
|
//setup_paging();
|
||||||
|
|
||||||
init_kb();
|
init_kb();
|
||||||
|
|
||||||
|
@ -115,8 +115,8 @@ int printf(const char* restrict format, ...) {
|
|||||||
written += len;
|
written += len;
|
||||||
} else if (*format == '1') {
|
} else if (*format == '1') {
|
||||||
format++;
|
format++;
|
||||||
int32_t i = (int32_t) va_arg(parameters, int32_t);
|
int32_t i = (uint32_t) va_arg(parameters, int32_t);
|
||||||
s32toa(i, buffer, 10);
|
u32toa(i, buffer, 10);
|
||||||
size_t len = strlen(buffer);
|
size_t len = strlen(buffer);
|
||||||
if (maxrem < len) {
|
if (maxrem < len) {
|
||||||
// TODO: Set errno to EOVERFLOW.
|
// TODO: Set errno to EOVERFLOW.
|
||||||
|
Reference in New Issue
Block a user