Allocation de mémoire pour le noyau
Implémentation du VMM
Allouer un range
On utilise le premier emplacement qui convienne (first fit) et on applique l'algorithme suivant :
- l'emplacement fait exactement la taille recherchée, c'est le cas le plus simple : on supprime celui-ci de la liste des emplacements libres et on l'ajoute à la liste des emplacements occupés (sos/kmem_vmm.c:293) ;
if(free_range->nb_pages == nb_pages) { list_delete(kmem_free_range_list, free_range); kmem_used_range_list = insert_range(kmem_used_range_list, free_range); /* The new_range is exactly the free_range */ new_range = free_range; }
cas certainement plus courant, l'emplacement est plus grand que celui recherché, il faut donc le découper en deux :
On choisit de créer un nouveau range en le prenant dans le début de l'emplacement libre.
else { /* free_range split in { new_range | free_range } */ new_range = (struct sos_kmem_range*) sos_kmem_cache_alloc(kmem_range_cache, (flags & SOS_KMEM_VMM_ATOMIC)? SOS_KSLAB_ALLOC_ATOMIC:0); if (! new_range) return NULL; new_range->base_vaddr = free_range->base_vaddr; new_range->nb_pages = nb_pages; free_range->base_vaddr += nb_pages*SOS_PAGE_SIZE; free_range->nb_pages -= nb_pages;
new_range->base_vaddr = free_range->base_vaddr;
- Le nouveau range prend pour début le début du range libre qu'on est en train de découper.
new_range->nb_pages = nb_pages;
- On sauvegarde dans la structure du nouveau range quelle taille il fait.
free_range->base_vaddr += nb_pages*SOS_PAGE_SIZE;
- On décale le début du range libre en cours de découpage pour que son début coïncide avec la fin du nouveau.
free_range->nb_pages -= nb_pages;
- Comme on a découpé le range libre et qu'on lui a pris nb_pages pour les affecter au nouveau range, on met à jour le nombre de pages que fait à présent le range libre.
On a déjà mis à jour le range libre, il n'y a donc plus que le nouveau qu'il faille insérer dans la liste des ranges occupés :
kmem_used_range_list = insert_range(kmem_used_range_list, new_range); }
Initialiser les ranges
- la zone du code noyau ;
- la mémoire vidéo ;
- ...
On va donc appeler la fonction create_range sur toutes les zones de la mémoire qu'on souhaite organiser. On va ainsi marquer libre ou occupée chaque zone de mémoire de la machine. (sos/kmem_vmm.c:220)
La zone entre le début de la RAM et la mémoire vidéo est disponible :
create_range(TRUE,
SOS_KMEM_VMM_BASE,
SOS_PAGE_ALIGN_INF(BIOS_N_VIDEO_START),
NULL);
On n'écrit pas dans la mémoire vidéo :
create_range(FALSE,
SOS_PAGE_ALIGN_INF(BIOS_N_VIDEO_START),
SOS_PAGE_ALIGN_SUP(BIOS_N_VIDEO_END),
NULL);
La zone entre la mémoire vidéo et le code du noyau est libre :
create_range(TRUE,
SOS_PAGE_ALIGN_SUP(BIOS_N_VIDEO_END),
SOS_PAGE_ALIGN_INF(kernel_core_base),
NULL);
On ne touche pas au code noyau, etc. :
create_range(FALSE,
SOS_PAGE_ALIGN_INF(kernel_core_base),
SOS_PAGE_ALIGN_SUP(kernel_core_top),
NULL);
...