����13-3 linux/mm/swap.c


  1 /*

  2  *  linux/mm/swap.c

  3  *

  4  *  (C) 1991  Linus Torvalds

  5  */

  6

  7 /*

  8  * This file should contain most things doing the swapping from/to disk.

  9  * Started 18.12.91

 10  */

    /*

     * ������Ӧ�ð������󲿷�ִ���ڴ潻���Ĵ��루���ڴ浽���̻�֮����

     * ��91��12��18�տ�ʼ���ơ�

     */

 11

 12 #include <string.h>       // �ַ���ͷ�ļ���������һЩ�й��ڴ���ַ���������Ƕ�뺯����

 13

 14 #include <linux/mm.h>     // �ڴ����ͷ�ļ�������ҳ�泤�ȣ���һЩ�ڴ��������ԭ�͡�

 15 #include <linux/sched.h>  // ���ȳ���ͷ�ļ�������������ṹtask_struct������0�����ݣ�

                              // ����һЩ�й��������������úͻ�ȡ��Ƕ��ʽ��ຯ������䡣

 16 #include <linux/head.h>   // headͷ�ļ��������˶��������ļ򵥽ṹ���ͼ���ѡ���������

 17 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�Ͷ��塣

 18

    // ÿ���ֽ�8λ�����1ҳ��4096�ֽڣ�����32768������λ����1������λ��Ӧ1ҳ�ڴ棬

    // �����ɹ���32768��ҳ�棬��Ӧ128MB�ڴ�������

 19 #define SWAP_BITS (4096<<3)

 20

    // ����λ�����ꡣͨ��������ͬ��"op"���ɶ����ָ������λ���в��ԡ����û�������ֲ�����

    // ����addr��ָ�����Ե�ַ��nr��ָ����ַ����ʼ�ı���λƫ��λ���ú�Ѹ�����ַaddr��

    // ��nr������λ��ֵ�����λ��־�����û�λ�ñ���λ�����ؽ�λ��־ֵ����ԭ����λֵ����

    // ��25���ϵ�һ��ָ����"op"�ַ��IJ�ͬ������γɲ�ͬ��ָ�

    // ��"op"= ""ʱ������ָ��bt �C ��Bit Test�����Բ���ԭֵ���ý�λλ��

    // ��"op"="s"ʱ������ָ��bts - ��Bit Test and Set�����ñ���λֵ����ԭֵ���ý�λλ��

    // ��"op"="r"ʱ������ָ��btr - ��Bit Test and Reset����λ����λֵ��ԭֵ���ý�λλ��

    // ���룺%0 �C ������ֵ)��%1 -λƫ��(nr)��%2 �C��ַ(addr)��%3 �C �Ӳ����Ĵ�����ֵ(0)��

    // ��Ƕ������ѻ���ַ��%2���ͱ���ƫ��ֵ��%1����ָ���ı���λֵ�ȱ��浽��λ��־CF�У�

    // Ȼ�����ã���λ���ñ���λ��ָ��adcl�Ǵ���λλ�ӣ����ڸ��ݽ�λλCF���ò�������%0����

    // ���CF = 1 �򷵻ؼĴ���ֵ = 1�����򷵻ؼĴ���ֵ = 0 ��

 21 #define bitop(name,op) \

 22 static inline int name(char * addr,unsigned int nr) \

 23 { \

 24 int __res; \

 25 __asm__ __volatile__("bt" op " %1,%2; adcl $0,%0" \

 26 :"=g" (__res) \

 27 :"r" (nr),"m" (*(addr)),"0" (0)); \

 28 return __res; \

 29 }

 30

    // ������ݲ�ͬ��op�ַ�����3����Ƕ������

 31 bitop(bit,"")                // ������Ƕ���� bit(char * addr, unsigned int nr)��

 32 bitop(setbit,"s")            // ������Ƕ���� setbit(char * addr, unsigned int nr)��

 33 bitop(clrbit,"r")            // ������Ƕ���� clrbit(char * addr, unsigned int nr)��

 34

 35 static char * swap_bitmap = NULL;

 36 int SWAP_DEV = 0;                            // �ں˳�ʼ��ʱ���õĽ����豸�š�

 37

 38 /*

 39  * We never page the pages in task[0] - kernel memory.

 40  * We page all other pages.

 41  */

    /*

     * ���ǴӲ���������0��task[0]����ҳ�� �C ���������ں�ҳ�档

     * ����ֻ������ҳ����н���������

     */

    // ��1�������ڴ�ҳ�档��������0ĩ�ˣ�64MB������ʼ�������ڴ�ҳ�档

 42 #define FIRST_VM_PAGE (TASK_SIZE>>12)              // = 64MB/4KB = 16384��

 43 #define LAST_VM_PAGE (1024*1024)                   // = 4GB/4KB  = 1048576��

 44 #define VM_PAGES (LAST_VM_PAGE - FIRST_VM_PAGE)    // = 1032192����0��ʼ�ƣ���

 45

    // ����1ҳ����ҳ�档

    // ɨ����������ӳ��λͼ������Ӧλͼ������λ0���⣩������ֵΪ1�ĵ�һ������λ�ţ�

    // ��Ŀǰ���еĽ���ҳ��š��������ɹ��򷵻ؽ���ҳ��ţ����򷵻�0��

 46 static int get_swap_page(void)

 47 {

 48         int nr;

 49

 50         if (!swap_bitmap)

 51                 return 0;

 52         for (nr = 1; nr < 32768 ; nr++)

 53                 if (clrbit(swap_bitmap,nr))

 54                         return nr;                // ����Ŀǰ���еĽ���ҳ��š�

 55         return 0;

 56 }

 57

    // �ͷŽ����豸��ָ���Ľ���ҳ�档

    // �ڽ���λͼ������ָ��ҳ��Ŷ�Ӧ�ı���λ����1������ԭ���ñ���λ�͵���1�����ʾ

    // �����豸��ԭ����ҳ���û�б�ռ�ã�����λͼ������������ʾ������Ϣ�����ء�

    // ����ָ������ҳ��š�

 58 void swap_free(int swap_nr)

 59 {

 60         if (!swap_nr)

 61                 return;

 62         if (swap_bitmap && swap_nr < SWAP_BITS)

 63                 if (!setbit(swap_bitmap,swap_nr))

 64                         return;

 65         printk("Swap-space bad (swap_free())\n\r");

 66         return;

 67 }

 68

    // ��ָ��ҳ�潻�����ڴ��С�

    // ��ָ��ҳ����Ķ�Ӧҳ��ӽ����豸�ж��뵽��������ڴ�ҳ���С��޸Ľ���λͼ�ж�Ӧ

    // ����λ����λ����ͬʱ�޸�ҳ�������ݣ�����ָ����ڴ�ҳ�棬��������Ӧ��־��

 69 void swap_in(unsigned long *table_ptr)

 70 {

 71         int swap_nr;

 72         unsigned long page;

 73

    // ���ȼ�齻��λͼ�Ͳ�����Ч�ԡ��������λͼ�����ڣ�����ָ��ҳ�����Ӧ��ҳ���Ѵ���

    // ���ڴ��У����߽���ҳ���Ϊ 0������ʾ������Ϣ���˳��������ѷŵ������豸��ȥ���ڴ�

    // ҳ�棬��Ӧҳ�����д�ŵ�Ӧ�ǽ���ҳ���*2����(swap_nr << 1)���μ�����Գ��Խ�����

    // ��try_to_swap_out()�е�111�е�˵����

 74         if (!swap_bitmap) {

 75                 printk("Trying to swap in without swap bit-map");

 76                 return;

 77         }

 78         if (1 & *table_ptr) {

 79                 printk("trying to swap in present page\n\r");

 80                 return;

 81         }

 82         swap_nr = *table_ptr >> 1;

 83         if (!swap_nr) {

 84                 printk("No swap page in swap_in\n\r");

 85                 return;

 86         }

    // Ȼ������һҳ�����ڴ沢�ӽ����豸�ж���ҳ���Ϊswap_nr��ҳ�档�ڰ�ҳ�潻������

    // �󣬾Ͱѽ���λͼ�ж�Ӧ����λ��λ�������ԭ��������λ�ģ�˵���˴����ٴδӽ�����

    // ���ж�����ͬ��ҳ�棬������ʾһ�¾�����Ϣ�������ҳ����ָ�������ҳ�棬������ҳ

    // �����޸ġ��û��ɶ�д�ʹ��ڱ�־��Dirty��U/S��R/W��P����

 87         if (!(page = get_free_page()))

 88                 oom();

 89         read_swap_page(swap_nr, (char *) page);  // ��include/linux/mm.h�ж��塣

 90         if (setbit(swap_bitmap,swap_nr))

 91                 printk("swapping in multiply from same page\n\r");

 92         *table_ptr = page | (PAGE_DIRTY | 7);

 93 }

 94

    // ���԰�ҳ�潻����ȥ��

    // ��ҳ��û�б��޸Ĺ����ñ����ڽ����豸�У���Ϊ��Ӧҳ�滹������ֱ�Ӵ���Ӧӳ���ļ�

    // �ж��롣���ǿ���ֱ���ͷŵ���Ӧ����ҳ�����¡����������һ������ҳ��ţ�Ȼ���ҳ��

    // ������ȥ����ʱ����ҳ���Ҫ�����ڶ�Ӧҳ�����У���������Ҫ����ҳ�������λP = 0��

    // ������ҳ����ָ�롣ҳ�潻�����ͷųɹ�����1�����򷵻�0��

 95 int try_to_swap_out(unsigned long * table_ptr)

 96 {

 97         unsigned long page;

 98         unsigned long swap_nr;

 99

    // �����жϲ�������Ч�ԡ�����Ҫ������ȥ���ڴ�ҳ�沢�����ڣ������Ч�����򼴿��˳���

    // ��ҳ����ָ��������ҳ���ַ���ڷ�ҳ�������ڴ�߶�PAGING_MEMORY��15MB����Ҳ�˳���

100         page = *table_ptr;

101         if (!(PAGE_PRESENT & page))

102                 return 0;

103         if (page - LOW_MEM > PAGING_MEMORY)

104                 return 0;

    // ���ڴ�ҳ���ѱ��޸Ĺ������Ǹ�ҳ���DZ������ģ���ôΪ���������Ч�ʣ�����ҳ�治��

    // ��������ȥ������ֱ���˳�����������0�����������һ����ҳ��ţ�������������ҳ��

    // ���У�Ȼ���ҳ�潻����ȥ���ͷŶ�Ӧ�����ڴ�ҳ�档

105         if (PAGE_DIRTY & page) {

106                 page &= 0xfffff000;                    // ȡ����ҳ���ַ��

107                 if (mem_map[MAP_NR(page)] != 1)

108                         return 0;

109                 if (!(swap_nr = get_swap_page()))      // ���뽻��ҳ��š�

110                         return 0;

    // ����Ҫ�������豸�е�ҳ�棬��Ӧҳ�����н���ŵ���(swap_nr << 1)�� ��2������1λ��

    // ��Ϊ�˿ճ�ԭ��ҳ����Ĵ���λ��P����ֻ�д���λP=0����ҳ�������ݲ�Ϊ0��ҳ��Ż�

    // �ڽ����豸�С� Intel�ֲ�����ȷָ������һ������Ĵ���λ P = 0ʱ����Чҳ�����

    // ��������λ��λ31��1���ɹ�����ʹ�á�����д����ҳ����write_swap_page(nr, buffer)

    // ������Ϊll_rw_page(WRITE,SWAP_DEV,(nr),(buffer))���μ�linux/mm.h �ļ���12�С�

111                 *table_ptr = swap_nr<<1;

112                 invalidate();                        // ˢ��CPUҳ�任���ٻ��塣

113                 write_swap_page(swap_nr, (char *) page);

114                 free_page(page);

115                 return 1;

116         }

    // �������ҳ��û���޸Ĺ�����ô�Ͳ��ý�����ȥ����ֱ���ͷż��ɡ�

117         *table_ptr = 0;

118         invalidate();

119         free_page(page);

120         return 1;

121 }

