Verified Commit ad794d46 authored by Allie Sargente's avatar Allie Sargente 😑

Added Simple Memory management

and a bit of license cleanup
Signed-off-by: Allie Sargente's avatarAllison Sargente <[email protected]>
parent 435843ce
No preview for this file type
No preview for this file type
No preview for this file type
/*
* (c) 2019 Apollo Developers
* For terms, See LICENSE
* free_memory.c - Multiboot header reading to find ranges of free memory
*/
#include <sys/hal.h>
#include <sys/multiboot.h>
#include <stdio.h>
extern multiboot_info_t mboot;
#define MBOOT_IS_MMAP_TYPE_RAM(x) (x == 1)
#define MBOOT_MEM (1<<0)
#define MBOOT_BOOT_DEV (1<<1)
#define MBOOT_CMDLINE (1<<2)
#define MBOOT_MODULES (1<<3)
#define MBOOT_ELF_SYMS (1<<5)
#define MBOOT_MMAP (1<<6)
static void remove_range(range_t *r, uint64_t start, uint64_t extent)
{
// TODO: Stop assuming that a range exists which starts at 'start' and
// extends to extent
// Sanity check to make sure this is the right range
if(r->start == start) {
r->start += extent; // Move range up past extent
r->extent -= extent; // Nullify extent
}
}
static int free_memory()
{
extern int __start, __end; // Provided by linker
if ((mboot.flags & MBOOT_MMAP) == 0) {
panic("Bootloader did not provide memory map info!");
}
// Store ranges in easy format, instead of multiboot
range_t ranges[128], ranges_cpy[128];
// Assign I to beginning of the mmap for looping
uint32_t i = mboot.mmap_addr;
unsigned n = 0;
uint64_t extent = 0;
// Iterate until we're at the end of the mmap
while (i < mboot.mmap_addr + mboot.mmap_length) {
if (n >= 128) { // Allow 128 loops before a break, avoid looping errors
break;
}
// An entry exists at memory location i, map it to a mmap struct.
multiboot_memory_map_t *entry = (multiboot_memory_map_t*)i;
// Is this ram? (Only ram is useful for us)
if (MBOOT_IS_MMAP_TYPE_RAM(entry->type)) {
// Make note of start and length of the range, then increment n.
ranges[n].start = entry->addr;
ranges[n++].extent = entry->len;
// Does this new info move out how far RAM goes? Update the extent
if (entry->addr + entry->len > extent) {
extent = entry->addr + entry->len;
}
}
uint32_t megs = ((uint32_t)entry->len / 0x100000);
uint32_t kilos = ((uint32_t)entry->len / 0x400);
if(megs) {
printf("Found %d MB at Address 0x%x\n", megs, (uint32_t)entry->addr);
} else {
printf("Found %d KB at Address 0x%x\n", kilos, (uint32_t)entry->addr);
}
// Go to the next entry in mboot's mmap
i += entry->size + 4;
}
// __end is size of our kernel from ld, we add some flags to it.
uintptr_t end = (((uintptr_t)&__end) & ~get_page_mask()) + get_page_size();
// Run over the ranges, one of them has our kernel in it and shouldn't be
// Marked as free (as our kernel would be overridden)
for (i = 0; i < n; i++)
remove_range(&ranges[i], (uintptr_t)&__start, end);
// Copy the ranges to a backup, as init_physical_memory mutates them and
// init_cow_refcnts needs to run after init_physical_memory
for (i = 0; i < n; i++) {
ranges_cpy[i] = ranges[i];
}
init_physical_memory_early(ranges, n, extent);
init_virtual_memory(ranges, n);
init_physical_memory();
init_cow_refcnts(ranges, n);
return 0;
}
MODULE = {
.name = "x86/free_memory",
.required = NULL,
.load_after = NULL,
.init = &free_memory,
.fini = NULL
};
/*
* (c) 2018 Apollo Project Developers
* For terms, see LICENSE
* arch/x86/gdt.c - GDT & TSS
*/
......
/*
* (oc) 2018 Apollo Developers
* For terms, see LICENSE
* idt.c - Interrupt Descriptor Table
*/
#include <sys/hal.h>
......
/*
* (c) 2018 Apollo Project Developers
* (c) 2019 Apollo Project Developers
* For terms, see LICENSE
* arch/x86/init.c - Initialization function for x86 platform.
*/
......@@ -11,8 +12,8 @@ extern int main(int argc, char **argv);
multiboot_info_t mboot;
// 4k for early allocator - for mult
#define EARLYALLOC_SZ 2048
// 4k for early allocator - for multiboot and things
#define EARLYALLOC_SZ 4096
// Bump Allocator, used to store multiboot info to a safe location
static uintptr_t earlyalloc(unsigned len)
......@@ -30,7 +31,7 @@ static uintptr_t earlyalloc(unsigned len)
}
// Called by assembly.
int archInit(multiboot_info_t* mbt, unsigned int magic)
int arch_init(multiboot_info_t* mbt, unsigned int magic)
{
int i, len;
// Be nice to c++
......@@ -80,8 +81,7 @@ int archInit(multiboot_info_t* mbt, unsigned int magic)
i = 1;
argv[0] = strtok((char*)mboot.cmdline, " ");
while(argv[i] != NULL) {
argv[i] = strtok((char*)mboot.cmdline, " ");
i++;
argv[i++] = strtok((char*)mboot.cmdline, " ");
}
(void)main(i+1, argv);
......
/*
* (C) 2018 Apollo Project Developers
* For terms, see LICENSE
* irq.c - Interrupt Request Lines (hardware)
*/
......
/*
* (c) 2018 Apollo Project Developers
* For terms, see LICENSE
* pic.c - Initialize the programmable interrupt controllers
*
*/
......
/*
* (c) 2018 Apollo Project Developers
* For terms, see LICENSE
* pit.c - Initialize the programmable interrupt timer
* Driver for the 8253/8254
*/
......
/*
* (c) 2018 Apollo Project Developers
* For terms, see LICENSE
* ports.c - x86 I/O databus commends
*/
......@@ -46,3 +47,38 @@ uint8_t read_register(int base, int reg)
return inb((uint16_t)base+reg);
}
inline uint32_t read_cr0()
{
uint32_t ret;
__asm__ __volatile__ ("mov %0, cr0" : "=r" (ret));
return ret;
}
inline uint32_t read_cr2()
{
uint32_t ret;
__asm__ __volatile__ ("mov %0, cr2" : "=r" (ret));
return ret;
}
inline uint32_t read_cr3()
{
uint32_t ret;
__asm__ __volatile__ ("mov %0, cr3" : "=r" (ret));
return ret;
}
inline void write_cr0(uint32_t val)
{
__asm__ __volatile__ ("mov cr0, %0" : : "r" (val));
}
inline void write_cr2(uint32_t val)
{
__asm__ __volatile__ ("mov cr2, %0" : : "r" (val));
}
inline void write_cr3(uint32_t val)
{
__asm__ __volatile__ ("mov cr3, %0" : : "r" (val));
}
/*
* (c) 2018 Apollo Developers
* For terms, see LICENSE
* Serial.c - x86 Serial Driver
*/
......
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (c) 2018 Apollo Project Developers ;;
;; For terms, see LICENSE ;;
;; start.s - x86 bootloader passover ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
......@@ -10,7 +11,7 @@ MULTIBOOT_VIDEO_MODE equ 1<<2
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS equ (MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO)
MULTIBOOT_HEADER_FLAGS equ (MULTIBOOT_PAGE_ALIGN + MULTIBOOT_MEMORY_INFO)
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
......@@ -22,7 +23,7 @@ KERNEL_STACK_SIZE equ 0x4000
[BITS 32]
[GLOBAL mboot]
[GLOBAL start]
[EXTERN archInit]
[EXTERN arch_init]
[GLOBAL KERNEL_STACK]
[EXTERN code]
[EXTERN bss]
......@@ -32,35 +33,33 @@ KERNEL_STACK_SIZE equ 0x4000
;==================
section .init
align 32
; This is the multiboot header.
mboot:
align 32
dd MULTIBOOT_HEADER_MAGIC
dd MULTIBOOT_HEADER_FLAGS
dd MULTIBOOT_CHECKSUM
dd mboot
dd code
dd bss
dd end
dd start
resb 0x24 ; just some more space for rest of the header
; Bootloader dropoff point
;==========================
;==========================;
; Bootloader dropoff point ;
;==========================;
start:
; Set up stack
mov esp, KERNEL_STACK + KERNEL_STACK_SIZE
push eax ; Should be the multiboot magic number
push ebx ; Should be the multiboot header
cli
call archInit
cli
cli ; Make sure we don't get any errornous interrupts
call arch_init ; Pass control to C
cli ;
jmp $ ; endless loop
hlt ; Deadlock Stop.
jmp $ ; In case we get an NMI
;;;;;;;;;;;;;;;;;;;;;;;;;
; Multiboot Padding
section .init.bss nobits
......
/*
* (c) 2017 Apollo Project Developers
* For terms, see LICENSE
* vga_console.c - Early Kernel mode console for debugging
* We use VGA cause it's easy, though this can be anything
* that can output a charecter set
......@@ -27,24 +28,24 @@
#define C_LIGHTBROWN 14
#define C_WHITE 15
static char escape_buf[4];
static int escape_buf_idx = 0;
static int escape_nums[4];
static int escape_num_idx = 0;
static char cursorY = 0;
static char cursorX = 0;
static unsigned short *VGAPointer;
static int backColor = C_BLACK;
static int foreColor = C_LIGHTGRAY;
static int foreBold = 0;
static int in_escape = 0;
static char escape_buf[4];
static int escape_buf_idx = 0;
static int escape_nums[4];
static int escape_num_idx = 0;
static uint8_t cursorY = 0;
static uint8_t cursorX = 0;
static uint16_t *VGAPointer;
static int backColor = C_BLACK;
static int foreColor = C_LIGHTGRAY;
static int foreBold = 0;
static int in_escape = 0;
static void cls();
static void move_cursor()
{
unsigned short cursorLocation = cursorY * 80 + cursorX;
uint16_t cursorLocation = cursorY * 80 + cursorX;
outb(VGA_INDEX_3, VGA_CURSOR_HIGH_BYTE);
outb(VGA_INDEX_3+1, cursorLocation >> 8);
outb(VGA_INDEX_3, VGA_CURSOR_LOW_BYTE);
......@@ -134,8 +135,8 @@ static int handle_escape(char c) {
static void scroll()
{
// Yes this isn't a byte, but the real info is only in 8 bits.
unsigned short attributeByte = (backColor<<12) | (foreColor<<8);
unsigned short blank = 0x20 | attributeByte;
uint16_t attributeByte = (backColor<<12) | (foreColor<<8);
uint16_t blank = 0x20 | attributeByte;
if(cursorY >= 25) {
int i;
for(i=0; i<24*80; i++) {
......@@ -148,10 +149,10 @@ static void scroll()
}
}
static void putChar(char c)
static void put_char(char c)
{
unsigned short attributeByte = (backColor<<12) | (foreColor<<8);
unsigned short *location;
uint16_t attributeByte = (backColor<<12) | (foreColor<<8);
uint16_t *location;
if (in_escape) {
in_escape = handle_escape(c);
return;
......@@ -187,7 +188,7 @@ static void cls()
{
int i;
for(i=0; i<=25*80; i++) {
putChar(' ');
put_char(' ');
}
cursorY = 0;
cursorX = 0;
......@@ -197,7 +198,7 @@ static void cls()
static int write(console_t *obj, const char *buf, int len)
{
for (int i = 0; i<len; i++){
putChar(buf[i]);
put_char(buf[i]);
}
return len;
}
......@@ -213,7 +214,7 @@ console_t c = {
static int register_screen()
{
VGAPointer = (unsigned short *)VGA_BASE_POINTER;
VGAPointer = (uint16_t *)VGA_BASE_POINTER;
cls();
register_console(&c);
return 0;
......
/*
* (c) 2019 Apollo Developers
* For terms, see LICENSE
* vmm.c - x86 virtual memory manager - requires a 486 or higher
*/
#include <sys/hal.h>
#include <stdio.h>
#include <string.h>
#include <arch/x86/regs.h>
#include <arch/x86/ports.h>
#ifdef DEBUG_vmm
# define dbg(args...) printf("vmm: " args)
#else
# define dbg(args...)
#endif
// Defined in platform specific HAL
static address_space_t *current = NULL;
static spinlock_t global_vmm_lock = SPINLOCK_RELEASED;
// Helper functions to map x86-specific page flags
static int from_x86_flags(int flags)
{
int f = 0;
if (flags & X86_WRITE) f |= PAGE_WRITE;
if (flags & X86_EXECUTE) f |= PAGE_EXECUTE;
if (flags & X86_USER) f |= PAGE_USER;
if (flags & X86_COW) f |= PAGE_COW;
return f;
}
static int to_x86_flags(int flags)
{
int f = 0;
if (flags & PAGE_WRITE) f |= X86_WRITE;
if (flags & PAGE_USER) f |= X86_USER;
if (flags & PAGE_EXECUTE) f |= X86_EXECUTE;
if (flags & PAGE_COW) f |= X86_COW;
return f;
}
address_space_t *get_current_address_space()
{
return current;
}
int switch_address_space(address_space_t *dest)
{
write_cr3((uintptr_t)dest->directory | X86_PRESENT | X86_WRITE);
return 0;
}
/*
* (c) 2017 Apollo Project Developers
* For terms, see LICENSE
* core/console.c - Console interface for early kernel debugging
*
* TODO: Implement spinlocks and uncomment the lines for them!
......
/*
* (c) 2019 Apollo Developers
* For terms, see LICENSE
* early_pmm.c - trivial physical memory manager for pre-virtual memory manager
* enviorment
*/
#include <sys/hal.h>
#include <assert.h>
#include <string.h>
// Debugging needs printf. defined somewhere else, probably
#ifdef DEBUG_early_pmm
# include <stdio.h>
# define dbg(args...) printf("early_pmm: " args)
#else
# define dbg(args...)
#endif
// The system (another module) gives us ranges of free memory,
// We're gonna modify them in place
range_t early_ranges[128];
unsigned early_nranges;
// Largest valid memory address
uint64_t early_max_extent;
// Copy the ranges. Be simple with it, if something complex happens? Let's panic
int init_physical_memory_early(range_t *ranges, unsigned nranges, uint64_t max)
{
assert(pmm_init_stage == PMM_INIT_START && "Early mem init called twice!");
assert(nranges < 128 && "Too many ranges!");
// You ever read a word too many times and it stops being a word?
// Well, "ranges"
// BTW, we're just gonna copy everything here
memcpy(early_ranges, ranges, nranges * sizeof(range_t));
early_nranges = nranges;
early_max_extent = max;
pmm_init_stage = PMM_INIT_EARLY;
return 0;
}
uint64_t early_alloc_page()
{
// This should only be called if the function above was run, but not after
// the virtual memory is online either
unsigned i;
assert(pmm_init_stage == PMM_INIT_EARLY);
for(i = 0; i < early_nranges; i++) {
if(early_ranges[i].extent <= 0x1000 ||
early_ranges[i].start >= 0x100000000ULL) {
// Throw away pages that exist over 4GB for now, or tinier than 4k.
continue;
}
// Under 1MB? Ignore it!
if(early_ranges[i].start < 0x100000) {
continue;
}
uint32_t ret = (uint32_t)early_ranges[i].start;
early_ranges[i].start += 0x1000;
early_ranges[i].extent -= 0x1000;
dbg("early_allog_page() -> %x\n", ret);
return ret;
}
panic("Early_alloc_page couldn't find any pages to use!");
}
/*
* (c) 2018 Apollo Project Developers
* For terms, see LICENSE
* hal.c - Hardware Abstraction Layer
* Contains weak function prototypes that are overridden by implementaion.
* Idea and most of implementation borrowed from James Molloy
......
/*
* (c) 2016 Apollo Project Developers
* (c) 2019 Apollo Project Developers
* For terms, see LICENSE
* Main.c - Main function of kernel activity
*/
......@@ -27,7 +28,7 @@ module_t *test_module __attribute__((weak)) = (module_t*)NULL;
static int logLevel;
int main(int argc, char **argv)
int main(int argc, char* argv[])
{
set_log_level(1); // Turn on logging
// Set all module states to not initialised so the dependency tree works
......@@ -51,7 +52,6 @@ int main(int argc, char **argv)
init_module(m);
}
}
if(test_module && TEST_HARNESS == 1) {
set_log_level(0);
init_module(test_module);
......
......@@ -15,5 +15,10 @@ void iowait(void);
uint8_t read_register(int base, int reg);
void write_register(int base, int reg, uint8_t value);
void device_init(int base, device_init_t arr[]);
uint32_t read_cr0();
uint32_t read_cr2();
uint32_t read_cr3();
void write_cr0(uint32_t);
void write_cr2(uint32_t);
void write_cr3(uint32_t);
#endif
#ifndef ASSERT_H
#define ASSERT_H
#if defined(HOSTED)
# include_next <assert.h>
#else
#define _stringify(x) (#x)
#define assert(cond) ( (cond) ? (void)0 : assert_fail(#cond, __FILE__, __LINE__) )
#endif
#endif
......@@ -93,7 +93,7 @@
#include <stdint.h>
struct multiboot_header
typedef struct multiboot_header
{
/* Must be MULTIBOOT_MAGIC - see above. */
uint32_t magic;
......@@ -116,7 +116,7 @@ struct multiboot_header
uint32_t width;
uint32_t height;
uint32_t depth;
};
} multiboot_t;
/* The symbol table for a.out. */
struct multiboot_aout_symbol_table
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment