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 */
/*
* ��������Ǵ�91.12.1��ʼ��д�� - �ڳ�����Ʊ����ƺ�������Ҫ�ij���
* ����Ӧ���Ǻ����ױ��Ƶ� - Linus
*/
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 */
/*
* OK����������DZȽ����ױ�д�ģ�������ҳ��ȴ��Ҫ�е㼼�ɡ�����ҳ�������
* 91.12.2��ʼ��д�ģ������ܹ����� - Linus��
*
* ͨ��ִ�д�Լ30��/bin/sh�Թ������������˲��ԣ������ں˵�����Ҫռ�ö���
* 6M���ڴ棬��Ŀǰȴ���á����ڿ��������úܺá�
*
* ��"invalidate()"����Ҳ���������� - ���ⷽ���һ����IJ�����
*/
22
23 /*
24 * Real VM (paging to/from disk) started 18.12.91. Much more work and
25 * thought has to go into this. Oh, well..
26 * 19.12.91 - works, somewhat. Sometimes I get faults, don't know why.
27 * Found it. Everything seems to work now.
28 * 20.12.91 - Ok, making the swap-device changeable like the root.
29 */
/*
* 91.12.18��ʼ��д�����������ڴ����VM������ҳ�浽/�Ӵ��̣�����Ҫ�Դ�
* ���Ǻܶಢ����Ҫ���ܶ�����Ǻǣ�Ҳֻ�������ˡ�
* 91.12.19 - ��ij�̶ֳ��Ͽ��Թ����ˣ�����ʱ���������֪����ô���¡�
* �ҵ������ˣ����ں���һ�ж��ܹ����ˡ�
* 91.12.20 - OK���ѽ����豸�ijɿɸ��ĵ��ˣ�������ļ��豸������
*/
30
31 #include <signal.h> // �ź�ͷ�ļ��������źŷ��ų������źŽṹ���źź���ԭ�͡�
32
33 #include <asm/system.h> // ϵͳͷ�ļ����������û���������/�ж��ŵ�Ƕ����ꡣ
34
35 #include <linux/sched.h> // ���ȳ���ͷ�ļ�����������ṹtask_struct������0�����ݡ�
36 #include <linux/head.h> // headͷ�ļ���������������ļṹ���ͼ���ѡ���������
37 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
38
// CODE_SPACE(addr) ((((addr)+0xfff)&~0xfff)<current->start_code+current->end_code)��
// �ú������жϸ������Ե�ַ�Ƿ�λ�ڵ�ǰ���̵Ĵ�����У���(((addr)+4095)&~4095)������
// ȡ�����Ե�ַaddr�����ڴ�ҳ���ĩ�˵�ַ���μ�265�С�
39 #define CODE_SPACE(addr) ((((addr)+4095)&~4095) < \
40 current->start_code + current->end_code)
41
42 unsigned long HIGH_MEMORY = 0; // ȫ�ֱ��������ʵ�������ڴ���߶˵�ַ��
43
// ��from������1ҳ�ڴ浽to����4K�ֽڣ���
44 #define copy_page(from,to) \
45 __asm__("cld ; rep ; movsl"::"S" (from),"D" (to),"c" (1024):"cx","di","si")
46
// �����ڴ�ӳ���ֽ�ͼ��1�ֽڴ���1ҳ�ڴ棩��ÿ��ҳ���Ӧ���ֽ����ڱ�־ҳ�浱ǰ������
// ��ռ�ã���������������ӳ��15Mb���ڴ�ռ䡣�ڳ�ʼ������mem_init()�У����ڲ�����
// �����ڴ���ҳ���λ�þ���Ԥ�ȱ����ó�USED��100����
47 unsigned char mem_map [ PAGING_PAGES ] = {0,};
48
49 /*
50 * Free a page of memory at physical address 'addr'. Used by
51 * 'free_page_tables()'
52 */
/*
* �ͷ�������ַ'addr'����һҳ�ڴ档���ں���'free_page_tables()'��
*/
//// �ͷ�������ַaddr��ʼ��1ҳ���ڴ档
// ������ַ1MB���µ��ڴ�ռ������ں˳���ͻ��壬����Ϊ����ҳ����ڴ�ռ䡣���
// ����addr��Ҫ����1MB��
53 void free_page(unsigned long addr)
54 {
// �����жϲ���������������ַaddr�ĺ����ԡ����������ַaddrС���ڴ�Ͷˣ�1MB����
// ���ʾ���ں˳������ٻ����У��Դ˲��账�������������ַaddr >= ϵͳ��������
// �ڴ���߶ˣ�����ʾ������Ϣ�����ں�ֹͣ������
55 if (addr < LOW_MEM) return;
56 if (addr >= HIGH_MEMORY)
57 panic("trying to free nonexistent page");
// ����Բ���addr��֤ͨ������ô�������������ַ��������ڴ�Ͷ˿�ʼ������ڴ�
// ҳ��š�ҳ��� = (addr �C LOW_MEM)/4096���ɼ�ҳ��Ŵ�0�ſ�ʼ���𡣴�ʱaddr
// �д����ҳ��š������ҳ��Ŷ�Ӧ��ҳ��ӳ���ֽڲ�����0�����1���ء���ʱ��ӳ��
// �ֽ�ֵӦ��Ϊ0����ʾҳ�����ͷš������Ӧҳ���ֽ�ԭ������0����ʾ������ҳ�汾��
// ���ǿ��еģ�˵���ں˴�������⡣������ʾ������Ϣ��ͣ����
58 addr -= LOW_MEM;
59 addr >>= 12;
60 if (mem_map[addr]--) return;
61 mem_map[addr]=0;
62 panic("trying to free free page");
63 }
64
65 /*
66 * This function frees a continuos block of page tables, as needed
67 * by 'exit()'. As does copy_page_tables(), this handles only 4Mb blocks.
68 */
/*
* ���溯���ͷ�ҳ���������ڴ�飬'exit()'��Ҫ�ú�������copy_page_tables()
* ���ƣ��ú���������4Mb���ȵ��ڴ�顣
*/
//// ����ָ�������Ե�ַ������ҳ�����������ͷŶ�Ӧ�ڴ�ҳ��ָ�����ڴ�鲢�ñ�����С�
// ҳĿ¼λ��������ַ0��ʼ������1024�ÿ��4�ֽڣ���ռ4K�ֽڡ�ÿ��Ŀ¼��ָ��һ
// ��ҳ�����ں�ҳ����������ַ0x1000����ʼ��������Ŀ¼�ռ䣩����4��ҳ����ÿ��ҳ����
// 1024�ÿ��4�ֽڡ����Ҳռ4K��1ҳ���ڴ档�����̣��������ں˴����еĽ���0��1��
// ��ҳ����ռ�ݵ�ҳ���ڽ��̱�����ʱ���ں�Ϊ�������ڴ�������õ���ÿ��ҳ�����Ӧ1ҳ
// �����ڴ棬���һ��ҳ������ӳ��4MB�������ڴ档
// ������from - ��ʼ���Ի���ַ��size - �ͷŵ��ֽڳ��ȡ�
69 int free_page_tables(unsigned long from,unsigned long size)
70 {
71 unsigned long *pg_table;
72 unsigned long * dir, nr;
73
// ���ȼ�����from���������Ի���ַ�Ƿ���4MB�ı߽紦����Ϊ�ú���ֻ�ܴ������������
// ��from = 0���������˵����ͼ�ͷ��ں˺ͻ�����ռ�ռ䡣
74 if (from & 0x3fffff)
75 panic("free_page_tables called with wrong alignment");
76 if (!from)
77 panic("Trying to free up swapper memory space");
// Ȼ��������size�����ij�����ռ��ҳĿ¼������4MB�Ľ�λ����������Ҳ����ռҳ������
// ��Ϊ1��ҳ���ɹ���4MB�����ڴ棬��������������22λ�ķ�ʽ����Ҫ���Ƶ��ڴ泤��ֵ
// ����4MB�����м���0x3fffff����4Mb -1�����ڵõ���λ���������������������������
// ���1�����磬���ԭsize = 4.01Mb����ô�ɵõ����size = 2�� ���ż������������
// ����ַ��Ӧ����ʼĿ¼���Ӧ��Ŀ¼��� = from >> 22����Ϊÿ��ռ4�ֽڣ���������
// ҳĿ¼����������ַ0��ʼ��ţ����ʵ��Ŀ¼��ָ�� = Ŀ¼���<<2��Ҳ��(from>>20)��
// ��������0xffcȷ��Ŀ¼��ָ�뷶Χ��Ч��
78 size = (size + 0x3fffff) >> 22;
79 dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */
// ��ʱ size ���ͷŵ�ҳ����������ҳĿ¼��������dir����ʼĿ¼��ָ�롣���ڿ�ʼѭ��
// ����ҳĿ¼������ͷ�ÿ��ҳ���е�ҳ��������ǰĿ¼����Ч��Pλ=0������ʾ��
// Ŀ¼��û��ʹ�ã���Ӧ��ҳ�������ڣ��������������һ��Ŀ¼������Ŀ¼����ȡ��
// ҳ����ַ pg_table�����Ը�ҳ���е� 1024 ��������д������ͷ���Чҳ���Pλ=1��
// ��Ӧ�������ڴ�ҳ�棬���ߴӽ����豸���ͷ���Чҳ���Pλ=0����Ӧ��ҳ�棬���ͷ�
// �����豸�ж�Ӧ���ڴ�ҳ�棨��Ϊҳ������Ѿ�������ȥ����Ȼ��Ѹ�ҳ�������㣬����
// ��������һҳ�����һ��ҳ�����б��������Ͼ��ͷŸ�ҳ������ռ�ݵ��ڴ�ҳ�棬
// ������������һҳĿ¼����ˢ��ҳ�任���ٻ��壬������0��
80 for ( ; size-->0 ; dir++) {
81 if (!(1 & *dir))
82 continue;
83 pg_table = (unsigned long *) (0xfffff000 & *dir); // ȡҳ����ַ��
84 for (nr=0 ; nr<1024 ; nr++) {
85 if (*pg_table) { // ����ָҳ�������ݲ�Ϊ0����
86 if (1 & *pg_table) // ��������Ч�����ͷŶ�Ӧҳ��
87 free_page(0xfffff000 & *pg_table);
88 else // �����ͷŽ����豸�ж�Ӧҳ��
89 swap_free(*pg_table >> 1);
90 *pg_table = 0; // ��ҳ�����������㡣
91 }
92 pg_table++; // ָ��ҳ������һ�
93 }
94 free_page(0xfffff000 & *dir); // �ͷŸ�ҳ����ռ�ڴ�ҳ�档
95 *dir = 0; // ��Ӧҳ����Ŀ¼�����㡣
96 }
97 invalidate(); // ˢ��CPUҳ�任���ٻ��塣
98 return 0;
99 }
100
101 /*
102 * Well, here is one of the most complicated functions in mm. It
103 * copies a range of linerar addresses by copying only the pages.
104 * Let's hope this is bug-free, 'cause this one I don't want to debug :-)
105 *
106 * Note! We don't copy just any chunks of memory - addresses have to
107 * be divisible by 4Mb (one page-directory entry), as this makes the
108 * function easier. It's used only by fork anyway.
109 *
110 * NOTE 2!! When from==0 we are copying kernel space for the first
111 * fork(). Then we DONT want to copy a full page-directory entry, as
112 * that would lead to some serious memory waste - we just copy the
113 * first 160 pages - 640kB. Even that is more than we need, but it
114 * doesn't take any more memory - we don't copy-on-write in the low
115 * 1 Mb-range, so the pages can be shared with the kernel. Thus the
116 * special case for nr=xxxx.
117 */
/*
* ���ˣ��������ڴ����mm����Ϊ���ӵij���֮һ����ͨ��ֻ�����ڴ�ҳ��
* ������һ����Χ�����Ե�ַ�е����ݡ� ϣ��������û�д�����Ϊ�Ҳ���
* �ٵ�����������:-)��
*
* ע�⣡���Dz��������κ��ڴ�� - �ڴ��ĵ�ַ��Ҫ��4Mb�ı���������
* һ��ҳĿ¼���Ӧ���ڴ泤�ȣ�����Ϊ����������ʹ�����ܼ� ������
* ����������fork()ʹ�á�
*
* ע��2���� ��from==0ʱ��˵������Ϊ��һ��fork()���ø����ں˿ռ䡣
* ��ʱ���ǾͲ��븴������ҳĿ¼���Ӧ���ڴ棬��Ϊ�������ᵼ���ڴ���
* ���˷� - ����ֻ�븴�ƿ�ͷ160��ҳ�� - ��Ӧ 640kB����ʹ�Ǹ�����Щ
* ҳ��Ҳ�Ѿ��������ǵ������ⲻ��ռ�ø�����ڴ� - �ڵ� 1Mb �ڴ�
* ��Χ�����Dz�ִ��дʱ���Ʋ�����������Щҳ��������ں˹����������
* ��nr=xxxx�����������nr�ڳ�����ָҳ��������
*/
//// ����ҳĿ¼�����ҳ���
// ����ָ�����Ե�ַ�ͳ����ڴ��Ӧ��ҳĿ¼���ҳ����Ӷ������Ƶ�ҳĿ¼��ҳ����Ӧ
// ��ԭ�����ڴ�ҳ����������ҳ��ӳ�������ʹ�á�����ʱ����������ҳ���������ҳ����
// ԭ�����ڴ��������������˺��������̣������̺����ӽ��̣��������ڴ�����ֱ����һ��
// ����ִ��д����ʱ���ں˲Ż�Ϊд�������̷����µ��ڴ�ҳ��дʱ���ƻ��ƣ���
// ����from��to �����Ե�ַ��size����Ҫ���ƣ����������ڴ泤�ȣ���λ���ֽڡ�
118 int copy_page_tables(unsigned long from,unsigned long to,long size)
119 {
120 unsigned long * from_page_table;
121 unsigned long * to_page_table;
122 unsigned long this_page;
123 unsigned long * from_dir, * to_dir;
124 unsigned long new_page;
125 unsigned long nr;
126
// ���ȼ�����������Դ��ַfrom��Ŀ�ĵ�ַto����Ч�ԡ�Դ��ַ��Ŀ�ĵ�ַ����Ҫ��4Mb
// �ڴ�߽��ַ�ϡ����������������������Ҫ������Ϊһ��ҳ����1024��ɹ���4Mb�ڴ档
// Դ��ַ from ��Ŀ�ĵ�ַ to ֻ���������Ҫ����ܱ�֤��һ��ҳ���ĵ�1�ʼ����ҳ��
// �������ҳ����������������Ч�ġ� Ȼ��ȡ��Դ��ַ��Ŀ�ĵ�ַ����ʼĿ¼��ָ��
// ��from_dir��to_dir�����ٸ��ݲ��������ij���size����Ҫ���Ƶ��ڴ��ռ�õ�ҳ����
// ����Ŀ¼���������μ�ǰ���78��79�еĽ��͡�
127 if ((from&0x3fffff) || (to&0x3fffff))
128 panic("copy_page_tables called with wrong alignment");
129 from_dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */
130 to_dir = (unsigned long *) ((to>>20) & 0xffc);
131 size = ((unsigned) (size+0x3fffff)) >> 22;
// �ڵõ���Դ��ʼĿ¼��ָ��from_dir��Ŀ����ʼĿ¼��ָ��to_dir�Լ���Ҫ���Ƶ�ҳ��
// ���� size �����濪ʼ��ÿ��ҳĿ¼����������1ҳ�ڴ��������Ӧ��ҳ�������ҿ�ʼ
// ҳ����Ʋ��������Ŀ��Ŀ¼��ָ����ҳ���Ѿ����ڣ�P=1��������������� ���ԴĿ
// ¼����Ч����ָ����ҳ�������ڣ�P=0���������ѭ��������һ��ҳĿ¼�
132 for( ; size-->0 ; from_dir++,to_dir++) {
133 if (1 & *to_dir)
134 panic("copy_page_tables: already exist");
135 if (!(1 & *from_dir))
136 continue;
// ����֤�˵�ǰԴĿ¼���Ŀ��������֮������ȡԴĿ¼����ҳ����ַfrom_page_table��
// Ϊ�˱���Ŀ��Ŀ¼���Ӧ��ҳ������Ҫ�����ڴ���������1ҳ�����ڴ�ҳ�����ȡ����ҳ��
// ����get_free_page() ����0����˵��û�����뵽�����ڴ�ҳ�棬�������ڴ治�������Ƿ�
// ��-1ֵ�˳���
137 from_page_table = (unsigned long *) (0xfffff000 & *from_dir);
138 if (!(to_page_table = (unsigned long *) get_free_page()))
139 return -1; /* Out of memory, see freeing */
// ������������Ŀ��Ŀ¼����Ϣ�������3λ��λ������ǰĿ��Ŀ¼�����7����ʾ��Ӧ
// ҳ��ӳ����ڴ�ҳ�����û����ģ����ҿɶ�д�����ڣ�Usr, R/W, Present���� �����U/S
// λ��0����R/W��û�����á���� U/S��1���� R/W��0����ô�������û���Ĵ����ֻ��
// ��ҳ�档���U/S��R/W����λ������ж�д��Ȩ�ޣ���Ȼ����Ե�ǰ������ҳĿ¼���Ӧ
// ��ҳ����������Ҫ���Ƶ�ҳ����������������ں˿ռ䣬����踴��ͷ160ҳ��Ӧ��ҳ����
// ��nr= 160������Ӧ�ڿ�ʼ640KB�����ڴ档������Ҫ����һ��ҳ���е�����1024��ҳ����
// ��nr= 1024������ӳ��4MB�����ڴ档
140 *to_dir = ((unsigned long) to_page_table) | 7;
141 nr = (from==0)?0xA0:1024;
// ��ʱ���ڵ�ǰҳ������ʼѭ������ָ����nr���ڴ�ҳ������ȡ��Դҳ�������ݣ����
// ��ǰԴҳ��û��ʹ�ã�������Ϊ0�������ø��Ƹñ������������һ�
142 for ( ; nr-- > 0 ; from_page_table++,to_page_table++) {
143 this_page = *from_page_table;
144 if (!this_page)
145 continue;
// ����ñ��������ݣ����������λP=0����ñ����Ӧ��ҳ������ڽ����豸�С���������
// ��1ҳ�ڴ棬���ӽ����豸�ж����ҳ�棨�������豸���еĻ�����Ȼ��ҳ����Ƶ�
// Ŀ��ҳ�����С�����Դҳ��������ָ�����������ڴ�ҳ�������ñ����־Ϊ��ҳ���ࡱ
// ����7��Ȼ�����������һҳ�������λҳ������ R/W ��־��λ1��0��������ҳ����
// ��Ӧ���ڴ�ҳ��ֻ����Ȼ��ҳ����Ƶ�Ŀ��ҳ���С�
146 if (!(1 & this_page)) {
147 if (!(new_page = get_free_page()))
148 return -1;
149 read_swap_page(this_page>>1, (char *) new_page);
150 *to_page_table = this_page;
151 *from_page_table = new_page | (PAGE_DIRTY | 7);
152 continue;
153 }
154 this_page &= ~2;
155 *to_page_table = this_page;
// �����ҳ������ָ����ҳ��ĵ�ַ��1MB���ϣ�����Ҫ�����ڴ�ҳ��ӳ������mem_map[]��
// ���Ǽ���ҳ��ţ�������Ϊ������ҳ��ӳ��������Ӧ�����������ô�����������λ��1MB
// ���µ�ҳ�棬˵�����ں�ҳ�棬��˲���Ҫ��mem_map[]�������á���Ϊ mem_map[]����
// �ڹ������ڴ����е�ҳ��ʹ������� ��˶����ں��ƶ�������0�в��ҵ���fork()����
// ����1ʱ����������init()�������ڴ�ʱ���Ƶ�ҳ�滹��Ȼ�����ں˴��������������
// �ж��е���䲻��ִ�У�����0 ��ҳ����Ȼ������ʱ��д��ֻ�е����� fork() �ĸ�����
// ���봦�����ڴ�����ҳ��λ�ô���1MB��ʱ�Ż�ִ�С����������Ҫ�ڽ��̵���execve()��
// ��װ��ִ�����³������ʱ�Ż���֡�
// 157����京������Դҳ������ָ�ڴ�ҳҲΪֻ������Ϊ���ڿ�ʼ�����������̹����ڴ�
// ���ˡ�������1��������Ҫ����д�����������ͨ��ҳ�쳣д��������Ϊִ��д�����Ľ�
// �̷���1ҳ�¿���ҳ�棬Ҳ������дʱ���ƣ�copy on write��������
156 if (this_page > LOW_MEM) {
157 *from_page_table = this_page; // ��Դҳ����Ҳֻ����
158 this_page -= LOW_MEM;
159 this_page >>= 12;
160 mem_map[this_page]++;
161 }
162 }
163 }
164 invalidate(); // ˢ��ҳ�任���ٻ��塣
165 return 0;
166 }
167
168 /*
169 * This function puts a page in memory at the wanted address.
170 * It returns the physical address of the page gotten, 0 if
171 * out of memory (either when trying to access page-table or
172 * page.)
173 */
/*
* ���溯����һ�ڴ�ҳ����ã�ӳ�䣩��ָ�����Ե�ַ����������ҳ��
* ��������ַ������ڴ治��(�ڷ���ҳ����ҳ��ʱ)����0��
*/
// ��һ�����ڴ�ҳ��ӳ�䵽���Ե�ַ�ռ�ָ������
// ����˵�ǰ����Ե�ַ�ռ���ָ����ַaddress����ҳ��ӳ�䵽���ڴ���ҳ��page�ϡ���Ҫ
// �����������ҳĿ¼���ҳ����������ָ��ҳ�����Ϣ�����ɹ�������ҳ���ַ�� ��
// ����ȱҳ�쳣��C����do_no_page() �л���ô˺���������ȱҳ������쳣�������κ�ȱ
// ҳԵ�ʶ���ҳ������ʱ��������Ҫˢ��CPU��ҳ�任���壨���Translation Lookaside
// Buffer - TLB������ʹҳ�����б�־P����0�ij�1����Ϊ��Чҳ��ᱻ���壬��˵�
// ����һ����Ч��ҳ����ʱ����Ҫˢ�¡��ڴ˾ͱ���Ϊ���õ���Invalidate()������
// ����page�Ƿ�������ڴ�����ijһҳ�棨ҳ֡��ҳ��ָ�룻address�����Ե�ַ��
174 static unsigned long put_page(unsigned long page,unsigned long address)
175 {
176 unsigned long tmp, *page_table;
177
178 /* NOTE !!! This uses the fact that _pg_dir=0 */
/* ע��!!! ����ʹ����ҳĿ¼������ַ_pg_dir=0������ */
179
// �����жϲ������������ڴ�ҳ��page ����Ч�ԡ������ҳ��λ�õ���LOW_MEM��1MB����
// ����ϵͳʵ�ʺ����ڴ�߶� HIGH_MEMORY�������档LOW_MEM �����ڴ��������е���
// С��ʼλ�á���ϵͳ�����ڴ�С�ڻ����6MBʱ�����ڴ�����ʼ��LOW_MEM�����ٲ鿴һ
// �¸� pageҳ���Ƿ����Ѿ������ҳ�棬���ж������ڴ�ҳ��ӳ���ֽ�ͼ mem_map[]����
// Ӧ�ֽ��Ƿ��Ѿ���λ����û�����跢�����档
180 if (page < LOW_MEM || page >= HIGH_MEMORY)
181 printk("Trying to put page %p at %p\n",page,address);
182 if (mem_map[(page-LOW_MEM)>>12] != 1)
183 printk("mem_map disagrees with %p at %p\n",page,address);
// Ȼ����ݲ���ָ�������Ե�ַaddress��������ҳĿ¼���ж�Ӧ��Ŀ¼��ָ�룬������ȡ��
// ����ҳ����ַ�� �����Ŀ¼����Ч��P=1������ָ����ҳ�����ڴ��У������ȡ��ָ��ҳ��
// ��ַ�ŵ�page_table �����С���������һ����ҳ���ҳ��ʹ�ã����ڶ�ӦĿ¼��������Ӧ
// ��־��7 �C User��U/S��R/W����Ȼ��ҳ����ַ�ŵ�page_table�����С�
184 page_table = (unsigned long *) ((address>>20) & 0xffc);
185 if ((*page_table)&1)
186 page_table = (unsigned long *) (0xfffff000 & *page_table);
187 else {
188 if (!(tmp=get_free_page()))
189 return 0;
190 *page_table = tmp | 7;
191 page_table = (unsigned long *) tmp;
192 }
// ������ҵ���ҳ�� page_table ���������ҳ�������ݣ���������ҳ��page�ĵ�ַ�����
// ��ͬʱ��λ3����־��U/S��W/R��P������ҳ������ҳ���е�����ֵ�������Ե�ַλ21 --
// λ12��ɵ�10���ص�ֵ��ÿ��ҳ��������1024�0 -- 0x3ff����
193 page_table[(address>>12) & 0x3ff] = page | 7;
194 /* no need for invalidate */
/* ����Ҫˢ��ҳ�任���ٻ��� */
195 return page; // ��������ҳ���ַ��
196 }
197
198 /*
199 * The previous function doesn't work very well if you also want to mark
200 * the page dirty: exec.c wants this, as it has earlier changed the page,
201 * and we want the dirty-status to be correct (for VM). Thus the same
202 * routine, but this time we mark it dirty too.
203 */
/*
* �����Ҳ������ҳ�����ı�־������һ�����������ò��Ǻܺã�exec.c����
* ��Ҫ�������á���Ϊexec.c�к������ڷ���ҳ��֮ǰ�Ĺ�ҳ�����ݡ�Ϊ��ʵ
* ��VM��������Ҫ����ȷ��������״̬��־����������������������ͬ�ĺ�
* �������Ǹú����ڷ���ҳ��ʱ���ҳ���־Ϊ����״̬��
*/
// ��һ�������Ĺ��������ڴ�ҳ��ӳ�䵽���Ե�ַ�ռ�ָ������
// �ú�������һ������put_page()������ȫһ�������˱�������223������ҳ��������ʱ��
// ͬʱ��������ҳ�����ı�־��λ6��PAGE_DIRTY����
204 unsigned long put_dirty_page(unsigned long page, unsigned long address)
205 {
206 unsigned long tmp, *page_table;
207
208 /* NOTE !!! This uses the fact that _pg_dir=0 */
209
210 if (page < LOW_MEM || page >= HIGH_MEMORY)
211 printk("Trying to put page %p at %p\n",page,address);
212 if (mem_map[(page-LOW_MEM)>>12] != 1)
213 printk("mem_map disagrees with %p at %p\n",page,address);
214 page_table = (unsigned long *) ((address>>20) & 0xffc);
215 if ((*page_table)&1)
216 page_table = (unsigned long *) (0xfffff000 & *page_table);
217 else {
218 if (!(tmp=get_free_page()))
219 return 0;
220 *page_table = tmp|7;
221 page_table = (unsigned long *) tmp;
222 }
223 page_table[(address>>12) & 0x3ff] = page | (PAGE_DIRTY | 7);
224 /* no need for invalidate */
225 return page;
226 }
227
//// ȡ��д����ҳ�溯��������ҳ�쳣�жϹ�����д�����쳣�Ĵ�����дʱ���ƣ���
// ���ں˴�������ʱ���½����븸���̱����óɹ�������������ڴ�ҳ�棬����������Щҳ��
// �������ó�ֻ��ҳ�档�����½��̻�ԭ������Ҫ���ڴ�ҳ��д����ʱ��CPU �ͻ�����
// ���������ҳ��д�����쳣������������������ں˾ͻ������ж�Ҫд��ҳ���Ƿ�����
// ��û�����ҳ�����óɿ�дȻ���˳�����ҳ���dz��ڹ���״̬������Ҫ��������һ��ҳ�沢
// ���Ʊ�дҳ�����ݣ��Թ�д���̵���ʹ�á�������ȡ����
// �������Ϊҳ����ָ�룬��������ַ��[ un_wp_page -- Un-Write Protect Page]
228 void un_wp_page(unsigned long * table_entry)
229 {
230 unsigned long old_page,new_page;
231
// ����ȡ����ָ����ҳ����������ҳ��λ�ã���ַ�����жϸ�ҳ���Ƿ��ǹ���ҳ�档���ԭ
// ҳ���ַ�����ڴ�Ͷ� LOW_MEM����ʾ�����ڴ����У�����������ҳ��ӳ���ֽ�ͼ������
// ֵΪ1����ʾҳ���������1�Σ�ҳ��û�б������������ڸ�ҳ���ҳ�������� R/W ��־
// ����д������ˢ��ҳ�任���ٻ��壬Ȼ�ء���������ڴ�ҳ���ʱֻ��һ������ʹ�ã�
// ���Ҳ����ں��еĽ��̣���ֱ�Ӱ����Ը�Ϊ��д���ɣ���������������һ����ҳ�档
232 old_page = 0xfffff000 & *table_entry; // ȡָ��ҳ����������ҳ���ַ��
233 if (old_page >= LOW_MEM && mem_map[MAP_NR(old_page)]==1) {
234 *table_entry |= 2;
235 invalidate();
236 return;
237 }
// �������Ҫ�����ڴ���������һҳ����ҳ���ִ��д�����Ľ��̵���ʹ�ã�ȡ��ҳ�湲����
// ���ԭҳ������ڴ�Ͷˣ�����ζ�� mem_map[] > 1��ҳ���ǹ����ģ�����ԭҳ���ҳ
// ��ӳ���ֽ�����ֵ�ݼ�1��Ȼ��ָ��ҳ�������ݸ���Ϊ��ҳ���ַ�����ÿɶ�д�ȱ�־
// ��U/S��R/W��P������ˢ��ҳ�任���ٻ���֮�����ԭҳ�����ݸ��Ƶ���ҳ�档
238 if (!(new_page=get_free_page()))
239 oom(); // Out of Memory���ڴ治��������
240 if (old_page >= LOW_MEM)
241 mem_map[MAP_NR(old_page)]--;
242 copy_page(old_page,new_page);
243 *table_entry = new_page | 7;
244 invalidate();
245 }
246
247 /*
248 * This routine handles present pages, when users try to write
249 * to a shared page. It is done by copying the page to a new address
250 * and decrementing the shared-page counter for the old page.
251 *
252 * If it's in code space we exit with a segment error.
253 */
/*
* ���û���ͼ��һ����ҳ����дʱ���ú��������Ѵ��ڵ��ڴ�ҳ�棨дʱ���ƣ���
* ����ͨ����ҳ�渴�Ƶ�һ���µ�ַ�ϲ��ҵݼ�ԭҳ��Ĺ�������ֵʵ�ֵġ�
*
* ������ڴ���ռ䣬���Ǿ���ʾ�γ�����Ϣ���˳���
*/
//// ִ��д����ҳ�洦����
// ��д����ҳ�洦����������ҳ�쳣�жϴ��������е��õ�C��������page.s�����б����á�
// ��������error_code �� address �ǽ�����дд����ҳ��ʱ�� CPU�����쳣���Զ����ɵġ�
// error_codeָ���������ͣ��μ����¿�ʼ���ġ��ڴ�ҳ������쳣��һ�ڣ�address�Dz���
// �쳣��ҳ�����Ե�ַ��д����ҳ��ʱ�踴��ҳ�棨дʱ���ƣ���
254 void do_wp_page(unsigned long error_code,unsigned long address)
255 {
// �����ж�CPU���ƼĴ���CR2����������ҳ���쳣�����Ե�ַ��ʲô��Χ�С����address
// С�� TASK_SIZE��0x4000000����64MB������ʾ�쳣ҳ��λ�����ں˻�����0������1����
// �����Ե�ַ��Χ�ڣ����Ƿ���������Ϣ���ں˷�Χ�ڴ汻д����������� (address�C��ǰ
// ���̴�����ʼ��ַ)����һ�����̵ij��ȣ�64MB������ʾaddress��ָ�����Ե�ַ��������
// �쳣�Ľ������Ե�ַ�ռ䷶Χ�ڣ����ڷ���������Ϣ���˳���
256 if (address < TASK_SIZE)
257 printk("\n\rBAD! KERNEL MEMORY WP-ERR!\n\r");
258 if (address - current->start_code > TASK_SIZE) {
259 printk("Bad things happen: page error in do_wp_page\n\r");
260 do_exit(SIGSEGV);
261 }
262 #if 0
263 /* we cannot do this yet: the estdio library writes to code space */
264 /* stupid, stupid. I really want the libc.a from GNU */
/* �������ڻ���������������Ϊestdio����ڴ���ռ�ִ��д���� */
/* ����̫���ˡ��������GNU�õ�libc.a�⡣*/
// ������Ե�ַλ�ڽ��̵Ĵ���ռ��У�����ִֹ�г�����Ϊ������ֻ���ġ�
265 if (CODE_SPACE(address))
266 do_exit(SIGSEGV);
267 #endif
// �������溯��un_wp_page()������ȡ��ҳ�汣������������ҪΪ�����ò�����������
// ���Ե�ַaddressָ��ҳ����ҳ���е�ҳ����ָ�룬����㷽���ǣ�
// �� ((address>>10) & 0xffc)������ָ�����Ե�ַ��ҳ������ҳ���е�ƫ�Ƶ�ַ����Ϊ
// �������Ե�ַ�ṹ��(address>>12) ����ҳ�����е���������ÿ��ռ4���ֽڣ���˳�
// 4��(address>>12)<<2 = (address>>10)&0xffc �Ϳɵõ�ҳ�����ڱ��е�ƫ�Ƶ�ַ��
// �����&0xffc�������Ƶ�ַ��Χ��һ��ҳ���ڡ� ����Ϊֻ�ƶ���10λ��������2λ
// �����Ե�ַ��12 λ�е����2λ��ҲӦ���ε��� ��������Ե�ַ��ҳ������ҳ����ƫ
// �Ƶ�ֱַ��һЩ�ı�ʾ������(((address>>12) & 0x3ff)<<2 )��
// �� (0xfffff000 & *((address>>20) &0xffc))������ȡĿ¼����ҳ���ĵ�ֵַ�����У�
// ((address>>20) &0xffc)����ȡ���Ե�ַ�е�Ŀ¼��������Ŀ¼���е�ƫ��λ�á���Ϊ
// address>>22 ��Ŀ¼������ֵ����ÿ��4���ֽڣ���˳���4�� (address>>22)<<2
// = (address>>20) ����ָ������Ŀ¼���е�ƫ�Ƶ�ַ�� &0xffc��������Ŀ¼������ֵ
// �����2λ����Ϊֻ�ƶ���20λ��������2λ��ҳ�����������ݣ�Ӧ�����ε�����
// *((address>>20) &0xffc) ����ȡָ��Ŀ¼���������ж�Ӧҳ����������ַ���������
// 0xffffff000�������ε�ҳĿ¼�������е�һЩ��־λ��Ŀ¼���12λ����ֱ�۱�ʾΪ
// (0xffffff000 & *((unsigned long *) (((address>>22) & 0x3ff)<<2)))��
// �� �ɢ���ҳ������ҳ����ƫ�Ƶ�ַ���� ����Ŀ¼���������ж�Ӧҳ����������ַ����
// �õ�ҳ�����ָ�루������ַ��������Թ�����ҳ����и��ơ�
268 un_wp_page((unsigned long *)
269 (((address>>10) & 0xffc) + (0xfffff000 &
270 *((unsigned long *) ((address>>20) &0xffc)))));
271
272 }
273
//// дҳ����֤��
// ��ҳ�治��д������ҳ�档��fork.c�е�34�б��ڴ���֤ͨ�ú���verify_area()���á�
// ����address��ָ��ҳ����4G�ռ��е����Ե�ַ��
274 void write_verify(unsigned long address)
275 {
276 unsigned long page;
277
// ����ȡָ�����Ե�ַ��Ӧ��ҳĿ¼�����Ŀ¼���еĴ���λ��P���ж�Ŀ¼���Ӧ��ҳ��
// �Ƿ���ڣ�����λP=1?�����������ڣ�P=0���ء�������������Ϊ���ڲ����ڵ�ҳ��û
// �й�����дʱ���ƿ��ԣ�����������Դ˲����ڵ�ҳ��ִ��д����ʱ��ϵͳ�ͻ���Ϊȱҳ��
// ����ȥִ��do_no_page()����Ϊ����ط�ʹ�� put_page()����ӳ��һ������ҳ�档
// ���ų����Ŀ¼����ȡҳ����ַ������ָ��ҳ����ҳ���е�ҳ����ƫ��ֵ���ö�Ӧ��ַ��ҳ
// ����ָ�롣�ڸñ����а����Ÿ������Ե�ַ��Ӧ������ҳ�档
278 if (!( (page = *((unsigned long *) ((address>>20) & 0xffc)) )&1))
279 return;
280 page &= 0xfffff000;
281 page += ((address>>10) & 0xffc);
// Ȼ���жϸ�ҳ�����е�λ1��R/W����λ0��P����־�������ҳ�治��д��R/W=0���Ҵ��ڣ�
// ��ô��ִ�й����������ҳ�������дʱ���ƣ�������ʲôҲ������ֱ���˳���
282 if ((3 & *(unsigned long *) page) == 1) /* non-writeable, present */
283 un_wp_page((unsigned long *) page);
284 return;
285 }
286
//// ȡ��һҳ�����ڴ�ҳ��ӳ�䵽ָ�����Ե�ַ����
// get_free_page()��������ȡ�������ڴ�����һҳ�����ڴ档�����������ǻ�ȡ��һҳ
// �����ڴ�ҳ�棬����һ������put_page()��������ҳ��ӳ�䵽ָ�������Ե�ַ����
// ����address��ָ��ҳ������Ե�ַ��
287 void get_empty_page(unsigned long address)
288 {
289 unsigned long tmp;
290
// ������ȡ��һ����ҳ�棬���߲��ܽ���ȡҳ����õ�ָ����ַ��������ʾ�ڴ治������Ϣ��
// 292����Ӣ��ע�͵ĺ����ǣ�free_page()�����IJ���tmp��0Ҳû�й�ϵ���ú��������
// �������������ء�
291 if (!(tmp=get_free_page()) || !put_page(tmp,address)) {
292 free_page(tmp); /* 0 is ok - ignored */
293 oom();
294 }
295 }
296
297 /*
298 * try_to_share() checks the page at address "address" in the task "p",
299 * to see if it exists, and if it is clean. If so, share it with the current
300 * task.
301 *
302 * NOTE! This assumes we have checked that p != current, and that they
303 * share the same executable or library.
304 */
/*
* try_to_share()������"p"�м��λ�ڵ�ַ"address"����ҳ�棬��ҳ���Ƿ���ڣ�
* �Ƿ�ɾ�������Ǹɾ��Ļ������뵱ǰ��������
*
* ע�⣡���������Ѽٶ�p !=��ǰ���������ǹ���ͬһ��ִ�г��������
*/
//// ���ԶԵ�ǰ����ָ����ַ����ҳ����й���������
// ��ǰ���������p��ͬһִ�д��룬Ҳ������Ϊ��ǰ��������p����ִ��fork����������
// ���̣�������ǵĴ�������һ�������δ�����ݶ�������������ô���ݶ�����ҲӦһ����
// ���� address �ǽ����е�����ַ�����ǵ�ǰ�������� p ���̹���ҳ�����ҳ���ַ��
// ����p�ǽ�������ҳ��Ľ��̡����p����address����ҳ����ڲ���û�б��Ĺ��Ļ���
// ���õ�ǰ������p���̹���֮��ͬʱ����Ҫ��ָ֤���ĵ�ַ���Ƿ��Ѿ�������ҳ�棬����
// ����������������أ�1 - ҳ�湲�������ɹ���0 - ʧ�ܡ�
305 static int try_to_share(unsigned long address, struct task_struct * p)
306 {
307 unsigned long from;
308 unsigned long to;
309 unsigned long from_page;
310 unsigned long to_page;
311 unsigned long phys_addr;
312
// ���ȷֱ����ָ������p�к͵�ǰ����������ַaddress��Ӧ��ҳĿ¼�Ϊ�˼��㷽��
// �����ָ������ַaddress����'��'ҳĿ¼��ţ����Խ��̿ռ䣨0 - 64MB�������ҳ
// Ŀ¼��š���'��'ҳĿ¼��ż��Ͻ���p ��CPU 4G���Կռ�����ʼ��ַ��Ӧ��ҳĿ¼�
// ���õ�����p�е�ַ address ��ҳ������Ӧ��4G ���Կռ��е�ʵ��ҳĿ¼��from_page��
// ��'��'ҳĿ¼��ż��ϵ�ǰ����CPU 4G ���Կռ�����ʼ��ַ��Ӧ��ҳĿ¼��������
// �õ���ǰ�����е�ַaddress��ҳ������Ӧ��4G���Կռ��е�ʵ��ҳĿ¼��to_page��
313 from_page = to_page = ((address>>20) & 0xffc);
314 from_page += ((p->start_code>>20) & 0xffc); // p����Ŀ¼�
315 to_page += ((current->start_code>>20) & 0xffc); // ��ǰ����Ŀ¼�
// �ڵõ�p���̺͵�ǰ����address��Ӧ��Ŀ¼�������ֱ�Խ���p�͵�ǰ���̽��д�����
// �������ȶ�p���̵ı�����в�����Ŀ����ȡ��p������ address��Ӧ�������ڴ�ҳ���ַ��
// ���Ҹ�����ҳ����ڣ����Ҹɾ���û�б��Ĺ������ࣩ��
// ��������ȡĿ¼�����ݡ������Ŀ¼����Ч��P=0������ʾĿ¼���Ӧ�Ķ���ҳ�������ڣ�
// ���Ƿ��ء�����ȡ��Ŀ¼���Ӧҳ����ַfrom���Ӷ����������ַaddress��Ӧ��ҳ����
// ָ�룬��ȡ����ҳ����������ʱ������phys_addr�С�
316 /* is there a page-directory at from? */
/* ��from���Ƿ����ҳĿ¼�*/
317 from = *(unsigned long *) from_page; // p����Ŀ¼�����ݡ�
318 if (!(from & 1))
319 return 0;
320 from &= 0xfffff000; // ҳ����ַ��
321 from_page = from + ((address>>10) & 0xffc); // ҳ����ָ�롣
322 phys_addr = *(unsigned long *) from_page; // ҳ�������ݡ�
// ���ſ���ҳ����ӳ�������ҳ���Ƿ���ڲ��Ҹɾ��� 0x41 ��Ӧҳ�����е�D��Dirty����
// P��Present����־�����ҳ�治�ɾ�����Ч�ء�Ȼ�����ǴӸñ�����ȡ������ҳ���ַ
// �ٱ�����phys_addr�С���������ټ��һ���������ҳ���ַ����Ч�ԣ�������Ӧ�ó���
// �������������ֵַ��Ҳ��Ӧ��С���ڴ�Ͷ�(1MB)��
323 /* is the page clean and present? */
/* ����ҳ��ɾ����Ҵ�����*/
324 if ((phys_addr & 0x41) != 0x01)
325 return 0;
326 phys_addr &= 0xfffff000; // ����ҳ���ַ��
327 if (phys_addr >= HIGH_MEMORY || phys_addr < LOW_MEM)
328 return 0;
// �������ȶԵ�ǰ���̵ı�����в�����Ŀ����ȡ�õ�ǰ������address��Ӧ��ҳ�����ַ��
// ���Ҹ�ҳ���û��ӳ������ҳ�棬����P=0��
// ����ȡ��ǰ����ҳĿ¼��������to�������Ŀ¼����Ч��P=0������Ŀ¼���Ӧ�Ķ���ҳ��
// �����ڣ�������һ����ҳ�������ҳ����������Ŀ¼��to_page���ݣ�����ָ����ڴ�ҳ�档
329 to = *(unsigned long *) to_page; // ��ǰ����Ŀ¼�����ݡ�
330 if (!(to & 1))
331 if (to = get_free_page())
332 *(unsigned long *) to_page = to | 7;
333 else
334 oom();
// ����ȡĿ¼���е�ҳ����ַ��to������ҳ��������ֵ<<2����ҳ�����ڱ���ƫ�Ƶ�ַ���õ�
// ҳ�����ַ��to_page����Ը�ҳ��������ʱ���Ǽ������Ӧ������ҳ���Ѿ����ڣ�
// ��ҳ����Ĵ���λP=1����˵��ԭ�������빲������p�ж�Ӧ������ҳ�棬�����������Լ�
// �Ѿ�ռ���ˣ�ӳ���У�����ҳ�档����˵���ں˳�����������
335 to &= 0xfffff000; // ҳ����ַ��
336 to_page = to + ((address>>10) & 0xffc); // ҳ�����ַ��
337 if (1 & *(unsigned long *) to_page)
338 panic("try_to_share: to_page already exists");
// ���ҵ��˽���p������ַaddress����Ӧ�ĸɾ����Ҵ��ڵ�����ҳ�棬����Ҳȷ���˵�ǰ
// ����������ַ address ����Ӧ�Ķ���ҳ�����ַ֮���������ڶ����ǽ��й���������
// �����ܼ��������ȶ�p���̵�ҳ��������ģ�������д������R/W=0��ֻ������־��
// Ȼ���õ�ǰ���̸��� p���̵����ҳ�����ʱ��ǰ��������ַ address ��ҳ�漴��
// ӳ�䵽p��������ַaddress��ҳ��ӳ�������ҳ���ϡ�
339 /* share them: write-protect */
/* �����ǽ��й���������д���� */
340 *(unsigned long *) from_page &= ~2;
341 *(unsigned long *) to_page = *(unsigned long *) from_page;
// ���ˢ��ҳ�任���ٻ��塣��������������ҳ���ҳ��ţ�������Ӧҳ��ӳ���ֽ���������
// �����õ���1�����1����ʾ���������ɹ���
342 invalidate();
343 phys_addr -= LOW_MEM;
344 phys_addr >>= 12; // ��ҳ��š�
345 mem_map[phys_addr]++;
346 return 1;
347 }
348
349 /*
350 * share_page() tries to find a process that could share a page with
351 * the current one. Address is the address of the wanted page relative
352 * to the current data space.
353 *
354 * We first check if it is at all feasible by checking executable->i_count.
355 * It should be >1 if there are other tasks sharing this inode.
356 */
/*
* share_page()��ͼ�ҵ�һ�����̣��������뵱ǰ���̹���ҳ�档����address��
* ��ǰ�������ݿռ�������������ijҳ���ַ��
*
* ��������ͨ�����executable->i_count����֤�Ƿ���С���������������ѹ���
* ��inode������Ӧ�ô���1��
*/
//// ����ҳ�洦����
// �ڷ���ȱҳ�쳣ʱ�����ȿ����ܷ�������ͬһ��ִ���ļ����������̽���ҳ�湲��������
// �ú��������ж�ϵͳ���Ƿ�����һ������Ҳ�����е�ǰ����һ����ִ���ļ������У�����
// ϵͳ��ǰ����������Ѱ���������������ҵ�������������ͳ������乲��ָ����ַ����
// ҳ�档��ϵͳ��û�������������������뵱ǰ������ͬ��ִ���ļ�����ô����ҳ�������
// ǰ�����������ڣ���˺��������˳����ж�ϵͳ���Ƿ�����һ������Ҳ��ִ��ͬһ��ִ��
// �ļ��ķ��������ý����������ݽṹ�е� executable �ֶΣ���library�ֶΣ������ֶ�
// ָ���������ִ�г���ʹ�õĿ��ļ������ڴ��е� i�ڵ㡣���ݸ� i�ڵ�����ô���
// i_count ���ǿ��Խ��������жϡ� ���ڵ��i_countֵ����1�������ϵͳ������������
// ��������ͬһ��ִ���ļ�������ļ��������ǿ����ٶ�����ṹ��������������Ƚ��Ƿ�
// ����ͬ�� executable�ֶΣ��� library�ֶΣ������ȷ�����������������ִͬ���ļ�
// �������
// ����inode�������й���ҳ�����ִ���ļ����ڴ�i�ڵ㡣address�ǽ����е�����ַ��
// ���ǵ�ǰ��������p���̹���ҳ�����ҳ���ַ������1 �C���������ɹ���0 - ʧ�ܡ�
357 static int share_page(struct m_inode * inode, unsigned long address)
358 {
359 struct task_struct ** p;
360
// ���ȼ��һ�²���ָ�����ڴ� i�ڵ����ü���ֵ��������ڴ� i�ڵ�����ü���ֵ����
// 1��executable->i_count =1������i�ڵ�ָ��գ���ʾ��ǰϵͳ��ֻ��1������������
// ��ִ���ļ������ṩ��i�ڵ���Ч������������ԣ�ֱ���˳�������
361 if (inode->i_count < 2 || !inode)
362 return 0;
// ��������������������������Ѱ���뵱ǰ���̿ɹ���ҳ��Ľ��̣���������ִͬ���ļ�
// ����һ�����̣������Զ�ָ����ַ��ҳ����й���������������ַaddressС�ڽ��̿�
// �ļ�������ַ�ռ����ʼ��ַLIBRARY_OFFSET�������������ҳ���ڽ���ִ���ļ���Ӧ
// ������ַ�ռ䷶Χ�ڣ����Ǽ��һ��ָ��i�ڵ��Ƿ�����̵�ִ���ļ�i�ڵ㣨������
// ��executable��ͬ��������ͬ�����Ѱ�ҡ�����������ַaddress���ڵ��ڽ��̿��ļ�
// ������ַ�ռ����ʼ��ַLIBRARY_OFFSET���������Ҫ������ҳ���ڽ���ʹ�õĿ��ļ�
// �У����Ǽ��ָ���ڵ� inode �Ƿ�����̵Ŀ��ļ� i�ڵ���ͬ��������ͬ�����Ѱ�ҡ�
// ����ҵ�ij������p����executable��library��ָ���Ľڵ�inode��ͬ�������ҳ��
// ��̽����try_to_share() ����ҳ�湲���������������ɹ�����������1������0��
// ��ʾ����ҳ�����ʧ�ܡ�
363 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
364 if (!*p) // �������������У������Ѱ�ҡ�
365 continue;
366 if (current == *p) // ������ǵ�ǰ����Ҳ����Ѱ�ҡ�
367 continue;
368 if (address < LIBRARY_OFFSET) {
369 if (inode != (*p)->executable) // ����ִ���ļ�i�ڵ㡣
370 continue;
371 } else {
372 if (inode != (*p)->library) // ����ʹ�ÿ��ļ�i�ڵ㡣
373 continue;
374 }
375 if (try_to_share(address,*p)) // ���Թ���ҳ�档
376 return 1;
377 }
378 return 0;
379 }
380
//// ִ��ȱҳ������
// ���ʲ�����ҳ��Ĵ���������ҳ�쳣�жϴ��������е��ô˺�������page.s�����б����á�
// ��������error_code �� address �ǽ����ڷ���ҳ��ʱ�� CPU��ȱҳ�����쳣���Զ����ɡ�
// error_codeָ���������ͣ��μ����¿�ʼ���ġ��ڴ�ҳ������쳣��һ�ڣ�address�Dz���
// �쳣��ҳ�����Ե�ַ��
// �ú������Ȳ鿴��ȱҳ�Ƿ��ڽ����豸�У����������������������Ѽ��ص���ͬ�ļ�
// ����ҳ�湲��������ֻ�����ڽ��̶�̬�����ڴ�ҳ���ֻ��ӳ��һҳ�����ڴ�ҳ���ɡ�����
// ���������ɹ�����ôֻ�ܴ���Ӧ�ļ��ж�����ȱ������ҳ�浽ָ�����Ե�ַ����
381 void do_no_page(unsigned long error_code,unsigned long address)
382 {
383 int nr[4];
384 unsigned long tmp;
385 unsigned long page;
386 int block,i;
387 struct m_inode * inode;
388
// �����ж�CPU���ƼĴ���CR2����������ҳ���쳣�����Ե�ַ��ʲô��Χ�С����address
// С�� TASK_SIZE��0x4000000����64MB������ʾ�쳣ҳ��λ�����ں˻�����0������1����
// �����Ե�ַ��Χ�ڣ����Ƿ���������Ϣ���ں˷�Χ�ڴ汻д����������� (address�C��ǰ
// ���̴�����ʼ��ַ)����һ�����̵ij��ȣ�64MB������ʾaddress��ָ�����Ե�ַ��������
// �쳣�Ľ������Ե�ַ�ռ䷶Χ�ڣ����ڷ���������Ϣ���˳���
389 if (address < TASK_SIZE)
390 printk("\n\rBAD!! KERNEL PAGE MISSING\n\r");
391 if (address - current->start_code > TASK_SIZE) {
392 printk("Bad things happen: nonexistent page error in do_no_page\n\r");
393 do_exit(SIGSEGV);
394 }
// Ȼ�����ָ�������Ե�ַaddress������Ӧ�Ķ���ҳ����ָ�룬�����ݸ�ҳ���������ж�
// address����ҳ���Ƿ��ڽ����豸�С����������ҳ�沢�˳�������������ȡָ�����Ե�ַ
// address��Ӧ��Ŀ¼�����ݡ������Ӧ�Ķ���ҳ�����ڣ���ȡ����Ŀ¼���ж���ҳ���ĵ�ַ��
// ����ҳ����ƫ��ֵ���õ����Ե�ַaddress��ҳ���Ӧ��ҳ�����ָ�룬�Ӷ����ҳ������
// �ݡ���ҳ�������ݲ�Ϊ0����ҳ�������λP=0����˵����ҳ����ָ��������ҳ��Ӧ���ڽ�
// ���豸�С����Ǵӽ����豸�е���ָ��ҳ����˳�������
395 page = *(unsigned long *) ((address >> 20) & 0xffc); // ȡĿ¼�����ݡ�
396 if (page & 1) {
397 page &= 0xfffff000; // ����ҳ����ַ��
398 page += (address >> 10) & 0xffc; // ҳ����ָ�롣
399 tmp = *(unsigned long *) page; // ҳ�������ݡ�
400 if (tmp && !(1 & tmp)) {
401 swap_in((unsigned long *) page); // �ӽ����豸��ҳ�档
402 return;
403 }
404 }
// ����ȡ���Կռ���ָ����ַaddress��ҳ���ַ�������ָ�����Ե�ַ�ڽ��̿ռ��������
// ���̻�ַ��ƫ�Ƴ���ֵtmp������Ӧ������ַ���Ӷ��������ȱҳҳ����ִ���ļ�ӳ����
// ���ڿ��ļ��еľ�����ʼ���ݿ�š�
405 address &= 0xfffff000; // address��ȱҳҳ���ַ��
406 tmp = address - current->start_code; // ȱҳҳ���Ӧ����ַ��
// ���ȱҳ��Ӧ������ַtmp���ڿ�ӳ���ļ��ڽ������ռ��е���ʼλ�ã�˵��ȱ�ٵ�ҳ
// ���ڿ�ӳ���ļ��С����Ǵӵ�ǰ�����������ݽṹ�п���ȡ�ÿ�ӳ���ļ���i�ڵ�library��
// ���������ȱҳ�ڿ��ļ��е���ʼ���ݿ��block�����ȱҳ��Ӧ������ַtmpС�ڽ���
// ��ִ��ӳ���ļ�������ַ�ռ��ĩ��λ�ã���˵��ȱ�ٵ�ҳ���ڽ���ִ���ļ�ӳ���У���
// �ǿ��Դӵ�ǰ�����������ݻ�����ȡ��ִ���ļ���i�ڵ��executable�����������ȱҳ
// ��ִ���ļ�ӳ���е���ʼ���ݿ��block��������ַtmp�Ȳ���ִ���ļ�ӳ��ĵ�ַ��Χ
// �ڣ�Ҳ���ڿ��ļ��ռ䷶Χ�ڣ���˵��ȱҳ�ǽ��̷��ʶ�̬������ڴ�ҳ���������£����
// û�ж�Ӧi�ڵ�����ݿ�ţ����ÿգ���
// ��Ϊ���豸�ϴ�ŵ�ִ���ļ�ӳ���1�������dz���ͷ�ṹ������ڶ�ȡ���ļ�ʱ��Ҫ����
// ��1�����ݡ�������Ҫ���ȼ���ȱҳ���ڵ����ݿ�š���Ϊÿ�����ݳ���ΪBLOCK_SIZE =
// 1KB�����һҳ�ڴ�ɴ��4�����ݿ顣��������ַtmp�������ݿ��С�ټ�1���ɵó�
// ȱ�ٵ�ҳ����ִ��ӳ���ļ��е���ʼ���block��
407 if (tmp >= LIBRARY_OFFSET ) {
408 inode = current->library; // ���ļ�i�ڵ��ȱҳ��ʼ��š�
409 block = 1 + (tmp-LIBRARY_OFFSET) / BLOCK_SIZE;
410 } else if (tmp < current->end_data) {
411 inode = current->executable; // ִ���ļ�i�ڵ��ȱҳ��ʼ��š�
412 block = 1 + tmp / BLOCK_SIZE;
413 } else {
414 inode = NULL; // �Ƕ�̬��������ݻ�ջ�ڴ�ҳ�档
415 block = 0;
416 }
// ���ǽ��̷����䶯̬�����ҳ���Ϊ�˴��ջ��Ϣ�������ȱҳ�쳣����ֱ������һҳ��
// ���ڴ�ҳ�沢ӳ�䵽���Ե�ַaddress�����ɡ�����˵����ȱҳ���ڽ���ִ���ļ������
// ����Χ�ڣ����Ǿͳ��Թ���ҳ����������ɹ����˳��������ɹ���ֻ������һҳ�����ڴ�
// ҳ��page��Ȼ����豸�϶�ȡִ���ļ��е���Ӧҳ�沢���ã�ӳ�䣩������ҳ������ַ
// tmp����
417 if (!inode) { // �Ƕ�̬����������ڴ�ҳ�档
418 get_empty_page(address);
419 return;
420 }
421 if (share_page(inode,tmp)) // ��������ַtmp��ҳ��Ĺ�����
422 return;
423 if (!(page = get_free_page())) // ����һҳ�����ڴ档
424 oom();
425 /* remember that 1 block is used for header */
/* ��ס��������ͷҪʹ��1�����ݿ� */
// ���������ź�ִ���ļ���i�ڵ㣬���ǾͿ��Դ�ӳ��λͼ���ҵ���Ӧ���豸�ж�Ӧ���豸
// ����ţ�������nr[]�����У�������bread_page()���ɰ���4��������뵽����ҳ��
// page�С�
426 for (i=0 ; i<4 ; block++,i++)
427 nr[i] = bmap(inode,block);
428 bread_page(page,inode->i_dev,nr);
// �ڶ��豸�������ʱ�����ܻ��������һ�����������ִ���ļ��еĶ�ȡҳ��λ�ÿ�����
// �ļ�β����1��ҳ��ij��ȡ���˾Ϳ��ܶ���һЩ���õ���Ϣ������IJ������ǰ��ⲿ�ֳ�
// ��ִ���ļ�end_data�Ժ�IJ��ֽ������㴦������Ȼ������ҳ����ĩ�˳���1ҳ��˵����
// �Ǵ�ִ���ļ�ӳ���ж�ȡ��ҳ�棬���Ǵӿ��ļ��ж�ȡ�ģ���˲���ִ�����������
429 i = tmp + 4096 - current->end_data; // �������ֽڳ���ֵ��
430 if (i>4095) // ��ĩ�˳���1ҳ�������㡣
431 i = 0;
432 tmp = page + 4096; // tmpָ��ҳ��ĩ�ˡ�
433 while (i-- > 0) { // ҳ��ĩ��i�ֽ����㡣
434 tmp--;
435 *(char *)tmp = 0;
436 }
// ��������ȱҳ�쳣��һҳ����ҳ��ӳ�䵽ָ�����Ե�ַaddress�����������ɹ��ͷ��ء�
// ������ͷ��ڴ�ҳ����ʾ�ڴ治����
437 if (put_page(page,address))
438 return;
439 free_page(page);
440 oom();
441 }
442
//// �����ڴ������ʼ����
// �ú�����1MB�����ڴ�������ҳ��Ϊ��λ���й���ǰ�ij�ʼ�����ù�����һ��ҳ�泤��Ϊ
// 4KB�ֽڡ��ú����� 1MB�������������ڴ滮�ֳ�һ����ҳ�棬��ʹ��һ��ҳ��ӳ���ֽ�
// ����mem_map[] ������������Щҳ�档���ھ���16MB�ڴ������Ļ����������鹲��3840
// �� ((16MB - 1MB)/4KB)�����ɹ���3840������ҳ�档ÿ��һ�������ڴ�ҳ�汻ռ��ʱ��
// �� mem_map[]�ж�Ӧ�ĵ��ֽ�ֵ��1�����ͷ�һ������ҳ�棬�ͰѶ�Ӧ�ֽ�ֵ��1�� ����
// ��ֵΪ 0�����ʾ��Ӧҳ����У� ���ֽ�ֵ���ڻ����1�����ʾ��Ӧҳ�汻ռ�û�
// ͬ������ռ�á�
// �ڸð汾�� Linux�ں��У�����ܹ��� 16MB�������ڴ棬����16MB���ڴ潫���ò��á�
// ���ھ���16MB�ڴ��PC��ϵͳ����û������������ RAMDISK������� start_memͨ��
// ��4MB��end_mem��16MB����˴�ʱ���ڴ�����Χ��4MB��16MB������3072������ҳ���
// �����䡣����Χ0 - 1MB�ڴ�ռ������ں�ϵͳ����ʵ�ں�ֻʹ��0 ��640Kb��ʣ�µIJ�
// �ֱ����ָ��ٻ�����豸�ڴ�ռ�ã���
// ����start_mem�ǿ�����ҳ���������ڴ�����ʼ��ַ����ȥ��RAMDISK��ռ�ڴ�ռ䣩��
// end_mem��ʵ�������ڴ�����ַ������ַ��Χstart_mem��end_mem�����ڴ�����
443 void mem_init(long start_mem, long end_mem)
444 {
445 int i;
446
// ���Ƚ�1MB��16MB��Χ�������ڴ�ҳ���Ӧ���ڴ�ӳ���ֽ���������Ϊ��ռ��״̬������
// ���ֽ�ֵȫ�����ó�USED��100����PAGING_PAGES������Ϊ(PAGING_MEMORY>>12)����1MB
// �������������ڴ��ҳ����ڴ�ҳ����(15MB/4KB = 3840)��
447 HIGH_MEMORY = end_mem; // �����ڴ���߶ˣ�16MB����
448 for (i=0 ; i<PAGING_PAGES ; i++)
449 mem_map[i] = USED;
// Ȼ��������ڴ�����ʼ�ڴ� start_mem ��ҳ���Ӧ�ڴ�ӳ���ֽ����������i�����ڴ���
// ҳ��������ʱ mem_map[] ����ĵ�i������Ӧ���ڴ����е�1��ҳ�档������ڴ�����
// ҳ���Ӧ�����������㣨��ʾ���У������ھ���16MB�����ڴ��ϵͳ��mem_map[] �ж�Ӧ
// 4Mb--16Mb���ڴ���������㡣
450 i = MAP_NR(start_mem); // ���ڴ�����ʼλ�ô�ҳ��š�
451 end_mem -= start_mem;
452 end_mem >>= 12; // ���ڴ����е���ҳ������
453 while (end_mem-->0)
454 mem_map[i++]=0; // ���ڴ���ҳ���Ӧ�ֽ�ֵ���㡣
455 }
456
// ��ʾϵͳ�ڴ���Ϣ��
// �����ڴ�ӳ���ֽ����� mem_map[] �е���Ϣ�Լ�ҳĿ¼��ҳ������ͳ��ϵͳ��ʹ�õ��ڴ�ҳ
// ���������ڴ������������ڴ�ҳ�������ú����� chr_drv/keyboard.S�����186�б����á�
// �������¡�Shift + Scroll Lock����ϼ�ʱ����ʾϵͳ�ڴ�ͳ����Ϣ��
457 void show_mem(void)
458 {
459 int i,j,k,free=0,total=0;
460 int shared=0;
461 unsigned long * pg_tbl;
462
// �����ڴ�ӳ���ֽ�����mem_map[]��ͳ��ϵͳ���ڴ���ҳ������total���Լ����п���ҳ��
// ��free�ͱ�������ҳ����shared������Щ��Ϣ��ʾ��
463 printk("Mem-info:\n\r");
464 for(i=0 ; i<PAGING_PAGES ; i++) {
465 if (mem_map[i] == USED) // 1MB�����ڴ�ϵͳռ�õ�ҳ�档
466 continue;
467 total++;
468 if (!mem_map[i])
469 free++; // ���ڴ�������ҳ��ͳ�ơ�
470 else
471 shared += mem_map[i]-1; // ������ҳ�������ֽ�ֵ>1����
472 }
473 printk("%d free pages of %d\n\r",free,total);
474 printk("%d pages shared\n\r",shared);
// ͳ�ƴ�������ҳ������ҳ������ҳĿ¼��ǰ4��ں˴���ʹ�ã�����Ϊͳ�Ʒ�Χ�����
// ɨ�账����ҳĿ¼��ӵ�5�ʼ��������ѭ����������ҳĿ¼���ǰ4���������Ӧ
// �Ķ���ҳ�����ڣ���ô��ͳ�ƶ���ҳ������ռ�õ��ڴ�ҳ�棨484�У���Ȼ��Ը�ҳ������
// ��ҳ�����Ӧҳ���������ͳ�ơ�
475 k = 0; // һ������ռ��ҳ��ͳ��ֵ��
476 for(i=4 ; i<1024 ;) {
477 if (1&pg_dir[i]) {
// �����ҳĿ¼���Ӧ����ҳ����ַ���ڻ�����������ڴ��ַHIGH_MEMORY����˵����Ŀ¼��
// �����⡣������ʾ��Ŀ¼����Ϣ������������һ��Ŀ¼���
478 if (pg_dir[i]>HIGH_MEMORY) { // Ŀ¼�����ݲ�������
479 printk("page directory[%d]: %08X\n\r",
480 i,pg_dir[i]);
481 continue; // continue֮ǰ�����i++��
482 }
// ���ҳĿ¼���Ӧ����ҳ���ġ���ַ������LOW_MEM����1MB�������һ������ռ�õ�����
// �ڴ�ҳͳ��ֵk��1����ϵͳռ�õ����������ڴ�ҳͳ��ֵfree��1��Ȼ��ȡ��Ӧҳ����ַ
// pg_tbl�����Ը�ҳ��������ҳ�������ͳ�ơ������ǰҳ������ָ����ҳ����ڲ��Ҹ�����
// ҳ�桰��ַ������LOW_MEM����ô�ͽ�ҳ�����Ӧҳ������ͳ��ֵ��
483 if (pg_dir[i]>LOW_MEM)
484 free++,k++; // ͳ��ҳ��ռ��ҳ�档
485 pg_tbl=(unsigned long *) (0xfffff000 & pg_dir[i]);
486 for(j=0 ; j<1024 ; j++)
487 if ((pg_tbl[j]&1) && pg_tbl[j]>LOW_MEM)
// ����������ҳ���ַ���ڻ�����������ڴ��ַHIGH_MEMORY����˵����ҳ�������������⣬
// ������ʾ��ҳ�������ݡ�����ҳ�����Ӧҳ������ͳ��ֵ����
488 if (pg_tbl[j]>HIGH_MEMORY)
489 printk("page_dir[%d][%d]: %08X\n\r",
490 i,j, pg_tbl[j]);
491 else
492 k++,free++; // ͳ��ҳ�����Ӧҳ�档
493 }
// ��ÿ���������Կռ䳤����64MB������һ������ռ��16��Ŀ¼��������ÿͳ����16��
// Ŀ¼��Ͱѽ��̵�����ṹռ�õ�ҳ��ͳ�ƽ���������ʱk=0���ʾ��ǰ��16��ҳĿ¼����
// Ӧ�Ľ�����ϵͳ�в����ڣ�û�д��������Ѿ���ֹ���� ����ʾ�˶�Ӧ���̺ź���ռ�õ�����
// �ڴ�ҳͳ��ֵk��k���㣬������ͳ����һ������ռ�õ��ڴ�ҳ������
494 i++;
495 if (!(i&15) && k) { // k !=0 ��ʾ��Ӧ���̴��ڡ�
496 k++,free++; /* one page/process for task_struct */
497 printk("Process %d: %d pages\n\r",(i>>4)-1,k);
498 k = 0;
499 }
500 }
// �����ʾϵͳ������ʹ�õ��ڴ�ҳ������ڴ������ܵ��ڴ�ҳ������
501 printk("Memory found: %d (%d)\n\r",free-shared,total);
502 }
503