| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: pmap.c,v 1.210 2016/07/09 09:33:21 maxv Exp $ */ | | 1 | /* $NetBSD: pmap.c,v 1.211 2016/07/11 14:18:16 maxv Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2008, 2010, 2016 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2008, 2010, 2016 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Andrew Doran, and by Maxime Villard. | | 8 | * by Andrew Doran, and by Maxime Villard. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -161,27 +161,27 @@ | | | @@ -161,27 +161,27 @@ |
161 | * Hibler/Jolitz pmap, as modified for FreeBSD by John S. Dyson | | 161 | * Hibler/Jolitz pmap, as modified for FreeBSD by John S. Dyson |
162 | * and David Greenman. | | 162 | * and David Greenman. |
163 | * | | 163 | * |
164 | * [3] the Mach pmap. this pmap, from CMU, seems to have migrated | | 164 | * [3] the Mach pmap. this pmap, from CMU, seems to have migrated |
165 | * between several processors. the VAX version was done by | | 165 | * between several processors. the VAX version was done by |
166 | * Avadis Tevanian, Jr., and Michael Wayne Young. the i386 | | 166 | * Avadis Tevanian, Jr., and Michael Wayne Young. the i386 |
167 | * version was done by Lance Berc, Mike Kupfer, Bob Baron, | | 167 | * version was done by Lance Berc, Mike Kupfer, Bob Baron, |
168 | * David Golub, and Richard Draves. the alpha version was | | 168 | * David Golub, and Richard Draves. the alpha version was |
169 | * done by Alessandro Forin (CMU/Mach) and Chris Demetriou | | 169 | * done by Alessandro Forin (CMU/Mach) and Chris Demetriou |
170 | * (NetBSD/alpha). | | 170 | * (NetBSD/alpha). |
171 | */ | | 171 | */ |
172 | | | 172 | |
173 | #include <sys/cdefs.h> | | 173 | #include <sys/cdefs.h> |
174 | __KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.210 2016/07/09 09:33:21 maxv Exp $"); | | 174 | __KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.211 2016/07/11 14:18:16 maxv Exp $"); |
175 | | | 175 | |
176 | #include "opt_user_ldt.h" | | 176 | #include "opt_user_ldt.h" |
177 | #include "opt_lockdebug.h" | | 177 | #include "opt_lockdebug.h" |
178 | #include "opt_multiprocessor.h" | | 178 | #include "opt_multiprocessor.h" |
179 | #include "opt_xen.h" | | 179 | #include "opt_xen.h" |
180 | #if !defined(__x86_64__) | | 180 | #if !defined(__x86_64__) |
181 | #include "opt_kstack_dr0.h" | | 181 | #include "opt_kstack_dr0.h" |
182 | #endif /* !defined(__x86_64__) */ | | 182 | #endif /* !defined(__x86_64__) */ |
183 | | | 183 | |
184 | #include <sys/param.h> | | 184 | #include <sys/param.h> |
185 | #include <sys/systm.h> | | 185 | #include <sys/systm.h> |
186 | #include <sys/proc.h> | | 186 | #include <sys/proc.h> |
187 | #include <sys/pool.h> | | 187 | #include <sys/pool.h> |
| @@ -1646,27 +1646,26 @@ pmap_prealloc_lowmem_ptps(void) | | | @@ -1646,27 +1646,26 @@ pmap_prealloc_lowmem_ptps(void) |
1646 | pmap_pte_flush(); | | 1646 | pmap_pte_flush(); |
1647 | pmap_update_pg((vaddr_t)early_zerop); | | 1647 | pmap_update_pg((vaddr_t)early_zerop); |
1648 | memset(early_zerop, 0, PAGE_SIZE); | | 1648 | memset(early_zerop, 0, PAGE_SIZE); |
1649 | #endif | | 1649 | #endif |
1650 | | | 1650 | |
1651 | #ifdef XEN | | 1651 | #ifdef XEN |
1652 | /* Mark R/O before installing */ | | 1652 | /* Mark R/O before installing */ |
1653 | HYPERVISOR_update_va_mapping ((vaddr_t)early_zerop, | | 1653 | HYPERVISOR_update_va_mapping ((vaddr_t)early_zerop, |
1654 | xpmap_ptom_masked(newp) | PG_u | PG_V, UVMF_INVLPG); | | 1654 | xpmap_ptom_masked(newp) | PG_u | PG_V, UVMF_INVLPG); |
1655 | if (newp < (NKL2_KIMG_ENTRIES * NBPD_L2)) | | 1655 | if (newp < (NKL2_KIMG_ENTRIES * NBPD_L2)) |
1656 | HYPERVISOR_update_va_mapping (newp + KERNBASE, | | 1656 | HYPERVISOR_update_va_mapping (newp + KERNBASE, |
1657 | xpmap_ptom_masked(newp) | PG_u | PG_V, UVMF_INVLPG); | | 1657 | xpmap_ptom_masked(newp) | PG_u | PG_V, UVMF_INVLPG); |
1658 | | | 1658 | |
1659 | | | | |
1660 | if (level == PTP_LEVELS) { /* Top level pde is per-cpu */ | | 1659 | if (level == PTP_LEVELS) { /* Top level pde is per-cpu */ |
1661 | pd_entry_t *kpm_pdir; | | 1660 | pd_entry_t *kpm_pdir; |
1662 | /* Reach it via recursive mapping */ | | 1661 | /* Reach it via recursive mapping */ |
1663 | kpm_pdir = normal_pdes[PTP_LEVELS - 2]; | | 1662 | kpm_pdir = normal_pdes[PTP_LEVELS - 2]; |
1664 | | | 1663 | |
1665 | /* Set it as usual. We can't defer this | | 1664 | /* Set it as usual. We can't defer this |
1666 | * outside the loop since recursive | | 1665 | * outside the loop since recursive |
1667 | * pte entries won't be accessible during | | 1666 | * pte entries won't be accessible during |
1668 | * further iterations at lower levels | | 1667 | * further iterations at lower levels |
1669 | * otherwise. | | 1668 | * otherwise. |
1670 | */ | | 1669 | */ |
1671 | pmap_pte_set(&kpm_pdir[pl_i(0, PTP_LEVELS)], | | 1670 | pmap_pte_set(&kpm_pdir[pl_i(0, PTP_LEVELS)], |
1672 | pmap_pa2pte(newp) | pteflags); | | 1671 | pmap_pa2pte(newp) | pteflags); |
| @@ -4295,83 +4294,77 @@ pmap_get_physpage(void) | | | @@ -4295,83 +4294,77 @@ pmap_get_physpage(void) |
4295 | | | 4294 | |
4296 | /* | | 4295 | /* |
4297 | * Allocate the amount of specified ptps for a ptp level, and populate | | 4296 | * Allocate the amount of specified ptps for a ptp level, and populate |
4298 | * all levels below accordingly, mapping virtual addresses starting at | | 4297 | * all levels below accordingly, mapping virtual addresses starting at |
4299 | * kva. | | 4298 | * kva. |
4300 | * | | 4299 | * |
4301 | * Used by pmap_growkernel. | | 4300 | * Used by pmap_growkernel. |
4302 | */ | | 4301 | */ |
4303 | static void | | 4302 | static void |
4304 | pmap_alloc_level(pd_entry_t * const *pdes, vaddr_t kva, int lvl, | | 4303 | pmap_alloc_level(pd_entry_t * const *pdes, vaddr_t kva, int lvl, |
4305 | long *needed_ptps) | | 4304 | long *needed_ptps) |
4306 | { | | 4305 | { |
4307 | unsigned long i; | | 4306 | unsigned long i; |
4308 | vaddr_t va; | | | |
4309 | paddr_t pa; | | 4307 | paddr_t pa; |
4310 | unsigned long index, endindex; | | 4308 | unsigned long index, endindex; |
4311 | int level; | | 4309 | int level; |
4312 | pd_entry_t *pdep; | | 4310 | pd_entry_t *pdep; |
4313 | #ifdef XEN | | 4311 | #ifdef XEN |
4314 | int s = splvm(); /* protect xpq_* */ | | 4312 | int s = splvm(); /* protect xpq_* */ |
4315 | #endif | | 4313 | #endif |
4316 | | | 4314 | |
4317 | for (level = lvl; level > 1; level--) { | | 4315 | for (level = lvl; level > 1; level--) { |
4318 | if (level == PTP_LEVELS) | | 4316 | if (level == PTP_LEVELS) |
4319 | pdep = pmap_kernel()->pm_pdir; | | 4317 | pdep = pmap_kernel()->pm_pdir; |
4320 | else | | 4318 | else |
4321 | pdep = pdes[level - 2]; | | 4319 | pdep = pdes[level - 2]; |
4322 | va = kva; | | | |
4323 | index = pl_i_roundup(kva, level); | | 4320 | index = pl_i_roundup(kva, level); |
4324 | endindex = index + needed_ptps[level - 1] - 1; | | 4321 | endindex = index + needed_ptps[level - 1] - 1; |
4325 | | | 4322 | |
4326 | | | | |
4327 | for (i = index; i <= endindex; i++) { | | 4323 | for (i = index; i <= endindex; i++) { |
4328 | pt_entry_t pte; | | 4324 | pt_entry_t pte; |
4329 | | | 4325 | |
4330 | KASSERT(!pmap_valid_entry(pdep[i])); | | 4326 | KASSERT(!pmap_valid_entry(pdep[i])); |
4331 | pa = pmap_get_physpage(); | | 4327 | pa = pmap_get_physpage(); |
4332 | pte = pmap_pa2pte(pa) | PG_k | PG_V | PG_RW; | | 4328 | pte = pmap_pa2pte(pa) | PG_k | PG_V | PG_RW; |
4333 | #ifdef XEN | | | |
4334 | pmap_pte_set(&pdep[i], pte); | | 4329 | pmap_pte_set(&pdep[i], pte); |
4335 | #if defined(PAE) || defined(__x86_64__) | | 4330 | |
| | | 4331 | #if defined(XEN) && (defined(PAE) || defined(__x86_64__)) |
4336 | if (level == PTP_LEVELS && i >= PDIR_SLOT_KERN) { | | 4332 | if (level == PTP_LEVELS && i >= PDIR_SLOT_KERN) { |
4337 | if (__predict_true( | | 4333 | if (__predict_true( |
4338 | cpu_info_primary.ci_flags & CPUF_PRESENT)) { | | 4334 | cpu_info_primary.ci_flags & CPUF_PRESENT)) { |
4339 | /* update per-cpu PMDs on all cpus */ | | 4335 | /* update per-cpu PMDs on all cpus */ |
4340 | xen_kpm_sync(pmap_kernel(), i); | | 4336 | xen_kpm_sync(pmap_kernel(), i); |
4341 | } else { | | 4337 | } else { |
4342 | /* | | 4338 | /* |
4343 | * too early; update primary CPU | | 4339 | * too early; update primary CPU |
4344 | * PMD only (without locks) | | 4340 | * PMD only (without locks) |
4345 | */ | | 4341 | */ |
4346 | #ifdef PAE | | 4342 | #ifdef PAE |
4347 | pd_entry_t *cpu_pdep = | | 4343 | pd_entry_t *cpu_pdep = |
4348 | &cpu_info_primary.ci_kpm_pdir[l2tol2(i)]; | | 4344 | &cpu_info_primary.ci_kpm_pdir[l2tol2(i)]; |
4349 | #endif | | 4345 | #endif |
4350 | #ifdef __x86_64__ | | 4346 | #ifdef __x86_64__ |
4351 | pd_entry_t *cpu_pdep = | | 4347 | pd_entry_t *cpu_pdep = |
4352 | &cpu_info_primary.ci_kpm_pdir[i]; | | 4348 | &cpu_info_primary.ci_kpm_pdir[i]; |
4353 | #endif | | 4349 | #endif |
4354 | pmap_pte_set(cpu_pdep, pte); | | 4350 | pmap_pte_set(cpu_pdep, pte); |
4355 | } | | 4351 | } |
4356 | } | | 4352 | } |
4357 | #endif /* PAE || __x86_64__ */ | | 4353 | #endif /* XEN && (PAE || __x86_64__) */ |
4358 | #else /* XEN */ | | 4354 | |
4359 | pdep[i] = pte; | | | |
4360 | #endif /* XEN */ | | | |
4361 | KASSERT(level != PTP_LEVELS || nkptp[level - 1] + | | 4355 | KASSERT(level != PTP_LEVELS || nkptp[level - 1] + |
4362 | pl_i(VM_MIN_KERNEL_ADDRESS, level) == i); | | 4356 | pl_i(VM_MIN_KERNEL_ADDRESS, level) == i); |
4363 | nkptp[level - 1]++; | | 4357 | nkptp[level - 1]++; |
4364 | va += nbpd[level - 1]; | | | |
4365 | } | | 4358 | } |
4366 | pmap_pte_flush(); | | 4359 | pmap_pte_flush(); |
4367 | } | | 4360 | } |
4368 | #ifdef XEN | | 4361 | #ifdef XEN |
4369 | splx(s); | | 4362 | splx(s); |
4370 | #endif | | 4363 | #endif |
4371 | } | | 4364 | } |
4372 | | | 4365 | |
4373 | /* | | 4366 | /* |
4374 | * pmap_growkernel: increase usage of KVM space | | 4367 | * pmap_growkernel: increase usage of KVM space |
4375 | * | | 4368 | * |
4376 | * => we allocate new PTPs for the kernel and install them in all | | 4369 | * => we allocate new PTPs for the kernel and install them in all |
4377 | * the pmaps on the system. | | 4370 | * the pmaps on the system. |
| @@ -4393,74 +4386,68 @@ pmap_growkernel(vaddr_t maxkvaddr) | | | @@ -4393,74 +4386,68 @@ pmap_growkernel(vaddr_t maxkvaddr) |
4393 | mutex_enter(kpm->pm_lock); | | 4386 | mutex_enter(kpm->pm_lock); |
4394 | | | 4387 | |
4395 | if (maxkvaddr <= pmap_maxkvaddr) { | | 4388 | if (maxkvaddr <= pmap_maxkvaddr) { |
4396 | mutex_exit(kpm->pm_lock); | | 4389 | mutex_exit(kpm->pm_lock); |
4397 | splx(s); | | 4390 | splx(s); |
4398 | return pmap_maxkvaddr; | | 4391 | return pmap_maxkvaddr; |
4399 | } | | 4392 | } |
4400 | | | 4393 | |
4401 | maxkvaddr = x86_round_pdr(maxkvaddr); | | 4394 | maxkvaddr = x86_round_pdr(maxkvaddr); |
4402 | #if !defined(XEN) || !defined(__x86_64__) | | 4395 | #if !defined(XEN) || !defined(__x86_64__) |
4403 | old = nkptp[PTP_LEVELS - 1]; | | 4396 | old = nkptp[PTP_LEVELS - 1]; |
4404 | #endif | | 4397 | #endif |
4405 | | | 4398 | |
4406 | /* | | 4399 | /* Initialize needed_kptp. */ |
4407 | * This loop could be optimized more, but pmap_growkernel() | | | |
4408 | * is called infrequently. | | | |
4409 | */ | | | |
4410 | for (i = PTP_LEVELS - 1; i >= 1; i--) { | | 4400 | for (i = PTP_LEVELS - 1; i >= 1; i--) { |
4411 | target_nptp = pl_i_roundup(maxkvaddr, i + 1) - | | 4401 | target_nptp = pl_i_roundup(maxkvaddr, i + 1) - |
4412 | pl_i_roundup(VM_MIN_KERNEL_ADDRESS, i + 1); | | 4402 | pl_i_roundup(VM_MIN_KERNEL_ADDRESS, i + 1); |
4413 | /* | | 4403 | |
4414 | * XXX only need to check toplevel. | | | |
4415 | */ | | | |
4416 | if (target_nptp > nkptpmax[i]) | | 4404 | if (target_nptp > nkptpmax[i]) |
4417 | panic("out of KVA space"); | | 4405 | panic("out of KVA space"); |
4418 | KASSERT(target_nptp >= nkptp[i]); | | 4406 | KASSERT(target_nptp >= nkptp[i]); |
4419 | needed_kptp[i] = target_nptp - nkptp[i]; | | 4407 | needed_kptp[i] = target_nptp - nkptp[i]; |
4420 | } | | 4408 | } |
4421 | | | 4409 | |
4422 | pmap_alloc_level(normal_pdes, pmap_maxkvaddr, PTP_LEVELS, needed_kptp); | | 4410 | pmap_alloc_level(normal_pdes, pmap_maxkvaddr, PTP_LEVELS, needed_kptp); |
4423 | | | 4411 | |
4424 | /* | | 4412 | /* |
4425 | * If the number of top level entries changed, update all | | 4413 | * If the number of top level entries changed, update all pmaps. |
4426 | * pmaps. | | | |
4427 | */ | | 4414 | */ |
4428 | if (needed_kptp[PTP_LEVELS - 1] != 0) { | | 4415 | if (needed_kptp[PTP_LEVELS - 1] != 0) { |
4429 | #ifdef XEN | | 4416 | #ifdef XEN |
4430 | #ifdef __x86_64__ | | 4417 | #ifdef __x86_64__ |
4431 | /* nothing, kernel entries are never entered in user pmap */ | | 4418 | /* nothing, kernel entries are never entered in user pmap */ |
4432 | #else /* __x86_64__ */ | | 4419 | #else /* __x86_64__ */ |
4433 | mutex_enter(&pmaps_lock); | | 4420 | mutex_enter(&pmaps_lock); |
4434 | LIST_FOREACH(pm, &pmaps, pm_list) { | | 4421 | LIST_FOREACH(pm, &pmaps, pm_list) { |
4435 | int pdkidx; | | 4422 | int pdkidx; |
4436 | for (pdkidx = PDIR_SLOT_KERN + old; | | 4423 | for (pdkidx = PDIR_SLOT_KERN + old; |
4437 | pdkidx < PDIR_SLOT_KERN + nkptp[PTP_LEVELS - 1]; | | 4424 | pdkidx < PDIR_SLOT_KERN + nkptp[PTP_LEVELS - 1]; |
4438 | pdkidx++) { | | 4425 | pdkidx++) { |
4439 | pmap_pte_set(&pm->pm_pdir[pdkidx], | | 4426 | pmap_pte_set(&pm->pm_pdir[pdkidx], |
4440 | kpm->pm_pdir[pdkidx]); | | 4427 | kpm->pm_pdir[pdkidx]); |
4441 | } | | 4428 | } |
4442 | pmap_pte_flush(); | | 4429 | pmap_pte_flush(); |
4443 | } | | 4430 | } |
4444 | mutex_exit(&pmaps_lock); | | 4431 | mutex_exit(&pmaps_lock); |
4445 | #endif /* __x86_64__ */ | | 4432 | #endif /* __x86_64__ */ |
4446 | #else /* XEN */ | | 4433 | #else /* XEN */ |
4447 | unsigned newpdes; | | 4434 | unsigned newpdes; |
4448 | newpdes = nkptp[PTP_LEVELS - 1] - old; | | 4435 | newpdes = nkptp[PTP_LEVELS - 1] - old; |
4449 | mutex_enter(&pmaps_lock); | | 4436 | mutex_enter(&pmaps_lock); |
4450 | LIST_FOREACH(pm, &pmaps, pm_list) { | | 4437 | LIST_FOREACH(pm, &pmaps, pm_list) { |
4451 | memcpy(&pm->pm_pdir[PDIR_SLOT_KERN + old], | | 4438 | memcpy(&pm->pm_pdir[PDIR_SLOT_KERN + old], |
4452 | &kpm->pm_pdir[PDIR_SLOT_KERN + old], | | 4439 | &kpm->pm_pdir[PDIR_SLOT_KERN + old], |
4453 | newpdes * sizeof (pd_entry_t)); | | 4440 | newpdes * sizeof (pd_entry_t)); |
4454 | } | | 4441 | } |
4455 | mutex_exit(&pmaps_lock); | | 4442 | mutex_exit(&pmaps_lock); |
4456 | #endif | | 4443 | #endif |
4457 | invalidate = true; | | 4444 | invalidate = true; |
4458 | } | | 4445 | } |
4459 | pmap_maxkvaddr = maxkvaddr; | | 4446 | pmap_maxkvaddr = maxkvaddr; |
4460 | mutex_exit(kpm->pm_lock); | | 4447 | mutex_exit(kpm->pm_lock); |
4461 | splx(s); | | 4448 | splx(s); |
4462 | | | 4449 | |
4463 | if (invalidate && pmap_initialized) { | | 4450 | if (invalidate && pmap_initialized) { |
4464 | /* Invalidate the PDP cache. */ | | 4451 | /* Invalidate the PDP cache. */ |
4465 | pool_cache_invalidate(&pmap_pdp_cache); | | 4452 | pool_cache_invalidate(&pmap_pdp_cache); |
4466 | } | | 4453 | } |