#define get_npd(addr) (((u32)(addr))>>22)
#define get_npt(addr) ((((u32)(addr))>>12) & 0x3FF)
+
#include <list.h>
typedef unsigned long pde_t;
#define PAGE_UP(page) (((unsigned long)page + PAGE_SIZE -1) & PAGE_MASK)
#define PAGE_DOWN PAGE_ALIGN
+#define PAGE_FLAGS(addr) ((addr) - PAGE_ALIGN(addr))
+
#define va2pa(x) (((unsigned long)(x)) - PAGE_OFFSET)
#define pa2va(x) ((void *) (((unsigned long)(x)) + PAGE_OFFSET))
typedef struct page
{
+ unsigned long count;
unsigned long flags;
unsigned long private;
unsigned long index;
void *page2va(page_t *page);
page_t *va2page(unsigned long addr);
+#define pa2page(addr) va2page((unsigned long)pa2va(addr))
+
static inline page_t *get_head_page(page_t *page) { return page->head_page; }
#define __GETPAGEFLAG(name) \
unsigned long alloc_pages(unsigned int gfp_mask, unsigned int order);
void free_pages(unsigned long addr);
+#define alloc_one_page(gfp_mask) alloc_pages(gfp_mask, 0)
struct kmem_cache
{
pid_t ppid;
unsigned int state;
long exit_code;
- void *cr3;
+ unsigned long cr3;
long tty;
if(tsk == NULL)
panic("can not malloc PCB");
+ {
+ tsk->cr3 = (unsigned long) alloc_one_page(0);
+ if(tsk->cr3 == 0)
+ panic("failed init tsk cr3");
+
+ memcpy((void *)tsk->cr3, (void*)current->cr3, PAGE_SIZE);
+
+ unsigned int i, j;
+ pde_t *pde_src = (pde_t*) current->cr3;
+ pde_t *pde_dst = (pde_t*) tsk->cr3;
+ for(i=0; i<PAGE_PDE_CNT; ++i)
+ {
+ unsigned long spde = (unsigned long) pde_src[i];
+ unsigned long dpde = 0;
+ if(spde != 0)
+ dpde = PAGE_FLAGS(spde) | (unsigned long) va2pa(alloc_one_page(0));
+ pde_dst[i] = dpde;
+
+
+ pte_t *pte_src = pa2va(PAGE_ALIGN(spde));
+ pte_t *pte_dst = pa2va(PAGE_ALIGN(dpde));
+ for(j=0; j< PAGE_PTE_CNT; ++j)
+ {
+ pte_src[j] &= ~PAGE_WR;
+ pte_dst[j] = pte_src[j];
+
+ page_t *page = pa2page(pte_src[j]);
+ page->count ++;
+ }
+ }
+ }
+
memcpy(tsk, current, sizeof(task_union));
tsk->pid = get_next_pid();
inline void load_cr3(task_union * tsk)
{
//printk("tsk %08x cr3: %08x\n",tsk, tsk->cr3);
- asm("movl %%eax,%%cr3;"::"a"(tsk->cr3));
+ // asm("movl %%eax,%%cr3;"::"a"(tsk->cr3));
//int j=10000; while(j--);
+ LOAD_CR3(tsk->cr3);
}
void init_tsk_cr3(task_union * tsk)
{
- tsk->cr3 = pa2va(get_phys_pages(1));
+ tsk->cr3 = (unsigned long) pa2va(get_phys_pages(1));
- if(tsk->cr3 == NULL)
+ if(tsk->cr3 == 0)
panic("failed init tsk cr3");
- memset(tsk->cr3, 0, PAGE_SIZE);
+ memset((void *)tsk->cr3, 0, PAGE_SIZE);
memcpy((void *)tsk->cr3, (void*)system.page_dir, PAGE_SIZE);
- tsk->cr3 = (void *)va2pa(tsk->cr3);
+ tsk->cr3 = va2pa(tsk->cr3);
}
void init_root_tsk()
p->order = order;
}
+ page->count = 1;
+
return page;
}
void do_wp_page(void *addr)
{
- int npde = ((u32)addr)>>22;
- int npte = (((u32)addr)>>12) & 0x3FF;
-
+ int npde = get_npd(addr);
+ int npte = get_npt(addr);
- u32 *pd = (u32 *)pa2va(current->cr3);
- u32 *pt = NULL;
+ unsigned long *pd = (u32 *)pa2va(current->cr3);
+ unsigned long *pt = NULL;
+ pt = pa2va(PAGE_ALIGN(pd[npde]));
- pt = pa2va(pd[npde] & 0xFFFFF000);
+ unsigned long src, dst;
- void *dst, *src;
+ src = pt[npte];
- src = (void*)pt[npte];
+ page_t *page = pa2page(src);
- if(pgmap[((u32)src)>>PAGE_SHIFT].count > 0)
+ if(page->count > 0)
{
- pgmap[((u32)src)>>PAGE_SHIFT].count--;
+ unsigned long flags = PAGE_FLAGS(src);
- src = (void *)pa2va(((u32)src) & 0xFFFFF000);
+ page->count--;
- dst = get_phys_pages(1);
- if(dst == NULL)
+ src = (unsigned long) pa2va(PAGE_ALIGN(src));
+
+ dst = alloc_one_page(0);
+
+ if(0 == dst)
panic("out of memory");
- dst = pa2va(dst);
- memcpy(dst, src, PAGE_SIZE);
+ pt[npte] = dst | flags;
+
+ dst = (unsigned long)pa2va(PAGE_ALIGN(dst));
- dst = (void *)va2pa(dst);
- pt[npte] = (u32)dst | 7;
+ memcpy((void *)dst, (void *)src, PAGE_SIZE);
}
else
{
- pt[npte] |= 7;
+ pt[npte] |= PAGE_WR;
}
load_cr3(current);