forever-learner 3 years ago
commit fc3a77a1ce

@ -1,10 +1,22 @@
#ifndef _MM_H
#define _MM_H
#define PAGE_SIZE 4096 #ifndef _mm_H
#define _mm_H
extern unsigned long get_free_page(void);
extern void calc_mem(void);
extern void mem_init(long start_mem, long end_mem);
extern void do_no_page(unsigned long error_code,unsigned long address);
extern int share_page(unsigned long address);
extern int try_to_share(unsigned long address, struct task_struct * p);
extern void get_empty_page(unsigned long address);
extern void write_verify(unsigned long address);
extern void do_wp_page(unsigned long error_code,unsigned long address);
extern void un_wp_page(unsigned long * table_entry);
extern unsigned long put_page(unsigned long page,unsigned long address); extern unsigned long put_page(unsigned long page,unsigned long address);
extern int copy_page_tables(unsigned long from,unsigned long to,long size);
extern int free_page_tables(unsigned long from,unsigned long size);
extern void free_page(unsigned long addr); extern void free_page(unsigned long addr);
extern unsigned long get_free_page(void);
#endif extern void oom(void);
extern void do_exit(long code);
#endif // MACRO

@ -36,7 +36,7 @@ void verify_area(void * addr,int size)
} }
} }
int copy_mem(int nr,struct task_struct * p,int flag) int copy_mem(int nr,struct task_struct * p)
{ {
unsigned long old_data_base,new_data_base,data_limit; unsigned long old_data_base,new_data_base,data_limit;
unsigned long old_code_base,new_code_base,code_limit; unsigned long old_code_base,new_code_base,code_limit;
@ -53,7 +53,7 @@ int copy_mem(int nr,struct task_struct * p,int flag)
p->start_code = new_code_base; p->start_code = new_code_base;
set_base(p->ldt[1],new_code_base); set_base(p->ldt[1],new_code_base);
set_base(p->ldt[2],new_data_base); set_base(p->ldt[2],new_data_base);
if (copy_page_tables(old_data_base,new_data_base,data_limit,flag)) { if (copy_page_tables(old_data_base,new_data_base,data_limit)) {
free_page_tables(new_data_base,data_limit); free_page_tables(new_data_base,data_limit);
return -ENOMEM; return -ENOMEM;
} }
@ -65,11 +65,12 @@ int copy_mem(int nr,struct task_struct * p,int flag)
* information (task[nr]) and sets up the necessary registers. It * information (task[nr]) and sets up the necessary registers. It
* also copies the data segment in it's entirety. * also copies the data segment in it's entirety.
*/ */
int copy_process(int flag,int nr,long ebp,long edi,long esi,long gs,long none, int copy_process(int nr,long ebp,long edi,long esi,long gs,long none,
long ebx,long ecx,long edx, long ebx,long ecx,long edx,
long fs,long es,long ds, long fs,long es,long ds,
long eip,long cs,long eflags,long esp,long ss) long eip,long cs,long eflags,long esp,long ss)
{ {
sys_signal(SIGCHLD,NULL,NULL);
struct task_struct *p; struct task_struct *p;
int i; int i;
struct file *f; struct file *f;
@ -113,7 +114,7 @@ int copy_process(int flag,int nr,long ebp,long edi,long esi,long gs,long none,
p->tss.trace_bitmap = 0x80000000; p->tss.trace_bitmap = 0x80000000;
if (last_task_used_math == current) if (last_task_used_math == current)
__asm__("clts ; fnsave %0"::"m" (p->tss.i387)); __asm__("clts ; fnsave %0"::"m" (p->tss.i387));
if (copy_mem(nr,p,flag)) { if (copy_mem(nr,p)) {
task[nr] = NULL; task[nr] = NULL;
free_page((long) p); free_page((long) p);
return -EAGAIN; return -EAGAIN;
@ -147,95 +148,99 @@ int find_empty_process(void)
return -EAGAIN; return -EAGAIN;
} }
/*
esp int copy_mem_clone(int nr,struct task_struct * p)
eipret 0xec8353c3 ps:0xc3
eipeipret
int (*fn)(void *) fnexit
*/
int do_clone(int nr,long tmp,int (*fn)(void *), void *child_stack, int flag)
{
//设置压栈表,方便操作;
long stack[1024];
unsigned long len=0;
task[nr]->tss.esp=(unsigned long) child_stack - 8;
stack[0] = (unsigned long) fn;
task[nr]->tss.eip = (unsigned long) child_stack - 4;
stack[1]= 0xec8353c3;
//栈区赋值;
len = 8;
char *p1=stack ,*p2=(char *)((unsigned long)child_stack-len);
while(len--)
put_fs_byte(*(p1++),p2++);
return 0;
}
/*
childstack
//子进程task[nr]的页表项获取目的是更新成child——stacK的物理页
nrfrom_page = ((address>>20) & 0xffc);
nrfrom_page += ((task[nr]->start_code>>20) & 0xffc);//页目录
nrfrom=*(unsigned long *)nrfrom_page; //页表项
if(!(nrfrom&1)) //无页表项分配一个
{
if(!(tpage=get_free_page()))
{
printk("out of memory.\n");
return -1;
}
else
{
*(unsigned long *)nrfrom_page= tpage | 7;
mem_map[(tpage-LOW_MEM)>>12]++;
}
}
nrfrom &= 0xfffff000;
nrfrom_page = nrfrom + ((address>>10) & 0xffc);
//获取child_stack的物理页,并将其复制给task[nr];
address=(unsigned long) child_stack;
from_page = ((address>>20) & 0xffc);
from_page += ((current->start_code>>20) & 0xffc);//页目录
if(!(*(unsigned long *)from_page&1)) //页表项不存在,申请页面
if(!(tpage=get_free_page()))
{
printk("out of memory.\n");
return -1;
}
else
{
*(unsigned long *)from_page= tpage | 7;
mem_map[(tpage-LOW_MEM)>>12]++;
}
from=*(unsigned long *)from_page; //页表项
from &= 0xfffff000;
from_page = from + ((address>>10) & 0xffc);
if(!(*(unsigned long *)from_page & 1)) //物理页不存在
if(!(tpage=get_free_page()))
{ {
printk("out of memory.\n"); unsigned long old_data_base,new_data_base,data_limit;
return -1; unsigned long old_code_base,new_code_base,code_limit;
code_limit=get_limit(0x0f);
data_limit=get_limit(0x17);
old_code_base = get_base(current->ldt[1]);
old_data_base = get_base(current->ldt[2]);
if (old_data_base != old_code_base)
panic("We don't support separate I&D");
if (data_limit < code_limit)
panic("Bad data_limit");
new_data_base = new_code_base = nr * 0x4000000;
p->start_code = new_code_base;
set_base(p->ldt[1],new_code_base);
set_base(p->ldt[2],new_data_base);
if (copy_page_tables_clone(old_data_base,new_data_base,data_limit)) {
free_page_tables(new_data_base,data_limit);
return -ENOMEM;
} }
else return 0;
{
*(unsigned long *)from_page= tpage | 7;
mem_map[(tpage-LOW_MEM)>>12]++;
} }
//复制给nr
*(unsigned long *)nrfrom_page = *(unsigned long *)from_page;
//更新esp,让其指向child_stack同样偏移的地点;
task[nr]->tss.esp=(unsigned long) child_stack;
//注意这里child_stack 指向的是高地址要向下面push.
unsigned long phy_addr = (*(unsigned long *)nrfrom_page & 0xfffff000) | ((unsigned long) child_stack & 0xfff);
if(argv)//参数列表不为空,将参数压入栈中,这里直接修改物理页 int copy_process_clone(int nr,long ebp,long edi,long esi,long gs,long none,
long ebx,long ecx,long edx,
long fs,long es,long ds,
long eip,long cs,long eflags,long esp,long ss)
{ {
struct task_struct *p;
int i;
struct file *f;
p = (struct task_struct *) get_free_page();
if (!p)
return -EAGAIN;
task[nr] = p;
__asm__ volatile ("cld"); /* by wyj */
*p = *current; /* NOTE! this doesn't copy the supervisor stack */
p->state = TASK_UNINTERRUPTIBLE;
p->pid = last_pid;
p->father = current->pid;
p->counter = p->priority;
p->signal = 0;
p->alarm = 0;
p->leader = 0; /* process leadership doesn't inherit */
p->utime = p->stime = 0;
p->cutime = p->cstime = 0;
p->start_time = jiffies;
p->tss.back_link = 0;
p->tss.esp0 = PAGE_SIZE + (long) p;
p->tss.ss0 = 0x10;
p->tss.eip = ebx;
p->tss.eflags = eflags;
p->tss.eax = 0;
p->tss.ecx = ecx;
p->tss.edx = edx;
p->tss.ebx = ebx;
p->tss.esp = ecx;
p->tss.ebp = ebp;
p->tss.esi = esi;
p->tss.edi = edi;
p->tss.es = es & 0xffff;
p->tss.cs = cs & 0xffff;
p->tss.ss = ss & 0xffff;
p->tss.ds = ds & 0xffff;
p->tss.fs = fs & 0xffff;
p->tss.gs = gs & 0xffff;
p->tss.ldt = _LDT(nr);
p->tss.trace_bitmap = 0x80000000;
if (last_task_used_math == current)
__asm__("clts ; fnsave %0"::"m" (p->tss.i387));
if (copy_mem_clone(nr,p)) {
task[nr] = NULL;
free_page((long) p);
return -EAGAIN;
} }
//char * tmp1=nrfrom, *tmp2=child_stack-1024,len=; for (i=0; i<NR_OPEN;i++)
//while() if (f=p->filp[i])
return 0; f->f_count++;
if (current->pwd)
current->pwd->i_count++;
if (current->root)
current->root->i_count++;
if (current->executable)
current->executable->i_count++;
set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));
set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt));
p->state = TASK_RUNNING; /* do this last, just in case */
return last_pid;
} }
*/

