|
|
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: #include <oskit/x86/paging.h> ! 39: #define INTEL_PGBYTES I386_PGBYTES ! 40: #define INTEL_PTE_WIRED 0x00000200 ! 41: #define ptenum(a) lin2ptenum(a) ! 42: #define intel_btop(x) atop(x) ! 43: #define intel_ptob(x) ptoa(x) ! 44: ! 45: #ifndef ASSEMBLER ! 46: ! 47: #include <kern/zalloc.h> ! 48: #include <kern/lock.h> ! 49: #include <mach/machine/vm_param.h> ! 50: #include <mach/vm_statistics.h> ! 51: #include <mach/kern_return.h> ! 52: ! 53: #include <oskit/x86/base_vm.h> ! 54: #include <oskit/x86/proc_reg.h> ! 55: ! 56: /* ! 57: * Convert page table entry to kernel virtual address ! 58: */ ! 59: #define ptetokv(a) (phystokv(pte_to_pa(a))) ! 60: ! 61: typedef volatile long cpu_set; /* set of CPUs - must be <= 32 */ ! 62: /* changed by other processors */ ! 63: ! 64: struct pmap { ! 65: pt_entry_t *dirbase; /* page directory pointer register */ ! 66: int ref_count; /* reference count */ ! 67: decl_simple_lock_data(,lock) ! 68: /* lock on map */ ! 69: struct pmap_statistics stats; /* map statistics */ ! 70: cpu_set cpus_using; /* bitmap of cpus using pmap */ ! 71: }; ! 72: ! 73: typedef struct pmap *pmap_t; ! 74: ! 75: #define PMAP_NULL ((pmap_t) 0) ! 76: ! 77: #if i860 ! 78: /*#define set_dirbase(dirbase) flush_and_ctxsw(dirbase)*//*akp*/ ! 79: #else ! 80: #define set_dirbase(dirbase) set_cr3(dirbase) ! 81: #endif ! 82: ! 83: #if NCPUS > 1 ! 84: /* ! 85: * List of cpus that are actively using mapped memory. Any ! 86: * pmap update operation must wait for all cpus in this list. ! 87: * Update operations must still be queued to cpus not in this ! 88: * list. ! 89: */ ! 90: cpu_set cpus_active; ! 91: ! 92: /* ! 93: * List of cpus that are idle, but still operating, and will want ! 94: * to see any kernel pmap updates when they become active. ! 95: */ ! 96: cpu_set cpus_idle; ! 97: ! 98: /* ! 99: * Quick test for pmap update requests. ! 100: */ ! 101: volatile ! 102: boolean_t cpu_update_needed[NCPUS]; ! 103: ! 104: /* ! 105: * External declarations for PMAP_ACTIVATE. ! 106: */ ! 107: ! 108: void process_pmap_updates(); ! 109: void pmap_update_interrupt(); ! 110: extern pmap_t kernel_pmap; ! 111: ! 112: #endif /* NCPUS > 1 */ ! 113: ! 114: /* ! 115: * Machine dependent routines that are used only for i386/i486/i860. ! 116: */ ! 117: ! 118: pt_entry_t *pmap_pte(pmap_t pmap, vm_offset_t addr); ! 119: ! 120: /* ! 121: * Macros for speed. ! 122: */ ! 123: ! 124: #if NCPUS > 1 ! 125: ! 126: /* ! 127: * For multiple CPUS, PMAP_ACTIVATE and PMAP_DEACTIVATE must manage ! 128: * fields to control TLB invalidation on other CPUS. ! 129: */ ! 130: ! 131: #define PMAP_ACTIVATE_KERNEL(my_cpu) { \ ! 132: \ ! 133: /* \ ! 134: * Let pmap updates proceed while we wait for this pmap. \ ! 135: */ \ ! 136: i_bit_clear((my_cpu), &cpus_active); \ ! 137: \ ! 138: /* \ ! 139: * Lock the pmap to put this cpu in its active set. \ ! 140: * Wait for updates here. \ ! 141: */ \ ! 142: simple_lock(&kernel_pmap->lock); \ ! 143: \ ! 144: /* \ ! 145: * Process invalidate requests for the kernel pmap. \ ! 146: */ \ ! 147: if (cpu_update_needed[(my_cpu)]) \ ! 148: process_pmap_updates(kernel_pmap); \ ! 149: \ ! 150: /* \ ! 151: * Mark that this cpu is using the pmap. \ ! 152: */ \ ! 153: i_bit_set((my_cpu), &kernel_pmap->cpus_using); \ ! 154: \ ! 155: /* \ ! 156: * Mark this cpu active - IPL will be lowered by \ ! 157: * load_context(). \ ! 158: */ \ ! 159: i_bit_set((my_cpu), &cpus_active); \ ! 160: \ ! 161: simple_unlock(&kernel_pmap->lock); \ ! 162: } ! 163: ! 164: #define PMAP_DEACTIVATE_KERNEL(my_cpu) { \ ! 165: /* \ ! 166: * Mark pmap no longer in use by this cpu even if \ ! 167: * pmap is locked against updates. \ ! 168: */ \ ! 169: i_bit_clear((my_cpu), &kernel_pmap->cpus_using); \ ! 170: } ! 171: ! 172: #define PMAP_ACTIVATE_USER(pmap, th, my_cpu) { \ ! 173: register pmap_t tpmap = (pmap); \ ! 174: \ ! 175: if (tpmap == kernel_pmap) { \ ! 176: /* \ ! 177: * If this is the kernel pmap, switch to its page tables. \ ! 178: */ \ ! 179: set_dirbase(kvtophys(tpmap->dirbase)); \ ! 180: } \ ! 181: else { \ ! 182: /* \ ! 183: * Let pmap updates proceed while we wait for this pmap. \ ! 184: */ \ ! 185: i_bit_clear((my_cpu), &cpus_active); \ ! 186: \ ! 187: /* \ ! 188: * Lock the pmap to put this cpu in its active set. \ ! 189: * Wait for updates here. \ ! 190: */ \ ! 191: simple_lock(&tpmap->lock); \ ! 192: \ ! 193: /* \ ! 194: * No need to invalidate the TLB - the entire user pmap \ ! 195: * will be invalidated by reloading dirbase. \ ! 196: */ \ ! 197: set_dirbase(kvtophys(tpmap->dirbase)); \ ! 198: \ ! 199: /* \ ! 200: * Mark that this cpu is using the pmap. \ ! 201: */ \ ! 202: i_bit_set((my_cpu), &tpmap->cpus_using); \ ! 203: \ ! 204: /* \ ! 205: * Mark this cpu active - IPL will be lowered by \ ! 206: * load_context(). \ ! 207: */ \ ! 208: i_bit_set((my_cpu), &cpus_active); \ ! 209: \ ! 210: simple_unlock(&tpmap->lock); \ ! 211: } \ ! 212: } ! 213: ! 214: #define PMAP_DEACTIVATE_USER(pmap, thread, my_cpu) { \ ! 215: register pmap_t tpmap = (pmap); \ ! 216: \ ! 217: /* \ ! 218: * Do nothing if this is the kernel pmap. \ ! 219: */ \ ! 220: if (tpmap != kernel_pmap) { \ ! 221: /* \ ! 222: * Mark pmap no longer in use by this cpu even if \ ! 223: * pmap is locked against updates. \ ! 224: */ \ ! 225: i_bit_clear((my_cpu), &(pmap)->cpus_using); \ ! 226: } \ ! 227: } ! 228: ! 229: #define MARK_CPU_IDLE(my_cpu) { \ ! 230: /* \ ! 231: * Mark this cpu idle, and remove it from the active set, \ ! 232: * since it is not actively using any pmap. Signal_cpus \ ! 233: * will notice that it is idle, and avoid signaling it, \ ! 234: * but will queue the update request for when the cpu \ ! 235: * becomes active. \ ! 236: */ \ ! 237: int s = splvm(); \ ! 238: i_bit_set((my_cpu), &cpus_idle); \ ! 239: i_bit_clear((my_cpu), &cpus_active); \ ! 240: splx(s); \ ! 241: } ! 242: ! 243: #define MARK_CPU_ACTIVE(my_cpu) { \ ! 244: \ ! 245: int s = splvm(); \ ! 246: /* \ ! 247: * If a kernel_pmap update was requested while this cpu \ ! 248: * was idle, process it as if we got the interrupt. \ ! 249: * Before doing so, remove this cpu from the idle set. \ ! 250: * Since we do not grab any pmap locks while we flush \ ! 251: * our TLB, another cpu may start an update operation \ ! 252: * before we finish. Removing this cpu from the idle \ ! 253: * set assures that we will receive another update \ ! 254: * interrupt if this happens. \ ! 255: */ \ ! 256: i_bit_clear((my_cpu), &cpus_idle); \ ! 257: \ ! 258: if (cpu_update_needed[(my_cpu)]) \ ! 259: pmap_update_interrupt(); \ ! 260: \ ! 261: /* \ ! 262: * Mark that this cpu is now active. \ ! 263: */ \ ! 264: i_bit_set((my_cpu), &cpus_active); \ ! 265: splx(s); \ ! 266: } ! 267: ! 268: #else /* NCPUS > 1 */ ! 269: ! 270: /* ! 271: * With only one CPU, we just have to indicate whether the pmap is ! 272: * in use. ! 273: */ ! 274: ! 275: #define PMAP_ACTIVATE_KERNEL(my_cpu) { \ ! 276: kernel_pmap->cpus_using = TRUE; \ ! 277: } ! 278: ! 279: #define PMAP_DEACTIVATE_KERNEL(my_cpu) { \ ! 280: kernel_pmap->cpus_using = FALSE; \ ! 281: } ! 282: ! 283: #define PMAP_ACTIVATE_USER(pmap, th, my_cpu) { \ ! 284: register pmap_t tpmap = (pmap); \ ! 285: \ ! 286: set_dirbase(kvtophys(tpmap->dirbase)); \ ! 287: if (tpmap != kernel_pmap) { \ ! 288: tpmap->cpus_using = TRUE; \ ! 289: } \ ! 290: } ! 291: ! 292: #define PMAP_DEACTIVATE_USER(pmap, thread, cpu) { \ ! 293: if ((pmap) != kernel_pmap) \ ! 294: (pmap)->cpus_using = FALSE; \ ! 295: } ! 296: ! 297: #endif /* NCPUS > 1 */ ! 298: ! 299: #define PMAP_CONTEXT(pmap, thread) ! 300: ! 301: #define pmap_kernel() (kernel_pmap) ! 302: #define pmap_resident_count(pmap) ((pmap)->stats.resident_count) ! 303: #define pmap_phys_address(frame) ((vm_offset_t) (intel_ptob(frame))) ! 304: #define pmap_phys_to_frame(phys) ((int) (intel_btop(phys))) ! 305: #define pmap_copy(dst_pmap,src_pmap,dst_addr,len,src_addr) ! 306: #define pmap_attribute(pmap,addr,size,attr,value) \ ! 307: (KERN_INVALID_ADDRESS) ! 308: ! 309: #endif /* ASSEMBLER */ ! 310: ! 311: #endif /* _PMAP_MACHINE_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.