misc: changes from a long time ago
This commit is contained in:
@@ -45,7 +45,14 @@ target_include_directories(${kernel_exe_name} PRIVATE
|
|||||||
target_compile_options(${kernel_exe_name} PRIVATE
|
target_compile_options(${kernel_exe_name} PRIVATE
|
||||||
-nostdlib -ffreestanding
|
-nostdlib -ffreestanding
|
||||||
-Wall -Werror -pedantic -Wno-language-extension-token -Wno-unused-function -Wno-gnu-statement-expression
|
-Wall -Werror -pedantic -Wno-language-extension-token -Wno-unused-function -Wno-gnu-statement-expression
|
||||||
-O2 -g -fPIC -Iinclude -Iarch/${kernel_arch}/include -Ilibc/include)
|
-g -fPIC -Iinclude -Iarch/${kernel_arch}/include -Ilibc/include)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
TARGET ${kernel_exe_name}
|
||||||
|
POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${kernel_exe_name}> $<TARGET_FILE:${kernel_exe_name}>.debug
|
||||||
|
COMMAND ${CMAKE_STRIP} -g $<TARGET_FILE:${kernel_exe_name}>)
|
||||||
|
|
||||||
target_link_libraries(${kernel_exe_name} -nostdlib -ffreestanding -lgcc)
|
target_link_libraries(${kernel_exe_name} -nostdlib -ffreestanding -lgcc)
|
||||||
target_compile_definitions(${kernel_exe_name} PRIVATE BUILD_ID="0")
|
target_compile_definitions(${kernel_exe_name} PRIVATE BUILD_ID="0")
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "arch/serial.h"
|
|
||||||
|
|
||||||
#include <arch/e820.h>
|
#include <arch/e820.h>
|
||||||
#include <arch/pit.h>
|
#include <arch/pit.h>
|
||||||
|
#include <arch/serial.h>
|
||||||
|
#include <arch/vgacon.h>
|
||||||
#include <mango/arg.h>
|
#include <mango/arg.h>
|
||||||
#include <mango/clock.h>
|
#include <mango/clock.h>
|
||||||
#include <mango/console.h>
|
#include <mango/console.h>
|
||||||
@@ -52,11 +52,12 @@ void early_console_init(void)
|
|||||||
{
|
{
|
||||||
const char *dest = arg_value("kernel.early-console");
|
const char *dest = arg_value("kernel.early-console");
|
||||||
if (!dest) {
|
if (!dest) {
|
||||||
dest = "ttyS0";
|
dest = "tty0";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(dest, "tty0")) {
|
if (!strcmp(dest, "tty0")) {
|
||||||
/* show log messages on VGA */
|
/* show log messages on VGA */
|
||||||
|
vgacon_init();
|
||||||
} else if (!strcmp(dest, "ttyS0")) {
|
} else if (!strcmp(dest, "ttyS0")) {
|
||||||
/* write log messages to serial port */
|
/* write log messages to serial port */
|
||||||
early_serialcon_init(115200);
|
early_serialcon_init(115200);
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
#include <mango/types.h>
|
#include <mango/compiler.h>
|
||||||
#include <mango/memblock.h>
|
#include <mango/memblock.h>
|
||||||
#include <mango/vm.h>
|
#include <mango/pmap.h>
|
||||||
#include <mango/printk.h>
|
#include <mango/printk.h>
|
||||||
#include <mango/status.h>
|
#include <mango/status.h>
|
||||||
#include <mango/compiler.h>
|
#include <mango/types.h>
|
||||||
#include <mango/pmap.h>
|
#include <mango/vm.h>
|
||||||
|
|
||||||
/* some helpful datasize constants */
|
/* some helpful datasize constants */
|
||||||
#define C_1GiB 0x40000000ULL
|
#define C_1GiB 0x40000000ULL
|
||||||
#define C_2GiB (2 * C_1GiB)
|
#define C_2GiB (2 * C_1GiB)
|
||||||
|
|
||||||
#define BAD_INDEX ((unsigned int)-1)
|
#define BAD_INDEX ((unsigned int)-1)
|
||||||
#define PTR_TO_ENTRY(x) (((x) & ~VM_PAGE_MASK) | PTE_PRESENT | PTE_RW)
|
#define PTR_TO_ENTRY(x) (((x) & ~VM_PAGE_MASK) | PTE_PRESENT | PTE_RW)
|
||||||
#define ENTRY_TO_PTR(x) ((x) & ~VM_PAGE_MASK)
|
#define ENTRY_TO_PTR(x) ((x) & ~VM_PAGE_MASK)
|
||||||
|
|
||||||
#define PFN(x) ((x) >> VM_PAGE_SHIFT)
|
#define PFN(x) ((x) >> VM_PAGE_SHIFT)
|
||||||
|
|
||||||
static int can_use_gbpages = 0;
|
static int can_use_gbpages = 0;
|
||||||
static pmap_t kernel_pmap;
|
static pmap_t kernel_pmap;
|
||||||
@@ -33,7 +33,7 @@ static size_t ps_size(enum page_size ps)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static pmap_t alloc_pmap()
|
static pmap_t alloc_pmap(void)
|
||||||
{
|
{
|
||||||
struct pml4t *p = kzalloc(sizeof *p, 0);
|
struct pml4t *p = kzalloc(sizeof *p, 0);
|
||||||
return vm_virt_to_phys(p);
|
return vm_virt_to_phys(p);
|
||||||
@@ -45,12 +45,14 @@ static pte_t make_pte(pfn_t pfn, enum vm_prot prot, enum page_size size)
|
|||||||
|
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case PS_1G:
|
case PS_1G:
|
||||||
/* pfn_t is in terms of 4KiB pages, convert to 1GiB page frame number */
|
/* pfn_t is in terms of 4KiB pages, convert to 1GiB page frame
|
||||||
|
* number */
|
||||||
pfn >>= 18;
|
pfn >>= 18;
|
||||||
v = (pfn & 0x3FFFFF) << 30;
|
v = (pfn & 0x3FFFFF) << 30;
|
||||||
break;
|
break;
|
||||||
case PS_2M:
|
case PS_2M:
|
||||||
/* pfn_t is in terms of 4KiB pages, convert to 2MiB page frame number */
|
/* pfn_t is in terms of 4KiB pages, convert to 2MiB page frame
|
||||||
|
* number */
|
||||||
pfn >>= 9;
|
pfn >>= 9;
|
||||||
v = (pfn & 0x7FFFFFFF) << 21;
|
v = (pfn & 0x7FFFFFFF) << 21;
|
||||||
break;
|
break;
|
||||||
@@ -129,14 +131,16 @@ static void delete_pdir(phys_addr_t pd)
|
|||||||
kfree(pdir);
|
kfree(pdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
static kern_status_t do_pmap_add(pmap_t pmap, void *p, pfn_t pfn, enum vm_prot prot, enum page_size size)
|
static kern_status_t do_pmap_add(
|
||||||
|
pmap_t pmap,
|
||||||
|
void *p,
|
||||||
|
pfn_t pfn,
|
||||||
|
enum vm_prot prot,
|
||||||
|
enum page_size size)
|
||||||
{
|
{
|
||||||
uintptr_t pv = (uintptr_t)p;
|
uintptr_t pv = (uintptr_t)p;
|
||||||
unsigned int
|
unsigned int pml4t_index = BAD_INDEX, pdpt_index = BAD_INDEX,
|
||||||
pml4t_index = BAD_INDEX,
|
pd_index = BAD_INDEX, pt_index = BAD_INDEX;
|
||||||
pdpt_index = BAD_INDEX,
|
|
||||||
pd_index = BAD_INDEX,
|
|
||||||
pt_index = BAD_INDEX;
|
|
||||||
|
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case PS_4K:
|
case PS_4K:
|
||||||
@@ -171,16 +175,19 @@ static kern_status_t do_pmap_add(pmap_t pmap, void *p, pfn_t pfn, enum vm_prot p
|
|||||||
struct pdpt *pdpt = NULL;
|
struct pdpt *pdpt = NULL;
|
||||||
if (!pml4t->p_entries[pml4t_index]) {
|
if (!pml4t->p_entries[pml4t_index]) {
|
||||||
pdpt = kzalloc(sizeof *pdpt, 0);
|
pdpt = kzalloc(sizeof *pdpt, 0);
|
||||||
pml4t->p_entries[pml4t_index] = PTR_TO_ENTRY(vm_virt_to_phys(pdpt));
|
pml4t->p_entries[pml4t_index]
|
||||||
|
= PTR_TO_ENTRY(vm_virt_to_phys(pdpt));
|
||||||
} else {
|
} else {
|
||||||
pdpt = vm_phys_to_virt(ENTRY_TO_PTR(pml4t->p_entries[pml4t_index]));
|
pdpt = vm_phys_to_virt(
|
||||||
|
ENTRY_TO_PTR(pml4t->p_entries[pml4t_index]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we're mapping a 1GiB page, we stop here */
|
/* if we're mapping a 1GiB page, we stop here */
|
||||||
if (size == PS_1G) {
|
if (size == PS_1G) {
|
||||||
if (pdpt->p_entries[pdpt_index] != 0) {
|
if (pdpt->p_entries[pdpt_index] != 0) {
|
||||||
/* this slot points to a pdir, delete it.
|
/* this slot points to a pdir, delete it.
|
||||||
if this slot points to a hugepage, this does nothing */
|
if this slot points to a hugepage, this does nothing
|
||||||
|
*/
|
||||||
delete_pdir(pdpt->p_entries[pdpt_index]);
|
delete_pdir(pdpt->p_entries[pdpt_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,22 +196,25 @@ static kern_status_t do_pmap_add(pmap_t pmap, void *p, pfn_t pfn, enum vm_prot p
|
|||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* 3. traverse PDPT, get PDIR (optional, 4K and 2M only) */
|
/* 3. traverse PDPT, get PDIR (optional, 4K and 2M only) */
|
||||||
struct pdir *pdir = NULL;
|
struct pdir *pdir = NULL;
|
||||||
if (!pdpt->p_entries[pdpt_index] || pdpt->p_pages[pdpt_index] & PTE_PAGESIZE) {
|
if (!pdpt->p_entries[pdpt_index]
|
||||||
|
|| pdpt->p_pages[pdpt_index] & PTE_PAGESIZE) {
|
||||||
/* entry is null, or points to a hugepage */
|
/* entry is null, or points to a hugepage */
|
||||||
pdir = kzalloc(sizeof *pdir, 0);
|
pdir = kzalloc(sizeof *pdir, 0);
|
||||||
pdpt->p_entries[pdpt_index] = PTR_TO_ENTRY(vm_virt_to_phys(pdir));
|
pdpt->p_entries[pdpt_index]
|
||||||
|
= PTR_TO_ENTRY(vm_virt_to_phys(pdir));
|
||||||
} else {
|
} else {
|
||||||
pdir = vm_phys_to_virt(ENTRY_TO_PTR(pdpt->p_entries[pdpt_index]));
|
pdir = vm_phys_to_virt(
|
||||||
|
ENTRY_TO_PTR(pdpt->p_entries[pdpt_index]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we're mapping a 2MiB page, we stop here */
|
/* if we're mapping a 2MiB page, we stop here */
|
||||||
if (size == PS_2M) {
|
if (size == PS_2M) {
|
||||||
if (pdir->p_entries[pd_index] != 0) {
|
if (pdir->p_entries[pd_index] != 0) {
|
||||||
/* this slot points to a ptab, delete it.
|
/* this slot points to a ptab, delete it.
|
||||||
if this slot points to a hugepage, this does nothing */
|
if this slot points to a hugepage, this does nothing
|
||||||
|
*/
|
||||||
delete_ptab(pdir->p_entries[pd_index]);
|
delete_ptab(pdir->p_entries[pd_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,7 +224,8 @@ static kern_status_t do_pmap_add(pmap_t pmap, void *p, pfn_t pfn, enum vm_prot p
|
|||||||
|
|
||||||
/* 4. traverse PDIR, get PTAB (optional, 4K only) */
|
/* 4. traverse PDIR, get PTAB (optional, 4K only) */
|
||||||
struct ptab *ptab = NULL;
|
struct ptab *ptab = NULL;
|
||||||
if (!pdir->p_entries[pd_index] || pdir->p_pages[pd_index] & PTE_PAGESIZE) {
|
if (!pdir->p_entries[pd_index]
|
||||||
|
|| pdir->p_pages[pd_index] & PTE_PAGESIZE) {
|
||||||
/* entry is null, or points to a hugepage */
|
/* entry is null, or points to a hugepage */
|
||||||
ptab = kzalloc(sizeof *ptab, 0);
|
ptab = kzalloc(sizeof *ptab, 0);
|
||||||
pdir->p_entries[pd_index] = PTR_TO_ENTRY(vm_virt_to_phys(ptab));
|
pdir->p_entries[pd_index] = PTR_TO_ENTRY(vm_virt_to_phys(ptab));
|
||||||
@@ -234,7 +245,8 @@ pmap_t get_kernel_pmap(void)
|
|||||||
void pmap_bootstrap(void)
|
void pmap_bootstrap(void)
|
||||||
{
|
{
|
||||||
can_use_gbpages = gigabyte_pages();
|
can_use_gbpages = gigabyte_pages();
|
||||||
printk("pmap: gigabyte pages %sabled", can_use_gbpages == 1 ? "en" : "dis");
|
printk("pmap: gigabyte pages %sabled",
|
||||||
|
can_use_gbpages == 1 ? "en" : "dis");
|
||||||
enable_nx();
|
enable_nx();
|
||||||
printk("pmap: NX protection enabled");
|
printk("pmap: NX protection enabled");
|
||||||
|
|
||||||
@@ -251,16 +263,19 @@ void pmap_bootstrap(void)
|
|||||||
the kernel and memblock-allocated data. */
|
the kernel and memblock-allocated data. */
|
||||||
uintptr_t vbase = VM_KERNEL_VOFFSET;
|
uintptr_t vbase = VM_KERNEL_VOFFSET;
|
||||||
for (size_t i = 0; i < C_2GiB; i += hugepage_sz) {
|
for (size_t i = 0; i < C_2GiB; i += hugepage_sz) {
|
||||||
do_pmap_add(kernel_pmap,
|
do_pmap_add(
|
||||||
(void *)(vbase + i),
|
kernel_pmap,
|
||||||
PFN(i),
|
(void *)(vbase + i),
|
||||||
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXEC | VM_PROT_SVR,
|
PFN(i),
|
||||||
hugepage);
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXEC
|
||||||
|
| VM_PROT_SVR,
|
||||||
|
hugepage);
|
||||||
}
|
}
|
||||||
|
|
||||||
phys_addr_t pmem_limit = 0x0;
|
phys_addr_t pmem_limit = 0x0;
|
||||||
struct memblock_iter it;
|
struct memblock_iter it;
|
||||||
for_each_mem_range(&it, 0x00, UINTPTR_MAX) {
|
for_each_mem_range(&it, 0x00, UINTPTR_MAX)
|
||||||
|
{
|
||||||
if (it.it_limit > pmem_limit) {
|
if (it.it_limit > pmem_limit) {
|
||||||
pmem_limit = it.it_limit;
|
pmem_limit = it.it_limit;
|
||||||
}
|
}
|
||||||
@@ -268,10 +283,13 @@ void pmap_bootstrap(void)
|
|||||||
|
|
||||||
vbase = VM_PAGEMAP_BASE;
|
vbase = VM_PAGEMAP_BASE;
|
||||||
for (size_t i = 0; i < pmem_limit; i += hugepage_sz) {
|
for (size_t i = 0; i < pmem_limit; i += hugepage_sz) {
|
||||||
do_pmap_add(kernel_pmap,
|
do_pmap_add(
|
||||||
(void *)(vbase + i),
|
kernel_pmap,
|
||||||
PFN(i),
|
(void *)(vbase + i),
|
||||||
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_SVR | VM_PROT_NOCACHE, hugepage);
|
PFN(i),
|
||||||
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_SVR
|
||||||
|
| VM_PROT_NOCACHE,
|
||||||
|
hugepage);
|
||||||
}
|
}
|
||||||
|
|
||||||
pmap_switch(kernel_pmap);
|
pmap_switch(kernel_pmap);
|
||||||
@@ -284,10 +302,14 @@ pmap_t pmap_create(void)
|
|||||||
|
|
||||||
void pmap_destroy(pmap_t pmap)
|
void pmap_destroy(pmap_t pmap)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kern_status_t pmap_add(pmap_t pmap, void *p, pfn_t pfn, enum vm_prot prot, enum pmap_flags flags)
|
kern_status_t pmap_add(
|
||||||
|
pmap_t pmap,
|
||||||
|
void *p,
|
||||||
|
pfn_t pfn,
|
||||||
|
enum vm_prot prot,
|
||||||
|
enum pmap_flags flags)
|
||||||
{
|
{
|
||||||
enum page_size ps = PS_4K;
|
enum page_size ps = PS_4K;
|
||||||
if (flags & PMAP_HUGEPAGE) {
|
if (flags & PMAP_HUGEPAGE) {
|
||||||
@@ -297,7 +319,13 @@ kern_status_t pmap_add(pmap_t pmap, void *p, pfn_t pfn, enum vm_prot prot, enum
|
|||||||
return do_pmap_add(pmap, p, pfn, prot, ps);
|
return do_pmap_add(pmap, p, pfn, prot, ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
kern_status_t pmap_add_block(pmap_t pmap, void *p, pfn_t pfn, size_t len, enum vm_prot prot, enum pmap_flags flags)
|
kern_status_t pmap_add_block(
|
||||||
|
pmap_t pmap,
|
||||||
|
void *p,
|
||||||
|
pfn_t pfn,
|
||||||
|
size_t len,
|
||||||
|
enum vm_prot prot,
|
||||||
|
enum pmap_flags flags)
|
||||||
{
|
{
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +1,50 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
uint8_t inportb(uint16_t port) {
|
uint8_t inportb(uint16_t port)
|
||||||
uint8_t data;
|
{
|
||||||
__asm__ __volatile__("inb %1, %0" : "=a"(data) : "dN"(port));
|
uint8_t data;
|
||||||
return data;
|
__asm__ __volatile__("inb %1, %0" : "=a"(data) : "dN"(port));
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void outportb(uint16_t port, uint8_t data) {
|
void outportb(uint16_t port, uint8_t data)
|
||||||
__asm__ __volatile__("outb %1, %0" : : "dN"(port), "a"(data));
|
{
|
||||||
|
__asm__ __volatile__("outb %1, %0" : : "dN"(port), "a"(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t inportw(uint16_t port) {
|
uint16_t inportw(uint16_t port)
|
||||||
uint16_t data;
|
{
|
||||||
__asm__ __volatile__("inw %1, %0" : "=a"(data) : "dN"(port));
|
uint16_t data;
|
||||||
return data;
|
__asm__ __volatile__("inw %1, %0" : "=a"(data) : "dN"(port));
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void outportw(uint16_t port, uint16_t data) {
|
void outportw(uint16_t port, uint16_t data)
|
||||||
__asm__ __volatile__("outw %1, %0" : : "dN"(port), "a"(data));
|
{
|
||||||
|
__asm__ __volatile__("outw %1, %0" : : "dN"(port), "a"(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t inportl(uint16_t port) {
|
uint32_t inportl(uint16_t port)
|
||||||
uint32_t data;
|
{
|
||||||
__asm__ __volatile__("inl %%dx, %%eax" : "=a"(data) : "dN"(port));
|
uint32_t data;
|
||||||
return data;
|
__asm__ __volatile__("inl %%dx, %%eax" : "=a"(data) : "dN"(port));
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void outportl(uint16_t port, uint32_t data) {
|
void outportl(uint16_t port, uint32_t data)
|
||||||
__asm__ __volatile__("outl %%eax, %%dx" : : "dN"(port), "a"(data));
|
{
|
||||||
|
__asm__ __volatile__("outl %%eax, %%dx" : : "dN"(port), "a"(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void outportsw(uint16_t port, void *data, uint32_t size) {
|
void outportsw(uint16_t port, void *data, uint32_t size)
|
||||||
__asm__ __volatile__("rep outsw" : "+S"(data), "+c"(size) : "d"(port));
|
{
|
||||||
|
__asm__ __volatile__("rep outsw" : "+S"(data), "+c"(size) : "d"(port));
|
||||||
}
|
}
|
||||||
|
|
||||||
void inportsw(uint16_t port, unsigned char *data, unsigned long size) {
|
void inportsw(uint16_t port, unsigned char *data, unsigned long size)
|
||||||
__asm__ __volatile__("rep insw" : "+D"(data), "+c"(size) : "d"(port) : "memory");
|
{
|
||||||
|
__asm__ __volatile__("rep insw"
|
||||||
|
: "+D"(data), "+c"(size)
|
||||||
|
: "d"(port)
|
||||||
|
: "memory");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,21 @@
|
|||||||
find_program(QEMU qemu-system-x86_64)
|
find_program(QEMU qemu-system-x86_64)
|
||||||
|
set(DEBUG_SESSION ${CMAKE_SOURCE_DIR}/tools/kernel-debug/debug_session.sh)
|
||||||
|
set(DEBUG_CFG_GDB ${CMAKE_SOURCE_DIR}/tools/kernel-debug/gdb_session_init)
|
||||||
|
set(DEBUG_CFG_LLDB ${CMAKE_SOURCE_DIR}/tools/kernel-debug/lldb_session_init)
|
||||||
|
|
||||||
add_custom_target(run
|
add_custom_target(run
|
||||||
USES_TERMINAL
|
USES_TERMINAL
|
||||||
COMMAND ${QEMU}
|
COMMAND ${QEMU}
|
||||||
-kernel $<TARGET_FILE:${kernel_exe_name}>
|
-kernel $<TARGET_FILE:${kernel_exe_name}>
|
||||||
-serial stdio)
|
-serial stdio)
|
||||||
|
|
||||||
|
# LLDB DEPENDS ON AN ELF64 EXECUTABLE.
|
||||||
|
# .DBG FILE MUST NOT BE PATCHED WITH E64PATCH!
|
||||||
|
add_custom_target(debug
|
||||||
|
USES_TERMINAL
|
||||||
|
COMMAND ${DEBUG_SESSION}
|
||||||
|
${DEBUG_CFG_GDB}
|
||||||
|
${DEBUG_CFG_LLDB}
|
||||||
|
${QEMU} -kernel $<TARGET_FILE:${kernel_exe_name}>
|
||||||
|
-S -s
|
||||||
|
-monitor stdio)
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ set(CMAKE_C_COMPILER x86_64-elf-gcc)
|
|||||||
set(CMAKE_ASM_COMPILER x86_64-elf-gcc)
|
set(CMAKE_ASM_COMPILER x86_64-elf-gcc)
|
||||||
set(CMAKE_CXX_COMPILER x86_64-elf-g++)
|
set(CMAKE_CXX_COMPILER x86_64-elf-g++)
|
||||||
|
|
||||||
|
set(CMAKE_STRIP x86_64-elf-strip)
|
||||||
|
|
||||||
set(CMAKE_C_COMPILER_WORKS TRUE)
|
set(CMAKE_C_COMPILER_WORKS TRUE)
|
||||||
set(CMAKE_CXX_COMPILER_WORKS TRUE)
|
set(CMAKE_CXX_COMPILER_WORKS TRUE)
|
||||||
|
|
||||||
|
|||||||
126
arch/x86_64/vga.c
Normal file
126
arch/x86_64/vga.c
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
#include <arch/irq.h>
|
||||||
|
#include <arch/ports.h>
|
||||||
|
#include <arch/serial.h>
|
||||||
|
#include <mango/libc/stdio.h>
|
||||||
|
#include <mango/machine/vm.h>
|
||||||
|
#include <mango/printk.h>
|
||||||
|
|
||||||
|
struct vga_console {
|
||||||
|
uint16_t *vga_framebuffer;
|
||||||
|
unsigned int vga_cursor_x, vga_cursor_y;
|
||||||
|
unsigned int vga_screen_width, vga_screen_height;
|
||||||
|
uint8_t vga_attrib;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct vga_console vga_con = {
|
||||||
|
.vga_attrib = 0x0F,
|
||||||
|
.vga_screen_width = 80,
|
||||||
|
.vga_screen_height = 25,
|
||||||
|
.vga_framebuffer = (uint16_t *)0xffffffff800b8000,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void vga_console_clear(struct vga_console *con)
|
||||||
|
{
|
||||||
|
size_t len = con->vga_screen_width * con->vga_screen_height;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
con->vga_framebuffer[i] = (uint16_t)con->vga_attrib << 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
con->vga_cursor_x = 0;
|
||||||
|
con->vga_cursor_y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vga_console_show_cursor(struct vga_console *con)
|
||||||
|
{
|
||||||
|
size_t start = 0, end = 15;
|
||||||
|
|
||||||
|
outportb(0x3D4, 0x0A);
|
||||||
|
outportb(0x3D5, (inportb(0x3D5) & 0xC0) | start);
|
||||||
|
|
||||||
|
outportb(0x3D4, 0x0B);
|
||||||
|
outportb(0x3D5, (inportb(0x3D5) & 0xE0) | end);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vga_console_update_cursor(struct vga_console *con)
|
||||||
|
{
|
||||||
|
uint16_t pos
|
||||||
|
= con->vga_cursor_y * con->vga_screen_width + con->vga_cursor_x;
|
||||||
|
|
||||||
|
outportb(0x3D4, 0x0F);
|
||||||
|
outportb(0x3D5, (uint8_t)(pos & 0xFF));
|
||||||
|
outportb(0x3D4, 0x0E);
|
||||||
|
outportb(0x3D5, (uint8_t)((pos >> 8) & 0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vga_console_scroll(struct vga_console *con)
|
||||||
|
{
|
||||||
|
uint16_t *src = &con->vga_framebuffer[con->vga_screen_width];
|
||||||
|
uint16_t *dest = &con->vga_framebuffer[0];
|
||||||
|
size_t len = (con->vga_screen_height - 1) * con->vga_screen_width
|
||||||
|
* sizeof *con->vga_framebuffer;
|
||||||
|
|
||||||
|
memcpy(dest, src, len);
|
||||||
|
|
||||||
|
dest = &con->vga_framebuffer
|
||||||
|
[(con->vga_screen_height - 1) * con->vga_screen_width];
|
||||||
|
len = con->vga_screen_width;
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
dest[i] = (uint16_t)con->vga_attrib << 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
con->vga_cursor_x = 0;
|
||||||
|
con->vga_cursor_y = con->vga_screen_height - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vga_console_putc(struct vga_console *con, char c)
|
||||||
|
{
|
||||||
|
switch (c) {
|
||||||
|
case '\n':
|
||||||
|
con->vga_cursor_x = 0;
|
||||||
|
con->vga_cursor_y++;
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
con->vga_cursor_x = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
con->vga_framebuffer
|
||||||
|
[con->vga_cursor_y * con->vga_screen_width
|
||||||
|
+ con->vga_cursor_x]
|
||||||
|
= ((uint16_t)con->vga_attrib << 8) | c;
|
||||||
|
con->vga_cursor_x++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (con->vga_cursor_x >= con->vga_screen_width) {
|
||||||
|
con->vga_cursor_x = 0;
|
||||||
|
con->vga_cursor_y++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (con->vga_cursor_y >= con->vga_screen_height) {
|
||||||
|
vga_console_scroll(con);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vgacon_write(struct console *con, const char *s, unsigned int len)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < len; i++) {
|
||||||
|
vga_console_putc(&vga_con, s[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
vga_console_update_cursor(&vga_con);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct console vgacon = {
|
||||||
|
.c_name = "vgacon",
|
||||||
|
.c_flags = CON_BOOT,
|
||||||
|
.c_write = vgacon_write,
|
||||||
|
.c_lock = SPIN_LOCK_INIT,
|
||||||
|
};
|
||||||
|
|
||||||
|
void vgacon_init(void)
|
||||||
|
{
|
||||||
|
vga_console_clear(&vga_con);
|
||||||
|
vga_console_show_cursor(&vga_con);
|
||||||
|
console_register(&vgacon);
|
||||||
|
}
|
||||||
@@ -7,24 +7,27 @@ shift 2
|
|||||||
if command -v gdb &> /dev/null; then
|
if command -v gdb &> /dev/null; then
|
||||||
printf " \033[93;1mGDB\033[0m boot/mango_kernel\n"
|
printf " \033[93;1mGDB\033[0m boot/mango_kernel\n"
|
||||||
tmux \
|
tmux \
|
||||||
new-session -d -s hz-debug "sleep 0.3; gdb -tui -x $gdb_cfg" \; \
|
new-session -d -s mango-debug "sleep 0.3; gdb -tui -x $gdb_cfg" \; \
|
||||||
split-window -h -l 80 \; \
|
split-window -h -l 80 \; \
|
||||||
split-window -v -l 25 "$@"\; \
|
split-window -v -l 25 "$@"\; \
|
||||||
select-pane -t 1 \; \
|
select-pane -t 1 \; \
|
||||||
resize-pane -R 20
|
resize-pane -R 20 \; \
|
||||||
|
select-pane -t 0
|
||||||
|
|
||||||
elif command -v lldb &> /dev/null; then
|
elif command -v lldb &> /dev/null; then
|
||||||
printf " \033[93;1mLLDB\033[0m boot/mango_kernel\n"
|
printf " \033[93;1mLLDB\033[0m boot/mango_kernel\n"
|
||||||
tmux \
|
tmux \
|
||||||
new-session -d -s hz-debug "sleep 0.1; lldb --source $lldb_cfg" \; \
|
new-session -d -s mango-debug "sleep 0.1; lldb --source $lldb_cfg" \; \
|
||||||
split-window -h -l 160 \; \
|
split-window -h -l 160 \; \
|
||||||
split-window -v -l 25 "$@"\; \
|
split-window -v -l 25 "$@"\; \
|
||||||
select-pane -t 1 \; \
|
select-pane -t 1 \; \
|
||||||
resize-pane -R 50
|
resize-pane -R 50 \; \
|
||||||
|
select-pane -t 0
|
||||||
else
|
else
|
||||||
printf " \033[91;1mERR\033[0m No debugger available\n"
|
printf " \033[91;1mERR\033[0m No debugger available\n"
|
||||||
exit -1
|
exit -1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
tmux a -t hz-debug
|
tmux a -t mango-debug
|
||||||
tmux kill-session -t hz-debug
|
tmux kill-session -t mango-debug
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
set confirm off
|
set confirm off
|
||||||
symbol-file build/mango_kernel.dbg
|
symbol-file mango_kernel.debug
|
||||||
target remote localhost:1234
|
target remote localhost:1234
|
||||||
set confirm on
|
set confirm on
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
file build/mango_kernel.dbg
|
file mango_kernel.debug
|
||||||
gdb-remote localhost:1234
|
gdb-remote localhost:1234
|
||||||
|
|||||||
Reference in New Issue
Block a user