|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: /* ! 27: * File: pmap.h ! 28: * ! 29: * Authors: Avadis Tevanian, Jr., Michael Wayne Young ! 30: * Date: 1985 ! 31: * ! 32: * Machine-dependent structures for the physical map module. ! 33: */ ! 34: ! 35: #ifndef _PMAP_MACHINE_ ! 36: #define _PMAP_MACHINE_ 1 ! 37: ! 38: #ifndef ASSEMBLER ! 39: ! 40: #include <kern/zalloc.h> ! 41: #include <kern/lock.h> ! 42: #include <mach/machine/vm_param.h> ! 43: #include <mach/vm_statistics.h> ! 44: #include <mach/kern_return.h> ! 45: ! 46: /* ! 47: * Define the generic in terms of the specific ! 48: */ ! 49: ! 50: #if i386 ! 51: #define INTEL_PGBYTES I386_PGBYTES ! 52: #define INTEL_PGSHIFT I386_PGSHIFT ! 53: #define intel_btop(x) i386_btop(x) ! 54: #define intel_ptob(x) i386_ptob(x) ! 55: #define intel_round_page(x) i386_round_page(x) ! 56: #define intel_trunc_page(x) i386_trunc_page(x) ! 57: #define trunc_intel_to_vm(x) trunc_i386_to_vm(x) ! 58: #define round_intel_to_vm(x) round_i386_to_vm(x) ! 59: #define vm_to_intel(x) vm_to_i386(x) ! 60: #endif i386 ! 61: #if i860 ! 62: #define INTEL_PGBYTES I860_PGBYTES ! 63: #define INTEL_PGSHIFT I860_PGSHIFT ! 64: #define intel_btop(x) i860_btop(x) ! 65: #define intel_ptob(x) i860_ptob(x) ! 66: #define intel_round_page(x) i860_round_page(x) ! 67: #define intel_trunc_page(x) i860_trunc_page(x) ! 68: #define trunc_intel_to_vm(x) trunc_i860_to_vm(x) ! 69: #define round_intel_to_vm(x) round_i860_to_vm(x) ! 70: #define vm_to_intel(x) vm_to_i860(x) ! 71: #endif i860 ! 72: ! 73: /* ! 74: * i386/i486/i860 Page Table Entry ! 75: */ ! 76: ! 77: typedef unsigned int pt_entry_t; ! 78: #define PT_ENTRY_NULL ((pt_entry_t *) 0) ! 79: ! 80: #endif ASSEMBLER ! 81: ! 82: #define INTEL_OFFMASK 0xfff /* offset within page */ ! 83: #define PDESHIFT 22 /* page descriptor shift */ ! 84: #define PDEMASK 0x3ff /* mask for page descriptor index */ ! 85: #define PTESHIFT 12 /* page table shift */ ! 86: #define PTEMASK 0x3ff /* mask for page table index */ ! 87: ! 88: /* ! 89: * Convert linear offset to page descriptor index ! 90: */ ! 91: #define lin2pdenum(a) (((a) >> PDESHIFT) & PDEMASK) ! 92: ! 93: /* ! 94: * Convert page descriptor index to linear address ! 95: */ ! 96: #define pdenum2lin(a) ((vm_offset_t)(a) << PDESHIFT) ! 97: ! 98: /* ! 99: * Convert linear offset to page table index ! 100: */ ! 101: #define ptenum(a) (((a) >> PTESHIFT) & PTEMASK) ! 102: ! 103: #define NPTES (intel_ptob(1)/sizeof(pt_entry_t)) ! 104: #define NPDES (intel_ptob(1)/sizeof(pt_entry_t)) ! 105: ! 106: /* ! 107: * Hardware pte bit definitions (to be used directly on the ptes ! 108: * without using the bit fields). ! 109: */ ! 110: ! 111: #if i860 ! 112: #define INTEL_PTE_valid 0x00000001 ! 113: #else ! 114: #define INTEL_PTE_VALID 0x00000001 ! 115: #endif ! 116: #define INTEL_PTE_WRITE 0x00000002 ! 117: #define INTEL_PTE_USER 0x00000004 ! 118: #define INTEL_PTE_WTHRU 0x00000008 ! 119: #define INTEL_PTE_NCACHE 0x00000010 ! 120: #define INTEL_PTE_REF 0x00000020 ! 121: #define INTEL_PTE_MOD 0x00000040 ! 122: #define INTEL_PTE_WIRED 0x00000200 ! 123: #define INTEL_PTE_PFN 0xfffff000 ! 124: ! 125: #if i860 ! 126: #if NOCACHE ! 127: #define INTEL_PTE_VALID (INTEL_PTE_valid \ ! 128: |INTEL_PTE_WTHRU \ ! 129: |INTEL_PTE_NCACHE \ ! 130: |INTEL_PTE_REF \ ! 131: |INTEL_PTE_MOD \ ! 132: ) ! 133: #else NOCACHE ! 134: #define INTEL_PTE_VALID (INTEL_PTE_valid \ ! 135: |INTEL_PTE_REF \ ! 136: |INTEL_PTE_MOD \ ! 137: ) ! 138: #endif NOCACHE ! 139: #endif i860 ! 140: ! 141: #define pa_to_pte(a) ((a) & INTEL_PTE_PFN) ! 142: #define pte_to_pa(p) ((p) & INTEL_PTE_PFN) ! 143: #define pte_increment_pa(p) ((p) += INTEL_OFFMASK+1) ! 144: ! 145: /* ! 146: * Convert page table entry to kernel virtual address ! 147: */ ! 148: #define ptetokv(a) (phystokv(pte_to_pa(a))) ! 149: ! 150: #ifndef ASSEMBLER ! 151: typedef volatile long cpu_set; /* set of CPUs - must be <= 32 */ ! 152: /* changed by other processors */ ! 153: ! 154: struct pmap { ! 155: pt_entry_t *dirbase; /* page directory pointer register */ ! 156: int ref_count; /* reference count */ ! 157: decl_simple_lock_data(,lock) ! 158: /* lock on map */ ! 159: struct pmap_statistics stats; /* map statistics */ ! 160: cpu_set cpus_using; /* bitmap of cpus using pmap */ ! 161: }; ! 162: ! 163: typedef struct pmap *pmap_t; ! 164: ! 165: #define PMAP_NULL ((pmap_t) 0) ! 166: ! 167: #if i860 ! 168: /*#define set_dirbase(dirbase) flush_and_ctxsw(dirbase)*//*akp*/ ! 169: #else ! 170: #define set_dirbase(dirbase) set_cr3(dirbase) ! 171: #endif ! 172: ! 173: #if NCPUS > 1 ! 174: /* ! 175: * List of cpus that are actively using mapped memory. Any ! 176: * pmap update operation must wait for all cpus in this list. ! 177: * Update operations must still be queued to cpus not in this ! 178: * list. ! 179: */ ! 180: cpu_set cpus_active; ! 181: ! 182: /* ! 183: * List of cpus that are idle, but still operating, and will want ! 184: * to see any kernel pmap updates when they become active. ! 185: */ ! 186: cpu_set cpus_idle; ! 187: ! 188: /* ! 189: * Quick test for pmap update requests. ! 190: */ ! 191: volatile ! 192: boolean_t cpu_update_needed[NCPUS]; ! 193: ! 194: /* ! 195: * External declarations for PMAP_ACTIVATE. ! 196: */ ! 197: ! 198: void process_pmap_updates(); ! 199: void pmap_update_interrupt(); ! 200: extern pmap_t kernel_pmap; ! 201: ! 202: #endif NCPUS > 1 ! 203: ! 204: /* ! 205: * Machine dependent routines that are used only for i386/i486/i860. ! 206: */ ! 207: ! 208: pt_entry_t *pmap_pte(pmap_t pmap, vm_offset_t addr); ! 209: ! 210: /* ! 211: * Macros for speed. ! 212: */ ! 213: ! 214: #if NCPUS > 1 ! 215: ! 216: /* ! 217: * For multiple CPUS, PMAP_ACTIVATE and PMAP_DEACTIVATE must manage ! 218: * fields to control TLB invalidation on other CPUS. ! 219: */ ! 220: ! 221: #define PMAP_ACTIVATE_KERNEL(my_cpu) { \ ! 222: \ ! 223: /* \ ! 224: * Let pmap updates proceed while we wait for this pmap. \ ! 225: */ \ ! 226: i_bit_clear((my_cpu), &cpus_active); \ ! 227: \ ! 228: /* \ ! 229: * Lock the pmap to put this cpu in its active set. \ ! 230: * Wait for updates here. \ ! 231: */ \ ! 232: simple_lock(&kernel_pmap->lock); \ ! 233: \ ! 234: /* \ ! 235: * Process invalidate requests for the kernel pmap. \ ! 236: */ \ ! 237: if (cpu_update_needed[(my_cpu)]) \ ! 238: process_pmap_updates(kernel_pmap); \ ! 239: \ ! 240: /* \ ! 241: * Mark that this cpu is using the pmap. \ ! 242: */ \ ! 243: i_bit_set((my_cpu), &kernel_pmap->cpus_using); \ ! 244: \ ! 245: /* \ ! 246: * Mark this cpu active - IPL will be lowered by \ ! 247: * load_context(). \ ! 248: */ \ ! 249: i_bit_set((my_cpu), &cpus_active); \ ! 250: \ ! 251: simple_unlock(&kernel_pmap->lock); \ ! 252: } ! 253: ! 254: #define PMAP_DEACTIVATE_KERNEL(my_cpu) { \ ! 255: /* \ ! 256: * Mark pmap no longer in use by this cpu even if \ ! 257: * pmap is locked against updates. \ ! 258: */ \ ! 259: i_bit_clear((my_cpu), &kernel_pmap->cpus_using); \ ! 260: } ! 261: ! 262: #define PMAP_ACTIVATE_USER(pmap, th, my_cpu) { \ ! 263: register pmap_t tpmap = (pmap); \ ! 264: \ ! 265: if (tpmap == kernel_pmap) { \ ! 266: /* \ ! 267: * If this is the kernel pmap, switch to its page tables. \ ! 268: */ \ ! 269: set_dirbase(kvtophys(tpmap->dirbase)); \ ! 270: } \ ! 271: else { \ ! 272: /* \ ! 273: * Let pmap updates proceed while we wait for this pmap. \ ! 274: */ \ ! 275: i_bit_clear((my_cpu), &cpus_active); \ ! 276: \ ! 277: /* \ ! 278: * Lock the pmap to put this cpu in its active set. \ ! 279: * Wait for updates here. \ ! 280: */ \ ! 281: simple_lock(&tpmap->lock); \ ! 282: \ ! 283: /* \ ! 284: * No need to invalidate the TLB - the entire user pmap \ ! 285: * will be invalidated by reloading dirbase. \ ! 286: */ \ ! 287: set_dirbase(kvtophys(tpmap->dirbase)); \ ! 288: \ ! 289: /* \ ! 290: * Mark that this cpu is using the pmap. \ ! 291: */ \ ! 292: i_bit_set((my_cpu), &tpmap->cpus_using); \ ! 293: \ ! 294: /* \ ! 295: * Mark this cpu active - IPL will be lowered by \ ! 296: * load_context(). \ ! 297: */ \ ! 298: i_bit_set((my_cpu), &cpus_active); \ ! 299: \ ! 300: simple_unlock(&tpmap->lock); \ ! 301: } \ ! 302: } ! 303: ! 304: #define PMAP_DEACTIVATE_USER(pmap, thread, my_cpu) { \ ! 305: register pmap_t tpmap = (pmap); \ ! 306: \ ! 307: /* \ ! 308: * Do nothing if this is the kernel pmap. \ ! 309: */ \ ! 310: if (tpmap != kernel_pmap) { \ ! 311: /* \ ! 312: * Mark pmap no longer in use by this cpu even if \ ! 313: * pmap is locked against updates. \ ! 314: */ \ ! 315: i_bit_clear((my_cpu), &(pmap)->cpus_using); \ ! 316: } \ ! 317: } ! 318: ! 319: #define MARK_CPU_IDLE(my_cpu) { \ ! 320: /* \ ! 321: * Mark this cpu idle, and remove it from the active set, \ ! 322: * since it is not actively using any pmap. Signal_cpus \ ! 323: * will notice that it is idle, and avoid signaling it, \ ! 324: * but will queue the update request for when the cpu \ ! 325: * becomes active. \ ! 326: */ \ ! 327: int s = splvm(); \ ! 328: i_bit_set((my_cpu), &cpus_idle); \ ! 329: i_bit_clear((my_cpu), &cpus_active); \ ! 330: splx(s); \ ! 331: } ! 332: ! 333: #define MARK_CPU_ACTIVE(my_cpu) { \ ! 334: \ ! 335: int s = splvm(); \ ! 336: /* \ ! 337: * If a kernel_pmap update was requested while this cpu \ ! 338: * was idle, process it as if we got the interrupt. \ ! 339: * Before doing so, remove this cpu from the idle set. \ ! 340: * Since we do not grab any pmap locks while we flush \ ! 341: * our TLB, another cpu may start an update operation \ ! 342: * before we finish. Removing this cpu from the idle \ ! 343: * set assures that we will receive another update \ ! 344: * interrupt if this happens. \ ! 345: */ \ ! 346: i_bit_clear((my_cpu), &cpus_idle); \ ! 347: \ ! 348: if (cpu_update_needed[(my_cpu)]) \ ! 349: pmap_update_interrupt(); \ ! 350: \ ! 351: /* \ ! 352: * Mark that this cpu is now active. \ ! 353: */ \ ! 354: i_bit_set((my_cpu), &cpus_active); \ ! 355: splx(s); \ ! 356: } ! 357: ! 358: #else NCPUS > 1 ! 359: ! 360: /* ! 361: * With only one CPU, we just have to indicate whether the pmap is ! 362: * in use. ! 363: */ ! 364: ! 365: #define PMAP_ACTIVATE_KERNEL(my_cpu) { \ ! 366: kernel_pmap->cpus_using = TRUE; \ ! 367: } ! 368: ! 369: #define PMAP_DEACTIVATE_KERNEL(my_cpu) { \ ! 370: kernel_pmap->cpus_using = FALSE; \ ! 371: } ! 372: ! 373: #define PMAP_ACTIVATE_USER(pmap, th, my_cpu) { \ ! 374: register pmap_t tpmap = (pmap); \ ! 375: \ ! 376: set_dirbase(kvtophys(tpmap->dirbase)); \ ! 377: if (tpmap != kernel_pmap) { \ ! 378: tpmap->cpus_using = TRUE; \ ! 379: } \ ! 380: } ! 381: ! 382: #define PMAP_DEACTIVATE_USER(pmap, thread, cpu) { \ ! 383: if ((pmap) != kernel_pmap) \ ! 384: (pmap)->cpus_using = FALSE; \ ! 385: } ! 386: ! 387: #endif NCPUS > 1 ! 388: ! 389: #define PMAP_CONTEXT(pmap, thread) ! 390: ! 391: #define pmap_kernel() (kernel_pmap) ! 392: #define pmap_resident_count(pmap) ((pmap)->stats.resident_count) ! 393: #define pmap_phys_address(frame) ((vm_offset_t) (intel_ptob(frame))) ! 394: #define pmap_phys_to_frame(phys) ((int) (intel_btop(phys))) ! 395: #define pmap_copy(dst_pmap,src_pmap,dst_addr,len,src_addr) ! 396: #define pmap_attribute(pmap,addr,size,attr,value) \ ! 397: (KERN_INVALID_ADDRESS) ! 398: ! 399: #endif ASSEMBLER ! 400: ! 401: #endif _PMAP_MACHINE_
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.