|
|
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.