Compare commits
4 Commits
kbd-buffer
...
real-hw-fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
03f87723d1
|
|||
|
3607a7179c
|
|||
|
424b4c4632
|
|||
|
6a82d581fb
|
4
Makefile
4
Makefile
@@ -12,13 +12,13 @@ CC_PROBLEMATIC_FLAGS=-Wno-unused-parameter -Wno-unused-variable
|
|||||||
LD := x86_64-elf-ld
|
LD := x86_64-elf-ld
|
||||||
|
|
||||||
$(ELFFILE): $(BUILDDIR) $(OBJFILES)
|
$(ELFFILE): $(BUILDDIR) $(OBJFILES)
|
||||||
nasm -f elf64 src/idt/idt.S -o $(BUILDDIR)/idt_stub.o
|
nasm -f elf64 src/arch/x86/idt.S -o $(BUILDDIR)/idt_stub.o
|
||||||
$(LD) -o $(ELFFILE) -T linker.ld $(OBJFILES) $(BUILDDIR)/idt_stub.o
|
$(LD) -o $(ELFFILE) -T linker.ld $(OBJFILES) $(BUILDDIR)/idt_stub.o
|
||||||
# Get the symbols for debugging
|
# Get the symbols for debugging
|
||||||
nm -n $(ELFFILE) | awk '$$2 ~ /[TtDdBbRr]/ {print $$1, $$3}' > symbols.map
|
nm -n $(ELFFILE) | awk '$$2 ~ /[TtDdBbRr]/ {print $$1, $$3}' > symbols.map
|
||||||
python3 symbols.py
|
python3 symbols.py
|
||||||
nasm -f elf64 symbols.S -o $(BUILDDIR)/symbols.o
|
nasm -f elf64 symbols.S -o $(BUILDDIR)/symbols.o
|
||||||
$(LD) -o $(ELFFILE) -T linker.ld $(OBJFILES) $(BUILDDIR)/idt_stub.o
|
$(LD) -o $(ELFFILE) -T linker.ld $(OBJFILES) $(BUILDDIR)/idt_stub.o $(BUILDDIR)/symbols.o
|
||||||
|
|
||||||
$(BUILDDIR):
|
$(BUILDDIR):
|
||||||
@mkdir -p $(BUILDDIR)
|
@mkdir -p $(BUILDDIR)
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
/*
|
#ifndef X86_H
|
||||||
* @author xamidev <xamidev@riseup.net>
|
#define X86_H
|
||||||
* @brief Interrupt Descriptor Table setup and dispatching
|
|
||||||
* @license GPL-3.0-only
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IDT_H
|
|
||||||
#define IDT_H
|
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
uint64_t rdmsr(uint32_t msr);
|
||||||
|
void cpuid(uint32_t leaf, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx);
|
||||||
|
void wrmsr(uint32_t msr, uint64_t value);
|
||||||
|
bool x86_has_msr();
|
||||||
|
void x86_arch_init();
|
||||||
|
|
||||||
|
/* Interrupt Descriptor Table */
|
||||||
|
|
||||||
void idt_init(void);
|
void idt_init(void);
|
||||||
|
|
||||||
struct interrupt_descriptor {
|
struct interrupt_descriptor {
|
||||||
@@ -11,7 +11,14 @@
|
|||||||
#define PEPPEROS_VERSION_MAJOR "0"
|
#define PEPPEROS_VERSION_MAJOR "0"
|
||||||
#define PEPPEROS_VERSION_MINOR "0"
|
#define PEPPEROS_VERSION_MINOR "0"
|
||||||
#define PEPPEROS_VERSION_PATCH "58"
|
#define PEPPEROS_VERSION_PATCH "58"
|
||||||
#define PEPPEROS_SPLASH "\x1b[38;5;196mPepperOS\x1b[0m version \x1b[38;5;220m"PEPPEROS_VERSION_MAJOR"."PEPPEROS_VERSION_MINOR"."PEPPEROS_VERSION_PATCH"\x1b[0m built on \x1b[38;5;40m"__DATE__" "__TIME__"\x1b[0m\n"
|
#define PEPPEROS_SPLASH \
|
||||||
|
"\x1b[38;5;196m \x1b[38;5;231m____ _____\r\n\x1b[0m"\
|
||||||
|
"\x1b[38;5;196m ____ ___ ____ ____ ___ _____\x1b[38;5;231m/ __ \\/ ___/\r\n\x1b[0m"\
|
||||||
|
"\x1b[38;5;196m / __ \\/ _ \\/ __ \\/ __ \\/ _ \\/ ___\x1b[38;5;231m/ / / /\\__ \\ \r\n\x1b[0m"\
|
||||||
|
"\x1b[38;5;196m / /_/ / __/ /_/ / /_/ / __/ / \x1b[38;5;231m/ /_/ /___/ / \r\n\x1b[0m"\
|
||||||
|
"\x1b[38;5;196m / .___/\\___/ .___/ .___/\\___/_/ \x1b[38;5;231m\\____//____/ \r\n\x1b[0m"\
|
||||||
|
"\x1b[38;5;196m/_/ /_/ /_/ \r\n\x1b[0m"\
|
||||||
|
" --- version \x1b[38;5;220m"PEPPEROS_VERSION_MAJOR"."PEPPEROS_VERSION_MINOR"."PEPPEROS_VERSION_PATCH"\x1b[0m built on \x1b[38;5;40m"__DATE__" "__TIME__"\x1b[0m\r\n"
|
||||||
|
|
||||||
/* process */
|
/* process */
|
||||||
#define PROCESS_NAME_MAX 64
|
#define PROCESS_NAME_MAX 64
|
||||||
@@ -31,7 +38,7 @@
|
|||||||
#define KERNEL_IDT_ENTRIES 33
|
#define KERNEL_IDT_ENTRIES 33
|
||||||
|
|
||||||
/* paging */
|
/* paging */
|
||||||
#define PAGING_MAX_PHYS 0x100000000
|
#define PAGING_MAX_PHYS 0x200000000
|
||||||
|
|
||||||
/* heap */
|
/* heap */
|
||||||
#define KHEAP_SIZE (32*1024*1024)
|
#define KHEAP_SIZE (32*1024*1024)
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
#define TERM_H
|
#define TERM_H
|
||||||
|
|
||||||
void kputs(const char* str);
|
void kputs(const char* str);
|
||||||
void _putchar(char character);
|
|
||||||
void term_init(void);
|
void term_init(void);
|
||||||
int printf(const char* fmt, ...);
|
int printf(const char* fmt, ...);
|
||||||
|
void internal_putc(int c, void *_);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ enum ErrorCodes {
|
|||||||
|
|
||||||
#include <io/serial/serial.h>
|
#include <io/serial/serial.h>
|
||||||
#include <io/term/term.h>
|
#include <io/term/term.h>
|
||||||
#include <idt/idt.h>
|
#include <arch/x86.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
extern volatile uint64_t ticks;
|
extern volatile uint64_t ticks;
|
||||||
|
|||||||
21
src/arch/x86/cpuid.c
Normal file
21
src/arch/x86/cpuid.c
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief x86 CPU identification
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cpuid - Wrapper for CPUID instruction
|
||||||
|
* @leaf: Requested leaf (input EAX)
|
||||||
|
* @eax: EAX register value (output)
|
||||||
|
* @ebx: EBX register value (output)
|
||||||
|
* @ecx: ECX register value (output)
|
||||||
|
* @edx: EDX register value (output)
|
||||||
|
*/
|
||||||
|
void cpuid(uint32_t leaf, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx)
|
||||||
|
{
|
||||||
|
__asm__ volatile("cpuid" : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) : "a"(leaf));
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
* @license GPL-3.0-only
|
* @license GPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <idt/idt.h>
|
#include <arch/x86.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <io/serial/serial.h>
|
#include <io/serial/serial.h>
|
||||||
@@ -258,7 +258,7 @@ struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context)
|
|||||||
|
|
||||||
case 33: // Keyboard Interrupt
|
case 33: // Keyboard Interrupt
|
||||||
keyboard_handler();
|
keyboard_handler();
|
||||||
//process_create("keyboard-initiated", kbdproc_main, NULL); // DEBUG
|
process_create("keyboard-initiated", kbdproc_main, NULL); // DEBUG
|
||||||
outb(0x20, 0x20);
|
outb(0x20, 0x20);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
46
src/arch/x86/init.c
Normal file
46
src/arch/x86/init.c
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief x86 architecture-dependant initialization
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <mem/gdt.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <arch/x86.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* x86_overwrite_pat - Set PAT to WC
|
||||||
|
*
|
||||||
|
* This function overwrites the 1st Page Attribute
|
||||||
|
* Table entry, to enable the Write-Combining property
|
||||||
|
* when we map memory regions later on.
|
||||||
|
* The framebuffer will be mapped with WC, which makes
|
||||||
|
* memory access significantly faster by using burst
|
||||||
|
* operations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void x86_overwrite_pat()
|
||||||
|
{
|
||||||
|
uint64_t pat = rdmsr(0x277);
|
||||||
|
pat &= ~(0xFFULL << 8); // Clear PAT1
|
||||||
|
pat |= (0x01ULL << 8); // PAT1 = 0x01 (WC)
|
||||||
|
wrmsr(0x277, pat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* x86_arch_init - Initialize x86 CPU structures
|
||||||
|
*
|
||||||
|
* This function is responsible for overriding a PAT entry
|
||||||
|
* (to put the framebuffer area in WC mode) only.
|
||||||
|
*
|
||||||
|
* Later, all architecture-dependant init (GDT, IDT, TSS, ...)
|
||||||
|
* should be initialized here, and separate function pointers
|
||||||
|
* should be set up for each arch.
|
||||||
|
*/
|
||||||
|
void x86_arch_init()
|
||||||
|
{
|
||||||
|
x86_overwrite_pat();
|
||||||
|
idt_init();
|
||||||
|
gdt_init();
|
||||||
|
}
|
||||||
66
src/arch/x86/msr.c
Normal file
66
src/arch/x86/msr.c
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief x86 MSR C wrappers
|
||||||
|
* @description
|
||||||
|
* Wrapper functions to access Model Specific Registers
|
||||||
|
*
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <arch/x86.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rdmsr - Read from MSR
|
||||||
|
* @msr: model specific register number
|
||||||
|
*
|
||||||
|
* Read a 64-bit word from a Model Specific Register.
|
||||||
|
* Wrapper for the "rdmsr" instruction. It originally
|
||||||
|
* outputs to two 32-bit registers (EDX:EAX), so the
|
||||||
|
* function does the job of uniting them as a 64-bit
|
||||||
|
* value for us.
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* <value> - value read from MSR
|
||||||
|
*/
|
||||||
|
uint64_t rdmsr(uint32_t msr)
|
||||||
|
{
|
||||||
|
uint32_t low;
|
||||||
|
uint32_t high;
|
||||||
|
|
||||||
|
__asm__ volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(msr));
|
||||||
|
|
||||||
|
return ((uint64_t)high << 32) | low;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* wrmsr - Write to MSR
|
||||||
|
* @msr: model specific register number
|
||||||
|
*
|
||||||
|
* Write a 64-bit value to a Model Specific Register.
|
||||||
|
*/
|
||||||
|
void wrmsr(uint32_t msr, uint64_t value)
|
||||||
|
{
|
||||||
|
uint32_t low = (uint32_t)(value & 0xFFFFFFFF);
|
||||||
|
uint32_t high = (uint32_t)(value >> 32);
|
||||||
|
|
||||||
|
__asm__ volatile("wrmsr" : : "c"(msr), "a"(low), "d"(high) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* x86_has_msr - Test for MSR support
|
||||||
|
*
|
||||||
|
* Checks if CPU supports Model Specific Registers
|
||||||
|
* using CPUID.01h:EDX[bit 5].
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* true - MSR are supported
|
||||||
|
* false - MSR are not supported
|
||||||
|
*/
|
||||||
|
bool x86_has_msr()
|
||||||
|
{
|
||||||
|
uint32_t eax, ebx, ecx, edx;
|
||||||
|
cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||||
|
return (edx & (1 << 5)) != 0;
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <idt/idt.h>
|
#include <arch/x86.h>
|
||||||
#include <io/serial/serial.h>
|
#include <io/serial/serial.h>
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
|
|
||||||
@@ -36,27 +36,6 @@ void read_rflags(uint64_t rflags)
|
|||||||
CHECK_BIT(rflags, 19) ? "VIF " : "", /*virtual interrupt flag*/
|
CHECK_BIT(rflags, 19) ? "VIF " : "", /*virtual interrupt flag*/
|
||||||
CHECK_BIT(rflags, 20) ? "VIP " : "", /*virtual interrupt pending*/
|
CHECK_BIT(rflags, 20) ? "VIP " : "", /*virtual interrupt pending*/
|
||||||
CHECK_BIT(rflags, 21) ? "ID " : ""); /*id flag*/
|
CHECK_BIT(rflags, 21) ? "ID " : ""); /*id flag*/
|
||||||
|
|
||||||
if (init.terminal) {
|
|
||||||
printf("\x1b[38;5;226m%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\x1b[38;5;231m\r\n",
|
|
||||||
CHECK_BIT(rflags, 0) ? "CF " : "",
|
|
||||||
CHECK_BIT(rflags, 2) ? "PF " : "",
|
|
||||||
CHECK_BIT(rflags, 4) ? "AF " : "",
|
|
||||||
CHECK_BIT(rflags, 6) ? "ZF " : "",
|
|
||||||
CHECK_BIT(rflags, 7) ? "SF " : "",
|
|
||||||
CHECK_BIT(rflags, 8) ? "TF " : "",
|
|
||||||
CHECK_BIT(rflags, 9) ? "IF " : "",
|
|
||||||
CHECK_BIT(rflags, 10) ? "DF " : "",
|
|
||||||
CHECK_BIT(rflags, 11) ? "OF " : "",
|
|
||||||
(CHECK_BIT(rflags, 12) && CHECK_BIT(rflags, 13)) ? "IOPL3 " : "IOPL0 ",
|
|
||||||
CHECK_BIT(rflags, 14) ? "NT " : "",
|
|
||||||
CHECK_BIT(rflags, 16) ? "RF " : "",
|
|
||||||
CHECK_BIT(rflags, 17) ? "VM " : "",
|
|
||||||
CHECK_BIT(rflags, 18) ? "AC " : "",
|
|
||||||
CHECK_BIT(rflags, 19) ? "VIF " : "",
|
|
||||||
CHECK_BIT(rflags, 20) ? "VIP " : "",
|
|
||||||
CHECK_BIT(rflags, 21) ? "ID " : "");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -216,10 +216,10 @@ void keyboard_handler()
|
|||||||
|
|
||||||
if (c) {
|
if (c) {
|
||||||
if (c == '\n') {
|
if (c == '\n') {
|
||||||
_putchar('\r');
|
internal_putc('\r', NULL);
|
||||||
}
|
}
|
||||||
// Should probably have a keyboard buffer here... instead of this
|
|
||||||
_putchar(c);
|
internal_putc(c, NULL);
|
||||||
keyboard_putchar(c);
|
keyboard_putchar(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,13 @@
|
|||||||
|
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <io/serial/serial.h>
|
#include <io/serial/serial.h>
|
||||||
|
#include <sched/spinlock.h>
|
||||||
|
|
||||||
extern struct init_status init;
|
extern struct init_status init;
|
||||||
|
|
||||||
|
extern int panic_count;
|
||||||
|
struct spinlock_t serial_lock = {0};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* outb - Writes a byte to a CPU port
|
* outb - Writes a byte to a CPU port
|
||||||
* @port: CPU port to write to
|
* @port: CPU port to write to
|
||||||
@@ -85,9 +89,15 @@ static int is_transmit_empty()
|
|||||||
*/
|
*/
|
||||||
void skputc(char c)
|
void skputc(char c)
|
||||||
{
|
{
|
||||||
// TODO: Spinlock here (serial access)
|
if (panic_count == 0) {
|
||||||
|
spinlock_acquire(&serial_lock);
|
||||||
while (!is_transmit_empty()); // wait for free spot
|
while (!is_transmit_empty()); // wait for free spot
|
||||||
outb(PORT, c);
|
outb(PORT, c);
|
||||||
|
spinlock_release(&serial_lock);
|
||||||
|
} else {
|
||||||
|
while (!is_transmit_empty());
|
||||||
|
outb(PORT, c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -30,19 +30,10 @@ extern struct flanterm_context* ft_ctx;
|
|||||||
extern struct init_status init;
|
extern struct init_status init;
|
||||||
|
|
||||||
struct spinlock_t term_lock = {0};
|
struct spinlock_t term_lock = {0};
|
||||||
|
struct spinlock_t printf_lock = {0};
|
||||||
|
|
||||||
extern int panic_count;
|
extern int panic_count;
|
||||||
|
|
||||||
/*
|
|
||||||
* _putchar - Writes a character to terminal (DEPRECATED)
|
|
||||||
* @character: character to write
|
|
||||||
*/
|
|
||||||
void _putchar(char character)
|
|
||||||
{
|
|
||||||
// TODO: Spinlock here (terminal access)
|
|
||||||
flanterm_write(ft_ctx, &character, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* internal_putc - Internal putchar function
|
* internal_putc - Internal putchar function
|
||||||
* @c: char to print
|
* @c: char to print
|
||||||
@@ -83,14 +74,26 @@ void internal_putc(int c, void *_)
|
|||||||
*
|
*
|
||||||
* Return:
|
* Return:
|
||||||
* <ret> - number of characters sent to the callback
|
* <ret> - number of characters sent to the callback
|
||||||
|
* %-1 - error
|
||||||
*/
|
*/
|
||||||
int printf(const char* fmt, ...)
|
int printf(const char* fmt, ...)
|
||||||
{
|
{
|
||||||
|
if (panic_count == 0) {
|
||||||
|
spinlock_acquire(&printf_lock);
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
int ret = npf_vpprintf(internal_putc, NULL, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
spinlock_release(&printf_lock);
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
int ret = npf_vpprintf(internal_putc, NULL, fmt, args);
|
int ret = npf_vpprintf(internal_putc, NULL, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -103,30 +106,14 @@ void kputs(const char* str)
|
|||||||
{
|
{
|
||||||
size_t i=0;
|
size_t i=0;
|
||||||
while (str[i] != 0) {
|
while (str[i] != 0) {
|
||||||
_putchar(str[i]);
|
internal_putc(str[i], NULL);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
_putchar('\r');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern struct flanterm_context* ft_ctx;
|
extern struct flanterm_context* ft_ctx;
|
||||||
extern struct boot_context boot_ctx;
|
extern struct boot_context boot_ctx;
|
||||||
|
|
||||||
/*
|
|
||||||
* flanterm_free_wrapper - free() wrapper for Flanterm
|
|
||||||
* @ptr: pointer to free
|
|
||||||
* @size: amount of bytes to free
|
|
||||||
*
|
|
||||||
* This function exists solely because the Flanterm initialization
|
|
||||||
* function only accepts a free() function with a size parameter,
|
|
||||||
* and the default one doesn't have it.
|
|
||||||
*/
|
|
||||||
void flanterm_free_wrapper(void* ptr, size_t size)
|
|
||||||
{
|
|
||||||
(void)size;
|
|
||||||
kfree(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* term_init - Video output/terminal initialization
|
* term_init - Video output/terminal initialization
|
||||||
*
|
*
|
||||||
|
|||||||
16
src/kmain.c
16
src/kmain.c
@@ -4,6 +4,7 @@
|
|||||||
* @license GPL-3.0-only
|
* @license GPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "arch/x86.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
@@ -11,7 +12,6 @@
|
|||||||
#include <io/serial/serial.h>
|
#include <io/serial/serial.h>
|
||||||
#include <mem/gdt.h>
|
#include <mem/gdt.h>
|
||||||
#include <mem/utils.h>
|
#include <mem/utils.h>
|
||||||
#include <idt/idt.h>
|
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <time/timer.h>
|
#include <time/timer.h>
|
||||||
#include <io/kbd/ps2.h>
|
#include <io/kbd/ps2.h>
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <io/term/flanterm.h>
|
#include <io/term/flanterm.h>
|
||||||
#include <io/term/flanterm_backends/fb.h>
|
#include <io/term/flanterm_backends/fb.h>
|
||||||
|
#include <arch/x86.h>
|
||||||
|
|
||||||
// Limine version used
|
// Limine version used
|
||||||
__attribute__((used, section(".limine_requests")))
|
__attribute__((used, section(".limine_requests")))
|
||||||
@@ -68,7 +69,7 @@ struct process_t* idle_proc;
|
|||||||
// Never gets executed although pedicel is scheduled?
|
// Never gets executed although pedicel is scheduled?
|
||||||
void pedicel_main(void* arg)
|
void pedicel_main(void* arg)
|
||||||
{
|
{
|
||||||
printf("\n\nWelcome to PepperOS! Pedicel speaking.\r\nNothing left to do, let's go idle!\r\n");
|
printf("\n\n\rWelcome to PepperOS! Pedicel speaking.\r\nNothing left to do, let's go idle!\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void idle_main(void* arg)
|
void idle_main(void* arg)
|
||||||
@@ -111,26 +112,23 @@ void kmain()
|
|||||||
serial_init();
|
serial_init();
|
||||||
timer_init();
|
timer_init();
|
||||||
|
|
||||||
|
x86_arch_init();
|
||||||
|
|
||||||
boot_mem_display();
|
boot_mem_display();
|
||||||
pmm_init(boot_ctx);
|
pmm_init(boot_ctx);
|
||||||
|
|
||||||
// Remap kernel , HHDM and framebuffer
|
|
||||||
paging_init(boot_ctx);
|
paging_init(boot_ctx);
|
||||||
kheap_init();
|
kheap_init();
|
||||||
|
|
||||||
keyboard_init(FR);
|
keyboard_init(FR);
|
||||||
|
|
||||||
gdt_init();
|
|
||||||
idt_init();
|
|
||||||
|
|
||||||
process_init();
|
process_init();
|
||||||
idle_proc = process_create("idle", (void*)idle_main, 0);
|
idle_proc = process_create("idle", (void*)idle_main, 0);
|
||||||
struct process_t* pedicel = process_create("pedicel", (void*)pedicel_main, 0);
|
process_create("pedicel", (void*)pedicel_main, 0);
|
||||||
process_create("thing", thing_main, NULL);
|
process_create("thing", thing_main, NULL);
|
||||||
process_display_list(processes_list);
|
|
||||||
|
|
||||||
scheduler_init();
|
scheduler_init();
|
||||||
|
|
||||||
kputs(PEPPEROS_SPLASH);
|
printf(PEPPEROS_SPLASH);
|
||||||
idle();
|
idle();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,9 +173,9 @@ void paging_init(struct boot_context boot_ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4GB
|
// 8GB
|
||||||
if (max_phys > PAGING_MAX_PHYS) {
|
if (max_phys > PAGING_MAX_PHYS) {
|
||||||
DEBUG("WARNING: max_phys capped to 4GB (%x) (from max_phys=%p)", PAGING_MAX_PHYS, max_phys);
|
DEBUG("WARNING: max_phys capped to PAGING_MAX_PHYS (from max_phys=%p)", max_phys);
|
||||||
max_phys = PAGING_MAX_PHYS;
|
max_phys = PAGING_MAX_PHYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,9 +202,9 @@ void paging_init(struct boot_context boot_ctx)
|
|||||||
uint64_t fb_size = fb->pitch * fb->height;
|
uint64_t fb_size = fb->pitch * fb->height;
|
||||||
uint64_t fb_pages = (fb_size + PAGE_SIZE-1)/PAGE_SIZE;
|
uint64_t fb_pages = (fb_size + PAGE_SIZE-1)/PAGE_SIZE;
|
||||||
|
|
||||||
// Map the framebuffer (with cache-disable & write-through)
|
// Map the framebuffer (PWT set, and no PCD means PAT1 [Write-Combining] for this region)
|
||||||
for (uint64_t i=0; i<fb_pages; i++) {
|
for (uint64_t i=0; i<fb_pages; i++) {
|
||||||
paging_map_page(kernel_pml4, fb_virt+i*PAGE_SIZE, fb_phys+i*PAGE_SIZE, PTE_WRITABLE | PTE_PCD | PTE_PWT);
|
paging_map_page(kernel_pml4, fb_virt+i*PAGE_SIZE, fb_phys+i*PAGE_SIZE, PTE_WRITABLE | PTE_PWT);
|
||||||
page_count++;
|
page_count++;
|
||||||
}
|
}
|
||||||
DEBUG("Mapped %u pages for framebuffer", page_count);
|
DEBUG("Mapped %u pages for framebuffer", page_count);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ it will probably need to get some info from Limine,
|
|||||||
to see which pages are used by kernel/bootloader/mmio/fb etc.
|
to see which pages are used by kernel/bootloader/mmio/fb etc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
#include <mem/paging.h>
|
#include <mem/paging.h>
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@@ -24,42 +25,6 @@ First we'll have to discover the physical memory layout,
|
|||||||
and for that we can use a Limine request.
|
and for that we can use a Limine request.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct limine_memmap_entry* biggest_entry;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* pmm_find_biggest_usable_region - Finding the biggest free memory region
|
|
||||||
* @memmap: Limine memory map
|
|
||||||
* @hhdm: Limine HHDM offset
|
|
||||||
*
|
|
||||||
* This function uses the memory map provided by the bootloader
|
|
||||||
* to find the single biggest free memory region we can use.
|
|
||||||
*/
|
|
||||||
static void pmm_find_biggest_usable_region(struct limine_memmap_response* memmap, struct limine_hhdm_response* hhdm)
|
|
||||||
{
|
|
||||||
// Max length of a usable memory region
|
|
||||||
uint64_t length_max = 0;
|
|
||||||
uint64_t offset = hhdm->offset;
|
|
||||||
|
|
||||||
DEBUG("Usable Memory:");
|
|
||||||
for (size_t i=0; i<memmap->entry_count; i++) {
|
|
||||||
struct limine_memmap_entry* entry = memmap->entries[i];
|
|
||||||
|
|
||||||
if (entry->type == LIMINE_MEMMAP_USABLE) {
|
|
||||||
DEBUG("0x%p-0x%p mapped at 0x%p-0x%p", entry->base, entry->base+entry->length,
|
|
||||||
entry->base+offset, entry->base+entry->length+offset);
|
|
||||||
if (entry->length > length_max)
|
|
||||||
{
|
|
||||||
length_max = entry->length;
|
|
||||||
biggest_entry = entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG("Biggest usable memory region:");
|
|
||||||
DEBUG("0x%p-0x%p mapped at 0x%p-0x%p", biggest_entry->base, biggest_entry->base + biggest_entry->length,
|
|
||||||
biggest_entry->base+offset, biggest_entry->base+biggest_entry->length+offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Offset from Higher Half Direct Map
|
// Offset from Higher Half Direct Map
|
||||||
uint64_t hhdm_off;
|
uint64_t hhdm_off;
|
||||||
|
|
||||||
@@ -99,19 +64,32 @@ void pmm_free(uintptr_t addr)
|
|||||||
* This function marks the biggest memory region as
|
* This function marks the biggest memory region as
|
||||||
* free, so we can use it in pmm_alloc.
|
* free, so we can use it in pmm_alloc.
|
||||||
*/
|
*/
|
||||||
static void pmm_init_freelist()
|
static void pmm_init_freelist(struct limine_memmap_response* memmap)
|
||||||
{
|
{
|
||||||
// We simply call pmm_free() on each page that is marked USABLE
|
uint64_t total_pages = 0;
|
||||||
// in our big memory region.
|
|
||||||
uint64_t base = ALIGN_UP(biggest_entry->base, PAGE_SIZE);
|
for (size_t i=0; i<memmap->entry_count; i++) {
|
||||||
uint64_t end = ALIGN_DOWN(biggest_entry->base + biggest_entry->length, PAGE_SIZE);
|
struct limine_memmap_entry* entry = memmap->entries[i];
|
||||||
|
|
||||||
|
if (entry->type == LIMINE_MEMMAP_USABLE) {
|
||||||
|
uint64_t base = ALIGN_UP(entry->base, PAGE_SIZE);
|
||||||
|
uint64_t end = ALIGN_DOWN(entry->base + entry->length, PAGE_SIZE);
|
||||||
|
|
||||||
|
if (end > PAGING_MAX_PHYS) {
|
||||||
|
end = PAGING_MAX_PHYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Region above PAGING_MAX_PHYS
|
||||||
|
if (base >= end) continue;
|
||||||
|
|
||||||
uint64_t page_count=0;
|
|
||||||
for (uint64_t addr = base; addr < end; addr += PAGE_SIZE) {
|
for (uint64_t addr = base; addr < end; addr += PAGE_SIZE) {
|
||||||
pmm_free(addr);
|
pmm_free(addr);
|
||||||
page_count++;
|
total_pages++;
|
||||||
}
|
}
|
||||||
DEBUG("%u frames in freelist, available for use (%u bytes)", page_count, page_count*PAGE_SIZE);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG("%u frames in freelist, %u bytes available (%u MB)", total_pages, total_pages*PAGE_SIZE, total_pages*PAGE_SIZE/1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -124,9 +102,9 @@ static void pmm_init_freelist()
|
|||||||
void pmm_init(struct boot_context boot_ctx)
|
void pmm_init(struct boot_context boot_ctx)
|
||||||
{
|
{
|
||||||
hhdm_off = boot_ctx.hhdm->offset;
|
hhdm_off = boot_ctx.hhdm->offset;
|
||||||
pmm_find_biggest_usable_region(boot_ctx.mmap, boot_ctx.hhdm);
|
//pmm_find_biggest_usable_region(boot_ctx.mmap, boot_ctx.hhdm);
|
||||||
|
|
||||||
// Now we have biggest USABLE region,
|
// Now we have biggest USABLE region,
|
||||||
// so to populate the free list we just iterate through it
|
// so to populate the free list we just iterate through it
|
||||||
pmm_init_freelist();
|
pmm_init_freelist(boot_ctx.mmap);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ struct cpu_status_t* scheduler_schedule(struct cpu_status_t* context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
current_process->context = context;
|
current_process->context = context;
|
||||||
//current_process->status = READY;
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
struct process_t* prev_process = current_process;
|
struct process_t* prev_process = current_process;
|
||||||
@@ -65,6 +64,9 @@ struct cpu_status_t* scheduler_schedule(struct cpu_status_t* context)
|
|||||||
return idle_proc->context;
|
return idle_proc->context;
|
||||||
} else {
|
} else {
|
||||||
current_process->status = RUNNING;
|
current_process->status = RUNNING;
|
||||||
|
/* if (prev_process != current_process) {
|
||||||
|
DEBUG("Changed from {pid=%u, name=%s} to {pid=%u, name=%s}", prev_process->pid, prev_process->name, current_process->pid, current_process->name);
|
||||||
|
} */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user