715 lines
19 KiB
C
715 lines
19 KiB
C
/*******************************************************************************/
|
|
/* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */
|
|
/* */
|
|
#include "types.h"
|
|
#include "memory.h"
|
|
#include "multiboot2.h"
|
|
#include "queue.h"
|
|
#include "asm.h"
|
|
|
|
static u8 *kernelcurrentheap = NULL; /* pointeur vers le heap noyau */
|
|
static u8 bitmap[MAXMEMPAGE / 8]; /* bitmap */
|
|
static vrange_t vrange_head;
|
|
|
|
/*******************************************************************************/
|
|
/* Erreur fatale */
|
|
void panic(u8 * string)
|
|
{
|
|
printf("KERNEL PANIC: %s\r\nSysteme arrete...\n");
|
|
halt();
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Alloue plusieurs pages virtuelles (size) pour le heap du noyau */
|
|
|
|
tmalloc *mallocpage(u64 size)
|
|
{
|
|
tmalloc *chunk;
|
|
u8 *paddr;
|
|
u16 nbpages = size / PAGESIZE;
|
|
u64 realsize = nbpages * PAGESIZE;
|
|
if (size % PAGESIZE != 0)
|
|
realsize += PAGESIZE;
|
|
if ((kernelcurrentheap - KERNEL_HEAP + realsize) > MAXHEAPSIZE)
|
|
panic("Plus de memoire noyau heap disponible a allouer !\n");
|
|
chunk = (tmalloc *) kernelcurrentheap;
|
|
virtual_range_new_kernel(kernelcurrentheap, realsize);
|
|
kernelcurrentheap += realsize;
|
|
chunk->size = realsize;
|
|
chunk->used = 0;
|
|
return chunk;
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Retourne le nombre de blocs dynamiques (heap) */
|
|
|
|
u32 getmallocnb(void)
|
|
{
|
|
u32 realsize = 0;
|
|
tmalloc *chunk;
|
|
chunk = KERNEL_HEAP;
|
|
while (chunk < (tmalloc *) kernelcurrentheap)
|
|
{
|
|
realsize++;
|
|
chunk = (tmalloc *) ((u8 *) chunk + chunk->size);
|
|
}
|
|
return realsize;
|
|
}
|
|
|
|
|
|
/*******************************************************************************/
|
|
/* Retourne la mémoire virtuelle utilisée de façon dynamique (heap) */
|
|
|
|
u32 getmallocused(void)
|
|
{
|
|
u32 realsize = 0;
|
|
tmalloc *chunk;
|
|
chunk = KERNEL_HEAP;
|
|
while (chunk < (tmalloc *) kernelcurrentheap)
|
|
{
|
|
if (chunk->used)
|
|
realsize += chunk->size;
|
|
chunk = (tmalloc *) ((u8 *) chunk + chunk->size);
|
|
}
|
|
return realsize;
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Retourne la mémoire virtuelle libre de façon dynamique (heap) */
|
|
|
|
u32 getmallocfree(void)
|
|
{
|
|
u32 realsize = 0;
|
|
tmalloc *chunk;
|
|
chunk = KERNEL_HEAP;
|
|
while (chunk < (tmalloc *) kernelcurrentheap)
|
|
{
|
|
if (!chunk->used)
|
|
realsize += chunk->size;
|
|
chunk = (tmalloc *) ((u8 *) chunk + chunk->size);
|
|
}
|
|
return realsize;
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Retourne la mémoire virtuelle non allouée de façon dynamique (heap) */
|
|
|
|
u32 getmallocnonallocated(void)
|
|
{
|
|
return VESA_FBMEM - ((u32) kernelcurrentheap);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Alloue de la mémoire virtuelle au noyau de façon dynamique (heap) */
|
|
|
|
void *vmalloc(u32 size)
|
|
{
|
|
u32 realsize;
|
|
tmalloc *chunk, *new;
|
|
realsize = sizeof(tmalloc) + size;
|
|
if (realsize < MALLOC_MINIMUM)
|
|
realsize = MALLOC_MINIMUM;
|
|
chunk = KERNEL_HEAP;
|
|
while (chunk->used || chunk->size < realsize)
|
|
{
|
|
if (chunk->size == 0)
|
|
panic(sprintf
|
|
("Element du heap %x defectueux avec une taille nulle (heap %x) !",
|
|
chunk, kernelcurrentheap));
|
|
chunk = (tmalloc *) ((u8 *) chunk + chunk->size);
|
|
if (chunk == (tmalloc *) kernelcurrentheap)
|
|
mallocpage(realsize);
|
|
else if (chunk > (tmalloc *) kernelcurrentheap)
|
|
panic(sprintf
|
|
("Element du heap %x depassant la limite %x !",
|
|
chunk, kernelcurrentheap));
|
|
}
|
|
if (chunk->size - realsize < MALLOC_MINIMUM)
|
|
chunk->used = 1;
|
|
else
|
|
{
|
|
new = (tmalloc *) ((u8 *) chunk + realsize);
|
|
new->size = chunk->size - realsize;
|
|
new->used = 0;
|
|
chunk->size = realsize;
|
|
chunk->used = 1;
|
|
}
|
|
return (u8 *) chunk + sizeof(tmalloc);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Libère de la mémoire virtuelle depuis le heap noyau */
|
|
|
|
void vfree(void *vaddr)
|
|
{
|
|
tmalloc *chunk, *new;
|
|
chunk = (tmalloc *) (vaddr - sizeof(tmalloc));
|
|
chunk->used = 0;
|
|
while ((new = (tmalloc *) ((u8 *) chunk + chunk->size))
|
|
&& new < (tmalloc *) kernelcurrentheap && new->used == 0)
|
|
chunk->size += new->size;
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Retourne la taille de la mémoire physique (selon grub) */
|
|
|
|
u64 physical_getmemorysize()
|
|
{
|
|
u64 maxaddr = 0;
|
|
struct multiboot_tag_mmap *tag = getgrubinfo_mem();
|
|
multiboot_memory_map_t *mmap;
|
|
for (mmap = ((struct multiboot_tag_mmap *) tag)->entries;
|
|
(u8 *) mmap < (u8 *) tag + tag->size;
|
|
mmap =
|
|
(multiboot_memory_map_t *) ((unsigned long) mmap +
|
|
((struct multiboot_tag_mmap *)
|
|
tag)->entry_size))
|
|
if ((mmap->addr + mmap->len > maxaddr) && mmap->type == 1)
|
|
maxaddr = mmap->addr + mmap->len;
|
|
if (maxaddr >= MAXMEMSIZE)
|
|
maxaddr = MAXMEMSIZE - 1;
|
|
return maxaddr;
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Retourne que la page physique actuelle est occupée */
|
|
|
|
void physical_page_use(u32 page)
|
|
{
|
|
bitmap[(page / 8)] |= (1 << (page % 8));
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Retourne que la page physique actuelle est libre */
|
|
|
|
void physical_page_free(u32 page)
|
|
{
|
|
bitmap[(page / 8)] &= ~(1 << (page % 8));
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Reserve un espace mémoire physique dans le bitmap */
|
|
|
|
void physical_range_use(u64 addr, u64 len)
|
|
{
|
|
u32 nbpage = TOPAGE(len);
|
|
u32 pagesrc = TOPAGE(addr);
|
|
if (len & 0x3FF > 0)
|
|
nbpage++;
|
|
if (addr >= MAXMEMSIZE)
|
|
return;
|
|
if (addr + len >= MAXMEMSIZE)
|
|
len = MAXMEMSIZE - addr - 1;
|
|
for (u32 page = pagesrc; page < pagesrc + nbpage; page++)
|
|
physical_page_use(page);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Libère un espace mémoire physique dans le bitmap */
|
|
|
|
void physical_range_free(u64 addr, u64 len)
|
|
{
|
|
u32 nbpage = TOPAGE(len);
|
|
u32 pagesrc = TOPAGE(addr);
|
|
if (len & 0x3FF > 0)
|
|
nbpage++;
|
|
if (addr >= MAXMEMSIZE)
|
|
return;
|
|
if (addr + len >= MAXMEMSIZE)
|
|
len = MAXMEMSIZE - addr - 1;
|
|
for (u32 page = pagesrc; page < pagesrc + nbpage; page++)
|
|
physical_page_free(page);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Retourne une page physique libre */
|
|
|
|
u8 *physical_page_getfree(void)
|
|
{
|
|
u32 byte;
|
|
u8 bit;
|
|
u32 page = 0;
|
|
for (byte = 0; byte < sizeof(bitmap); byte++)
|
|
if (bitmap[byte] != 0xFF)
|
|
for (bit = 0; bit < 8; bit++)
|
|
if (!(bitmap[byte] & (1 << bit)))
|
|
{
|
|
page = 8 * byte + bit;
|
|
physical_page_use(page);
|
|
return (u8 *) (page * PAGESIZE);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Retourne l'espace libre */
|
|
|
|
u64 getmemoryfree(void)
|
|
{
|
|
u32 byte, bit;
|
|
u64 free = 0;
|
|
for (byte = 0; byte < sizeof(bitmap); byte++)
|
|
if (bitmap[byte] != 0xFF)
|
|
for (bit = 0; bit < 8; bit++)
|
|
if (!(bitmap[byte] & (1 << bit)))
|
|
free += PAGESIZE;
|
|
return free;
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Initialisation du bitmap pour la gestion physique de la mémoire */
|
|
|
|
void physical_init(void)
|
|
{
|
|
u64 page;
|
|
for (page = 0; page < sizeof(bitmap); page++)
|
|
bitmap[page] = 0xFF;
|
|
struct multiboot_tag_mmap *tag = getgrubinfo_mem();
|
|
multiboot_memory_map_t *mmap;
|
|
for (mmap = ((struct multiboot_tag_mmap *) tag)->entries;
|
|
(u8 *) mmap < (u8 *) tag + tag->size;
|
|
mmap =
|
|
(multiboot_memory_map_t *) ((unsigned long) mmap +
|
|
((struct multiboot_tag_mmap *)
|
|
tag)->entry_size))
|
|
if (mmap->type == 1)
|
|
physical_range_free(mmap->addr, mmap->len);
|
|
else
|
|
physical_range_use(mmap->addr, mmap->len);
|
|
physical_range_use(0x0, KERNELSIZE);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Retourne une page virtuelle de mémoire */
|
|
|
|
page *virtual_page_getfree(void)
|
|
{
|
|
page *pg;
|
|
vrange *vpages;
|
|
u8 *vaddr, *paddr;
|
|
paddr = physical_page_getfree();
|
|
if (paddr == NULL)
|
|
panic("Plus de memoire physique disponible !\n");
|
|
if (TAILQ_EMPTY(&vrange_head))
|
|
panic("Plus de place disponible dans la reserve de page !\n");
|
|
vpages = TAILQ_FIRST(&vrange_head);
|
|
vaddr = vpages->vaddrlow;
|
|
vpages->vaddrlow += PAGESIZE;
|
|
if (vpages->vaddrlow == vpages->vaddrhigh)
|
|
{
|
|
TAILQ_REMOVE(&vrange_head, vpages, tailq);
|
|
vfree(vpages);
|
|
}
|
|
virtual_pd_page_add(NULL, vaddr, paddr, 0);
|
|
pg = (page *) vmalloc(sizeof(page));
|
|
pg->vaddr = vaddr;
|
|
pg->paddr = paddr;
|
|
return pg;
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Création d'un directory pour la gestion virtuelle de la mémoire */
|
|
|
|
pd *virtual_pd_create()
|
|
{
|
|
pd *new;
|
|
u32 *pdir, *pd0;
|
|
u32 i;
|
|
new = (pd *) vmalloc(sizeof(pd));
|
|
new->addr = virtual_page_getfree();
|
|
pdir = (u32 *) new->addr->vaddr;
|
|
pd0 = (u32 *) KERNEL_PD_ADDR;
|
|
for (i = 0; i < 256; i++)
|
|
pdir[i] = pd0[i];
|
|
for (i = 256; i < 1023; i++)
|
|
pdir[i] = 0;
|
|
pdir[1023] =
|
|
((u32) new->addr->paddr | (PAGE_PRESENT | PAGE_WRITE));
|
|
TAILQ_INIT(&new->page_head);
|
|
return new;
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Attache une page virtuelle de la mémoire dans le directory spécifié */
|
|
|
|
void virtual_pd_page_add(pd * dst, u8 * vaddr, u8 * paddr, u32 flags)
|
|
{
|
|
u32 *pdir;
|
|
u32 *ptable;
|
|
u32 *pt;
|
|
page *pg;
|
|
int i;
|
|
if (dst == NULL)
|
|
if (vaddr > (u8 *) USER_CODE)
|
|
{
|
|
printf("ERREUR: Adresse %X n'est pas dans l'espace noyau !\n", vaddr);
|
|
return;
|
|
}
|
|
pdir = (u32 *) (0xFFFFF000 | (((u32) vaddr & 0xFFC00000) >> 20));
|
|
if ((*pdir & PAGE_PRESENT) == 0)
|
|
{
|
|
if (dst == NULL)
|
|
panic(sprintf
|
|
("Page table introuvable pour l'adresse %x !\r\n",
|
|
vaddr));
|
|
pg = virtual_page_getfree();
|
|
pt = (u32 *) pg->vaddr;
|
|
for (i = 1; i < 1024; i++)
|
|
pt[i] = 0;
|
|
*pdir = (u32) pg->paddr | (PAGE_PRESENT | PAGE_WRITE |
|
|
flags);
|
|
if (dst)
|
|
TAILQ_INSERT_TAIL(&dst->page_head, pg, tailq);
|
|
}
|
|
ptable = (u32 *) (0xFFC00000 | (((u32) vaddr & 0xFFFFF000) >> 10));
|
|
*ptable = ((u32) paddr) | (PAGE_PRESENT | PAGE_WRITE | flags);
|
|
return;
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Retire une page virtuelle de la mémoire dans le directory spécifié */
|
|
|
|
void virtual_pd_page_remove(u8 * vaddr)
|
|
{
|
|
u32 *ptable;
|
|
if (virtual_to_physical(vaddr))
|
|
{
|
|
ptable = (u32 *) (0xFFC00000 |
|
|
(((u32) vaddr & 0xFFFFF000) >> 10));
|
|
*ptable = (*ptable & (~PAGE_PRESENT));
|
|
asm("invlpg %0"::"m"(vaddr));
|
|
}
|
|
return;
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Renvoie l'adresse physique de la page virtuel */
|
|
|
|
u8 *virtual_to_physical(u8 * vaddr)
|
|
{
|
|
u32 *pdir;
|
|
u32 *ptable;
|
|
|
|
pdir = (u32 *) (0xFFFFF000 | (((u32) vaddr & 0xFFC00000) >> 20));
|
|
if ((*pdir & PAGE_PRESENT))
|
|
{
|
|
ptable = (u32 *) (0xFFC00000 |
|
|
(((u32) vaddr & 0xFFFFF000) >> 10));
|
|
if ((*ptable & PAGE_PRESENT))
|
|
return (u8 *) ((*ptable & 0xFFFFF000) +
|
|
(TOPG((u32) vaddr)));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Détermine une plage virtuelle de mémoire comme étant mappé aux adresses physiques spécifiées GENERIQUE*/
|
|
|
|
void virtual_range_use(pd * dst, u8 * vaddr, u8 * paddr, u64 len,
|
|
u32 flags)
|
|
{
|
|
u64 i;
|
|
u32 realen = len / PAGESIZE;
|
|
page *pg;
|
|
if (len % PAGESIZE != 0)
|
|
realen++;
|
|
for (i = 0; i < realen; i++)
|
|
{
|
|
if (dst == NULL)
|
|
{
|
|
virtual_pd_page_add(dst, vaddr + i * PAGESIZE,
|
|
paddr + i * PAGESIZE, flags);
|
|
}
|
|
else
|
|
{
|
|
pg = (page *) vmalloc(sizeof(page));
|
|
pg->paddr = paddr + i * PAGESIZE;
|
|
pg->vaddr = vaddr + i * PAGESIZE;
|
|
TAILQ_INSERT_TAIL(&dst->page_head, pg, tailq);
|
|
virtual_pd_page_add(dst, pg->vaddr, pg->paddr,
|
|
flags);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Supprime une plage virtuelle de mémoire GENERIQUE */
|
|
|
|
void virtual_range_free(pd * dst, u8 * vaddr, u64 len)
|
|
{
|
|
u64 i;
|
|
u32 realen = len / PAGESIZE;
|
|
if (len % PAGESIZE != 0)
|
|
realen++;
|
|
for (i = 0; i < realen; i++)
|
|
{
|
|
virtual_pd_page_remove(vaddr + i * PAGESIZE);
|
|
virtual_page_free(vaddr);
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Détermine une plage virtuelle de mémoire en attribuant de la mémoire physique GENERIQUE */
|
|
|
|
void virtual_range_new(pd * dst, u8 * vaddr, u64 len, u32 flags)
|
|
{
|
|
u64 i;
|
|
u32 realen = len / PAGESIZE;
|
|
page *pg;
|
|
if (len % PAGESIZE != 0)
|
|
realen++;
|
|
for (i = 0; i < realen; i++)
|
|
{
|
|
if (dst == NULL)
|
|
{
|
|
virtual_pd_page_add(dst, vaddr + i * PAGESIZE,
|
|
physical_page_getfree(),
|
|
flags);
|
|
}
|
|
else
|
|
{
|
|
pg = (page *) vmalloc(sizeof(page));
|
|
pg->paddr = physical_page_getfree();
|
|
pg->vaddr = vaddr + i * PAGESIZE;
|
|
TAILQ_INSERT_TAIL(&dst->page_head, pg, tailq);
|
|
virtual_pd_page_add(dst, pg->vaddr, pg->paddr,
|
|
flags);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Détermine une plage virtuelle de mémoire comme étant mappé aux adresses physiques spécifiées pour le noyau*/
|
|
|
|
void virtual_range_use_kernel(u8 * vaddr, u8 * paddr, u64 * len, u32 flags)
|
|
{
|
|
virtual_range_use(NULL, vaddr, paddr, len, flags);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Supprime une plage virtuelle de mémoire pour le noyau */
|
|
|
|
void virtual_range_free_kernel(u8 * vaddr, u64 len)
|
|
{
|
|
virtual_range_free(NULL, vaddr, len);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Détermine une plage virtuelle de mémoire en attribuant de la mémoire physique pour le noyau */
|
|
|
|
void virtual_range_new_kernel(u8 * vaddr, u64 len, u32 flags)
|
|
{
|
|
virtual_range_new(NULL, vaddr, len, flags);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Renvoie le nombre de pages virtuelles occupées */
|
|
|
|
u32 virtual_getpagesused()
|
|
{
|
|
u32 maxpage = ((u32) MAXPAGESSIZE) / ((u16) PAGESIZE);
|
|
return maxpage - virtual_getpagesfree();
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Renvoie le nombre de pages virtuelles libres */
|
|
|
|
u32 virtual_getpagesfree()
|
|
{
|
|
vrange *next;
|
|
u32 realsize = 0;
|
|
TAILQ_FOREACH(next, &vrange_head, tailq) realsize +=
|
|
(next->vaddrhigh - next->vaddrlow) / PAGESIZE;
|
|
return realsize;
|
|
}
|
|
|
|
|
|
/*******************************************************************************/
|
|
/* Libère une page virtuelle de la mémoire */
|
|
|
|
void virtual_page_free(u8 * vaddr)
|
|
{
|
|
vrange *next, *prev, *new;
|
|
u8 *paddr;
|
|
paddr = virtual_to_physical(vaddr);
|
|
if (paddr)
|
|
physical_page_free(TOPAGE((u32) paddr));
|
|
else
|
|
{
|
|
printf("Aucune page associee a l'adresse virtuelle %x\n",
|
|
vaddr);
|
|
return;
|
|
}
|
|
virtual_pd_page_remove(vaddr);
|
|
TAILQ_FOREACH(next, &vrange_head, tailq)
|
|
{
|
|
if (next->vaddrlow > vaddr)
|
|
break;
|
|
}
|
|
prev = TAILQ_PREV(next, vrange_s, tailq);
|
|
if (prev->vaddrhigh == vaddr)
|
|
{
|
|
prev->vaddrhigh += PAGESIZE;
|
|
if (prev->vaddrhigh == next->vaddrlow)
|
|
{
|
|
prev->vaddrhigh = next->vaddrhigh;
|
|
TAILQ_REMOVE(&vrange_head, next, tailq);
|
|
vfree(next);
|
|
}
|
|
}
|
|
else if (next->vaddrlow == vaddr + PAGESIZE)
|
|
{
|
|
next->vaddrlow = vaddr;
|
|
}
|
|
else if (next->vaddrlow > vaddr + PAGESIZE)
|
|
{
|
|
new = (vrange *) vmalloc(sizeof(vrange));
|
|
new->vaddrlow = vaddr;
|
|
new->vaddrhigh = vaddr + PAGESIZE;
|
|
TAILQ_INSERT_BEFORE(prev, new, tailq);
|
|
}
|
|
else
|
|
panic("Liste chainee corrompue !\n");
|
|
return 0;
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Destruction d'un directory pour la gestion virtuelle de la mémoire */
|
|
|
|
void virtual_pd_destroy(pd * dst)
|
|
{
|
|
page *pg;
|
|
TAILQ_FOREACH(pg, &dst->page_head, tailq)
|
|
{
|
|
virtual_page_free(pg->vaddr);
|
|
TAILQ_REMOVE(&dst->page_head, pg, tailq);
|
|
vfree(pg);
|
|
}
|
|
virtual_page_free(dst->addr->vaddr);
|
|
vfree(dst);
|
|
return 0;
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Initialise une pages virtuelles (size) pour le heap du noyau */
|
|
|
|
void malloc_init(void)
|
|
{
|
|
tmalloc *chunk;
|
|
chunk = (tmalloc *) KERNEL_HEAP;
|
|
virtual_pd_page_add(NULL, KERNEL_HEAP, physical_page_getfree(),
|
|
PAGE_NOFLAG);
|
|
kernelcurrentheap = KERNEL_HEAP + PAGESIZE;
|
|
chunk->size = PAGESIZE;
|
|
chunk->used = 0;
|
|
//virtual_range_new_kernel(kernelcurrentheap, chunk->size, PAGE_NOFLAG);
|
|
}
|
|
|
|
|
|
/*******************************************************************************/
|
|
/* Initialisation d'une STAILQ pour la gestion virtuelle de la mémoire */
|
|
|
|
void virtual_init(void)
|
|
{
|
|
vrange *vpages = (vrange *) vmalloc(sizeof(vrange));
|
|
vpages->vaddrlow = (u8 *) KERNEL_PAGES + PAGESIZE;
|
|
vpages->vaddrhigh = (u8 *) KERNEL_PAGES + MAXPAGESSIZE;
|
|
TAILQ_INIT(&vrange_head);
|
|
TAILQ_INSERT_TAIL(&vrange_head, vpages, tailq);
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Initialisation des 8 premiers MB de la mémoire en identity mapping */
|
|
|
|
void identity_init(void)
|
|
{
|
|
u32 i;
|
|
u32 *pd0 = KERNEL_PD_ADDR;
|
|
u8 *pg0 = (u8 *) 0;
|
|
u8 *pg1 = (u8 *) (PAGESIZE * PAGENUMBER);
|
|
pd0[0] = ((u32) pg0 | (PAGE_PRESENT | PAGE_WRITE | PAGE_4MB));
|
|
pd0[1] = ((u32) pg1 | (PAGE_PRESENT | PAGE_WRITE | PAGE_4MB));
|
|
for (i = 2; i < 1023; i++)
|
|
pd0[i] = ((u32) pg1 +
|
|
PAGESIZE * i) | (PAGE_PRESENT | PAGE_WRITE);
|
|
pd0[1023] = ((u32) pd0 | (PAGE_PRESENT | PAGE_WRITE));
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Initialisation des registres CR0, CR3, CR4 */
|
|
|
|
void registry_init(void)
|
|
{
|
|
asm("mov %[directory_addr], %%eax \n \
|
|
mov %%eax, %%cr3 \n \
|
|
mov %%cr4, %%eax \n \
|
|
or $0x00000010, %%eax \n \
|
|
mov %%eax, %%cr4 \n \
|
|
mov %%cr0, %%eax \n \
|
|
or $0x80000001, %%eax \n \
|
|
mov %%eax, %%cr0"::[directory_addr] "i"(KERNEL_PD_ADDR));
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Initialisation de la mémoire paginée */
|
|
|
|
void initpaging(void)
|
|
{
|
|
identity_init();
|
|
registry_init();
|
|
physical_init();
|
|
malloc_init();
|
|
virtual_init();
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Copie un octet une ou plusieurs fois en mémoire */
|
|
|
|
void memset(void *dst, u8 val, u32 count, u32 size)
|
|
{
|
|
u8 *d = (u8 *) dst;
|
|
if (size > 0)
|
|
size--;
|
|
for (; count != 0; count--)
|
|
{
|
|
*(d++) = val;
|
|
d += size;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Copie une portion de mémoire vers une autre */
|
|
|
|
void memcpy(void *src, void *dst, u32 count, u32 size)
|
|
{
|
|
u8 *s = (u8 *) src;
|
|
u8 *d = (u8 *) dst;
|
|
if (size > 0)
|
|
size--;
|
|
for (; count != 0; count--)
|
|
{
|
|
*(d++) = *(s++);
|
|
d += size;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************/
|
|
/* Compare 2 portions de mémoire */
|
|
|
|
u32 memcmp(void *src, void *dst, u32 count, u32 size)
|
|
{
|
|
u8 *s = (u8 *) src;
|
|
u8 *d = (u8 *) dst;
|
|
if (size > 0)
|
|
size--;
|
|
for (; count != 0; count--)
|
|
{
|
|
if (*(s++) != *(d++))
|
|
return *d - *s;
|
|
s += size;
|
|
d += size;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************/
|