Get mem mapping from bootloader
This commit is contained in:
parent
77b495e382
commit
8309174f1a
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "stdarg.h"
|
#include "stdarg.h"
|
||||||
|
#include "minmax.h"
|
||||||
|
|
||||||
#define islower(c) (('a' <= (c)) && ((c) <= 'z'))
|
#define islower(c) (('a' <= (c)) && ((c) <= 'z'))
|
||||||
#define isupper(c) (('A' <= (c)) && ((c) <= 'Z'))
|
#define isupper(c) (('A' <= (c)) && ((c) <= 'Z'))
|
||||||
|
50
core/main.c
50
core/main.c
@ -37,7 +37,9 @@ void idleThread(void *arg)
|
|||||||
// https://www.gnu.org/software/grub/manual/multiboot/html_node/Boot-information-format.html#Boot%20information%20format
|
// https://www.gnu.org/software/grub/manual/multiboot/html_node/Boot-information-format.html#Boot%20information%20format
|
||||||
void kmain(unsigned long magic, unsigned long addr)
|
void kmain(unsigned long magic, unsigned long addr)
|
||||||
{
|
{
|
||||||
unsigned long upperMem = 0;
|
unsigned long upperMemKB = 0;
|
||||||
|
int memMapAvailable = 0;
|
||||||
|
paddr_t lastUsedByMem;
|
||||||
|
|
||||||
VGASetup(BLACK, GREEN);
|
VGASetup(BLACK, GREEN);
|
||||||
cursorEnable(14, 15);
|
cursorEnable(14, 15);
|
||||||
@ -53,7 +55,7 @@ void kmain(unsigned long magic, unsigned long addr)
|
|||||||
/* Are mem_* valid? */
|
/* Are mem_* valid? */
|
||||||
if (CHECK_FLAG(mbi->flags, 0)) {
|
if (CHECK_FLAG(mbi->flags, 0)) {
|
||||||
printf("mem_lower = %dKiB mem_upper %dKiB\n", mbi->mem_lower, mbi->mem_upper);
|
printf("mem_lower = %dKiB mem_upper %dKiB\n", mbi->mem_lower, mbi->mem_upper);
|
||||||
upperMem = mbi->mem_upper;
|
upperMemKB = mbi->mem_upper;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is boot_device valid? */
|
/* Is boot_device valid? */
|
||||||
@ -79,31 +81,43 @@ void kmain(unsigned long magic, unsigned long addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (CHECK_FLAG(mbi->flags, 6)) {
|
if (CHECK_FLAG(mbi->flags, 6)) {
|
||||||
struct multiboot_mmap_entry *mmap = (struct multiboot_mmap_entry *)mbi->mmap_addr;
|
memMapAvailable = 1;
|
||||||
uint size = mbi->mmap_length / sizeof(struct multiboot_mmap_entry);
|
|
||||||
pr_devel("mmap buffer at %d size %d %d\n", mbi->mmap_addr, mbi->mmap_length,
|
|
||||||
sizeof(multiboot_memory_map_t));
|
|
||||||
for (uint i = 0; i < size; i++) {
|
|
||||||
printf("base_addr 0x%x 0x%x, length = 0x%x 0x%x, type = 0x%x\n",
|
|
||||||
(unsigned)(mmap[i].addr >> 32), (unsigned)(mmap[i].addr & 0xffffffff),
|
|
||||||
(unsigned)(mmap[i].len >> 32), (unsigned)(mmap[i].len & 0xffffffff),
|
|
||||||
(uint32_t)mmap[i].type);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (upperMem == 0) {
|
if (upperMemKB == 0) {
|
||||||
printf("Cannot get upper phy mem bound. Using default value 32MB\n");
|
printf("Cannot get upper phy mem bound. Using default value 32MB\n");
|
||||||
upperMem = 32 * 1024;
|
upperMemKB = 32 * 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Setting up Pagination\n");
|
printf("Setting up Mem\n");
|
||||||
paddr_t lastUserByMem;
|
memSetup(upperMemKB, &lastUsedByMem);
|
||||||
memSetup(upperMem, &lastUserByMem);
|
|
||||||
|
if (memMapAvailable) {
|
||||||
|
multiboot_info_t *mbi = (multiboot_info_t *)addr;
|
||||||
|
struct multiboot_mmap_entry *mmap = (struct multiboot_mmap_entry *)mbi->mmap_addr;
|
||||||
|
uint size = mbi->mmap_length / sizeof(struct multiboot_mmap_entry);
|
||||||
|
pr_devel("mmap buffer at 0x%x with %d entries\n", mbi->mmap_addr, size);
|
||||||
|
for (uint i = 0; i < size; i++) {
|
||||||
|
printf(" base_addr 0x%x 0x%x, length = 0x%x 0x%x, type = 0x%x\n",
|
||||||
|
(unsigned)(mmap[i].addr >> 32), (unsigned)(mmap[i].addr & 0xffffffff),
|
||||||
|
(unsigned)(mmap[i].len >> 32), (unsigned)(mmap[i].len & 0xffffffff),
|
||||||
|
(uint32_t)mmap[i].type);
|
||||||
|
memAddBank(
|
||||||
|
max(mmap[i].addr, (multiboot_uint64_t)lastUsedByMem),
|
||||||
|
min((multiboot_uint64_t)(upperMemKB * 1024), mmap[i].addr + mmap[i].len),
|
||||||
|
mmap[i].type == MULTIBOOT_MEMORY_AVAILABLE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("Cannot get memory Mapping information, using default value\n");
|
||||||
|
memAddBank(0, lastUsedByMem, 0);
|
||||||
|
memAddBank(lastUsedByMem, upperMemKB * 1024, 1);
|
||||||
|
}
|
||||||
#ifdef RUN_TEST
|
#ifdef RUN_TEST
|
||||||
testPhymem();
|
testPhymem();
|
||||||
#endif
|
#endif
|
||||||
pagingSetup(lastUserByMem);
|
printf("Setting up Pagination\n");
|
||||||
|
pagingSetup(lastUsedByMem);
|
||||||
|
|
||||||
printf("Setting up IRQ handlers\n");
|
printf("Setting up IRQ handlers\n");
|
||||||
irqSetRoutine(IRQ_KEYBOARD, keyboard_handler);
|
irqSetRoutine(IRQ_KEYBOARD, keyboard_handler);
|
||||||
|
35
core/mem.c
35
core/mem.c
@ -7,50 +7,49 @@
|
|||||||
static struct memDesc *pageDesc = (struct memDesc *)&__ld_kernel_end;
|
static struct memDesc *pageDesc = (struct memDesc *)&__ld_kernel_end;
|
||||||
static struct memDesc *freePage;
|
static struct memDesc *freePage;
|
||||||
static struct memDesc *usedPage;
|
static struct memDesc *usedPage;
|
||||||
static unsigned long memBottom;
|
|
||||||
static unsigned long memTop;
|
|
||||||
|
|
||||||
static unsigned long allocatedPage = 0;
|
static unsigned long allocatedPage = 0;
|
||||||
|
|
||||||
int memSetup(paddr_t upperMem, paddr_t *lastPageUsedOut)
|
int memSetup(paddr_t upperMemKB, paddr_t *lastMemUsedOut)
|
||||||
{
|
{
|
||||||
list_init(freePage);
|
list_init(freePage);
|
||||||
list_init(usedPage);
|
list_init(usedPage);
|
||||||
|
|
||||||
// Align upper mem (in kB) on page size even if it does loose a page
|
// Align upper mem (in kB) on page size even if it does loose a page
|
||||||
upperMem = ALIGN_DOWN(upperMem, PAGE_SIZE / 1024);
|
upperMemKB = ALIGN_DOWN(upperMemKB, PAGE_SIZE / 1024);
|
||||||
unsigned long nbPage = ((upperMem) / (PAGE_SIZE / 1024));
|
unsigned long nbPage = ((upperMemKB) / (PAGE_SIZE / 1024));
|
||||||
|
|
||||||
printf("Available Mem from 0x%x to 0x%x: %dMB and %dPages(%d)\n", &__ld_kernel_end,
|
printf("Available Mem from 0x%x to 0x%x: %dMB and %dPages(%d)\n", &__ld_kernel_end,
|
||||||
upperMem * 1024, (upperMem * 1024 - (uint32_t)&__ld_kernel_end) / (1024 * 1024),
|
upperMemKB * 1024, (upperMemKB * 1024 - (uint32_t)&__ld_kernel_end) / (1024 * 1024),
|
||||||
nbPage, PAGE_SIZE);
|
nbPage, PAGE_SIZE);
|
||||||
|
|
||||||
// Memory description is stored after the kernel. We need some place to store it
|
// Memory description is stored after the kernel. We need some place to store it
|
||||||
unsigned long pageDescEnd = (unsigned long)pageDesc + nbPage * sizeof(struct memDesc);
|
unsigned long pageDescEnd = (unsigned long)pageDesc + nbPage * sizeof(struct memDesc);
|
||||||
uint lastPageUsed = (pageDescEnd >> PAGE_SHIFT) + 1;
|
*lastMemUsedOut = ALIGN(pageDescEnd, PAGE_SIZE);
|
||||||
memBottom = lastPageUsed << PAGE_SHIFT;
|
|
||||||
memTop = upperMem * 1024;
|
|
||||||
*lastPageUsedOut = pageDescEnd;
|
|
||||||
|
|
||||||
for (uint i = 0; i < nbPage; i++) {
|
memAddBank(0, *lastMemUsedOut, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int memAddBank(paddr_t bottomMem, paddr_t topMem, int isFree)
|
||||||
|
{
|
||||||
|
for (uint i = (bottomMem >> PAGE_SHIFT); i < (topMem >> PAGE_SHIFT); i++) {
|
||||||
struct memDesc *mem = &pageDesc[i];
|
struct memDesc *mem = &pageDesc[i];
|
||||||
if (i < lastPageUsed) {
|
if (isFree) {
|
||||||
mem->ref = 1;
|
|
||||||
list_add_tail(usedPage, mem);
|
|
||||||
} else {
|
|
||||||
mem->ref = 0;
|
mem->ref = 0;
|
||||||
list_add_tail(freePage, mem);
|
list_add_tail(freePage, mem);
|
||||||
|
} else {
|
||||||
|
mem->ref = 1;
|
||||||
|
list_add_tail(usedPage, mem);
|
||||||
}
|
}
|
||||||
mem->phy_addr = i * PAGE_SIZE;
|
mem->phy_addr = i * PAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct memDesc *addr2memDesc(paddr_t addr)
|
struct memDesc *addr2memDesc(paddr_t addr)
|
||||||
{
|
{
|
||||||
if (addr > memTop || addr < memBottom)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
int idx = addr >> PAGE_SHIFT;
|
int idx = addr >> PAGE_SHIFT;
|
||||||
return pageDesc + idx;
|
return pageDesc + idx;
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ struct memDesc {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int memSetup(paddr_t upperMem, paddr_t *lastUsed);
|
int memSetup(paddr_t upperMem, paddr_t *lastUsed);
|
||||||
|
int memAddBank(paddr_t bottomMem, paddr_t topMem, int isFree);
|
||||||
paddr_t allocPhyPage(uint nbPage);
|
paddr_t allocPhyPage(uint nbPage);
|
||||||
int unrefPhyPage(paddr_t addr);
|
int unrefPhyPage(paddr_t addr);
|
||||||
int refPhyPage(paddr_t addr);
|
int refPhyPage(paddr_t addr);
|
||||||
|
169
core/minmax.h
Normal file
169
core/minmax.h
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
#ifndef _LINUX_MINMAX_H
|
||||||
|
#define _LINUX_MINMAX_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* From linux kernel include/linux/compiler_types.h
|
||||||
|
*/
|
||||||
|
#define ___PASTE(a,b) a##b
|
||||||
|
#define __PASTE(a,b) ___PASTE(a,b)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* From Linux kernel include/linux/compiler.h
|
||||||
|
*/
|
||||||
|
/* Not-quite-unique ID. */
|
||||||
|
#ifndef __UNIQUE_ID
|
||||||
|
# define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __LINE__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* min()/max()/clamp() macros must accomplish three things:
|
||||||
|
*
|
||||||
|
* - avoid multiple evaluations of the arguments (so side-effects like
|
||||||
|
* "x++" happen only once) when non-constant.
|
||||||
|
* - perform strict type-checking (to generate warnings instead of
|
||||||
|
* nasty runtime surprises). See the "unnecessary" pointer comparison
|
||||||
|
* in __typecheck().
|
||||||
|
* - retain result as a constant expressions when called with only
|
||||||
|
* constant expressions (to avoid tripping VLA warnings in stack
|
||||||
|
* allocation usage).
|
||||||
|
*/
|
||||||
|
#define __typecheck(x, y) \
|
||||||
|
(!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This returns a constant expression while determining if an argument is
|
||||||
|
* a constant expression, most importantly without evaluating the argument.
|
||||||
|
* Glory to Martin Uecker <Martin.Uecker@med.uni-goettingen.de>
|
||||||
|
*/
|
||||||
|
#define __is_constexpr(x) \
|
||||||
|
(sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8)))
|
||||||
|
|
||||||
|
#define __no_side_effects(x, y) \
|
||||||
|
(__is_constexpr(x) && __is_constexpr(y))
|
||||||
|
|
||||||
|
#define __safe_cmp(x, y) \
|
||||||
|
(__typecheck(x, y) && __no_side_effects(x, y))
|
||||||
|
|
||||||
|
#define __cmp(x, y, op) ((x) op (y) ? (x) : (y))
|
||||||
|
|
||||||
|
#define __cmp_once(x, y, unique_x, unique_y, op) ({ \
|
||||||
|
typeof(x) unique_x = (x); \
|
||||||
|
typeof(y) unique_y = (y); \
|
||||||
|
__cmp(unique_x, unique_y, op); })
|
||||||
|
|
||||||
|
#define __careful_cmp(x, y, op) \
|
||||||
|
__builtin_choose_expr(__safe_cmp(x, y), \
|
||||||
|
__cmp(x, y, op), \
|
||||||
|
__cmp_once(x, y, __UNIQUE_ID(__x), __UNIQUE_ID(__y), op))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* min - return minimum of two values of the same or compatible types
|
||||||
|
* @x: first value
|
||||||
|
* @y: second value
|
||||||
|
*/
|
||||||
|
#define min(x, y) __careful_cmp(x, y, <)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* max - return maximum of two values of the same or compatible types
|
||||||
|
* @x: first value
|
||||||
|
* @y: second value
|
||||||
|
*/
|
||||||
|
#define max(x, y) __careful_cmp(x, y, >)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* min3 - return minimum of three values
|
||||||
|
* @x: first value
|
||||||
|
* @y: second value
|
||||||
|
* @z: third value
|
||||||
|
*/
|
||||||
|
#define min3(x, y, z) min((typeof(x))min(x, y), z)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* max3 - return maximum of three values
|
||||||
|
* @x: first value
|
||||||
|
* @y: second value
|
||||||
|
* @z: third value
|
||||||
|
*/
|
||||||
|
#define max3(x, y, z) max((typeof(x))max(x, y), z)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* min_not_zero - return the minimum that is _not_ zero, unless both are zero
|
||||||
|
* @x: value1
|
||||||
|
* @y: value2
|
||||||
|
*/
|
||||||
|
#define min_not_zero(x, y) ({ \
|
||||||
|
typeof(x) __x = (x); \
|
||||||
|
typeof(y) __y = (y); \
|
||||||
|
__x == 0 ? __y : ((__y == 0) ? __x : min(__x, __y)); })
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clamp - return a value clamped to a given range with strict typechecking
|
||||||
|
* @val: current value
|
||||||
|
* @lo: lowest allowable value
|
||||||
|
* @hi: highest allowable value
|
||||||
|
*
|
||||||
|
* This macro does strict typechecking of @lo/@hi to make sure they are of the
|
||||||
|
* same type as @val. See the unnecessary pointer comparisons.
|
||||||
|
*/
|
||||||
|
#define clamp(val, lo, hi) min((typeof(val))max(val, lo), hi)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ..and if you can't take the strict
|
||||||
|
* types, you can specify one yourself.
|
||||||
|
*
|
||||||
|
* Or not use min/max/clamp at all, of course.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* min_t - return minimum of two values, using the specified type
|
||||||
|
* @type: data type to use
|
||||||
|
* @x: first value
|
||||||
|
* @y: second value
|
||||||
|
*/
|
||||||
|
#define min_t(type, x, y) __careful_cmp((type)(x), (type)(y), <)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* max_t - return maximum of two values, using the specified type
|
||||||
|
* @type: data type to use
|
||||||
|
* @x: first value
|
||||||
|
* @y: second value
|
||||||
|
*/
|
||||||
|
#define max_t(type, x, y) __careful_cmp((type)(x), (type)(y), >)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clamp_t - return a value clamped to a given range using a given type
|
||||||
|
* @type: the type of variable to use
|
||||||
|
* @val: current value
|
||||||
|
* @lo: minimum allowable value
|
||||||
|
* @hi: maximum allowable value
|
||||||
|
*
|
||||||
|
* This macro does no typechecking and uses temporary variables of type
|
||||||
|
* @type to make all the comparisons.
|
||||||
|
*/
|
||||||
|
#define clamp_t(type, val, lo, hi) min_t(type, max_t(type, val, lo), hi)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clamp_val - return a value clamped to a given range using val's type
|
||||||
|
* @val: current value
|
||||||
|
* @lo: minimum allowable value
|
||||||
|
* @hi: maximum allowable value
|
||||||
|
*
|
||||||
|
* This macro does no typechecking and uses temporary variables of whatever
|
||||||
|
* type the input argument @val is. This is useful when @val is an unsigned
|
||||||
|
* type and @lo and @hi are literals that will otherwise be assigned a signed
|
||||||
|
* integer type.
|
||||||
|
*/
|
||||||
|
#define clamp_val(val, lo, hi) clamp_t(typeof(val), val, lo, hi)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* swap - swap values of @a and @b
|
||||||
|
* @a: first value
|
||||||
|
* @b: second value
|
||||||
|
*/
|
||||||
|
#define swap(a, b) \
|
||||||
|
do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0)
|
||||||
|
|
||||||
|
#endif /* _LINUX_MINMAX_H */
|
@ -14,8 +14,6 @@
|
|||||||
void testPhymem(void)
|
void testPhymem(void)
|
||||||
{
|
{
|
||||||
printf("Testing memory PHY\n");
|
printf("Testing memory PHY\n");
|
||||||
assert(refPhyPage((paddr_t)(&__ld_kernel_end)) == -1);
|
|
||||||
assert(refPhyPage((paddr_t)(&__ld_kernel_begin)) == -1);
|
|
||||||
struct memDesc *allocated_page_list;
|
struct memDesc *allocated_page_list;
|
||||||
struct memDesc
|
struct memDesc
|
||||||
*page; // Cast in mem_desc to use it. In fact it's the addr of 4K free memory
|
*page; // Cast in mem_desc to use it. In fact it's the addr of 4K free memory
|
||||||
|
Loading…
Reference in New Issue
Block a user