5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <sys/types.h>
28 #include <sys/systm.h>
29 #include <sys/archsystm.h>
30 #include <sys/debug.h>
31 #include <sys/bootconf.h>
32 #include <sys/bootsvcs.h>
33 #include <sys/bootinfo.h>
34 #include <sys/mman.h>
35 #include <sys/cmn_err.h>
36 #include <sys/param.h>
37 #include <sys/machparam.h>
38 #include <sys/machsystm.h>
39 #include <sys/promif.h>
40 #include <sys/kobj.h>
41 #ifdef __xpv
42 #include <sys/hypervisor.h>
43 #endif
44 #include <vm/kboot_mmu.h>
128 */
129 /*ARGSUSED*/
130 void *
131 kbm_remap_window(paddr_t physaddr, int writeable)
132 {
133 x86pte_t pt_bits = PT_NOCONSIST | PT_VALID | PT_WRITABLE;
134
135 DBG(physaddr);
136
137 #ifdef __xpv
138 if (!writeable)
139 pt_bits &= ~PT_WRITABLE;
140 if (HYPERVISOR_update_va_mapping((uintptr_t)window,
141 pa_to_ma(physaddr) | pt_bits, UVMF_INVLPG | UVMF_LOCAL) < 0)
142 bop_panic("HYPERVISOR_update_va_mapping() failed");
143 #else
144 if (kbm_pae_support)
145 *((x86pte_t *)pte_to_window) = physaddr | pt_bits;
146 else
147 *((x86pte32_t *)pte_to_window) = physaddr | pt_bits;
148 mmu_tlbflush_entry(window);
149 #endif
150 DBG(window);
151 return (window);
152 }
153
154 /*
155 * Add a mapping for the physical page at the given virtual address.
156 */
157 void
158 kbm_map(uintptr_t va, paddr_t pa, uint_t level, uint_t is_kernel)
159 {
160 x86pte_t *ptep;
161 paddr_t pte_physaddr;
162 x86pte_t pteval;
163
164 if (khat_running)
165 panic("kbm_map() called too late");
166
167 pteval = pa_to_ma(pa) | PT_NOCONSIST | PT_VALID | PT_WRITABLE;
168 if (level >= 1)
178 UVMF_INVLPG | UVMF_LOCAL) == 0)
179 return;
180 #endif
181
182 /*
183 * Find the pte that will map this address. This creates any
184 * missing intermediate level page tables.
185 */
186 ptep = find_pte(va, &pte_physaddr, level, 0);
187 if (ptep == NULL)
188 bop_panic("kbm_map: find_pte returned NULL");
189
190 #ifdef __xpv
191 if (HYPERVISOR_update_va_mapping(va, pteval, UVMF_INVLPG | UVMF_LOCAL))
192 bop_panic("HYPERVISOR_update_va_mapping() failed");
193 #else
194 if (kbm_pae_support)
195 *ptep = pteval;
196 else
197 *((x86pte32_t *)ptep) = pteval;
198 mmu_tlbflush_entry((caddr_t)va);
199 #endif
200 }
201
202 #ifdef __xpv
203
204 /*
205 * Add a mapping for the machine page at the given virtual address.
206 */
207 void
208 kbm_map_ma(maddr_t ma, uintptr_t va, uint_t level)
209 {
210 paddr_t pte_physaddr;
211 x86pte_t pteval;
212
213 pteval = ma | PT_NOCONSIST | PT_VALID | PT_REF | PT_WRITABLE;
214 if (level == 1)
215 pteval |= PT_PAGESIZE;
216
217 /*
218 * try update_va_mapping first - fails if page table is missing.
332 {
333 if (khat_running)
334 panic("kbm_unmap() called too late");
335 else {
336 #ifdef __xpv
337 (void) HYPERVISOR_update_va_mapping(va, 0,
338 UVMF_INVLPG | UVMF_LOCAL);
339 #else
340 x86pte_t *ptep;
341 level_t level = 0;
342 uint_t probe_only = 1;
343
344 ptep = find_pte(va, NULL, level, probe_only);
345 if (ptep == NULL)
346 return;
347
348 if (kbm_pae_support)
349 *ptep = 0;
350 else
351 *((x86pte32_t *)ptep) = 0;
352 mmu_tlbflush_entry((caddr_t)va);
353 #endif
354 }
355 }
356
357
358 /*
359 * Change a boot loader page table 4K mapping.
360 * Returns the pfn of the old mapping.
361 */
362 pfn_t
363 kbm_remap(uintptr_t va, pfn_t pfn)
364 {
365 x86pte_t *ptep;
366 level_t level = 0;
367 uint_t probe_only = 1;
368 x86pte_t pte_val = pa_to_ma(pfn_to_pa(pfn)) | PT_WRITABLE |
369 PT_NOCONSIST | PT_VALID;
370 x86pte_t old_pte;
371
372 if (khat_running)
373 panic("kbm_remap() called too late");
374 ptep = find_pte(va, NULL, level, probe_only);
375 if (ptep == NULL)
376 bop_panic("kbm_remap: find_pte returned NULL");
377
378 if (kbm_pae_support)
379 old_pte = *ptep;
380 else
381 old_pte = *((x86pte32_t *)ptep);
382
383 #ifdef __xpv
384 if (HYPERVISOR_update_va_mapping(va, pte_val, UVMF_INVLPG | UVMF_LOCAL))
385 bop_panic("HYPERVISOR_update_va_mapping() failed");
386 #else
387 if (kbm_pae_support)
388 *((x86pte_t *)ptep) = pte_val;
389 else
390 *((x86pte32_t *)ptep) = pte_val;
391 mmu_tlbflush_entry((caddr_t)va);
392 #endif
393
394 if (!(old_pte & PT_VALID) || ma_to_pa(old_pte) == -1)
395 return (PFN_INVALID);
396 return (mmu_btop(ma_to_pa(old_pte)));
397 }
398
399
400 /*
401 * Change a boot loader page table 4K mapping to read only.
402 */
403 void
404 kbm_read_only(uintptr_t va, paddr_t pa)
405 {
406 x86pte_t pte_val = pa_to_ma(pa) |
407 PT_NOCONSIST | PT_REF | PT_MOD | PT_VALID;
408
409 #ifdef __xpv
410 if (HYPERVISOR_update_va_mapping(va, pte_val, UVMF_INVLPG | UVMF_LOCAL))
411 bop_panic("HYPERVISOR_update_va_mapping() failed");
412 #else
413 x86pte_t *ptep;
414 level_t level = 0;
415
416 ptep = find_pte(va, NULL, level, 0);
417 if (ptep == NULL)
418 bop_panic("kbm_read_only: find_pte returned NULL");
419
420 if (kbm_pae_support)
421 *ptep = pte_val;
422 else
423 *((x86pte32_t *)ptep) = pte_val;
424 mmu_tlbflush_entry((caddr_t)va);
425 #endif
426 }
427
428 /*
429 * interfaces for kernel debugger to access physical memory
430 */
431 static x86pte_t save_pte;
432
433 void *
434 kbm_push(paddr_t pa)
435 {
436 static int first_time = 1;
437
438 if (first_time) {
439 first_time = 0;
440 return (window);
441 }
442
443 if (kbm_pae_support)
444 save_pte = *((x86pte_t *)pte_to_window);
445 else
446 save_pte = *((x86pte32_t *)pte_to_window);
447 return (kbm_remap_window(pa, 0));
448 }
449
450 void
451 kbm_pop(void)
452 {
453 #ifdef __xpv
454 if (HYPERVISOR_update_va_mapping((uintptr_t)window, save_pte,
455 UVMF_INVLPG | UVMF_LOCAL) < 0)
456 bop_panic("HYPERVISOR_update_va_mapping() failed");
457 #else
458 if (kbm_pae_support)
459 *((x86pte_t *)pte_to_window) = save_pte;
460 else
461 *((x86pte32_t *)pte_to_window) = save_pte;
462 mmu_tlbflush_entry(window);
463 #endif
464 }
465
466 x86pte_t
467 get_pteval(paddr_t table, uint_t index)
468 {
469 void *table_ptr = kbm_remap_window(table, 0);
470
471 if (kbm_pae_support)
472 return (((x86pte_t *)table_ptr)[index]);
473 return (((x86pte32_t *)table_ptr)[index]);
474 }
475
476 #ifndef __xpv
477 void
478 set_pteval(paddr_t table, uint_t index, uint_t level, x86pte_t pteval)
479 {
480 void *table_ptr = kbm_remap_window(table, 0);
481 if (kbm_pae_support)
482 ((x86pte_t *)table_ptr)[index] = pteval;
|
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 *
26 * Copyright 2018 Joyent, Inc.
27 */
28
29 #include <sys/types.h>
30 #include <sys/systm.h>
31 #include <sys/archsystm.h>
32 #include <sys/debug.h>
33 #include <sys/bootconf.h>
34 #include <sys/bootsvcs.h>
35 #include <sys/bootinfo.h>
36 #include <sys/mman.h>
37 #include <sys/cmn_err.h>
38 #include <sys/param.h>
39 #include <sys/machparam.h>
40 #include <sys/machsystm.h>
41 #include <sys/promif.h>
42 #include <sys/kobj.h>
43 #ifdef __xpv
44 #include <sys/hypervisor.h>
45 #endif
46 #include <vm/kboot_mmu.h>
130 */
131 /*ARGSUSED*/
132 void *
133 kbm_remap_window(paddr_t physaddr, int writeable)
134 {
135 x86pte_t pt_bits = PT_NOCONSIST | PT_VALID | PT_WRITABLE;
136
137 DBG(physaddr);
138
139 #ifdef __xpv
140 if (!writeable)
141 pt_bits &= ~PT_WRITABLE;
142 if (HYPERVISOR_update_va_mapping((uintptr_t)window,
143 pa_to_ma(physaddr) | pt_bits, UVMF_INVLPG | UVMF_LOCAL) < 0)
144 bop_panic("HYPERVISOR_update_va_mapping() failed");
145 #else
146 if (kbm_pae_support)
147 *((x86pte_t *)pte_to_window) = physaddr | pt_bits;
148 else
149 *((x86pte32_t *)pte_to_window) = physaddr | pt_bits;
150 mmu_invlpg(window);
151 #endif
152 DBG(window);
153 return (window);
154 }
155
156 /*
157 * Add a mapping for the physical page at the given virtual address.
158 */
159 void
160 kbm_map(uintptr_t va, paddr_t pa, uint_t level, uint_t is_kernel)
161 {
162 x86pte_t *ptep;
163 paddr_t pte_physaddr;
164 x86pte_t pteval;
165
166 if (khat_running)
167 panic("kbm_map() called too late");
168
169 pteval = pa_to_ma(pa) | PT_NOCONSIST | PT_VALID | PT_WRITABLE;
170 if (level >= 1)
180 UVMF_INVLPG | UVMF_LOCAL) == 0)
181 return;
182 #endif
183
184 /*
185 * Find the pte that will map this address. This creates any
186 * missing intermediate level page tables.
187 */
188 ptep = find_pte(va, &pte_physaddr, level, 0);
189 if (ptep == NULL)
190 bop_panic("kbm_map: find_pte returned NULL");
191
192 #ifdef __xpv
193 if (HYPERVISOR_update_va_mapping(va, pteval, UVMF_INVLPG | UVMF_LOCAL))
194 bop_panic("HYPERVISOR_update_va_mapping() failed");
195 #else
196 if (kbm_pae_support)
197 *ptep = pteval;
198 else
199 *((x86pte32_t *)ptep) = pteval;
200 mmu_invlpg((caddr_t)va);
201 #endif
202 }
203
204 #ifdef __xpv
205
206 /*
207 * Add a mapping for the machine page at the given virtual address.
208 */
209 void
210 kbm_map_ma(maddr_t ma, uintptr_t va, uint_t level)
211 {
212 paddr_t pte_physaddr;
213 x86pte_t pteval;
214
215 pteval = ma | PT_NOCONSIST | PT_VALID | PT_REF | PT_WRITABLE;
216 if (level == 1)
217 pteval |= PT_PAGESIZE;
218
219 /*
220 * try update_va_mapping first - fails if page table is missing.
334 {
335 if (khat_running)
336 panic("kbm_unmap() called too late");
337 else {
338 #ifdef __xpv
339 (void) HYPERVISOR_update_va_mapping(va, 0,
340 UVMF_INVLPG | UVMF_LOCAL);
341 #else
342 x86pte_t *ptep;
343 level_t level = 0;
344 uint_t probe_only = 1;
345
346 ptep = find_pte(va, NULL, level, probe_only);
347 if (ptep == NULL)
348 return;
349
350 if (kbm_pae_support)
351 *ptep = 0;
352 else
353 *((x86pte32_t *)ptep) = 0;
354 mmu_invlpg((caddr_t)va);
355 #endif
356 }
357 }
358
359
360 /*
361 * Change a boot loader page table 4K mapping.
362 * Returns the pfn of the old mapping.
363 */
364 pfn_t
365 kbm_remap(uintptr_t va, pfn_t pfn)
366 {
367 x86pte_t *ptep;
368 level_t level = 0;
369 uint_t probe_only = 1;
370 x86pte_t pte_val = pa_to_ma(pfn_to_pa(pfn)) | PT_WRITABLE |
371 PT_NOCONSIST | PT_VALID;
372 x86pte_t old_pte;
373
374 if (khat_running)
375 panic("kbm_remap() called too late");
376 ptep = find_pte(va, NULL, level, probe_only);
377 if (ptep == NULL)
378 bop_panic("kbm_remap: find_pte returned NULL");
379
380 if (kbm_pae_support)
381 old_pte = *ptep;
382 else
383 old_pte = *((x86pte32_t *)ptep);
384
385 #ifdef __xpv
386 if (HYPERVISOR_update_va_mapping(va, pte_val, UVMF_INVLPG | UVMF_LOCAL))
387 bop_panic("HYPERVISOR_update_va_mapping() failed");
388 #else
389 if (kbm_pae_support)
390 *((x86pte_t *)ptep) = pte_val;
391 else
392 *((x86pte32_t *)ptep) = pte_val;
393 mmu_invlpg((caddr_t)va);
394 #endif
395
396 if (!(old_pte & PT_VALID) || ma_to_pa(old_pte) == -1)
397 return (PFN_INVALID);
398 return (mmu_btop(ma_to_pa(old_pte)));
399 }
400
401
402 /*
403 * Change a boot loader page table 4K mapping to read only.
404 */
405 void
406 kbm_read_only(uintptr_t va, paddr_t pa)
407 {
408 x86pte_t pte_val = pa_to_ma(pa) |
409 PT_NOCONSIST | PT_REF | PT_MOD | PT_VALID;
410
411 #ifdef __xpv
412 if (HYPERVISOR_update_va_mapping(va, pte_val, UVMF_INVLPG | UVMF_LOCAL))
413 bop_panic("HYPERVISOR_update_va_mapping() failed");
414 #else
415 x86pte_t *ptep;
416 level_t level = 0;
417
418 ptep = find_pte(va, NULL, level, 0);
419 if (ptep == NULL)
420 bop_panic("kbm_read_only: find_pte returned NULL");
421
422 if (kbm_pae_support)
423 *ptep = pte_val;
424 else
425 *((x86pte32_t *)ptep) = pte_val;
426 mmu_invlpg((caddr_t)va);
427 #endif
428 }
429
430 /*
431 * interfaces for kernel debugger to access physical memory
432 */
433 static x86pte_t save_pte;
434
435 void *
436 kbm_push(paddr_t pa)
437 {
438 static int first_time = 1;
439
440 if (first_time) {
441 first_time = 0;
442 return (window);
443 }
444
445 if (kbm_pae_support)
446 save_pte = *((x86pte_t *)pte_to_window);
447 else
448 save_pte = *((x86pte32_t *)pte_to_window);
449 return (kbm_remap_window(pa, 0));
450 }
451
452 void
453 kbm_pop(void)
454 {
455 #ifdef __xpv
456 if (HYPERVISOR_update_va_mapping((uintptr_t)window, save_pte,
457 UVMF_INVLPG | UVMF_LOCAL) < 0)
458 bop_panic("HYPERVISOR_update_va_mapping() failed");
459 #else
460 if (kbm_pae_support)
461 *((x86pte_t *)pte_to_window) = save_pte;
462 else
463 *((x86pte32_t *)pte_to_window) = save_pte;
464 mmu_invlpg(window);
465 #endif
466 }
467
468 x86pte_t
469 get_pteval(paddr_t table, uint_t index)
470 {
471 void *table_ptr = kbm_remap_window(table, 0);
472
473 if (kbm_pae_support)
474 return (((x86pte_t *)table_ptr)[index]);
475 return (((x86pte32_t *)table_ptr)[index]);
476 }
477
478 #ifndef __xpv
479 void
480 set_pteval(paddr_t table, uint_t index, uint_t level, x86pte_t pteval)
481 {
482 void *table_ptr = kbm_remap_window(table, 0);
483 if (kbm_pae_support)
484 ((x86pte_t *)table_ptr)[index] = pteval;
|