In my current implementation I have reserved a 64 MB region for my kernel heap which is not physically contiguous. The page tables are pre-allocated but the actual pages are allocated on an on demand basis.
In addition to this, I have the first 768 MB of RAM mapped contiguously starting at 0xc0000000 - 0xf0000000. This is for speed of access and simplicity of code. Basically the idea (as I'm sure most people here know) is that to get a usable virtual address of any physical address <= 768 MB, i can just add 0xc0000000.
This results in the following memory map:
Code: Select all
0x0000000000000000 - 0x0000000000001000 : (unaccesible/null pointer detection)
0x0000000000001000 - 0x00000000c0000000 : (user space, to be divided up more)
0x00000000bfffd000 - 0x00000000c0000000 : primary thread stack of current process
0x00000000c0000000 - 0x00000000f0000000 : Identity map of lower 768 megs of mem including kernel
0x00000000c0000000 - 0x00000000c0000400 : Real Mode IVT (Interrupt Vector Table)
0x00000000c00b8000 - 0x00000000c00c0000 : Video RAM
0x00000000c00c0000 - 0x00000000c00cd000 : Video Bios
0x00000000c0100000 - ? : Kernel (code/data/bss)
0x00000000f0000000 - 0x00000000f4000000 : Kernel Heap (64 megs)
0x00000000f5000000 - 0x00000000fd000000 : Video Linear Frame Buffer
0x00000000fe000000 - 0x00000000fe010000 : Temp page mapping
0x00000000ffc00000 - 0x00000000fffff000 : Page Tables as mapped by active page directory
0x00000000fffff000 - 0x0000000100000000 : Page Directory
Now, on to my question
I would like my Heap to not be hard coded to a 64 MB region. What I would like is to have the heap also co-exist in this 768 MB of "low memory" where i adjust the kernel "brk" value as the heap needs to grow. This would have some benefits.
#1 Heap is physically contiguous, makes it more often suitable for 32-bit DMA
#2 Heap has limit which is relative to ability to allocate more pages, not some arbitrary number.
#3 I could use the 64MB for other purposes .
I believe that this is what linux does, because kmalloc by definition returns physically contiguous memory (as apposed to vmalloc which doesn't have to be, but can handle much larger blocks).
So my question is, how do I do this well and efficiently. I can think of 2 methods off hand, but neither seem good to me.
#1 Heap is primary allocator, pages are allocated from Heap by asking for a page sized block aligned by page size. This has the downsides of being slower to allocate pages AND wastes a few bytes per page allocated for the heap meta-data.
#2 have the page "stack" be sorted. Favor allocating for general use from high end of list, and only extend the heap by increasing "brk" value and taking the pages between old brk and new brk from page list, if this can't be done, heap cannot be extended at this time. This has the down side of being more complicated and in addition heap allocation can fail even when there are pages available since general page allocation and the heap are basically fighting for pages.
What do you guys think? I've tried sorting out what linux does and to be honest, it is VERY confusing.
Thanks,
proxy