122

123 /*

124  * Ok, this has a rather intricate logic - the idea is to make good

125  * and fast machine code. If we didn't worry about that, things would

126  * be easier.

127  */

    /*

     * OK�������������һ���dz����ӵ��߼� �C ���ڲ����߼��Ժò����ٶȿ��

     * �����롣������Dz��Դ˲��ĵĻ�����ô������ܸ�����Щ��

     */

    // ���ڴ�ҳ��ŵ������豸�С�

    // �����Ե�ַ64MB��Ӧ��Ŀ¼�FIRST_VM_PAGE>>10����ʼ����������4GB���Կռ䣬����

    // ЧҳĿ¼����ҳ����ҳ����ָ���������ڴ�ҳ��ִ�н����������豸��ȥ�ij��ԡ�һ���ɹ�

    // �ػ���һ��ҳ�棬�ͷ���1�����򷵻�0���ú�������get_free_page()�б����á�

128 int swap_out(void)

129 {

130         static int dir_entry = FIRST_VM_PAGE>>10;   // ������1�ĵ�1��Ŀ¼��������

131         static int page_entry = -1;

132         int counter = VM_PAGES;

133         int pg_table;

134

    // ��������ҳĿ¼�������Ҷ���ҳ�����ڵ�ҳĿ¼��pg_table���ҵ����˳�ѭ�����������

    // ҳĿ¼������Ӧʣ�����ҳ������counter��Ȼ����������һҳĿ¼� ��ȫ��������

    // ��û���ҵ��ʺϵģ����ڵģ�ҳĿ¼������¼���������

135         while (counter>0) {

136                 pg_table = pg_dir[dir_entry];        // ҳĿ¼�����ݡ�

137                 if (pg_table & 1)

138                         break;

139                 counter -= 1024;                     // 1��ҳ����Ӧ1024��ҳ֡��

140                 dir_entry++;                         // ��һĿ¼�

141                 if (dir_entry >= 1024)

142                         dir_entry = FIRST_VM_PAGE>>10;

143         }

    // ��ȡ�õ�ǰĿ¼���ҳ��ָ�����Ը�ҳ���е����� 1024 ��ҳ�棬��һ���ý�������

    // try_to_swap_out()���Խ�����ȥ��һ��ij��ҳ��ɹ������������豸�оͷ���1��������

    // ��Ŀ¼�������ҳ�����ѳ���ʧ�ܣ�����ʾ�������ڴ����ꡱ�ľ��棬������0��

144         pg_table &= 0xfffff000;                      // ҳ��ָ�루��ַ����

145         while (counter-- > 0) {

146                 page_entry++;                        // ҳ������������ʼΪ-1����

    // ����Ѿ����Դ����굱ǰҳ�������û���ܹ��ɹ��ؽ�����һ��ҳ�棬����ʱҳ��������

    // ���ڵ���1024������ͬǰ���135 �C 143��ִ����ͬ�Ĵ�����ѡ��һ������ҳ�����ڵ�ҳ

    // Ŀ¼���ȡ����Ӧ����ҳ��ָ�롣

147                 if (page_entry >= 1024) {

148                         page_entry = 0;

149                 repeat:

150                         dir_entry++;

151                         if (dir_entry >= 1024)

152                                 dir_entry = FIRST_VM_PAGE>>10;

153                         pg_table = pg_dir[dir_entry];  // ҳĿ¼�����ݡ�

154                         if (!(pg_table&1))

155                                 if ((counter -= 1024) > 0)

156                                         goto repeat;

157                                 else

158                                         break;

159                         pg_table &= 0xfffff000;        // ҳ��ָ�롣

160                 }

161                 if (try_to_swap_out(page_entry + (unsigned long *) pg_table))

162                         return 1;

163         }

164         printk("Out of swap-memory\n\r");

165         return 0;

166 }

