| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: pmap.c,v 1.239 2017/02/02 17:37:49 maxv Exp $ */ | | 1 | /* $NetBSD: pmap.c,v 1.240 2017/02/11 14:11:24 maxv Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2008, 2010, 2016, 2017 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2008, 2010, 2016, 2017 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.239 2017/02/02 17:37:49 maxv Exp $"); | | 174 | __KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.240 2017/02/11 14:11:24 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 | | | 180 | |
181 | #include <sys/param.h> | | 181 | #include <sys/param.h> |
182 | #include <sys/systm.h> | | 182 | #include <sys/systm.h> |
183 | #include <sys/proc.h> | | 183 | #include <sys/proc.h> |
184 | #include <sys/pool.h> | | 184 | #include <sys/pool.h> |
185 | #include <sys/kernel.h> | | 185 | #include <sys/kernel.h> |
186 | #include <sys/atomic.h> | | 186 | #include <sys/atomic.h> |
187 | #include <sys/cpu.h> | | 187 | #include <sys/cpu.h> |
| @@ -486,49 +486,35 @@ paddr_t local_apic_pa __read_mostly; | | | @@ -486,49 +486,35 @@ paddr_t local_apic_pa __read_mostly; |
486 | | | 486 | |
487 | /* | | 487 | /* |
488 | * pool that pmap structures are allocated from | | 488 | * pool that pmap structures are allocated from |
489 | */ | | 489 | */ |
490 | static struct pool_cache pmap_cache; | | 490 | static struct pool_cache pmap_cache; |
491 | | | 491 | |
492 | /* | | 492 | /* |
493 | * pv_entry cache | | 493 | * pv_entry cache |
494 | */ | | 494 | */ |
495 | static struct pool_cache pmap_pv_cache; | | 495 | static struct pool_cache pmap_pv_cache; |
496 | | | 496 | |
497 | #ifndef __HAVE_DIRECT_MAP | | 497 | #ifndef __HAVE_DIRECT_MAP |
498 | /* | | 498 | /* |
499 | * MULTIPROCESSOR: special VAs and PTEs are actually allocated inside a | | | |
500 | * (maxcpus * NPTECL) array of PTE, to avoid cache line thrashing due to | | | |
501 | * false sharing. | | | |
502 | */ | | | |
503 | #ifdef MULTIPROCESSOR | | | |
504 | #define PTESLEW(pte, id) ((pte)+(id)*NPTECL) | | | |
505 | #define VASLEW(va,id) ((va)+(id)*NPTECL*PAGE_SIZE) | | | |
506 | #else | | | |
507 | #define PTESLEW(pte, id) ((void)id, pte) | | | |
508 | #define VASLEW(va,id) ((void)id, va) | | | |
509 | #endif | | | |
510 | | | | |
511 | /* | | | |
512 | * Special VAs and the PTEs that map them | | 499 | * Special VAs and the PTEs that map them |
513 | */ | | 500 | */ |
514 | static pt_entry_t *csrc_pte, *cdst_pte, *zero_pte, *ptp_pte, *early_zero_pte; | | 501 | static pt_entry_t *early_zero_pte; |
515 | static char *csrcp, *cdstp, *zerop, *ptpp; | | 502 | static void pmap_vpage_cpualloc(struct cpu_info *); |
516 | #ifdef XEN | | 503 | #ifdef XEN |
517 | char *early_zerop; /* also referenced from xen_locore() */ | | 504 | char *early_zerop; /* also referenced from xen_locore() */ |
518 | #else | | 505 | #else |
519 | static char *early_zerop; | | 506 | static char *early_zerop; |
520 | #endif | | 507 | #endif |
521 | | | | |
522 | #endif | | 508 | #endif |
523 | | | 509 | |
524 | int pmap_enter_default(pmap_t, vaddr_t, paddr_t, vm_prot_t, u_int); | | 510 | int pmap_enter_default(pmap_t, vaddr_t, paddr_t, vm_prot_t, u_int); |
525 | | | 511 | |
526 | /* PDP pool_cache(9) and its callbacks */ | | 512 | /* PDP pool_cache(9) and its callbacks */ |
527 | struct pool_cache pmap_pdp_cache; | | 513 | struct pool_cache pmap_pdp_cache; |
528 | static int pmap_pdp_ctor(void *, void *, int); | | 514 | static int pmap_pdp_ctor(void *, void *, int); |
529 | static void pmap_pdp_dtor(void *, void *); | | 515 | static void pmap_pdp_dtor(void *, void *); |
530 | #ifdef PAE | | 516 | #ifdef PAE |
531 | /* need to allocate items of 4 pages */ | | 517 | /* need to allocate items of 4 pages */ |
532 | static void *pmap_pdp_alloc(struct pool *, int); | | 518 | static void *pmap_pdp_alloc(struct pool *, int); |
533 | static void pmap_pdp_free(struct pool *, void *); | | 519 | static void pmap_pdp_free(struct pool *, void *); |
534 | static struct pool_allocator pmap_pdp_allocator = { | | 520 | static struct pool_allocator pmap_pdp_allocator = { |
| @@ -1318,80 +1304,49 @@ pmap_bootstrap(vaddr_t kva_start) | | | @@ -1318,80 +1304,49 @@ pmap_bootstrap(vaddr_t kva_start) |
1318 | /* | | 1304 | /* |
1319 | * The TLB must be flushed after enabling large pages on Pentium | | 1305 | * The TLB must be flushed after enabling large pages on Pentium |
1320 | * CPUs, according to section 3.6.2.2 of "Intel Architecture | | 1306 | * CPUs, according to section 3.6.2.2 of "Intel Architecture |
1321 | * Software Developer's Manual, Volume 3: System Programming". | | 1307 | * Software Developer's Manual, Volume 3: System Programming". |
1322 | */ | | 1308 | */ |
1323 | tlbflushg(); | | 1309 | tlbflushg(); |
1324 | | | 1310 | |
1325 | /* Remap the kernel. */ | | 1311 | /* Remap the kernel. */ |
1326 | pmap_remap_largepages(); | | 1312 | pmap_remap_largepages(); |
1327 | } | | 1313 | } |
1328 | pmap_init_lapic(); | | 1314 | pmap_init_lapic(); |
1329 | #endif /* !XEN */ | | 1315 | #endif /* !XEN */ |
1330 | | | 1316 | |
1331 | | | | |
1332 | #ifdef __HAVE_DIRECT_MAP | | 1317 | #ifdef __HAVE_DIRECT_MAP |
1333 | pmap_init_directmap(kpm); | | 1318 | pmap_init_directmap(kpm); |
1334 | #else | | 1319 | #else |
1335 | if (VM_MIN_KERNEL_ADDRESS != KERNBASE) { | | 1320 | pmap_vpage_cpualloc(&cpu_info_primary); |
| | | 1321 | |
| | | 1322 | if (VM_MIN_KERNEL_ADDRESS == KERNBASE) { /* i386 */ |
| | | 1323 | early_zerop = (void *)cpu_info_primary.vpage[VPAGE_ZER]; |
| | | 1324 | early_zero_pte = cpu_info_primary.vpage_pte[VPAGE_ZER]; |
| | | 1325 | } else { /* amd64 */ |
1336 | /* | | 1326 | /* |
1337 | * zero_pte is stuck at the end of mapped space for the kernel | | 1327 | * zero_pte is stuck at the end of mapped space for the kernel |
1338 | * image (disjunct from kva space). This is done so that it | | 1328 | * image (disjunct from kva space). This is done so that it |
1339 | * can safely be used in pmap_growkernel (pmap_get_physpage), | | 1329 | * can safely be used in pmap_growkernel (pmap_get_physpage), |
1340 | * when it's called for the first time. | | 1330 | * when it's called for the first time. |
1341 | * XXXfvdl fix this for MULTIPROCESSOR later. | | 1331 | * XXXfvdl fix this for MULTIPROCESSOR later. |
1342 | */ | | 1332 | */ |
1343 | #ifdef XEN | | 1333 | #ifdef XEN |
1344 | /* early_zerop initialized in xen_locore() */ | | 1334 | /* early_zerop initialized in xen_locore() */ |
1345 | #else | | 1335 | #else |
1346 | early_zerop = (void *)(KERNBASE + NKL2_KIMG_ENTRIES * NBPD_L2); | | 1336 | early_zerop = (void *)(KERNBASE + NKL2_KIMG_ENTRIES * NBPD_L2); |
1347 | #endif | | 1337 | #endif |
1348 | early_zero_pte = PTE_BASE + pl1_i((vaddr_t)early_zerop); | | 1338 | early_zero_pte = PTE_BASE + pl1_i((vaddr_t)early_zerop); |
1349 | } | | 1339 | } |
1350 | | | | |
1351 | /* | | | |
1352 | * Now we allocate the "special" VAs which are used for tmp mappings | | | |
1353 | * by pmap. We allocate the VAs, and find the PTE that maps them via | | | |
1354 | * the linear PTE mapping. | | | |
1355 | */ | | | |
1356 | vaddr_t cpuva_base; | | | |
1357 | pt_entry_t *pte; | | | |
1358 | | | | |
1359 | #ifdef MULTIPROCESSOR | | | |
1360 | /* | | | |
1361 | * Waste some VA space to avoid false sharing of cache lines for page | | | |
1362 | * table pages: give each possible CPU a cache line of 8 PTEs to play | | | |
1363 | * with, though we only need 4. | | | |
1364 | */ | | | |
1365 | cpuva_base = pmap_bootstrap_valloc(maxcpus * NPTECL); | | | |
1366 | #else | | | |
1367 | cpuva_base = pmap_bootstrap_valloc(4); | | | |
1368 | #endif | | | |
1369 | pte = PTE_BASE + pl1_i(cpuva_base); | | | |
1370 | | | | |
1371 | /* Values used to index the array */ | | | |
1372 | csrcp = (char *)cpuva_base; | | | |
1373 | csrc_pte = pte; | | | |
1374 | cdstp = (char *)cpuva_base + PAGE_SIZE; | | | |
1375 | cdst_pte = pte + 1; | | | |
1376 | zerop = (char *)cpuva_base + PAGE_SIZE * 2; | | | |
1377 | zero_pte = pte + 2; | | | |
1378 | ptpp = (char *)cpuva_base + PAGE_SIZE * 3; | | | |
1379 | ptp_pte = pte + 3; | | | |
1380 | | | | |
1381 | if (VM_MIN_KERNEL_ADDRESS == KERNBASE) { | | | |
1382 | early_zerop = zerop; | | | |
1383 | early_zero_pte = zero_pte; | | | |
1384 | } | | | |
1385 | #endif | | 1340 | #endif |
1386 | | | 1341 | |
1387 | #if defined(XEN) && defined(__x86_64__) | | 1342 | #if defined(XEN) && defined(__x86_64__) |
1388 | extern vaddr_t xen_dummy_page; | | 1343 | extern vaddr_t xen_dummy_page; |
1389 | paddr_t xen_dummy_user_pgd; | | 1344 | paddr_t xen_dummy_user_pgd; |
1390 | | | 1345 | |
1391 | /* | | 1346 | /* |
1392 | * We want a dummy page directory for Xen: when deactivating a pmap, | | 1347 | * We want a dummy page directory for Xen: when deactivating a pmap, |
1393 | * Xen will still consider it active. So we set user PGD to this one | | 1348 | * Xen will still consider it active. So we set user PGD to this one |
1394 | * to lift all protection on the now inactive page tables set. | | 1349 | * to lift all protection on the now inactive page tables set. |
1395 | */ | | 1350 | */ |
1396 | xen_dummy_user_pgd = xen_dummy_page - KERNBASE; | | 1351 | xen_dummy_user_pgd = xen_dummy_page - KERNBASE; |
1397 | | | 1352 | |
| @@ -1705,26 +1660,77 @@ pmap_cpu_init_late(struct cpu_info *ci) | | | @@ -1705,26 +1660,77 @@ pmap_cpu_init_late(struct cpu_info *ci) |
1705 | /* | | 1660 | /* |
1706 | * The BP has already its own PD page allocated during early | | 1661 | * The BP has already its own PD page allocated during early |
1707 | * MD startup. | | 1662 | * MD startup. |
1708 | */ | | 1663 | */ |
1709 | if (ci == &cpu_info_primary) | | 1664 | if (ci == &cpu_info_primary) |
1710 | return; | | 1665 | return; |
1711 | | | 1666 | |
1712 | #ifdef PAE | | 1667 | #ifdef PAE |
1713 | cpu_alloc_l3_page(ci); | | 1668 | cpu_alloc_l3_page(ci); |
1714 | #endif | | 1669 | #endif |
1715 | } | | 1670 | } |
1716 | #endif | | 1671 | #endif |
1717 | | | 1672 | |
| | | 1673 | #ifndef __HAVE_DIRECT_MAP |
| | | 1674 | CTASSERT(CACHE_LINE_SIZE > sizeof(pt_entry_t)); |
| | | 1675 | CTASSERT(CACHE_LINE_SIZE % sizeof(pt_entry_t) == 0); |
| | | 1676 | |
| | | 1677 | static void |
| | | 1678 | pmap_vpage_cpualloc(struct cpu_info *ci) |
| | | 1679 | { |
| | | 1680 | bool primary = (ci == &cpu_info_primary); |
| | | 1681 | size_t i, npages; |
| | | 1682 | vaddr_t vabase; |
| | | 1683 | vsize_t vrange; |
| | | 1684 | |
| | | 1685 | npages = (CACHE_LINE_SIZE / sizeof(pt_entry_t)); |
| | | 1686 | KASSERT(npages >= VPAGE_MAX); |
| | | 1687 | vrange = npages * PAGE_SIZE; |
| | | 1688 | |
| | | 1689 | if (primary) { |
| | | 1690 | while ((vabase = pmap_bootstrap_valloc(1)) % vrange != 0) { |
| | | 1691 | /* Waste some pages to align properly */ |
| | | 1692 | } |
| | | 1693 | /* The base is aligned, allocate the rest (contiguous) */ |
| | | 1694 | pmap_bootstrap_valloc(npages - 1); |
| | | 1695 | } else { |
| | | 1696 | vabase = uvm_km_alloc(kernel_map, vrange, vrange, |
| | | 1697 | UVM_KMF_VAONLY); |
| | | 1698 | if (vabase == 0) { |
| | | 1699 | panic("%s: failed to allocate tmp VA for CPU %d\n", |
| | | 1700 | __func__, cpu_index(ci)); |
| | | 1701 | } |
| | | 1702 | } |
| | | 1703 | |
| | | 1704 | KASSERT((vaddr_t)&PTE_BASE[pl1_i(vabase)] % CACHE_LINE_SIZE == 0); |
| | | 1705 | |
| | | 1706 | for (i = 0; i < VPAGE_MAX; i++) { |
| | | 1707 | ci->vpage[i] = vabase + i * PAGE_SIZE; |
| | | 1708 | ci->vpage_pte[i] = PTE_BASE + pl1_i(ci->vpage[i]); |
| | | 1709 | } |
| | | 1710 | } |
| | | 1711 | |
| | | 1712 | void |
| | | 1713 | pmap_vpage_cpu_init(struct cpu_info *ci) |
| | | 1714 | { |
| | | 1715 | if (ci == &cpu_info_primary) { |
| | | 1716 | /* cpu0 already taken care of in pmap_bootstrap */ |
| | | 1717 | return; |
| | | 1718 | } |
| | | 1719 | |
| | | 1720 | pmap_vpage_cpualloc(ci); |
| | | 1721 | } |
| | | 1722 | #endif |
| | | 1723 | |
1718 | /* | | 1724 | /* |
1719 | * p v _ e n t r y f u n c t i o n s | | 1725 | * p v _ e n t r y f u n c t i o n s |
1720 | */ | | 1726 | */ |
1721 | | | 1727 | |
1722 | /* | | 1728 | /* |
1723 | * pmap_free_pvs: free a list of pv_entrys | | 1729 | * pmap_free_pvs: free a list of pv_entrys |
1724 | */ | | 1730 | */ |
1725 | | | 1731 | |
1726 | static void | | 1732 | static void |
1727 | pmap_free_pvs(struct pv_entry *pve) | | 1733 | pmap_free_pvs(struct pv_entry *pve) |
1728 | { | | 1734 | { |
1729 | struct pv_entry *next; | | 1735 | struct pv_entry *next; |
1730 | | | 1736 | |
| @@ -3029,91 +3035,92 @@ pmap_virtual_space(vaddr_t *startp, vadd | | | @@ -3029,91 +3035,92 @@ pmap_virtual_space(vaddr_t *startp, vadd |
3029 | * pmap_zero_page: zero a page | | 3035 | * pmap_zero_page: zero a page |
3030 | */ | | 3036 | */ |
3031 | | | 3037 | |
3032 | void | | 3038 | void |
3033 | pmap_zero_page(paddr_t pa) | | 3039 | pmap_zero_page(paddr_t pa) |
3034 | { | | 3040 | { |
3035 | #if defined(__HAVE_DIRECT_MAP) | | 3041 | #if defined(__HAVE_DIRECT_MAP) |
3036 | pagezero(PMAP_DIRECT_MAP(pa)); | | 3042 | pagezero(PMAP_DIRECT_MAP(pa)); |
3037 | #else | | 3043 | #else |
3038 | #if defined(XEN) | | 3044 | #if defined(XEN) |
3039 | if (XEN_VERSION_SUPPORTED(3, 4)) | | 3045 | if (XEN_VERSION_SUPPORTED(3, 4)) |
3040 | xen_pagezero(pa); | | 3046 | xen_pagezero(pa); |
3041 | #endif | | 3047 | #endif |
| | | 3048 | struct cpu_info *ci; |
3042 | pt_entry_t *zpte; | | 3049 | pt_entry_t *zpte; |
3043 | void *zerova; | | 3050 | vaddr_t zerova; |
3044 | int id; | | | |
3045 | | | 3051 | |
3046 | const pd_entry_t pteflags = PG_V | PG_RW | pmap_pg_nx | PG_M | PG_U | | | 3052 | const pd_entry_t pteflags = PG_V | PG_RW | pmap_pg_nx | PG_M | PG_U | |
3047 | PG_k; | | 3053 | PG_k; |
3048 | | | 3054 | |
3049 | kpreempt_disable(); | | 3055 | kpreempt_disable(); |
3050 | id = cpu_number(); | | 3056 | |
3051 | zpte = PTESLEW(zero_pte, id); | | 3057 | ci = curcpu(); |
3052 | zerova = VASLEW(zerop, id); | | 3058 | zerova = ci->vpage[VPAGE_ZER]; |
| | | 3059 | zpte = ci->vpage_pte[VPAGE_ZER]; |
3053 | | | 3060 | |
3054 | #ifdef DIAGNOSTIC | | 3061 | #ifdef DIAGNOSTIC |
3055 | if (*zpte) | | 3062 | if (*zpte) |
3056 | panic("pmap_zero_page: lock botch"); | | 3063 | panic("pmap_zero_page: lock botch"); |
3057 | #endif | | 3064 | #endif |
3058 | | | 3065 | |
3059 | pmap_pte_set(zpte, pmap_pa2pte(pa) | pteflags); | | 3066 | pmap_pte_set(zpte, pmap_pa2pte(pa) | pteflags); |
3060 | pmap_pte_flush(); | | 3067 | pmap_pte_flush(); |
3061 | pmap_update_pg((vaddr_t)zerova); /* flush TLB */ | | 3068 | pmap_update_pg(zerova); /* flush TLB */ |
3062 | | | 3069 | |
3063 | memset(zerova, 0, PAGE_SIZE); | | 3070 | memset((void *)zerova, 0, PAGE_SIZE); |
3064 | | | 3071 | |
3065 | #if defined(DIAGNOSTIC) || defined(XEN) | | 3072 | #if defined(DIAGNOSTIC) || defined(XEN) |
3066 | pmap_pte_set(zpte, 0); /* zap ! */ | | 3073 | pmap_pte_set(zpte, 0); /* zap ! */ |
3067 | pmap_pte_flush(); | | 3074 | pmap_pte_flush(); |
3068 | #endif | | 3075 | #endif |
3069 | | | 3076 | |
3070 | kpreempt_enable(); | | 3077 | kpreempt_enable(); |
3071 | #endif /* defined(__HAVE_DIRECT_MAP) */ | | 3078 | #endif /* defined(__HAVE_DIRECT_MAP) */ |
3072 | } | | 3079 | } |
3073 | | | 3080 | |
3074 | /* | | 3081 | /* |
3075 | * pmap_pagezeroidle: the same, for the idle loop page zero'er. | | 3082 | * pmap_pagezeroidle: the same, for the idle loop page zero'er. |
3076 | * Returns true if the page was zero'd, false if we aborted for | | 3083 | * Returns true if the page was zero'd, false if we aborted for |
3077 | * some reason. | | 3084 | * some reason. |
3078 | */ | | 3085 | */ |
3079 | | | 3086 | |
3080 | bool | | 3087 | bool |
3081 | pmap_pageidlezero(paddr_t pa) | | 3088 | pmap_pageidlezero(paddr_t pa) |
3082 | { | | 3089 | { |
3083 | #ifdef __HAVE_DIRECT_MAP | | 3090 | #ifdef __HAVE_DIRECT_MAP |
3084 | KASSERT(cpu_feature[0] & CPUID_SSE2); | | 3091 | KASSERT(cpu_feature[0] & CPUID_SSE2); |
3085 | return sse2_idlezero_page((void *)PMAP_DIRECT_MAP(pa)); | | 3092 | return sse2_idlezero_page((void *)PMAP_DIRECT_MAP(pa)); |
3086 | #else | | 3093 | #else |
| | | 3094 | struct cpu_info *ci; |
3087 | pt_entry_t *zpte; | | 3095 | pt_entry_t *zpte; |
3088 | void *zerova; | | 3096 | vaddr_t zerova; |
3089 | bool rv; | | 3097 | bool rv; |
3090 | int id; | | | |
3091 | | | 3098 | |
3092 | const pd_entry_t pteflags = PG_V | PG_RW | pmap_pg_nx | PG_M | PG_U | | | 3099 | const pd_entry_t pteflags = PG_V | PG_RW | pmap_pg_nx | PG_M | PG_U | |
3093 | PG_k; | | 3100 | PG_k; |
3094 | | | 3101 | |
3095 | id = cpu_number(); | | 3102 | ci = curcpu(); |
3096 | zpte = PTESLEW(zero_pte, id); | | 3103 | zerova = ci->vpage[VPAGE_ZER]; |
3097 | zerova = VASLEW(zerop, id); | | 3104 | zpte = ci->vpage_pte[VPAGE_ZER]; |
3098 | | | 3105 | |
3099 | KASSERT(cpu_feature[0] & CPUID_SSE2); | | 3106 | KASSERT(cpu_feature[0] & CPUID_SSE2); |
3100 | KASSERT(*zpte == 0); | | 3107 | KASSERT(*zpte == 0); |
3101 | | | 3108 | |
3102 | pmap_pte_set(zpte, pmap_pa2pte(pa) | pteflags); | | 3109 | pmap_pte_set(zpte, pmap_pa2pte(pa) | pteflags); |
3103 | pmap_pte_flush(); | | 3110 | pmap_pte_flush(); |
3104 | pmap_update_pg((vaddr_t)zerova); /* flush TLB */ | | 3111 | pmap_update_pg(zerova); /* flush TLB */ |
3105 | | | 3112 | |
3106 | rv = sse2_idlezero_page(zerova); | | 3113 | rv = sse2_idlezero_page((void *)zerova); |
3107 | | | 3114 | |
3108 | #if defined(DIAGNOSTIC) || defined(XEN) | | 3115 | #if defined(DIAGNOSTIC) || defined(XEN) |
3109 | pmap_pte_set(zpte, 0); /* zap ! */ | | 3116 | pmap_pte_set(zpte, 0); /* zap ! */ |
3110 | pmap_pte_flush(); | | 3117 | pmap_pte_flush(); |
3111 | #endif | | 3118 | #endif |
3112 | | | 3119 | |
3113 | return rv; | | 3120 | return rv; |
3114 | #endif | | 3121 | #endif |
3115 | } | | 3122 | } |
3116 | | | 3123 | |
3117 | /* | | 3124 | /* |
3118 | * pmap_copy_page: copy a page | | 3125 | * pmap_copy_page: copy a page |
3119 | */ | | 3126 | */ |
| @@ -3123,101 +3130,104 @@ pmap_copy_page(paddr_t srcpa, paddr_t ds | | | @@ -3123,101 +3130,104 @@ pmap_copy_page(paddr_t srcpa, paddr_t ds |
3123 | { | | 3130 | { |
3124 | #if defined(__HAVE_DIRECT_MAP) | | 3131 | #if defined(__HAVE_DIRECT_MAP) |
3125 | vaddr_t srcva = PMAP_DIRECT_MAP(srcpa); | | 3132 | vaddr_t srcva = PMAP_DIRECT_MAP(srcpa); |
3126 | vaddr_t dstva = PMAP_DIRECT_MAP(dstpa); | | 3133 | vaddr_t dstva = PMAP_DIRECT_MAP(dstpa); |
3127 | | | 3134 | |
3128 | memcpy((void *)dstva, (void *)srcva, PAGE_SIZE); | | 3135 | memcpy((void *)dstva, (void *)srcva, PAGE_SIZE); |
3129 | #else | | 3136 | #else |
3130 | #if defined(XEN) | | 3137 | #if defined(XEN) |
3131 | if (XEN_VERSION_SUPPORTED(3, 4)) { | | 3138 | if (XEN_VERSION_SUPPORTED(3, 4)) { |
3132 | xen_copy_page(srcpa, dstpa); | | 3139 | xen_copy_page(srcpa, dstpa); |
3133 | return; | | 3140 | return; |
3134 | } | | 3141 | } |
3135 | #endif | | 3142 | #endif |
3136 | pt_entry_t *spte; | | 3143 | struct cpu_info *ci; |
3137 | pt_entry_t *dpte; | | 3144 | pt_entry_t *srcpte, *dstpte; |
3138 | void *csrcva; | | 3145 | vaddr_t srcva, dstva; |
3139 | void *cdstva; | | | |
3140 | int id; | | | |
3141 | | | 3146 | |
3142 | const pd_entry_t pteflags = PG_V | PG_RW | pmap_pg_nx | PG_U | PG_k; | | 3147 | const pd_entry_t pteflags = PG_V | PG_RW | pmap_pg_nx | PG_U | PG_k; |
3143 | | | 3148 | |
3144 | kpreempt_disable(); | | 3149 | kpreempt_disable(); |
3145 | id = cpu_number(); | | | |
3146 | spte = PTESLEW(csrc_pte, id); | | | |
3147 | dpte = PTESLEW(cdst_pte, id); | | | |
3148 | csrcva = VASLEW(csrcp, id); | | | |
3149 | cdstva = VASLEW(cdstp, id); | | | |
3150 | | | 3150 | |
3151 | KASSERT(*spte == 0 && *dpte == 0); | | 3151 | ci = curcpu(); |
| | | 3152 | srcva = ci->vpage[VPAGE_SRC]; |
| | | 3153 | dstva = ci->vpage[VPAGE_DST]; |
| | | 3154 | srcpte = ci->vpage_pte[VPAGE_SRC]; |
| | | 3155 | dstpte = ci->vpage_pte[VPAGE_DST]; |
| | | 3156 | |
| | | 3157 | KASSERT(*srcpte == 0 && *dstpte == 0); |
3152 | | | 3158 | |
3153 | pmap_pte_set(spte, pmap_pa2pte(srcpa) | pteflags); | | 3159 | pmap_pte_set(srcpte, pmap_pa2pte(srcpa) | pteflags); |
3154 | pmap_pte_set(dpte, pmap_pa2pte(dstpa) | pteflags | PG_M); | | 3160 | pmap_pte_set(dstpte, pmap_pa2pte(dstpa) | pteflags | PG_M); |
3155 | pmap_pte_flush(); | | 3161 | pmap_pte_flush(); |
3156 | pmap_update_2pg((vaddr_t)csrcva, (vaddr_t)cdstva); | | 3162 | pmap_update_2pg(srcva, dstva); |
3157 | | | 3163 | |
3158 | memcpy(cdstva, csrcva, PAGE_SIZE); | | 3164 | memcpy((void *)dstva, (void *)srcva, PAGE_SIZE); |
3159 | | | 3165 | |
3160 | #if defined(DIAGNOSTIC) || defined(XEN) | | 3166 | #if defined(DIAGNOSTIC) || defined(XEN) |
3161 | pmap_pte_set(spte, 0); | | 3167 | pmap_pte_set(srcpte, 0); |
3162 | pmap_pte_set(dpte, 0); | | 3168 | pmap_pte_set(dstpte, 0); |
3163 | pmap_pte_flush(); | | 3169 | pmap_pte_flush(); |
3164 | #endif | | 3170 | #endif |
3165 | | | 3171 | |
3166 | kpreempt_enable(); | | 3172 | kpreempt_enable(); |
3167 | #endif /* defined(__HAVE_DIRECT_MAP) */ | | 3173 | #endif /* defined(__HAVE_DIRECT_MAP) */ |
3168 | } | | 3174 | } |
3169 | | | 3175 | |
3170 | static pt_entry_t * | | 3176 | static pt_entry_t * |
3171 | pmap_map_ptp(struct vm_page *ptp) | | 3177 | pmap_map_ptp(struct vm_page *ptp) |
3172 | { | | 3178 | { |
3173 | #ifdef __HAVE_DIRECT_MAP | | 3179 | #ifdef __HAVE_DIRECT_MAP |
3174 | return (void *)PMAP_DIRECT_MAP(VM_PAGE_TO_PHYS(ptp)); | | 3180 | return (void *)PMAP_DIRECT_MAP(VM_PAGE_TO_PHYS(ptp)); |
3175 | #else | | 3181 | #else |
| | | 3182 | struct cpu_info *ci; |
3176 | pt_entry_t *ptppte; | | 3183 | pt_entry_t *ptppte; |
3177 | void *ptpva; | | 3184 | vaddr_t ptpva; |
3178 | int id; | | | |
3179 | | | 3185 | |
3180 | KASSERT(kpreempt_disabled()); | | 3186 | KASSERT(kpreempt_disabled()); |
3181 | | | 3187 | |
3182 | #ifndef XEN | | 3188 | #ifndef XEN |
3183 | const pd_entry_t pteflags = PG_V | PG_RW | pmap_pg_nx | PG_U | PG_M | | | 3189 | const pd_entry_t pteflags = PG_V | PG_RW | pmap_pg_nx | PG_U | PG_M | |
3184 | PG_k; | | 3190 | PG_k; |
3185 | #else | | 3191 | #else |
3186 | const pd_entry_t pteflags = PG_V | pmap_pg_nx | PG_U | PG_M | PG_k; | | 3192 | const pd_entry_t pteflags = PG_V | pmap_pg_nx | PG_U | PG_M | PG_k; |
3187 | #endif | | 3193 | #endif |
3188 | | | 3194 | |
3189 | id = cpu_number(); | | 3195 | ci = curcpu(); |
3190 | ptppte = PTESLEW(ptp_pte, id); | | 3196 | ptpva = ci->vpage[VPAGE_PTP]; |
3191 | ptpva = VASLEW(ptpp, id); | | 3197 | ptppte = ci->vpage_pte[VPAGE_PTP]; |
| | | 3198 | |
3192 | pmap_pte_set(ptppte, pmap_pa2pte(VM_PAGE_TO_PHYS(ptp)) | pteflags); | | 3199 | pmap_pte_set(ptppte, pmap_pa2pte(VM_PAGE_TO_PHYS(ptp)) | pteflags); |
3193 | | | 3200 | |
3194 | pmap_pte_flush(); | | 3201 | pmap_pte_flush(); |
3195 | pmap_update_pg((vaddr_t)ptpva); | | 3202 | pmap_update_pg(ptpva); |
3196 | | | 3203 | |
3197 | return (pt_entry_t *)ptpva; | | 3204 | return (pt_entry_t *)ptpva; |
3198 | #endif | | 3205 | #endif |
3199 | } | | 3206 | } |
3200 | | | 3207 | |
3201 | static void | | 3208 | static void |
3202 | pmap_unmap_ptp(void) | | 3209 | pmap_unmap_ptp(void) |
3203 | { | | 3210 | { |
3204 | #ifndef __HAVE_DIRECT_MAP | | 3211 | #ifndef __HAVE_DIRECT_MAP |
3205 | #if defined(DIAGNOSTIC) || defined(XEN) | | 3212 | #if defined(DIAGNOSTIC) || defined(XEN) |
| | | 3213 | struct cpu_info *ci; |
3206 | pt_entry_t *pte; | | 3214 | pt_entry_t *pte; |
3207 | | | 3215 | |
3208 | KASSERT(kpreempt_disabled()); | | 3216 | KASSERT(kpreempt_disabled()); |
3209 | | | 3217 | |
3210 | pte = PTESLEW(ptp_pte, cpu_number()); | | 3218 | ci = curcpu(); |
| | | 3219 | pte = ci->vpage_pte[VPAGE_PTP]; |
| | | 3220 | |
3211 | if (*pte != 0) { | | 3221 | if (*pte != 0) { |
3212 | pmap_pte_set(pte, 0); | | 3222 | pmap_pte_set(pte, 0); |
3213 | pmap_pte_flush(); | | 3223 | pmap_pte_flush(); |
3214 | } | | 3224 | } |
3215 | #endif | | 3225 | #endif |
3216 | #endif | | 3226 | #endif |
3217 | } | | 3227 | } |
3218 | | | 3228 | |
3219 | static pt_entry_t * | | 3229 | static pt_entry_t * |
3220 | pmap_map_pte(struct pmap *pmap, struct vm_page *ptp, vaddr_t va) | | 3230 | pmap_map_pte(struct pmap *pmap, struct vm_page *ptp, vaddr_t va) |
3221 | { | | 3231 | { |
3222 | | | 3232 | |
3223 | KASSERT(kpreempt_disabled()); | | 3233 | KASSERT(kpreempt_disabled()); |