1.page.s
1 /*
2 * linux/mm/page.s
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * page.s contains the low-level page-exception code.
9 * the real work is done in mm.c
10 */
用来处理页异常的
2 * linux/mm/page.s
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * page.s contains the low-level page-exception code.
9 * the real work is done in mm.c
10 */
用来处理页异常的
12 .globl _page_fault
14 _page_fault:
15 xchgl %eax,(%esp)
16 pushl %ecx
17 pushl %edx
18 push %ds
19 push %es
20 push %fs
21 movl $0x10,%edx
22 mov %dx,%ds
23 mov %dx,%es
24 mov %dx,%fs
与系统调用不同,这里ds,es,fs全部设置为内核数据段
25 movl %cr2,%edx
cr2中存放的是发生页异常时处理的指令
26 pushl %edx
27 pushl %eax
27 pushl %eax
26行压栈的是导致异常的指令线性地址
27行保存的是异常号
上面二者作为参数调用处理函数
28 testl $1,%eax
29 jne 1f
30 call _do_no_page // 缺页异常
31 jmp 2f
29 jne 1f
30 call _do_no_page // 缺页异常
31 jmp 2f
32 1: call _do_wp_page //写保护异常
33 2: addl $8,%esp
34 pop %fs
35 pop %es
36 pop %ds
37 popl %edx
38 popl %ecx
39 popl %eax
33 2: addl $8,%esp
34 pop %fs
35 pop %es
36 pop %ds
37 popl %edx
38 popl %ecx
39 popl %eax
40 iret
总结
该文件是用来处理页错误的,page_fault是在kernel/traps.c中注册的。如下:
181 void trap_init(void)
199: set_trap_gate(14,&page_fault);
当发生页错误时就会执行这里的_page_fault. 保存寄存器的值,把fs,es,ds均设为内核数据段,压栈发生页面异常的线性地址和出错号作为参数调用相应的函数(do_no_page或者do_wp_page),最后抛弃作为参数压栈的值,并弹出寄存器的值。
2.memory.c
1 /*
2 * linux/mm/memory.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * demand-loading started 01.12.91 - seems it is high on the list of
9 * things wanted, and it should be easy to implement. - Linus
10 */
11
12 /*
13 * Ok, demand-loading was easy, shared pages a little bit tricker. Shared
14 * pages started 02.12.91, seems to work. - Linus.
15 *
16 * Tested sharing by executing about 30 /bin/sh: under the old kernel it
17 * would have taken more than the 6M I have free, but it worked well as
18 * far as I could see.
19 *
20 * Also corrected some "invalidate()"s - I wasn't doing enough of them.
21 */
2 * linux/mm/memory.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * demand-loading started 01.12.91 - seems it is high on the list of
9 * things wanted, and it should be easy to implement. - Linus
10 */
11
12 /*
13 * Ok, demand-loading was easy, shared pages a little bit tricker. Shared
14 * pages started 02.12.91, seems to work. - Linus.
15 *
16 * Tested sharing by executing about 30 /bin/sh: under the old kernel it
17 * would have taken more than the 6M I have free, but it worked well as
18 * far as I could see.
19 *
20 * Also corrected some "invalidate()"s - I wasn't doing enough of them.
21 */
23 #include <signal.h>
24
25 #include <asm/system.h>
26
27 #include <linux/sched.h>
28 #include <linux/head.h>
29 #include <linux/kernel.h>
30
31 volatile void do_exit(long code);
32
33 static inline volatile void oom(void)
34 {
35 printk("out of memory\n\r");
36 do_exit(SIGSEGV);
37 }
38
39 #define invalidate() \
40 __asm__("movl %%eax,%%cr3"::"a" (0))
用于刷新页变换高速缓冲
24
25 #include <asm/system.h>
26
27 #include <linux/sched.h>
28 #include <linux/head.h>
29 #include <linux/kernel.h>
30
31 volatile void do_exit(long code);
32
33 static inline volatile void oom(void)
34 {
35 printk("out of memory\n\r");
36 do_exit(SIGSEGV);
37 }
38
39 #define invalidate() \
40 __asm__("movl %%eax,%%cr3"::"a" (0))
用于刷新页变换高速缓冲
42 /* these are not to be changed without changing head.s etc */
43 #define LOW_MEM 0x100000
44 #define PAGING_MEMORY (15*1024*1024) //分页的内存总量
45 #define PAGING_PAGES (PAGING_MEMORY>>12) //总共的内存页数
46 #define MAP_NR(addr) (((addr)-LOW_MEM)>>12) //计算内存页号
47 #define USED 100
48
49 #define CODE_SPACE(addr) ((((addr)+4095)&~4095) < \
50 current->start_code + current->end_code)
判断给定的线性地址是否在当前进程的代码段中,((addr)+4095)&~4095用于取得addr所在内存页面的末端地址
43 #define LOW_MEM 0x100000
44 #define PAGING_MEMORY (15*1024*1024) //分页的内存总量
45 #define PAGING_PAGES (PAGING_MEMORY>>12) //总共的内存页数
46 #define MAP_NR(addr) (((addr)-LOW_MEM)>>12) //计算内存页号
47 #define USED 100
48
49 #define CODE_SPACE(addr) ((((addr)+4095)&~4095) < \
50 current->start_code + current->end_code)
判断给定的线性地址是否在当前进程的代码段中,((addr)+4095)&~4095用于取得addr所在内存页面的末端地址
52 static long HIGH_MEMORY = 0;
53
54 #define copy_page(from,to) \
55 __asm__("cld ; rep ; movsl"::"S" (from),"D" (to),"c" (1024):"cx","di","si")
57 static unsigned char mem_map [ PAGING_PAGES ] = {0,};
存放内存页的数组
53
54 #define copy_page(from,to) \
55 __asm__("cld ; rep ; movsl"::"S" (from),"D" (to),"c" (1024):"cx","di","si")
57 static unsigned char mem_map [ PAGING_PAGES ] = {0,};
存放内存页的数组
59 /*
60 * Get physical address of first (actually last :-) free page, and mark it
61 * used. If no free pages left, return 0.
62 */
63 unsigned long get_free_page(void)
64 {
65 register unsigned long __res asm("ax");
67 __asm__("std ; repne ; scasb\n\t"
68 "jne 1f\n\t"
69 "movb $1,1(%%edi)\n\t"
70 "sall $12,%%ecx\n\t"
71 "addl %2,%%ecx\n\t"
72 "mo