167

168 /*

169  * Get physical address of first (actually last :-) free page, and mark it

170  * used. If no free pages left, return 0.

171  */

    /*

     * ��ȡ�׸�(ʵ���������1��:-)����ҳ�棬�����Ϊ��ʹ�á����û�п���ҳ�棬

     * �ͷ���0��

     */

    //// �����ڴ���������1ҳ��������ҳ�档

    // ����Ѿ�û�п��������ڴ�ҳ�棬�����ִ�н���������Ȼ���ٴ�����ҳ�档

    // ���룺%1(ax=0) - 0��%2(LOW_MEM)�ڴ��ֽ�λͼ��������ʼλ�ã�%3(cx= PAGING_PAGES)��

    // %4(edi=mem_map+PAGING_PAGES-1)��

    // ���������%0��ax = ����ҳ����ʼ��ַ��������������ҳ���������ַ��

    // ����%4�Ĵ���ʵ��ָ��mem_map[]�ڴ��ֽ�λͼ�����һ���ֽڡ���������λͼĩ�˿�ʼ��

    // ǰɨ������ҳ���־��ҳ������ΪPAGING_PAGES��������ҳ����У��ڴ�λͼ�ֽ�Ϊ0����

    // ����ҳ���ַ��ע�⣡������ֻ��ָ�������ڴ�����һҳ��������ҳ�棬����û��ӳ�䵽ij

    // �����̵ĵ�ַ�ռ���ȥ������� put_page() ���������ڰ�ָ��ҳ��ӳ�䵽ij�����̵ĵ�ַ

    // �ռ��С���Ȼ�����ں�ʹ�ñ�����������Ҫ��ʹ�� put_page() ����ӳ�䣬��Ϊ�ں˴����

    // ���ݿռ䣨16MB���Ѿ��Եȵ�ӳ�䵽������ַ�ռ䡣

    // ��65�ж�����һ���ֲ��Ĵ����������ñ������������� eax�Ĵ����У��Ա��ڸ�Ч���ʺ�

    // ���������ֶ�������ķ�����Ҫ������Ƕ�������С���ϸ˵���μ�gcc�ֲᡰ��ָ���Ĵ�

    // ���еı�������

