pmap_dispatch.c revision 175067
1/*-
2 * Copyright (c) 2005 Peter Grehan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: head/sys/powerpc/powerpc/pmap_dispatch.c 175067 2008-01-03 07:34:34Z alc $");
30
31/*
32 * Dispatch MI pmap calls to the appropriate MMU implementation
33 * through a previously registered kernel object.
34 *
35 * Before pmap_bootstrap() can be called, a CPU module must have
36 * called pmap_mmu_install(). This may be called multiple times:
37 * the highest priority call will be installed as the default
38 * MMU handler when pmap_bootstrap() is called.
39 *
40 * It is required that kobj_machdep_init() be called before
41 * pmap_bootstrap() to allow the kobj subsystem to initialise. This
42 * in turn requires that mutex_init() has been called.
43 */
44
45#include <sys/param.h>
46#include <sys/kernel.h>
47#include <sys/lock.h>
48#include <sys/mutex.h>
49#include <sys/systm.h>
50
51#include <vm/vm.h>
52#include <vm/vm_page.h>
53
54#include <machine/mmuvar.h>
55
56#include "mmu_if.h"
57
58static mmu_def_t	*mmu_def_impl;
59static mmu_t		mmu_obj;
60static struct mmu_kobj	mmu_kernel_obj;
61static struct kobj_ops	mmu_kernel_kops;
62
63/*
64 * pmap globals
65 */
66struct pmap kernel_pmap_store;
67
68struct msgbuf *msgbufp;
69vm_offset_t    msgbuf_phys;
70
71vm_offset_t kernel_vm_end;
72vm_offset_t phys_avail[PHYS_AVAIL_SZ];
73vm_offset_t virtual_avail;
74vm_offset_t virtual_end;
75
76int pmap_bootstrapped;
77
78void
79pmap_change_wiring(pmap_t pmap, vm_offset_t va, boolean_t wired)
80{
81	MMU_CHANGE_WIRING(mmu_obj, pmap, va, wired);
82}
83
84void
85pmap_clear_modify(vm_page_t m)
86{
87	MMU_CLEAR_MODIFY(mmu_obj, m);
88}
89
90void
91pmap_clear_reference(vm_page_t m)
92{
93	MMU_CLEAR_REFERENCE(mmu_obj, m);
94}
95
96void
97pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr,
98    vm_size_t len, vm_offset_t src_addr)
99{
100	MMU_COPY(mmu_obj, dst_pmap, src_pmap, dst_addr, len, src_addr);
101}
102
103void
104pmap_copy_page(vm_page_t src, vm_page_t dst)
105{
106	MMU_COPY_PAGE(mmu_obj, src, dst);
107}
108
109void
110pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t p,
111    vm_prot_t prot, boolean_t wired)
112{
113	MMU_ENTER(mmu_obj, pmap, va, p, prot, wired);
114}
115
116void
117pmap_enter_object(pmap_t pmap, vm_offset_t start, vm_offset_t end,
118    vm_page_t m_start, vm_prot_t prot)
119{
120	MMU_ENTER_OBJECT(mmu_obj, pmap, start, end, m_start, prot);
121}
122
123void
124pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot)
125{
126	MMU_ENTER_QUICK(mmu_obj, pmap, va, m, prot);
127}
128
129vm_paddr_t
130pmap_extract(pmap_t pmap, vm_offset_t va)
131{
132	return (MMU_EXTRACT(mmu_obj, pmap, va));
133}
134
135vm_page_t
136pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
137{
138	return (MMU_EXTRACT_AND_HOLD(mmu_obj, pmap, va, prot));
139}
140
141void
142pmap_growkernel(vm_offset_t va)
143{
144	MMU_GROWKERNEL(mmu_obj, va);
145}
146
147void
148pmap_init(void)
149{
150	MMU_INIT(mmu_obj);
151}
152
153boolean_t
154pmap_is_modified(vm_page_t m)
155{
156	return (MMU_IS_MODIFIED(mmu_obj, m));
157}
158
159boolean_t
160pmap_is_prefaultable(pmap_t pmap, vm_offset_t va)
161{
162	return (MMU_IS_PREFAULTABLE(mmu_obj, pmap, va));
163}
164
165boolean_t
166pmap_ts_referenced(vm_page_t m)
167{
168	return (MMU_TS_REFERENCED(mmu_obj, m));
169}
170
171vm_offset_t
172pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end, int prot)
173{
174	return (MMU_MAP(mmu_obj, virt, start, end, prot));
175}
176
177void
178pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object,
179    vm_pindex_t pindex, vm_size_t size)
180{
181	MMU_OBJECT_INIT_PT(mmu_obj, pmap, addr, object, pindex, size);
182}
183
184boolean_t
185pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
186{
187	return (MMU_PAGE_EXISTS_QUICK(mmu_obj, pmap, m));
188}
189
190void
191pmap_page_init(vm_page_t m)
192{
193	MMU_PAGE_INIT(mmu_obj, m);
194}
195
196int
197pmap_page_wired_mappings(vm_page_t m)
198{
199
200	return (MMU_PAGE_WIRED_MAPPINGS(mmu_obj, m));
201}
202
203int
204pmap_pinit(pmap_t pmap)
205{
206	MMU_PINIT(mmu_obj, pmap);
207	return (1);
208}
209
210void
211pmap_pinit0(pmap_t pmap)
212{
213	MMU_PINIT0(mmu_obj, pmap);
214}
215
216void
217pmap_protect(pmap_t pmap, vm_offset_t start, vm_offset_t end, vm_prot_t prot)
218{
219	MMU_PROTECT(mmu_obj, pmap, start, end, prot);
220}
221
222void
223pmap_qenter(vm_offset_t start, vm_page_t *m, int count)
224{
225	MMU_QENTER(mmu_obj, start, m, count);
226}
227
228void
229pmap_qremove(vm_offset_t start, int count)
230{
231	MMU_QREMOVE(mmu_obj, start, count);
232}
233
234void
235pmap_release(pmap_t pmap)
236{
237	MMU_RELEASE(mmu_obj, pmap);
238}
239
240void
241pmap_remove(pmap_t pmap, vm_offset_t start, vm_offset_t end)
242{
243	MMU_REMOVE(mmu_obj, pmap, start, end);
244}
245
246void
247pmap_remove_all(vm_page_t m)
248{
249	MMU_REMOVE_ALL(mmu_obj, m);
250}
251
252void
253pmap_remove_pages(pmap_t pmap)
254{
255	MMU_REMOVE_PAGES(mmu_obj, pmap);
256}
257
258void
259pmap_remove_write(vm_page_t m)
260{
261	MMU_REMOVE_WRITE(mmu_obj, m);
262}
263
264void
265pmap_zero_page(vm_page_t m)
266{
267	MMU_ZERO_PAGE(mmu_obj, m);
268}
269
270void
271pmap_zero_page_area(vm_page_t m, int off, int size)
272{
273	MMU_ZERO_PAGE_AREA(mmu_obj, m, off, size);
274}
275
276void
277pmap_zero_page_idle(vm_page_t m)
278{
279	MMU_ZERO_PAGE_IDLE(mmu_obj, m);
280}
281
282int
283pmap_mincore(pmap_t pmap, vm_offset_t addr)
284{
285	return (MMU_MINCORE(mmu_obj, pmap, addr));
286}
287
288void
289pmap_activate(struct thread *td)
290{
291	MMU_ACTIVATE(mmu_obj, td);
292}
293
294void
295pmap_deactivate(struct thread *td)
296{
297	MMU_DEACTIVATE(mmu_obj, td);
298}
299
300vm_offset_t
301pmap_addr_hint(vm_object_t obj, vm_offset_t addr, vm_size_t size)
302{
303	return (MMU_ADDR_HINT(mmu_obj, obj, addr, size));
304}
305
306
307
308/*
309 * Routines used in machine-dependent code
310 */
311void
312pmap_bootstrap(vm_offset_t start, vm_offset_t end)
313{
314	mmu_obj = &mmu_kernel_obj;
315
316	/*
317	 * Take care of compiling the selected class, and
318	 * then statically initialise the MMU object
319	 */
320	kobj_class_compile_static(mmu_def_impl, &mmu_kernel_kops);
321	kobj_init((kobj_t)mmu_obj, mmu_def_impl);
322
323	MMU_BOOTSTRAP(mmu_obj, start, end);
324}
325
326void *
327pmap_mapdev(vm_offset_t pa, vm_size_t size)
328{
329	return (MMU_MAPDEV(mmu_obj, pa, size));
330}
331
332void
333pmap_unmapdev(vm_offset_t va, vm_size_t size)
334{
335	MMU_UNMAPDEV(mmu_obj, va, size);
336}
337
338vm_offset_t
339pmap_kextract(vm_offset_t va)
340{
341	return (MMU_KEXTRACT(mmu_obj, va));
342}
343
344void
345pmap_kenter(vm_offset_t va, vm_offset_t pa)
346{
347	MMU_KENTER(mmu_obj, va, pa);
348}
349
350boolean_t
351pmap_dev_direct_mapped(vm_offset_t pa, vm_size_t size)
352{
353	return (MMU_DEV_DIRECT_MAPPED(mmu_obj, pa, size));
354}
355
356boolean_t
357pmap_page_executable(vm_page_t pg)
358{
359	return (MMU_PAGE_EXECUTABLE(mmu_obj, pg));
360}
361
362/*
363 * MMU install routines. Highest priority wins, equal priority also
364 * overrides allowing last-set to win.
365 */
366SET_DECLARE(mmu_set, mmu_def_t);
367
368boolean_t
369pmap_mmu_install(char *name, int prio)
370{
371	mmu_def_t	**mmupp, *mmup;
372	static int	curr_prio = 0;
373
374	/*
375	 * Try and locate the MMU kobj corresponding to the name
376	 */
377	SET_FOREACH(mmupp, mmu_set) {
378		mmup = *mmupp;
379
380		if (mmup->name &&
381		    !strcmp(mmup->name, name) &&
382		    prio >= curr_prio) {
383			curr_prio = prio;
384			mmu_def_impl = mmup;
385			return (TRUE);
386		}
387	}
388
389	return (FALSE);
390}
391