Compare commits

...

3 Commits

Author SHA1 Message Date
Mathieu Maret a120647ecb TOFIX: implement testing for paging 2018-11-12 23:07:59 +01:00
Mathieu Maret 4a5f5674ce implement paging map and unmap 2018-11-12 23:02:27 +01:00
Mathieu Maret 63ce78205a Add errno.h 2018-11-12 23:02:27 +01:00
6 changed files with 162 additions and 2 deletions

37
core/errno.h Normal file
View File

@ -0,0 +1,37 @@
#pragma once
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */

View File

@ -71,7 +71,7 @@ int unrefPhyPage(paddr_t addr)
list_add_tail(free_page, mem);
}
return 0;
return mem->ref;
}
int refPhyPage(paddr_t addr)

View File

@ -12,7 +12,7 @@ extern uint32_t __ld_kernel_end;
struct mem_desc{
paddr_t phy_addr;
unsigned long ref;
long ref;
struct mem_desc *next, *prev;
};

View File

@ -1,6 +1,9 @@
#include "klibc.h"
#include "errno.h"
#include "mem.h"
#include "paging.h"
#include "stdarg.h"
#include "vga.h"
// In a Vaddr, 10 first bit (MSB) are the index in the Page Directory. A Page Directory Entry point to a Page Table.
// The 10 next bits are then an index in this Page Table. A Page Table Entry then point to a physical address at which is added the remaining 12 bits.
@ -58,6 +61,8 @@ struct pdbr {
uint32_t pd_paddr : 20;
} __attribute__((packed));
// invalidate the TLB entry for the page located at the given virtual address
static inline void __native_flush_tlb_single(unsigned long addr)
{
asm volatile("invlpg (%0)" ::"r"(addr) : "memory");
@ -116,3 +121,74 @@ int pagingSetup(paddr_t upperKernelAddr)
"2:\n\t" ::"r"(cr3):"memory","eax");
return 0;
}
int pageMap(vaddr_t vaddr, paddr_t paddr, int flags)
{
uint pdEntry = vaddr >> (PD_SHIFT);
uint ptEntry = (vaddr >> PT_SHIFT) & PTE_MASK;
// Thank to mirroring, we can access the PD
struct pde *pd = (struct pde *)(PD_MIRROR_PAGE_IDX * (1U << 22) +
PD_MIRROR_PAGE_IDX * (1U << 12));
struct pte *pt = (struct pte *)(PD_MIRROR_PAGE_IDX * (1U << 22) +
pdEntry * (1U << 12));
if(!pd[pdEntry].present){
paddr_t ptPhy = allocPhyPage();
memset((void *)ptPhy, 0, PAGE_SIZE);
pd[pdEntry].user = (flags & PAGING_MEM_USER) ? 0:1;
pd[pdEntry].present = 1;
pd[pdEntry].write = 1;
pd[pdEntry].pt_addr = (ptPhy >> PT_SHIFT);
__native_flush_tlb_single((vaddr_t)pt);
}
// Already mapped ? Remove old mapping
if (pt[ptEntry].present) {
unrefPhyPage(pt[ptEntry].paddr << PAGE_SHIFT);
} // PTE not already used ? We will use it ! So increase the PT ref count
else {
refPhyPage(pd[pdEntry].pt_addr << PAGE_SHIFT);
}
pt[ptEntry].user = (flags & PAGING_MEM_USER) ? 0 : 1;
pt[ptEntry].present = 1;
pt[ptEntry].write = (flags & PAGING_MEM_WRITE) ? 0 : 1;
pt[ptEntry].paddr = paddr >> PAGE_SHIFT;
refPhyPage(paddr);
__native_flush_tlb_single(vaddr);
return 0;
}
int pageUnmap(vaddr_t vaddr)
{
uint pdEntry = vaddr >> (PD_SHIFT);
uint ptEntry = (vaddr >> PT_SHIFT) & PTE_MASK;
// Thank to mirroring, we can access the PD
struct pde *pd =
(struct pde *)(PD_MIRROR_PAGE_IDX * (1U << 22) + PD_MIRROR_PAGE_IDX * (1U << 12));
struct pte *pt =
(struct pte *)(PD_MIRROR_PAGE_IDX * (1U << 22) + pdEntry * (1U << 12));
if (!pd[pdEntry].present)
return -EINVAL;
if (!pt[ptEntry].present)
return -EINVAL;
unrefPhyPage(pt[ptEntry].paddr << PAGE_SHIFT);
pt[ptEntry].present = 0;
// PTE not used. Decrease refcount on it. Is PT not used anymore ?
if(unrefPhyPage(pd[pdEntry].pt_addr<< PT_SHIFT) == 0){
pd[pdEntry].present = 0;
__native_flush_tlb_single((vaddr_t)pt);
}
__native_flush_tlb_single(vaddr);
return 0;
}

View File

@ -1,4 +1,11 @@
#pragma once
#include "types.h"
#define PAGING_MEM_USER 1
#define PAGING_MEM_READ (1 << 1)
#define PAGING_MEM_WRITE (1 << 2)
int pagingSetup(paddr_t upperKernelAddr);
int pageMap(vaddr_t vaddr, paddr_t paddr, int flags);
int pageUnmap(vaddr_t vaddr);

View File

@ -1,5 +1,6 @@
#include "list.h"
#include "mem.h"
#include "paging.h"
#include "serial.h"
#include "vga.h"
@ -38,8 +39,47 @@ void testPhymem(void)
}
}
static void testPaging(void)
{
printf("Testing paging\n");
struct mem_desc *allocated_page_list;
struct mem_desc
*page; // Cast in mem_desc to use it. In fact it's the addr of 4K free memory
list_init(allocated_page_list);
int allocCount = 0;
int freeCount = 0;
while ((page = (struct mem_desc *)allocPhyPage()) != NULL) {
pageMap((vaddr_t)page, (paddr_t)page, 0);
page->phy_addr = allocCount;
allocCount++;
list_add_tail(allocated_page_list, page);
}
printf("%d pages allocated\n", allocCount);
while ((page = list_pop_head(allocated_page_list)) != NULL) {
if (page->phy_addr != (ulong)freeCount) {
printf("Error page %d modified\n", (ulong)page);
}
if (unrefPhyPage((ulong)page)) {
printf("Failed to free page %d\n", (ulong)page);
}
pageUnmap((vaddr_t)page);
freeCount++;
}
printf("%d pages freed\n", freeCount);
if ((page = (struct mem_desc *)allocPhyPage()) == NULL) {
printf("Error ! Cannot allocate memory\n");
} else {
unrefPhyPage((ulong)page);
pageUnmap((vaddr_t)page);
}
}
void run_test(void)
{
testPaging();
printf("Testing Serial");
serialWrite('h');
serialWrite('e');