172 unsigned long get_free_page(void)

173 {

174 register unsigned long __res asm("ax");

175

    // �������ڴ�ӳ���ֽ�λͼ�в���ֵΪ0���ֽ��Ȼ��Ѷ�Ӧ�����ڴ�ҳ�����㡣����õ�

    // ��ҳ���ַ����ʵ�������ڴ�����������Ѱ�ҡ����û���ҵ�����ҳ����ȥ����ִ�н�����

    // ���������²��ҡ���󷵻ؿ�������ҳ���ַ��

176 repeat:

177 __asm__("std ; repne ; scasb\n\t"     // �÷���λ��al(0)���Ӧÿ��ҳ���(di)���ݱȽϣ�

178         "jne 1f\n\t"                  // ���û�е���0���ֽڣ�����ת����������0����

179         "movb $1,1(%%edi)\n\t"         // 1 =>[1+edi], ����Ӧҳ���ڴ�ӳ�����λ��1��

180         "sall $12,%%ecx\n\t"          // ҳ����*4K = ���ҳ����ʼ��ַ��

181         "addl %2,%%ecx\n\t"           // �ټ��ϵͶ��ڴ��ַ����ҳ��ʵ��������ʼ��ַ��

182         "movl %%ecx,%%edx\n\t"        // ��ҳ��ʵ����ʼ��ַ��edx�Ĵ�����

183         "movl $1024,%%ecx\n\t"        // �Ĵ���ecx�ü���ֵ1024��

184         "leal 4092(%%edx),%%edi\n\t"  // ��4092+edx��λ����edi����ҳ���ĩ�ˣ���

185         "rep ; stosl\n\t"             // ��edi��ָ�ڴ����㣨�����򣬼�����ҳ�����㣩��

186         "movl %%edx,%%eax\n"          // ��ҳ����ʼ��ַ��eax������ֵ����

187         "1:"

188         :"=a" (__res)

189         :"0" (0),"i" (LOW_MEM),"c" (PAGING_PAGES),

190         "D" (mem_map+PAGING_PAGES-1)

191         :"di","cx","dx");

192         if (__res >= HIGH_MEMORY)     // ҳ���ַ����ʵ���ڴ�����������Ѱ�ҡ�

193                 goto repeat;

194         if (!__res && swap_out())     // ��û�õ�����ҳ����ִ�н��������������²��ҡ�

195                 goto repeat;

196         return __res;                 // ���ؿ�������ҳ���ַ��

197 }

