feat: gestion mémoire paginée, ajout de nouvelles fonctions

This commit is contained in:
Nicolas Hordé 2018-11-25 23:34:38 +01:00
parent f0a64729ee
commit b6f238ff8a
2 changed files with 78 additions and 21 deletions

View File

@ -5,7 +5,9 @@
#include "queue.h" #include "queue.h"
#define TOPAGE(addr) (addr) >> 12 #define TOPAGE(addr) (addr) >> 12
#define TOPD(addr) ((addr) & 0xFFC00000) >> 22
#define TOPT(addr) ((addr) & 0x003FF000) >> 12
#define TOPG(addr) (addr) & 0x00000FFF
#define PAGESIZE 4096 /* Taille d'une page */ #define PAGESIZE 4096 /* Taille d'une page */
#define PAGENUMBER 1024 /* Nombre de pages */ #define PAGENUMBER 1024 /* Nombre de pages */
@ -61,11 +63,9 @@ typedef TAILQ_HEAD(page_s, page) page_t;
/* Page directory, pour la gestion de la mémoire virtuelle */ /* Page directory, pour la gestion de la mémoire virtuelle */
typedef struct pd { typedef struct pd {
page *addr; page *addr;
TAILQ_ENTRY(pd) tailq; page_t page_head;
} __attribute__ ((packed)) pd; } __attribute__ ((packed)) pd;
typedef TAILQ_HEAD(pd_s, pd) pd_t;
/* vaddrrange, pour la gestion des pages de la mémoire virtuelle */ /* vaddrrange, pour la gestion des pages de la mémoire virtuelle */
typedef struct vrange { typedef struct vrange {
u8 *vaddrlow; u8 *vaddrlow;
@ -99,9 +99,7 @@ pd *virtual_pd_create();
Fonction à ajouter...pour gestion mémoire virtuelle Fonction à ajouter...pour gestion mémoire virtuelle
u8* virtual_to_physical(u8 *vaddr) u8* virtual_to_physical(u8 *vaddr)
pd *virtual_pd_create(void)
void virtual_pd_destroy(pd *dst)
void virtual_pd_page_remove(pd *dst, u8* vaddr) void virtual_pd_page_remove(pd *dst, u8* vaddr)
@ -115,9 +113,9 @@ void virtual_range_new(pd *dst, u8 vaddr, u8 len)
page *virtual_page_getfree(void) page *virtual_page_getfree(void)
void virtual_page_free(u8* vaddr) void virtual_page_free(pd *dst, u8* vaddr)
void virtual_page_use(u8* vaddr) void virtual_page_use(pd *dst, u8* vaddr)
void virtual_init(void) void virtual_init(void)

View File

@ -10,7 +10,7 @@
static pd *kerneldirectory=NULL; /* pointeur vers le page directory noyau */ static pd *kerneldirectory=NULL; /* pointeur vers le page directory noyau */
static u8 *kernelheap=NULL; /* pointeur vers le heap noyau */ static u8 *kernelheap=NULL; /* pointeur vers le heap noyau */
static u8 bitmap[MAXMEMPAGE / 8]; /* bitmap */ static u8 bitmap[MAXMEMPAGE / 8]; /* bitmap */
static vrange_t freepages; static vrange_t vrange_head;
/*******************************************************************************/ /*******************************************************************************/
/* Erreur fatale */ /* Erreur fatale */
@ -199,6 +199,7 @@ void physical_init(void)
} }
/*******************************************************************************/ /*******************************************************************************/
/* Allocation de page virtuelle de mémoire */ /* Allocation de page virtuelle de mémoire */
page *virtual_page_getfree(void) page *virtual_page_getfree(void)
{ {
page *pg; page *pg;
@ -207,13 +208,13 @@ page *virtual_page_getfree(void)
paddr = physical_page_getfree(); paddr = physical_page_getfree();
if (paddr == NULL) if (paddr == NULL)
panic ("Plus de memoire physique disponible !\n"); panic ("Plus de memoire physique disponible !\n");
if (TAILQ_EMPTY(&freepages)) if (TAILQ_EMPTY(&vrange_head))
panic("Plus de place disponible dans la reserve de page !\n"); panic("Plus de place disponible dans la reserve de page !\n");
vpages = TAILQ_FIRST(&freepages); vpages = TAILQ_FIRST(&vrange_head);
vaddr = vpages->vaddrlow; vaddr = vpages->vaddrlow;
vpages->vaddrlow += PAGESIZE; vpages->vaddrlow += PAGESIZE;
if (vpages->vaddrlow == vpages->vaddrhigh) { if (vpages->vaddrlow == vpages->vaddrhigh) {
TAILQ_REMOVE(&freepages, vpages, tailq); TAILQ_REMOVE(&vrange_head, vpages, tailq);
vfree(vpages); vfree(vpages);
} }
virtual_pd_page_add(kerneldirectory,vaddr,paddr, 0); virtual_pd_page_add(kerneldirectory,vaddr,paddr, 0);
@ -243,23 +244,81 @@ pd *virtual_pd_create()
pdir[i] = 0; pdir[i] = 0;
pdir[1023] = ((u32) new->addr->paddr | (PAGE_PRESENT | PAGE_WRITE)); pdir[1023] = ((u32) new->addr->paddr | (PAGE_PRESENT | PAGE_WRITE));
} }
//TAILQ_INIT(&new->addr); TAILQ_INIT(&new->page_head);
return new; return new;
} }
/*******************************************************************************/
/* 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;
}
/*******************************************************************************/
/* 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)
virtual_page_free(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 */ /* Destruction d'un directory pour la gestion virtuelle de la mémoire */
void pd_destroy(pd *dst) void virtual_pd_destroy(pd *dst)
{ {
page *pg; page *pg;
list_for_each_safe(p, n, &pd->pt) { TAILQ_FOREACH(pg, &dst->page_head, tailq) {
pg = list_entry(p, struct page, list); virtual_page_free(pg->vaddr);
release_page_from_heap(pg->vaddr); TAILQ_REMOVE(&dst->page_head, pg, tailq);
list_del(p);
vfree(pg); vfree(pg);
} }
release_page_from_heap(dst->add->vaddr); virtual_page_free(dst->addr->vaddr);
vfree(dst); vfree(dst);
return 0; return 0;
} }
@ -273,8 +332,8 @@ void virtual_init(void)
vrange *vpages = (vrange*) vmalloc(sizeof(vrange)); vrange *vpages = (vrange*) vmalloc(sizeof(vrange));
vpages->vaddrlow = (u8 *) KERNEL_HEAP; vpages->vaddrlow = (u8 *) KERNEL_HEAP;
vpages->vaddrhigh = (u8 *) KERNEL_HEAP+MAXHEAPSIZE; vpages->vaddrhigh = (u8 *) KERNEL_HEAP+MAXHEAPSIZE;
TAILQ_INIT(&freepages); TAILQ_INIT(&vrange_head);
TAILQ_INSERT_TAIL(&freepages, vpages, tailq); TAILQ_INSERT_TAIL(&vrange_head, vpages, tailq);
kerneldirectory=virtual_pd_create(); kerneldirectory=virtual_pd_create();
virtual_range_use_kernel(0x00000000, 0x00000000, KERNELSIZE); virtual_range_use_kernel(0x00000000, 0x00000000, KERNELSIZE);
} }