@ -179,11 +179,7 @@ unsigned int sys_sleep(unsigned int seconds)
return 0; return 0;
} }
int sys_clone()
{
return -1;
}
int sys_ftime() int sys_ftime()
{ {
@ -463,183 +459,4 @@ int sys_umask(int mask)
return (old); return (old);
} }
static int my_share(unsigned long address, struct task_struct * p)
{
unsigned long from;
unsigned long to;
unsigned long from_page;
unsigned long to_page;
unsigned long phys_addr;
from_page = to_page = ((address>>20) & 0xffc);
from_page += ((current->start_code>>20) & 0xffc);
to_page += ((p->start_code>>20) & 0xffc);
from = *(unsigned long *) from_page;
from &= 0xfffff000;
from_page = from + ((address>>10) & 0xffc);
phys_addr = *(unsigned long *) from_page;
to = *(unsigned long *) to_page;
if (!(to & 1))
if (to = get_free_page())
*(unsigned long *) to_page = to | 7;
else
return 0;
to &= 0xfffff000;
to_page = to + ((address>>10) & 0xffc);
if (1 & *(unsigned long *) to_page)
return 0;
/* share them: write-protect */
*(unsigned long *) to_page = *(unsigned long *) from_page;
phys_addr -= LOW_MEM;
phys_addr >>= 12;
mem_map[phys_addr]++;
return 1;
}
// rememeber to sync when munmap exit manual
long sys_mmap(void * start,size_t len,...)// int prot,int flags,int fd,off_t off
{
printk("start mmaping\n");
/* va_list args;
va_start(args,len); */
int prot=3,flags=1,fd=3,off=0;
/* prot=va_arg(args,int);flags=va_arg(args,int);fd=va_arg(args,int);
off_t off=va_arg(args,off_t);
int *ll=&len;printk("%d,%d,%d,%d,%d\n",*ll,*(ll+1),*(ll+2),*(ll+3),*(ll+4));
va_end(args);
printk("%d,%d,%d,%ld\n",prot,flags,fd,off); */
int block;
size_t l=len;
struct buffer_head * bh;
char *temp,*p1,*p2;
void * buf=start;
int tempprot=0;
//因为new.h和namei.c定义不一样要修改
if(prot &PROT_READ) tempprot |=4;
if(prot &PROT_EXEC) tempprot |=1;
if(prot &PROT_WRITE) tempprot |=2;
//特殊量len>0 off%4096==0 prot至少有read权限
if(len<=0 || off<0 || (off%PAGE_SIZE))
{
if(len<=0)
printk("the len of the wanting bytes must be positive");
else
printk("offset must be the mul of 4096");
return MAP_FAILED;
}
if(!(prot& PROT_READ)) return MAP_FAILED;
//permissions of the file ,搬运函数namei.c::permissions
printk("fd: %d\n",fd);
struct m_inode *inode=current->filp[fd]->f_inode;
printk("end of permissions\n");
int mode = inode->i_mode;
if (inode->i_dev && !inode->i_nlinks)
{printk("end of permissions1\n");return MAP_FAILED;}
else if (current->euid==inode->i_uid)
mode >>= 6;
else if (current->egid==inode->i_gid)
mode >>= 3;
if (!(((mode & tempprot & 0007) == tempprot) || suser()))
{
printk("error permission.");
return MAP_FAILED;
}
//end of permission check
printk("end of permissions\n");
//设置用户空间的虚拟地址初始为32MB处这样写在brk增长至32MB时会有bug,我们忽略
//同时,当栈向下增长到一定程度时,也会和当前地址冲突,我们忽略
if(start<=current->brk || start>=current->start_stack-0x8000 || start==NULL)
{
if(!current->mmap_tail)
buf=0x2000000;
else
buf=current->mmap_tail->endaddr;
}
//申请mmap
struct mmap_struct *mmap=(struct mmap_struct *)malloc(sizeof(struct mmap_struct));
mmap->address=buf;
mmap->size=len;
mmap->endaddr=(unsigned long)buf+(len + 0xfff)&0xfffff000;
mmap->rw=prot;
mmap->ps=flags;
mmap->next=NULL;
//加入current->mmap
if(!current->mmap)
{current->mmap=current->mmap_tail=mmap;}
else
current->mmap_tail->next=mmap;
printk("buf: %x\n",(unsigned long )buf);
//分配物理页
unsigned long from;
unsigned long to;
unsigned long from_page;
unsigned long to_page;
unsigned long phys_addr;
unsigned long tpage;
unsigned long address=mmap->address;
while(address<mmap->endaddr)
{
from_page = ((mmap->address>>20) & 0xffc);
from_page += ((current->start_code>>20) & 0xffc);//页目录
if(!(*(unsigned long *)from_page&1)) //页表项不存在,申请页面
if(!(tpage=get_free_page()))
{
printk("out of memory.\n");
return MAP_FAILED;
}
else
*(unsigned long *)from_page= tpage | 7;
from=*(unsigned long *)from_page; //页表项
from &= 0xfffff000;
from_page = from + ((address>>10) & 0xffc);
if(!(*(unsigned long *)from_page & 1)) //物理页不存在
if(!(tpage=get_free_page()))
{
printk("out of memory.\n");
return MAP_FAILED;
}
else
*(unsigned long *)from_page= tpage | 7;
*(unsigned long *)from_page &= (prot&PROT_WRITE); //分配读写权限
if(flags & MAP_SHARED)
{
struct task_struct ** p;
for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
if (!*p)
continue;
if (current == *p)
continue;
if(!my_share(address,*p))
printk("share failed at task:pid=%d",(*p)->pid);
}
}
address+=PAGE_SIZE;
}
//read and put in
if (!(block = inode->i_zone[0]))
return NULL;
if (!(bh = bread(inode->i_dev,block)))
return NULL;
temp = (char *) bh->b_data;
p1=temp;p2=buf;
while(l--)
put_fs_byte(*(p1++),p2++);
printk("%s\n",temp);
return buf;
}
int sys_munmap()
{
return -1;
}