198

    // �ڴ潻����ʼ����

199 void init_swapping(void)

200 {

    // blk_size[]ָ��ָ�����豸�ŵĿ��豸�������顣�ÿ�������ÿһ���Ӧһ�����豸����

    // ӵ�е����ݿ�������1���С=1KB����

201         extern int *blk_size[];              // blk_drv/ll_rw_blk.c��49�С�

202         int swap_size,i,j;

203

    // ���û�ж��彻���豸�򷵻ء���������豸û�����ÿ������飬����ʾ��Ϣ�����ء�

204         if (!SWAP_DEV)

205                 return;

206         if (!blk_size[MAJOR(SWAP_DEV)]) {

207                 printk("Unable to get size of swap device\n\r");

208                 return;

209         }

    // ȡָ�������豸�ŵĽ��������ݿ�����swap_size����Ϊ0�򷵻أ����ܿ���С��100��

    // ����ʾ��Ϣ�������豸��̫С����Ȼ���˳���

210         swap_size = blk_size[MAJOR(SWAP_DEV)][MINOR(SWAP_DEV)];

211         if (!swap_size)

212                 return;

213         if (swap_size < 100) {

214                 printk("Swap device too small (%d blocks)\n\r",swap_size);

215                 return;

216         }

    // �������ݿ�����ת���ɶ�Ӧ�ɽ���ҳ����������ֵ���ܴ���SWAP_BITS���ܱ�ʾ��ҳ������

    // ������ҳ���������ô��� 32768��  Ȼ������һҳ�����ڴ�������Ž���ҳ��λӳ������

    // swap_bitmap������ÿ1���ش���1ҳ����ҳ�档

217         swap_size >>= 2;

218         if (swap_size > SWAP_BITS)

219                 swap_size = SWAP_BITS;

220         swap_bitmap = (char *) get_free_page();

221         if (!swap_bitmap) {

222                 printk("Unable to start swapping: out of memory :-)\n\r");

223                 return;

224         }

    // read_swap_page(nr, buffer)������Ϊll_rw_page(READ,SWAP_DEV,(nr),(buffer))��

    // �μ�linux/mm.h�ļ���11�С�����ѽ����豸�ϵ�ҳ��0����swap_bitmapҳ���С�

    // ��ҳ���ǽ���������ҳ�档���е�4086�ֽڿ�ʼ������10���ַ��Ľ����豸������

    // ������SWAP-SPACE������û���ҵ��������ַ�������˵������һ����Ч�Ľ����豸��

    // ������ʾ��Ϣ���ͷŸ����������ҳ�沢�˳����������������ַ����ֽ����㡣

225         read_swap_page(0,swap_bitmap);

226         if (strncmp("SWAP-SPACE",swap_bitmap+4086,10)) {

227                 printk("Unable to find swap-space signature\n\r");

228                 free_page((long) swap_bitmap);

229                 swap_bitmap = NULL;

230                 return;

231         }

232         memset(swap_bitmap+4086,0,10);

    // Ȼ�������Ľ���λӳ��ͼ��Ӧ��32768������λȫΪ0����λͼ������λ�ı���λ0��

    // ���ʾλͼ�����⣬������ʾ������Ϣ���ͷ�λͼռ�õ�ҳ�沢�˳�������Ϊ�˼ӿ���

    // �ٶȣ��������Ƚ���ѡ�鿴λͼ��λ0�����һ������ҳ���Ӧ�ı���λ����swap_size

    // ����ҳ���Ӧ�ı���λ���Լ����SWAP_BITS��32768������λ��

233         for (i = 0 ; i < SWAP_BITS ; i++) {

234                 if (i == 1)

235                         i = swap_size;

236                 if (bit(swap_bitmap,i)) {

237                         printk("Bad swap-space bit-map\n\r");

238                         free_page((long) swap_bitmap);

239                         swap_bitmap = NULL;

240                         return;

241                 }

242         }

    // Ȼ������ϸ�ؼ��λ1��λswap_size���б���λ�Ƿ�Ϊ0�����в���0�ı���λ���ڣ�

    // ���ʾλͼ�����⣬�����ͷ�λͼռ�õ�ҳ�沢�˳�������������ʾ�����豸��������

    // �Լ�����ҳ�����ͽ����ռ����ֽ�����

243         j = 0;

244         for (i = 1 ; i < swap_size ; i++)

245                 if (bit(swap_bitmap,i))

246                         j++;

247         if (!j) {

248                 free_page((long) swap_bitmap);

249                 swap_bitmap = NULL;

250                 return;

251         }

252         printk("Swap device ok: %d pages (%d bytes) swap-space\n\r",j,j*4096);

253 }

254