提交 b3922680 创建 作者: Silas Boyd-Wickizer's avatar Silas Boyd-Wickizer

Use the memory map from the multiboot header.

上级 f9a1d033
......@@ -32,7 +32,6 @@ OBJS = \
cga.o \
condvar.o \
console.o \
e820.o \
exec.o \
file.o \
fs.o \
......
#include "types.h"
#include "kernel.h"
#include "e820.h"
// Make is easier to copy from dmesg
#define E820_LINUX(start, end, t) \
{ .addr = start, .size = end - start, .type = t }
#if defined(HW_qemu)
// For qemu -m 512
struct e820entry e820[NE820] = {
E820_LINUX(0x0000000000000000ull, 0x000000000009f400ull, E820_RAM),
E820_LINUX(0x000000000009f400ull, 0x00000000000a0000ull, E820_RESERVED),
E820_LINUX(0x00000000000f0000ull, 0x0000000000100000ull, E820_RESERVED),
E820_LINUX(0x0000000000100000ull, 0x000000001fffd000ull, E820_RAM),
E820_LINUX(0x000000001fffd000ull, 0x0000000020000000ull, E820_RESERVED),
E820_LINUX(0x00000000fffc0000ull, 0x0000000100000000ull, E820_RESERVED)
};
#elif defined(HW_josmp)
#elif defined(HW_ud0)
#endif
static struct e820entry *
e820search(paddr pa)
{
struct e820entry *e;
struct e820entry *q;
q = &e820[NE820];
for (e = &e820[0]; e < q; e++) {
if (e->type == E820_RAM && (e->addr <= pa) && ((e->addr + e->size) > pa))
return e;
}
return NULL;
}
u64
e820bytes(void)
{
u64 tot = 0;
for (int i = 0; i < NE820; i++) {
if (e820[i].type == E820_RAM)
tot += e820[i].size;
}
return tot;
}
u64
e820size(void *va)
{
struct e820entry *e;
paddr pa = v2p(va);
e = e820search(pa);
if (e == NULL)
return -1;
return (e->addr + e->size) - pa;
}
void *
e820next(void *va, u64 inc)
{
struct e820entry *e;
paddr pa = v2p(va);
e = e820search(pa);
if (e == NULL)
return (void *)-1;
pa += inc;
if (pa < (e->addr + e->size))
return p2v(pa);
for (e = e + 1; e < &e820[NE820]; e++) {
if (e->type == E820_RAM)
return p2v(e->addr);
}
return (void *)-1;
}
#define E820_RAM 1
#define E820_RESERVED 2
#define E820_ACPI 3
#define E820_NVS 4
#define NE820 32
struct e820entry {
u64 addr; // start of memory segment
u64 size; // size of memory segment
u32 type; // type of memory segment
} __attribute__((packed));
extern struct e820entry e820[NE820];
u64 e820bytes(void);
u64 e820size(void *va);
void *e820next(void *va, u64 inc);
......@@ -9,7 +9,11 @@
#include "kalloc.h"
#include "mtrace.h"
#include "cpu.h"
#include "e820.h"
#include "multiboot.h"
static struct Mbmem mem[128];
static u64 nmem;
static u64 membytes;
struct kmem kmems[NCPU];
struct kmem kstacks[NCPU];
......@@ -20,6 +24,77 @@ enum { kalloc_memset = 0 };
static int kinited __mpalign__;
static struct Mbmem *
memsearch(paddr pa)
{
struct Mbmem *e;
struct Mbmem *q;
q = mem+nmem;
for (e = &mem[0]; e < q; e++)
if ((e->base <= pa) && ((e->base+e->length) > pa))
return e;
return NULL;
}
static u64
memsize(void *va)
{
struct Mbmem *e;
paddr pa = v2p(va);
e = memsearch(pa);
if (e == NULL)
return -1;
return (e->base+e->length) - pa;
}
static void *
memnext(void *va, u64 inc)
{
struct Mbmem *e, *q;
paddr pa = v2p(va);
e = memsearch(pa);
if (e == NULL)
return (void *)-1;
pa += inc;
if (pa < (e->base+e->length))
return p2v(pa);
q = mem+nmem;
for (e = e + 1; e < q; e++)
return p2v(e->base);
return (void *)-1;
}
static void
initmem(u64 mbaddr)
{
struct Mbdata *mb;
struct Mbmem *mbmem;
u8 *p, *ep;
mb = p2v(mbaddr);
if(!(mb->flags & (1<<6)))
panic("multiboot header has no memory map");
p = p2v(mb->mmap_addr);
ep = p + mb->mmap_length;
while (p < ep) {
mbmem = (Mbmem *)(p+4);
p += 4 + *(u32*)p;
if (mbmem->type == 1) {
membytes += mbmem->length;
mem[nmem] = *mbmem;
nmem++;
}
}
}
// simple page allocator to get off the ground during boot
static char *
pgalloc(void)
......@@ -42,7 +117,7 @@ kfree_pool(struct kmem *m, char *v)
{
struct run *r;
if((uptr)v % PGSIZE || v < end || e820size(v) == -1ull)
if((uptr)v % PGSIZE || v < end || memsize(v) == -1ull)
panic("kfree_pool");
// Fill with junk to catch dangling refs.
......@@ -148,12 +223,14 @@ kminit(void)
// Initialize free list of physical pages.
void
initkalloc(void)
initkalloc(u64 mbaddr)
{
char *p;
u64 n;
u64 k;
initmem(mbaddr);
for (int c = 0; c < NCPU; c++) {
kmems[c].name[0] = (char) c + '0';
safestrcpy(kmems[c].name+1, "kmem", MAXNAME-1);
......@@ -168,9 +245,9 @@ initkalloc(void)
kstacks[c].size = KSTACKSIZE;
}
cprintf("%lu mbytes\n", e820bytes() / (1 << 20));
n = e820bytes() / NCPU;
if (n & (PGSIZE - 1)) {
cprintf("%lu mbytes\n", membytes / (1<<20));
n = membytes / NCPU;
if (n & (PGSIZE-1)) {
cprintf("bytes/CPU isn't aligned\n");
n = PGROUNDDOWN(n);
}
......@@ -183,14 +260,14 @@ initkalloc(void)
if (p == (void *)-1)
panic("initkalloc: e820next");
// XXX(sbw) handle this condition
if (e820size(p) < KSTACKSIZE)
if (memsize(p) < KSTACKSIZE)
panic("initkalloc: e820size");
kfree_pool(&kstacks[c], p);
p = e820next(p, KSTACKSIZE);
p = memnext(p, KSTACKSIZE);
}
// The rest goes to the page allocator
for (; k != n; k += PGSIZE, p = e820next(p, PGSIZE)) {
for (; k != n; k += PGSIZE, p = memnext(p, PGSIZE)) {
if (p == (void *)-1)
panic("initkalloc: e820next");
kfree_pool(&kmems[c], p);
......
......@@ -2,6 +2,7 @@
#include "multiboot.h"
#include "kernel.h"
#include "cpu.h"
#include "e820.h"
extern void initpic(void);
extern void initioapic(void);
......@@ -14,7 +15,7 @@ extern void initlapic(void);
extern void inittls(void);
extern void inittrap(void);
extern void initseg(void);
extern void initkalloc(void);
extern void initkalloc(u64 mbaddr);
extern void initrcu(void);
extern void initproc(void);
extern void initbio(void);
......@@ -74,7 +75,7 @@ bootothers(void)
}
void
cmain(void)
cmain(u64 mbmagic, u64 mbaddr)
{
extern pml4e_t kpml4[];
extern u64 cpuhz;
......@@ -92,7 +93,7 @@ cmain(void)
initmp();
initlapic();
initkalloc();
initkalloc(mbaddr);
initrcu(); // initialize rcu module
initproc(); // process table
initbio(); // buffer cache
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论