Paging
This commit is contained in:
parent
36279ec7ea
commit
7d0791d806
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
*.iso
|
*.iso
|
||||||
isodir
|
isodir
|
||||||
sysroot
|
sysroot
|
||||||
|
.vscode/
|
29
README.md
29
README.md
@ -5,8 +5,31 @@ Welcome to rockOS project, a hobby OS that aims to run rogue and nethack.
|
|||||||
- GDT
|
- GDT
|
||||||
- IDT
|
- IDT
|
||||||
- PIC initialization
|
- PIC initialization
|
||||||
- Semi-working keyboard driver
|
- PIT timer
|
||||||
- Paging initialization
|
- Keyboard driver
|
||||||
|
- Bitmap paging
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
Just grab the latest ISO from the releases and run it on a virtual machine
|
||||||
|
such as QEMU or Virtualbox, bare-metal not tested.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
### Dependencies
|
||||||
|
- a decent compiler such as gcc or clang
|
||||||
|
- grub2 (if under GNU/Linux)
|
||||||
|
- xorriso
|
||||||
|
- make
|
||||||
|
- tar (for compiling the toolchain)
|
||||||
|
- wget/curl (for compiling the toolchain)
|
||||||
|
|
||||||
|
If it is your first time building, you need to compile the toolchain first.
|
||||||
|
For that, you just need to run build-toolchain.sh, which will download binutils,
|
||||||
|
gcc, grub if youre on macOS, and then compile them to $HOME/opt/cross-i686 by default
|
||||||
|
which can be changed from the prompt.
|
||||||
|
|
||||||
|
After you compiled the toolchain and added $PREFIX/bin to your PATH as instructed by the script,
|
||||||
|
you can run qemu.sh to compile and open the OS on QEMU or iso.sh to just generate the ISO.
|
||||||
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
@ -15,7 +38,7 @@ Welcome to rockOS project, a hobby OS that aims to run rogue and nethack.
|
|||||||
|
|
||||||
|
|
||||||
## Acknowledgements
|
## Acknowledgements
|
||||||
- osdev.org community for huge documentation on osdev
|
- osdev.org community for huge documentation on OS Development
|
||||||
- musl for libc implementation
|
- musl for libc implementation
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#export PREFIX="$HOME/opt/cross-i686"
|
#export PREFIX="$HOME/opt/cross-i686"
|
||||||
|
|
||||||
echo "Welcome to rockOS toolchain compilation script, where would you like to install your toolchain?\nLeave blank for $HOME/opt/cross-i686"
|
echo "Welcome to rockOS toolchain compilation script, where would you like to install your toolchain?"
|
||||||
|
echo "Leave blank for $HOME/opt/cross-i686"
|
||||||
|
|
||||||
read PREFIX
|
read PREFIX
|
||||||
|
|
||||||
@ -9,6 +10,10 @@ if [ "$PREFIX" == "" ]; then
|
|||||||
export PREFIX="$HOME/opt/cross-i686"
|
export PREFIX="$HOME/opt/cross-i686"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "This is the location you chose: $PREFIX"
|
||||||
|
echo "Press Enter to continue"
|
||||||
|
read continue
|
||||||
|
|
||||||
mkdir -p "$PREFIX"
|
mkdir -p "$PREFIX"
|
||||||
export TARGET=i686-elf
|
export TARGET=i686-elf
|
||||||
export PATH="$PREFIX/bin:$PATH"
|
export PATH="$PREFIX/bin:$PATH"
|
||||||
|
@ -16,10 +16,16 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifndef _ROCKOS_PAGING_H
|
#ifndef _ROCKOS_PAGING_H
|
||||||
#define _ROCKOS_PAGING_H
|
#define _ROCKOS_PAGING_H
|
||||||
|
|
||||||
#define PAGE_ENTRIES 1024
|
#define PAGE_ENTRIES 1024
|
||||||
#define PAGE_SIZE 4 * PAGE_ENTRIES
|
#define PAGE_SIZE 4096
|
||||||
|
|
||||||
|
uint32_t* get_page();
|
||||||
|
void set_page_free(uint32_t*);
|
||||||
|
uint32_t get_used_memsize();
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -5,6 +5,7 @@
|
|||||||
#include <rockos/pic.h>
|
#include <rockos/pic.h>
|
||||||
#include <rockos/hal.h>
|
#include <rockos/hal.h>
|
||||||
#include <rockos/timer.h>
|
#include <rockos/timer.h>
|
||||||
|
#include <rockos/paging.h>
|
||||||
|
|
||||||
void kernel_main(void) {
|
void kernel_main(void) {
|
||||||
printf("Hello, kernel World!\n");
|
printf("Hello, kernel World!\n");
|
||||||
@ -15,13 +16,34 @@ void kernel_main(void) {
|
|||||||
printf("And now for 0.1 + 0.2...... which is: %.17f\n", 0.1 + 0.2);
|
printf("And now for 0.1 + 0.2...... which is: %.17f\n", 0.1 + 0.2);
|
||||||
initialize_keyset();
|
initialize_keyset();
|
||||||
|
|
||||||
outb(0x70, (0x80 << 7) | 0x0); // Seconds
|
outb(0x70, 0x0); // Seconds
|
||||||
uint8_t sec = inb(0x71);
|
uint8_t sec = inb(0x71);
|
||||||
outb(0x70, (0x80 << 7) | 0x02); // Minutes
|
outb(0x70, 0x02); // Minutes
|
||||||
uint8_t min = inb(0x71);
|
uint8_t min = inb(0x71);
|
||||||
outb(0x70, (0x80 << 7) | 0x04); // Hours
|
outb(0x70, 0x04); // Hours
|
||||||
uint8_t hour = inb(0x71);
|
uint8_t hour = inb(0x71);
|
||||||
printf("Time: %x:%x:%x\n", hour, min, sec);
|
// BCD to binary conversion
|
||||||
|
sec = (sec & 0x0F) + ((sec / 16) * 10);
|
||||||
|
min = (min & 0x0F) + ((min / 16) * 10);
|
||||||
|
hour = ((hour & 0x0F) + (((hour & 0x70) / 16) * 10)) | (hour & 0x80);
|
||||||
|
printf("Time: %02d:%02d:%02d UTC+3\n", (hour + 3) % 24, min, sec);
|
||||||
|
|
||||||
|
uint32_t first = get_used_memsize();
|
||||||
|
uint32_t limit = 1024 * 8;
|
||||||
|
uint32_t* pages[limit];
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < limit; i++) {
|
||||||
|
pages[i] = get_page();
|
||||||
|
}
|
||||||
|
uint32_t middle = get_used_memsize();
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < limit; i++) {
|
||||||
|
set_page_free(pages[i]);
|
||||||
|
}
|
||||||
|
uint32_t last = get_used_memsize();
|
||||||
|
|
||||||
|
printf("Before Allocation: %d KiB\nAfter allocation: %d KiB\nAfter Clear: %d KiB\n", first, middle, last);
|
||||||
|
printf("Finished!\n");
|
||||||
|
|
||||||
unsigned char key;
|
unsigned char key;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
@ -18,24 +18,80 @@ void enable_paging() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t page_dir[PAGE_ENTRIES] __attribute__((aligned(PAGE_SIZE)));
|
||||||
|
static uint32_t first_page_table[PAGE_ENTRIES] __attribute__((aligned(PAGE_SIZE)));
|
||||||
|
|
||||||
void paging_init() {
|
void paging_init() {
|
||||||
uint32_t page_dir[PAGE_ENTRIES] __attribute__((aligned(PAGE_SIZE)));
|
|
||||||
for(int i = 0; i < PAGE_ENTRIES; i++) {
|
for(int i = 0; i < PAGE_ENTRIES; i++) {
|
||||||
// Supervisor: only kernel-mode can access
|
// Supervisor: only kernel-mode can access
|
||||||
// Write Enabled: Can be both read and written to
|
// Write Enabled: Can be both read and written to
|
||||||
// Not Present: Page table not present
|
// Not Present: Page table not present
|
||||||
page_dir[i] = 0x00000002;
|
page_dir[i] = 0x00000002;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t first_page_table[PAGE_ENTRIES] __attribute__((aligned(PAGE_SIZE)));
|
|
||||||
for(unsigned int i = 0; i < PAGE_ENTRIES; i++) {
|
for(unsigned int i = 0; i < PAGE_ENTRIES; i++) {
|
||||||
// As the address is page aligned, it will leave 12 bits zeroed,
|
// As the address is page aligned, it will leave 12 bits zeroed,
|
||||||
// which are used by the attributes.
|
// which are used by the attributes.
|
||||||
first_page_table[i] = (i * 0x1000) | 3; // attr: supervisor, r/w, present
|
first_page_table[i] = (i * 0x1000) | 0x103; // attr: supervisor, r/w, present, 9th bit set
|
||||||
}
|
}
|
||||||
|
|
||||||
page_dir[0] = ((unsigned int)first_page_table) | 3; //attr: supervisor, r/w, present
|
page_dir[0] = ((unsigned int)first_page_table) | 3; //attr: supervisor, r/w, present
|
||||||
|
|
||||||
load_page_dir(page_dir);
|
load_page_dir(page_dir);
|
||||||
enable_paging();
|
enable_paging();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t* get_page() {
|
||||||
|
// Search directories for tables
|
||||||
|
for (int i = 0; i < PAGE_ENTRIES; ++i) {
|
||||||
|
// If table is found (if 2nd and 1st bit are set)
|
||||||
|
if((page_dir[i] & 0x3) == 0x3) {
|
||||||
|
// Cast table location
|
||||||
|
uint32_t *mytable = (uint32_t*)((page_dir[i] >> 12) << 12);
|
||||||
|
// Search table for pages
|
||||||
|
for(int j = 0; j < PAGE_ENTRIES; ++j) {
|
||||||
|
// If page is found (9th, 2nd, 1st bit set)
|
||||||
|
if((mytable[j] & 0x103) == 0x103) {
|
||||||
|
mytable[j] &= ~0x100; // Unset 9th bit
|
||||||
|
return &mytable[j];
|
||||||
|
}
|
||||||
|
} // No page found till last entry
|
||||||
|
// Check if next table is not initialized
|
||||||
|
if((page_dir[i+1] & 0x3) != 0x3) {
|
||||||
|
// The last page of previous table points to the next table
|
||||||
|
uint32_t *newtable = &mytable[2*PAGE_ENTRIES];
|
||||||
|
for(int k = 0; k < PAGE_ENTRIES; ++k) {
|
||||||
|
newtable[k] = (k * 0x1000) | 0x103; // attr: supervisor, r/w, present, 9th bit set
|
||||||
|
}
|
||||||
|
page_dir[i+1] = ((unsigned int)newtable) | 3; //attr: supervisor, r/w, present
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_page_free(uint32_t* addr) {
|
||||||
|
// Set 9th, 2nd and 1st bits
|
||||||
|
*(addr) |= 0x103;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t get_used_memsize() {
|
||||||
|
uint32_t used = 0;
|
||||||
|
// Iterate over page_dirs
|
||||||
|
for(int i = 0; i < PAGE_ENTRIES; ++i) {
|
||||||
|
// If a table is available
|
||||||
|
if((page_dir[i] & 3) == 3) {
|
||||||
|
// Cast the table
|
||||||
|
uint32_t* table = ((page_dir[i] >> 12) << 12);
|
||||||
|
// Iterate over table
|
||||||
|
for(int j = 0; j < PAGE_ENTRIES; ++j) {
|
||||||
|
// If a page is unavailable
|
||||||
|
if((table[j] & 0x103) != 0x103) {
|
||||||
|
// Then it is used
|
||||||
|
used += 4*4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return used;
|
||||||
}
|
}
|
Reference in New Issue
Block a user