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