@ -227,9 +227,8 @@ sys_fork:
pushl %edi pushl %edi
pushl %ebp pushl %ebp
pushl %eax pushl %eax
pushl $0x0 #for flag
call copy_process call copy_process
addl $24,%esp #for flag addl $20,%esp
1: ret 1: ret
.align 4 .align 4
@ -237,17 +236,13 @@ sys_clone:
call find_empty_process call find_empty_process
testl %eax,%eax testl %eax,%eax
js 1f js 1f
pushl %eax
push %gs push %gs
pushl %esi pushl %esi
pushl %edi pushl %edi
pushl %ebp pushl %ebp
pushl %eax pushl %eax
pushl $0x1 #for flag call copy_process_clone
call copy_process addl $20,%esp
addl $24,%esp #for flag
call do_clone
addl $4,%esp
1: ret 1: ret
hd_interrupt: hd_interrupt:

@ -809,3 +809,160 @@ mytag:
/*
esp
eipret 0xec8353c3 ps:0xc3
eipeipret
int (*fn)(void *) fnexit
*/
/* int do_clone(int nr,long tmp,int (*fn)(void *), void *child_stack, int flag)
{
//设置压栈表,方便操作;
long stack[1024];
unsigned long len=0;
task[nr]->tss.esp=(unsigned long) child_stack - 8;
stack[0] = (unsigned long) fn;
task[nr]->tss.eip = (unsigned long) child_stack - 4;
stack[1]= 0xec8353c3;
//栈区赋值;
len = 8;
char *p1=stack ,*p2=(char *)((unsigned long)child_stack-len);
while(len--)
put_fs_byte(*(p1++),p2++);
return 0;
} */
/* child_stack-4 00 00 00 00 */
/* child_stack-8 00 00 00 00 */
/* child_stack-12 arg */
/* child_stack-16 fn */ //esp
/* child_stack-20 00 00 00 00 */
/* child_stack-24 00 00 00 00 */
/* child_stack-28 00 00 00 00 */
/* child_stack-32 0x000000c3 */
/*
int do_clone(int nr,long tmp,int (*fn)(void *), void *child_stack, int flag)
{
void * argv =NULL;
//共享物理页写法有缺陷可能child——stack跨页
//子进程task[nr]的页表项获取目的是更新成child——stacK的物理页
unsigned long nrfrom_page,nrfrom,from_page,from,tpage,address;
address = task[nr]->tss.esp;
nrfrom_page = ((address>>20) & 0xffc);
nrfrom_page += ((task[nr]->start_code>>20) & 0xffc);//页目录
nrfrom=*(unsigned long *)nrfrom_page; //页表项
if(!(nrfrom&1)) //无页表项分配一个
{
if(!(tpage=get_free_page()))
{
printk("out of memory.\n");
return -1;
}
else
{
*(unsigned long *)nrfrom_page= tpage | 7;
mem_map[(tpage-LOW_MEM)>>12]++;
}
}
nrfrom &= 0xfffff000;
nrfrom_page = nrfrom + ((address>>10) & 0xffc);
//获取child_stack的物理页,并将其复制给task[nr];
address=(unsigned long) child_stack;
from_page = ((address>>20) & 0xffc);
from_page += ((current->start_code>>20) & 0xffc);//页目录
if(!(*(unsigned long *)from_page&1)) //页表项不存在,申请页面
if(!(tpage=get_free_page()))
{
printk("out of memory.\n");
return -1;
}
else
{
*(unsigned long *)from_page= tpage | 7;
mem_map[(tpage-LOW_MEM)>>12]++;
}
from=*(unsigned long *)from_page; //页表项
from &= 0xfffff000;
from_page = from + ((address>>10) & 0xffc);
if(!(*(unsigned long *)from_page & 1)) //物理页不存在
if(!(tpage=get_free_page()))
{
printk("out of memory.\n");
return -1;
}
else
{
*(unsigned long *)from_page= tpage | 7;
mem_map[(tpage-LOW_MEM)>>12]++;
}
//复制给nr
*(unsigned long *)nrfrom_page = *(unsigned long *)from_page;
unsigned long stack[128];
unsigned long off=(unsigned long)child_stack & 0xfff;
if(off < 32)
{
printk("地址跨页,我也没办法.\n");
return -1;
}
//更新esp,让其指向child_stack同样偏移的地点;
//注意这里child_stack 指向的是高地址要向下面push.
task[nr]->tss.esp &=0xfffff000;
task[nr]->tss.esp |=off - 16;
//eip 只有一条ret //所以传进来的fn必须以exit结尾不能return ,
//因为我不会return这个玩意push ebp 又pop 啥的
task[nr]->tss.eip &=0xfffff000;
task[nr]->tss.eip |=off - 32;
//ret eip
stack[0]=0x000000c3;
stack[4]=(unsigned long)fn;
stack[5]=(unsigned long)argv;
char * p1=stack, *p2=(unsigned long) child_stack - 32,len=32;
while(len--)
put_fs_byte(*(p1++),p2++);
printk("nr:%d::fn:%x\n",nr,(unsigned long )fn);
return 0;
}
*/
int copy_page_tables_clone(unsigned long from,unsigned long to,long size )
{
unsigned long * from_page_table;
unsigned long * to_page_table;
unsigned long this_page;
unsigned long * from_dir, * to_dir;
unsigned long nr;
if ((from&0x3fffff) || (to&0x3fffff))
panic("copy_page_tables called with wrong alignment");
from_dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */
to_dir = (unsigned long *) ((to>>20) & 0xffc);
size = ((unsigned) (size+0x3fffff)) >> 22;
for( ; size-->0 ; from_dir++,to_dir++) {
if (1 & *to_dir)
panic("copy_page_tables: already exist");
if (!(1 & *from_dir))
continue;
from_page_table = (unsigned long *) (0xfffff000 & *from_dir);
if (!(to_page_table = (unsigned long *) get_free_page()))
return -1; /* Out of memory, see freeing */
*to_dir = ((unsigned long) to_page_table) | 7;
nr = (from==0)?0xA0:1024;
for ( ; nr-- > 0 ; from_page_table++,to_page_table++) {
this_page = *from_page_table;
if (!(1 & this_page))
continue;
*to_page_table = this_page;
if (this_page > LOW_MEM) {
*from_page_table = this_page;
this_page -= LOW_MEM;
this_page >>= 12;
mem_map[this_page]++;
}
}
}
invalidate();
return 0;
}
Loading…
Cancel
Save