|
|
1.1 ! root 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: */ ! 11: ! 12: #include <string.h> ! 13: ! 14: #include <linux/mm.h> ! 15: #include <linux/sched.h> ! 16: #include <linux/head.h> ! 17: #include <linux/kernel.h> ! 18: ! 19: #define SWAP_BITS (4096<<3) ! 20: ! 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: ! 31: bitop(bit,"") ! 32: bitop(setbit,"s") ! 33: bitop(clrbit,"r") ! 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: */ ! 42: #define FIRST_VM_PAGE (TASK_SIZE>>12) ! 43: #define LAST_VM_PAGE (1024*1024) ! 44: #define VM_PAGES (LAST_VM_PAGE - FIRST_VM_PAGE) ! 45: ! 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: ! 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: ! 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: } ! 87: if (!(page = get_free_page())) ! 88: oom(); ! 89: read_swap_page(swap_nr, (char *) page); ! 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: ! 95: int try_to_swap_out(unsigned long * table_ptr) ! 96: { ! 97: unsigned long page; ! 98: unsigned long swap_nr; ! 99: ! 100: page = *table_ptr; ! 101: if (!(PAGE_PRESENT & page)) ! 102: return 0; ! 103: if (page - LOW_MEM > PAGING_MEMORY) ! 104: return 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; ! 111: *table_ptr = swap_nr<<1; ! 112: invalidate(); ! 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: */ ! 128: int swap_out(void) ! 129: { ! 130: static int dir_entry = FIRST_VM_PAGE>>10; ! 131: static int page_entry = -1; ! 132: int counter = VM_PAGES; ! 133: int pg_table; ! 134: ! 135: while (counter>0) { ! 136: pg_table = pg_dir[dir_entry]; ! 137: if (pg_table & 1) ! 138: break; ! 139: counter -= 1024; ! 140: dir_entry++; ! 141: if (dir_entry >= 1024) ! 142: dir_entry = FIRST_VM_PAGE>>10; ! 143: } ! 144: pg_table &= 0xfffff000; ! 145: while (counter-- > 0) { ! 146: page_entry++; ! 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: */ ! 172: unsigned long get_free_page(void) ! 173: { ! 174: register unsigned long __res asm("ax"); ! 175: ! 176: repeat: ! 177: __asm__("std ; repne ; scasb\n\t" ! 178: "jne 1f\n\t" ! 179: "movb $1,1(%%edi)\n\t" ! 180: "sall $12,%%ecx\n\t" ! 181: "addl %2,%%ecx\n\t" ! 182: "movl %%ecx,%%edx\n\t" ! 183: "movl $1024,%%ecx\n\t" ! 184: "leal 4092(%%edx),%%edi\n\t" ! 185: "rep ; stosl\n\t" ! 186: "movl %%edx,%%eax\n" ! 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: { ! 201: extern int *blk_size[]; ! 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: } ! 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: } ! 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: } ! 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); ! 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: } ! 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.