2010-08-02 07:43:56 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2010 Stefan Lankes, Chair for Operating Systems,
|
|
|
|
* RWTH Aachen University
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*
|
|
|
|
* This file is part of MetalSVM.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <metalsvm/stdio.h>
|
|
|
|
#include <metalsvm/string.h>
|
2010-12-10 06:16:58 +00:00
|
|
|
#include <metalsvm/stdlib.h>
|
2014-01-09 16:20:18 +01:00
|
|
|
#include <metalsvm/memory.h>
|
2010-08-09 11:47:51 +00:00
|
|
|
#include <metalsvm/spinlock.h>
|
2010-08-04 11:16:20 +00:00
|
|
|
#include <metalsvm/time.h>
|
2010-10-28 13:15:04 +00:00
|
|
|
#include <metalsvm/processor.h>
|
2010-12-10 06:16:58 +00:00
|
|
|
#include <metalsvm/page.h>
|
2011-02-24 18:32:58 +01:00
|
|
|
#include <metalsvm/errno.h>
|
2010-08-05 11:53:02 +00:00
|
|
|
#ifdef CONFIG_MULTIBOOT
|
2010-08-02 12:32:58 +00:00
|
|
|
#include <asm/multiboot.h>
|
|
|
|
#endif
|
2011-04-23 00:13:12 -07:00
|
|
|
#ifdef CONFIG_ROCKCREEK
|
2011-06-28 10:58:32 -07:00
|
|
|
#include <asm/RCCE.h>
|
|
|
|
#include <asm/RCCE_lib.h>
|
|
|
|
#include <asm/SCC_API.h>
|
2011-04-23 00:13:12 -07:00
|
|
|
#include <asm/icc.h>
|
|
|
|
#endif
|
2010-08-02 07:43:56 +00:00
|
|
|
|
|
|
|
/*
|
2013-11-18 15:47:26 +01:00
|
|
|
* Set whole address space as occupied:
|
|
|
|
* 0 => free, 1 => occupied
|
2010-08-02 07:43:56 +00:00
|
|
|
*/
|
2013-11-18 15:47:26 +01:00
|
|
|
static uint8_t bitmap[BITMAP_SIZE] = {[0 ... BITMAP_SIZE-1] = 0xFF};
|
|
|
|
static spinlock_t bitmap_lock = SPINLOCK_INIT;
|
|
|
|
|
|
|
|
atomic_int32_t total_pages = ATOMIC_INIT(0);
|
|
|
|
atomic_int32_t total_allocated_pages = ATOMIC_INIT(0);
|
|
|
|
atomic_int32_t total_available_pages = ATOMIC_INIT(0);
|
2010-08-02 07:43:56 +00:00
|
|
|
|
2010-12-10 06:16:58 +00:00
|
|
|
/*
|
|
|
|
* Note that linker symbols are not variables, they have no memory allocated for
|
|
|
|
* maintaining a value, rather their address is their value.
|
|
|
|
*/
|
2010-08-02 07:43:56 +00:00
|
|
|
extern const void kernel_start;
|
|
|
|
extern const void kernel_end;
|
|
|
|
|
2011-07-30 17:34:30 +02:00
|
|
|
inline static int page_marked(size_t i)
|
2010-08-02 07:43:56 +00:00
|
|
|
{
|
2011-07-30 17:34:30 +02:00
|
|
|
size_t index = i >> 3;
|
|
|
|
size_t mod = i & 0x7;
|
2010-08-02 07:43:56 +00:00
|
|
|
|
|
|
|
return (bitmap[index] & (1 << mod));
|
|
|
|
}
|
|
|
|
|
2011-07-30 17:34:30 +02:00
|
|
|
inline static void page_set_mark(size_t i)
|
2010-08-02 07:43:56 +00:00
|
|
|
{
|
2011-07-30 17:34:30 +02:00
|
|
|
size_t index = i >> 3;
|
|
|
|
size_t mod = i & 0x7;
|
2010-08-02 07:43:56 +00:00
|
|
|
|
2014-01-09 13:32:00 +01:00
|
|
|
bitmap[index] = bitmap[index] | (1 << mod);
|
2010-08-02 07:43:56 +00:00
|
|
|
}
|
|
|
|
|
2011-07-30 17:34:30 +02:00
|
|
|
inline static void page_clear_mark(size_t i)
|
2010-08-02 07:43:56 +00:00
|
|
|
{
|
2011-07-30 17:34:30 +02:00
|
|
|
size_t index = i / 8;
|
|
|
|
size_t mod = i % 8;
|
2010-08-02 07:43:56 +00:00
|
|
|
|
|
|
|
bitmap[index] = bitmap[index] & ~(1 << mod);
|
|
|
|
}
|
|
|
|
|
2013-11-18 15:47:26 +01:00
|
|
|
size_t get_pages(uint32_t npages)
|
|
|
|
{
|
2014-01-09 13:32:00 +01:00
|
|
|
// first page is reserved
|
2013-11-18 15:47:26 +01:00
|
|
|
static size_t start = 1;
|
|
|
|
|
2014-01-09 13:32:00 +01:00
|
|
|
size_t i, j, l;
|
|
|
|
size_t k = 0;
|
2013-11-18 15:47:26 +01:00
|
|
|
size_t ret = 0;
|
|
|
|
|
|
|
|
if (BUILTIN_EXPECT(!npages, 0))
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
if (BUILTIN_EXPECT(npages > atomic_int32_read(&total_available_pages), 0))
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
spinlock_lock(&bitmap_lock);
|
2014-01-09 13:32:00 +01:00
|
|
|
|
2013-11-18 15:47:26 +01:00
|
|
|
i = start;
|
|
|
|
next_try:
|
|
|
|
while((k < BITMAP_SIZE) && page_marked(i)) {
|
|
|
|
k++;
|
|
|
|
i = (i+1) & (BITMAP_SIZE-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (k >= BITMAP_SIZE)
|
|
|
|
goto oom;
|
|
|
|
|
|
|
|
for(j=1; (j<npages) && (i+j < BITMAP_SIZE) && (k < BITMAP_SIZE); j++, k++) {
|
|
|
|
if (page_marked(i+j)) {
|
|
|
|
i = (i+j) & (BITMAP_SIZE-1);
|
|
|
|
goto next_try;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i+j >= BITMAP_SIZE) {
|
|
|
|
i = 1;
|
|
|
|
goto next_try;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (k >= BITMAP_SIZE)
|
|
|
|
goto oom;
|
|
|
|
|
|
|
|
ret = i*PAGE_SIZE;
|
|
|
|
kprintf("get_pages: ret 0x%x, i = %d, j = %d, npages = %d\n", ret, i, j, npages); // TODO: remove
|
|
|
|
for(l=i; l<i+j; l++)
|
|
|
|
page_set_mark(l);
|
|
|
|
|
|
|
|
start = i+j;
|
2014-01-09 13:32:00 +01:00
|
|
|
|
2013-11-18 15:47:26 +01:00
|
|
|
spinlock_unlock(&bitmap_lock);
|
|
|
|
|
|
|
|
atomic_int32_add(&total_allocated_pages, npages);
|
|
|
|
atomic_int32_sub(&total_available_pages, npages);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
oom:
|
|
|
|
spinlock_unlock(&bitmap_lock);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int put_pages(size_t phyaddr, size_t npages)
|
|
|
|
{
|
|
|
|
if (BUILTIN_EXPECT(!phyaddr || !npages, 0))
|
|
|
|
return -EINVAL;
|
|
|
|
|
2014-01-09 13:32:00 +01:00
|
|
|
size_t i, ret = 0;
|
|
|
|
size_t base = phyaddr >> PAGE_BITS;
|
2013-11-18 15:47:26 +01:00
|
|
|
|
|
|
|
spinlock_lock(&bitmap_lock);
|
2014-01-09 13:32:00 +01:00
|
|
|
|
|
|
|
for (i=0; i<npages; i++) {
|
|
|
|
if (page_marked(base+i)) {
|
|
|
|
page_clear_mark(base+i);
|
|
|
|
ret++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-18 15:47:26 +01:00
|
|
|
spinlock_unlock(&bitmap_lock);
|
|
|
|
|
2014-01-09 13:32:00 +01:00
|
|
|
atomic_int32_sub(&total_allocated_pages, ret);
|
|
|
|
atomic_int32_add(&total_available_pages, ret);
|
|
|
|
|
|
|
|
kprintf("put_pages: phyaddr=%#lx, npages = %d, ret = %d\n", phyaddr, npages, ret); // TODO: remove
|
2013-11-18 15:47:26 +01:00
|
|
|
|
2014-01-09 13:32:00 +01:00
|
|
|
return ret;
|
2013-11-18 15:47:26 +01:00
|
|
|
}
|
|
|
|
|
2014-01-09 13:33:21 +01:00
|
|
|
int copy_pages(size_t pdest, size_t psrc, size_t npages)
|
|
|
|
{
|
|
|
|
size_t viraddr;
|
|
|
|
size_t vdest, vsrc;
|
|
|
|
|
|
|
|
// allocate virtual memory areas
|
|
|
|
viraddr = vma_alloc(2*npages*PAGE_SIZE, VMA_HEAP);
|
|
|
|
if (BUILTIN_EXPECT(!viraddr, 0))
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
// map pages
|
|
|
|
vsrc = map_region(viraddr, psrc, npages, MAP_KERNEL_SPACE);
|
|
|
|
vdest = map_region(viraddr+npages*PAGE_SIZE, pdest, npages, MAP_KERNEL_SPACE);
|
|
|
|
if (BUILTIN_EXPECT(!vsrc || !vdest, 0)) {
|
|
|
|
unmap_region(viraddr, 2*npages);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
kprintf("copy_pages: copy %u pages from: %#lx (%#lx) to %#lx (%#lx)\n", npages, vsrc, psrc, vdest, pdest); // TODO remove
|
|
|
|
|
|
|
|
// copy the whole page
|
|
|
|
memcpy((void*) vdest, (void*) vsrc, npages*PAGE_SIZE);
|
|
|
|
|
|
|
|
// householding
|
|
|
|
unmap_region(viraddr, 2*npages);
|
|
|
|
vma_free(viraddr, viraddr+2*npages*PAGE_SIZE);
|
|
|
|
|
|
|
|
return pdest;
|
|
|
|
}
|
|
|
|
|
2010-08-04 11:16:20 +00:00
|
|
|
int mmu_init(void)
|
2010-08-02 07:43:56 +00:00
|
|
|
{
|
|
|
|
unsigned int i;
|
2011-03-25 20:28:43 +01:00
|
|
|
size_t addr;
|
2012-06-10 08:05:24 +02:00
|
|
|
int ret = 0;
|
2010-08-02 07:43:56 +00:00
|
|
|
|
2010-08-05 11:53:02 +00:00
|
|
|
#ifdef CONFIG_MULTIBOOT
|
2013-11-20 11:15:10 +01:00
|
|
|
if (mb_info) {
|
|
|
|
if (mb_info->flags & MULTIBOOT_INFO_MEM_MAP) {
|
|
|
|
multiboot_memory_map_t* mmap = (multiboot_memory_map_t*) ((size_t) mb_info->mmap_addr);
|
|
|
|
multiboot_memory_map_t* mmap_end = (void*) ((size_t) mb_info->mmap_addr + mb_info->mmap_length);
|
|
|
|
|
|
|
|
// mark available memory as free
|
|
|
|
while (mmap < mmap_end) {
|
|
|
|
if (mmap->type == MULTIBOOT_MEMORY_AVAILABLE) {
|
|
|
|
for (addr=mmap->addr; addr < mmap->addr + mmap->len; addr += PAGE_SIZE) {
|
2014-01-09 13:32:00 +01:00
|
|
|
page_clear_mark(addr >> PAGE_BITS);
|
2013-11-20 11:15:10 +01:00
|
|
|
atomic_int32_inc(&total_pages);
|
|
|
|
atomic_int32_inc(&total_available_pages);
|
|
|
|
}
|
2010-08-02 12:32:58 +00:00
|
|
|
}
|
2013-11-20 11:15:10 +01:00
|
|
|
mmap++;
|
2010-08-02 12:32:58 +00:00
|
|
|
}
|
|
|
|
}
|
2013-11-20 11:15:10 +01:00
|
|
|
else if (mb_info->flags & MULTIBOOT_INFO_MEM) {
|
|
|
|
size_t page;
|
|
|
|
size_t pages_lower = mb_info->mem_lower >> 2;
|
|
|
|
size_t pages_upper = mb_info->mem_upper >> 2;
|
|
|
|
|
|
|
|
for (page=0; page<pages_lower; page++)
|
|
|
|
page_clear_mark(page);
|
|
|
|
|
|
|
|
for (page=0x100000; page<pages_upper+0x100000; page++)
|
|
|
|
page_clear_mark(page);
|
|
|
|
|
|
|
|
atomic_int32_add(&total_pages, pages_lower + pages_upper);
|
|
|
|
atomic_int32_add(&total_available_pages, pages_lower + pages_upper);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
kputs("Unable to initialize the memory management subsystem\n");
|
|
|
|
while (1) HALT;
|
2010-11-04 20:15:39 +00:00
|
|
|
}
|
2013-11-20 11:18:10 +01:00
|
|
|
|
|
|
|
// mark mb_info as used
|
2014-01-09 13:32:00 +01:00
|
|
|
page_set_mark((size_t) mb_info >> PAGE_BITS);
|
2013-11-20 11:18:10 +01:00
|
|
|
atomic_int32_inc(&total_allocated_pages);
|
|
|
|
atomic_int32_dec(&total_available_pages);
|
|
|
|
|
|
|
|
// mark modules list as used
|
|
|
|
if (mb_info->flags & MULTIBOOT_INFO_MODS) {
|
|
|
|
for(addr=mb_info->mods_addr; addr<mb_info->mods_addr+mb_info->mods_count*sizeof(multiboot_module_t); addr+=PAGE_SIZE) {
|
2014-01-09 13:32:00 +01:00
|
|
|
page_set_mark(addr >> PAGE_BITS);
|
2013-11-20 11:18:10 +01:00
|
|
|
atomic_int32_inc(&total_allocated_pages);
|
|
|
|
atomic_int32_dec(&total_available_pages);
|
|
|
|
}
|
|
|
|
}
|
2010-08-02 12:32:58 +00:00
|
|
|
}
|
2010-08-10 15:20:27 +00:00
|
|
|
#elif defined(CONFIG_ROCKCREEK)
|
2013-10-16 13:42:58 +02:00
|
|
|
// of course, the first slots belong to the private memory
|
2011-08-15 02:53:01 -07:00
|
|
|
for(addr=0x00; addr<1*0x1000000; addr+=PAGE_SIZE) {
|
2014-01-09 13:32:00 +01:00
|
|
|
page_clear_mark(addr >> PAGE_BITS);
|
2011-03-25 20:28:43 +01:00
|
|
|
if (addr > addr + PAGE_SIZE)
|
|
|
|
break;
|
|
|
|
atomic_int32_inc(&total_pages);
|
2013-11-20 11:18:10 +01:00
|
|
|
atomic_int32_inc(&total_available_pages);
|
2010-08-10 15:20:27 +00:00
|
|
|
}
|
2011-04-13 11:03:34 -07:00
|
|
|
|
2011-08-15 04:49:38 -07:00
|
|
|
// Note: The last slot belongs always to the private memory.
|
|
|
|
for(addr=0xFF000000; addr<0xFFFFFFFF; addr+=PAGE_SIZE) {
|
2014-01-09 13:32:00 +01:00
|
|
|
page_clear_mark(addr >> PAGE_BITS);
|
2011-08-15 04:49:38 -07:00
|
|
|
if (addr > addr + PAGE_SIZE)
|
|
|
|
break;
|
|
|
|
atomic_int32_inc(&total_pages);
|
|
|
|
atomic_int32_inc(&total_available_pages);
|
|
|
|
}
|
|
|
|
|
2013-10-16 13:42:58 +02:00
|
|
|
// mark the bootinfo as used.
|
2014-01-09 13:32:00 +01:00
|
|
|
page_set_mark((size_t)bootinfo >> PAGE_BITS);
|
2011-04-13 11:03:34 -07:00
|
|
|
atomic_int32_inc(&total_allocated_pages);
|
|
|
|
atomic_int32_dec(&total_available_pages);
|
2010-08-02 12:32:58 +00:00
|
|
|
#else
|
2010-09-08 07:10:02 +00:00
|
|
|
#error Currently, MetalSVM supports only the Multiboot specification or the RockCreek processor!
|
2010-08-02 12:32:58 +00:00
|
|
|
#endif
|
2010-08-02 07:43:56 +00:00
|
|
|
|
2013-11-20 11:18:10 +01:00
|
|
|
// mark kernel as used
|
|
|
|
for(addr=(size_t) &kernel_start; addr<(size_t) &kernel_end; addr+=PAGE_SIZE) {
|
2014-01-09 13:32:00 +01:00
|
|
|
page_set_mark(addr >> PAGE_BITS);
|
2013-11-20 11:18:10 +01:00
|
|
|
atomic_int32_inc(&total_allocated_pages);
|
|
|
|
atomic_int32_dec(&total_available_pages);
|
|
|
|
}
|
2010-08-04 11:16:20 +00:00
|
|
|
|
2011-07-18 09:13:33 +02:00
|
|
|
#if MAX_CORES > 1
|
2014-01-09 13:32:00 +01:00
|
|
|
page_set_mark(SMP_SETUP_ADDR >> PAGE_BITS);
|
2013-11-20 11:18:10 +01:00
|
|
|
atomic_int32_inc(&total_allocated_pages);
|
|
|
|
atomic_int32_dec(&total_available_pages);
|
2011-07-18 09:13:33 +02:00
|
|
|
#endif
|
2013-11-20 11:18:10 +01:00
|
|
|
|
|
|
|
// enable paging and map SMP, VGA, Multiboot modules etc.
|
2011-06-28 10:58:32 -07:00
|
|
|
ret = paging_init();
|
2012-06-10 08:54:08 +02:00
|
|
|
if (ret) {
|
|
|
|
kprintf("Failed to initialize paging: %d\n", ret);
|
2012-06-10 08:05:24 +02:00
|
|
|
return ret;
|
2012-06-10 08:54:08 +02:00
|
|
|
}
|
2011-06-28 10:58:32 -07:00
|
|
|
|
2013-11-20 11:27:49 +01:00
|
|
|
// add kernel to VMA list
|
2013-12-03 15:29:05 +01:00
|
|
|
vma_add(PAGE_CEIL((size_t) &kernel_start),
|
|
|
|
PAGE_FLOOR((size_t) &kernel_end),
|
2013-11-20 11:27:49 +01:00
|
|
|
VMA_READ|VMA_WRITE|VMA_EXECUTE|VMA_CACHEABLE);
|
|
|
|
|
|
|
|
// add LAPIC tp VMA list
|
|
|
|
vma_add((size_t) &kernel_start - PAGE_SIZE,
|
|
|
|
(size_t) &kernel_start,
|
|
|
|
VMA_READ|VMA_WRITE);
|
|
|
|
|
2014-01-09 13:32:00 +01:00
|
|
|
#ifdef CONFIG_VGA
|
|
|
|
// add VGA to VMA list
|
|
|
|
vma_add(PAGE_CEIL(VIDEO_MEM_ADDR),
|
|
|
|
PAGE_FLOOR(VIDEO_MEM_ADDR) + PAGE_SIZE,
|
|
|
|
VMA_READ|VMA_WRITE);
|
|
|
|
#endif
|
|
|
|
|
2013-11-20 11:27:49 +01:00
|
|
|
#if MAX_CORES > 1
|
|
|
|
// reserve page for SMP boot code
|
2013-12-03 15:29:05 +01:00
|
|
|
vma_add(PAGE_CEIL(SMP_SETUP_ADDR),
|
2014-01-09 13:32:00 +01:00
|
|
|
PAGE_FLOOR(SMP_SETUP_ADDR) + PAGE_SIZE,
|
2013-11-20 11:27:49 +01:00
|
|
|
VMA_READ|VMA_WRITE|VMA_EXECUTE|VMA_CACHEABLE);
|
|
|
|
#endif
|
|
|
|
|
2012-06-10 08:05:24 +02:00
|
|
|
#ifdef CONFIG_MULTIBOOT
|
|
|
|
/*
|
|
|
|
* Modules like the init ram disk are already loaded.
|
|
|
|
* Therefore, we set these pages as used.
|
|
|
|
*/
|
2013-11-20 11:18:10 +01:00
|
|
|
if (mb_info) {
|
2013-12-03 15:29:05 +01:00
|
|
|
vma_add(PAGE_CEIL((size_t) mb_info),
|
|
|
|
PAGE_FLOOR((size_t) mb_info + sizeof(multiboot_info_t)),
|
2013-11-20 11:27:49 +01:00
|
|
|
VMA_READ|VMA_CACHEABLE);
|
2012-06-10 08:05:24 +02:00
|
|
|
|
2013-11-20 11:18:10 +01:00
|
|
|
if (mb_info->flags & MULTIBOOT_INFO_MODS) {
|
|
|
|
multiboot_module_t* mmodule = (multiboot_module_t*) ((size_t) mb_info->mods_addr);
|
2012-06-10 08:05:24 +02:00
|
|
|
|
2013-12-03 15:29:05 +01:00
|
|
|
vma_add(PAGE_CEIL((size_t) mb_info->mods_addr),
|
|
|
|
PAGE_FLOOR((size_t) mb_info->mods_addr + mb_info->mods_count*sizeof(multiboot_module_t)),
|
2013-11-20 11:27:49 +01:00
|
|
|
VMA_READ|VMA_CACHEABLE);
|
2012-06-10 08:05:24 +02:00
|
|
|
|
2013-11-20 11:18:10 +01:00
|
|
|
for(i=0; i<mb_info->mods_count; i++) {
|
2013-12-03 15:29:05 +01:00
|
|
|
vma_add(PAGE_CEIL(mmodule[i].mod_start),
|
|
|
|
PAGE_FLOOR(mmodule[i].mod_end),
|
2013-11-20 11:27:49 +01:00
|
|
|
VMA_READ|VMA_WRITE|VMA_CACHEABLE);
|
2013-11-20 11:18:10 +01:00
|
|
|
|
|
|
|
for(addr=mmodule[i].mod_start; addr<mmodule[i].mod_end; addr+=PAGE_SIZE) {
|
2014-01-09 13:32:00 +01:00
|
|
|
page_set_mark(addr >> PAGE_BITS);
|
2013-11-20 11:18:10 +01:00
|
|
|
atomic_int32_inc(&total_allocated_pages);
|
|
|
|
atomic_int32_dec(&total_available_pages);
|
|
|
|
}
|
2012-06-10 08:05:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#elif defined(CONFIG_ROCKCREEK)
|
2011-06-28 10:58:32 -07:00
|
|
|
/*
|
2011-06-28 13:45:12 -07:00
|
|
|
* Now, we are able to read the FPGA registers and to
|
|
|
|
* determine the number of slots for private memory.
|
2011-06-28 10:58:32 -07:00
|
|
|
*/
|
2011-08-15 02:53:01 -07:00
|
|
|
uint32_t slots = *((volatile uint8_t*) (FPGA_BASE + 0x8244));
|
2011-06-28 10:58:32 -07:00
|
|
|
if (slots == 0)
|
2011-08-15 02:53:01 -07:00
|
|
|
slots = 1;
|
2011-06-28 10:58:32 -07:00
|
|
|
|
|
|
|
kprintf("MetalSVM use %d slots for private memory\n", slots);
|
|
|
|
|
2011-06-28 13:45:12 -07:00
|
|
|
// define the residual private slots as free
|
2011-08-15 02:53:01 -07:00
|
|
|
for(addr=1*0x1000000; addr<slots*0x1000000; addr+=PAGE_SIZE) {
|
2014-01-09 13:32:00 +01:00
|
|
|
page_clear_mark(addr >> PAGE_BITS);
|
2011-06-28 10:58:32 -07:00
|
|
|
if (addr > addr + PAGE_SIZE)
|
|
|
|
break;
|
|
|
|
atomic_int32_inc(&total_pages);
|
|
|
|
atomic_int32_inc(&total_available_pages);
|
|
|
|
}
|
2012-05-03 04:16:41 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The init ram disk are already loaded.
|
|
|
|
* Therefore, we set these pages as used.
|
|
|
|
*/
|
2013-11-20 12:03:24 +01:00
|
|
|
for(addr=bootinfo->addr; addr<bootinfo->addr+bootinfo->size; addr+=PAGE_SIZE) {
|
|
|
|
// this area is already mapped, so we need to virt_to_phys() these addresses.
|
2014-01-09 13:32:00 +01:00
|
|
|
page_set_mark(virt_to_phys(addr) >> PAGE_BITS);
|
2012-05-03 04:16:41 -07:00
|
|
|
atomic_int32_inc(&total_allocated_pages);
|
|
|
|
atomic_int32_dec(&total_available_pages);
|
|
|
|
}
|
2011-06-28 10:58:32 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return ret;
|
2010-08-02 07:43:56 +00:00
|
|
|
}
|
|
|
|
|