1
0
Fork 0
mirror of https://github.com/tailix/kernel.git synced 2024-10-30 12:03:52 -04:00
kernel/kernelmq/paging.c

122 lines
3.5 KiB
C
Raw Normal View History

#include "paging.h"
2020-11-25 07:27:40 -05:00
#include "page_dir.h"
2017-11-07 23:54:47 -05:00
#include "panic.h"
2017-11-05 01:14:55 -05:00
2020-11-27 09:05:20 -05:00
#include <kernaux/arch/i386.h>
2020-11-29 20:03:45 -05:00
#include <kernaux/stdlib.h>
2020-11-27 09:05:20 -05:00
2017-11-04 10:59:01 -04:00
// CR0 bits
2017-11-04 11:00:57 -04:00
#define I386_CR0_PE 0x00000001 // Protected mode
#define I386_CR0_MP 0x00000002 // Monitor Coprocessor
#define I386_CR0_EM 0x00000004 // Emulate
#define I386_CR0_TS 0x00000008 // Task Switched
#define I386_CR0_ET 0x00000010 // Extension Type
#define I386_CR0_WP 0x00010000 // Enable paging
#define I386_CR0_PG 0x80000000 // Enable paging
2017-11-04 10:59:01 -04:00
// some CR4 bits
2017-11-04 11:00:57 -04:00
#define I386_CR4_VME 0x00000001 // Virtual 8086
#define I386_CR4_PVI 0x00000002 // Virtual ints
#define I386_CR4_TSD 0x00000004 // RDTSC privileged
#define I386_CR4_DE 0x00000008 // Debugging extensions
#define I386_CR4_PSE 0x00000010 // Page size extensions
#define I386_CR4_PAE 0x00000020 // Physical addr extens
#define I386_CR4_MCE 0x00000040 // Machine check enable
#define I386_CR4_PGE 0x00000080 // Global page flag enable
2017-11-04 10:59:01 -04:00
2020-11-25 07:27:40 -05:00
static PageDir page_dir;
2017-11-04 10:59:01 -04:00
void paging_enable()
{
2020-11-27 09:05:20 -05:00
unsigned long cr0 = kernaux_arch_i386_read_cr0();
unsigned long cr4 = kernaux_arch_i386_read_cr4();
2017-11-04 10:59:01 -04:00
2017-11-07 23:54:47 -05:00
assert(cr0 & I386_CR0_PE, "The boot loader should have put us in protected mode.");
2017-11-04 10:59:01 -04:00
// First clear PG and PGE flag, as PGE must be enabled after PG.
2020-11-27 09:05:20 -05:00
kernaux_arch_i386_write_cr0(cr0 & ~I386_CR0_PG);
kernaux_arch_i386_write_cr4(cr4 & ~(I386_CR4_PGE | I386_CR4_PSE));
2017-11-04 10:59:01 -04:00
2020-11-27 09:05:20 -05:00
cr0 = kernaux_arch_i386_read_cr0();
cr4 = kernaux_arch_i386_read_cr4();
2017-11-04 10:59:01 -04:00
// Our page table contains 4MB entries.
cr4 |= I386_CR4_PSE;
2020-11-27 09:05:20 -05:00
kernaux_arch_i386_write_cr4(cr4);
2017-11-04 10:59:01 -04:00
// First enable paging, then enable global page flag.
cr0 |= I386_CR0_PG;
2020-11-27 09:05:20 -05:00
kernaux_arch_i386_write_cr0(cr0);
2017-11-04 10:59:01 -04:00
cr0 |= I386_CR0_WP;
2020-11-27 09:05:20 -05:00
kernaux_arch_i386_write_cr0(cr0);
kernaux_arch_i386_write_cr4(cr4);
2017-11-04 10:59:01 -04:00
}
void paging_clear()
{
2020-11-29 20:03:45 -05:00
kernaux_memset(page_dir, 0, sizeof(page_dir));
}
2017-11-05 01:56:53 -04:00
void paging_identity()
{
2017-11-08 02:58:25 -05:00
for (int i = 0; i < PAGE_DIR_LENGTH; ++i) {
2020-11-25 07:27:40 -05:00
page_dir[i].addr = PAGE_DIR_ADDR(i * PAGE_BIG_SIZE);
page_dir[i].unused = 0;
page_dir[i].ignored = 0;
page_dir[i].page_size = 1;
page_dir[i].always_0 = 0;
page_dir[i].accessed = 0;
page_dir[i].cache_disabled = 1;
page_dir[i].write_through = 1;
page_dir[i].user = 1;
page_dir[i].writable = 1;
page_dir[i].present = 1;
}
}
int paging_mapkernel(const struct KernelMQ_Info *const kinfo)
{
2017-11-07 23:54:47 -05:00
assert(!(kinfo->kernel_phys_base % PAGE_BIG_SIZE), "Kernel physical address is not aligned.");
assert(!(kinfo->kernel_virt_base % PAGE_BIG_SIZE), "Kernel virtual address is not aligned.");
2017-11-05 01:14:55 -05:00
int pde = kinfo->kernel_virt_base / PAGE_BIG_SIZE;
unsigned long mapped = 0;
unsigned long kern_phys = kinfo->kernel_phys_base;
while (mapped < kinfo->kernel_size) {
2020-11-25 07:27:40 -05:00
page_dir[pde].addr = PAGE_DIR_ADDR(kern_phys);
page_dir[pde].unused = 0;
page_dir[pde].ignored = 0;
page_dir[pde].page_size = 1;
page_dir[pde].always_0 = 0;
page_dir[pde].accessed = 0;
page_dir[pde].cache_disabled = 0;
page_dir[pde].write_through = 0;
page_dir[pde].user = 0;
page_dir[pde].writable = 1;
page_dir[pde].present = 1;
2017-11-05 01:14:55 -05:00
mapped += PAGE_BIG_SIZE;
kern_phys += PAGE_BIG_SIZE;
++pde;
}
return pde;
}
2017-11-04 10:43:07 -04:00
unsigned long paging_load()
{
2020-11-25 07:27:40 -05:00
unsigned long page_dir_phys = (unsigned long)page_dir;
2020-11-27 09:05:20 -05:00
kernaux_arch_i386_write_cr3(page_dir_phys);
2020-11-25 07:27:40 -05:00
return page_dir_phys;
2017-11-04 10:43:07 -04:00
}