| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: pmap.c,v 1.287 2021/05/30 06:41:19 thorpej Exp $ */ | | 1 | /* $NetBSD: pmap.c,v 1.288 2021/05/30 13:34:21 thorpej Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1998, 1999, 2000, 2001, 2007, 2008, 2020 | | 4 | * Copyright (c) 1998, 1999, 2000, 2001, 2007, 2008, 2020 |
5 | * The NetBSD Foundation, Inc. | | 5 | * The NetBSD Foundation, Inc. |
6 | * All rights reserved. | | 6 | * All rights reserved. |
7 | * | | 7 | * |
8 | * This code is derived from software contributed to The NetBSD Foundation | | 8 | * This code is derived from software contributed to The NetBSD Foundation |
9 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | | 9 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, |
10 | * NASA Ames Research Center, by Andrew Doran and Mindaugas Rasiukevicius, | | 10 | * NASA Ames Research Center, by Andrew Doran and Mindaugas Rasiukevicius, |
11 | * and by Chris G. Demetriou. | | 11 | * and by Chris G. Demetriou. |
12 | * | | 12 | * |
13 | * Redistribution and use in source and binary forms, with or without | | 13 | * Redistribution and use in source and binary forms, with or without |
14 | * modification, are permitted provided that the following conditions | | 14 | * modification, are permitted provided that the following conditions |
| @@ -125,27 +125,27 @@ | | | @@ -125,27 +125,27 @@ |
125 | * this module may delay invalidate or reduced protection | | 125 | * this module may delay invalidate or reduced protection |
126 | * operations until such time as they are actually | | 126 | * operations until such time as they are actually |
127 | * necessary. This module is given full information as | | 127 | * necessary. This module is given full information as |
128 | * to which processors are currently using which maps, | | 128 | * to which processors are currently using which maps, |
129 | * and to when physical maps must be made correct. | | 129 | * and to when physical maps must be made correct. |
130 | */ | | 130 | */ |
131 | | | 131 | |
132 | #include "opt_lockdebug.h" | | 132 | #include "opt_lockdebug.h" |
133 | #include "opt_sysv.h" | | 133 | #include "opt_sysv.h" |
134 | #include "opt_multiprocessor.h" | | 134 | #include "opt_multiprocessor.h" |
135 | | | 135 | |
136 | #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ | | 136 | #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ |
137 | | | 137 | |
138 | __KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.287 2021/05/30 06:41:19 thorpej Exp $"); | | 138 | __KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.288 2021/05/30 13:34:21 thorpej Exp $"); |
139 | | | 139 | |
140 | #include <sys/param.h> | | 140 | #include <sys/param.h> |
141 | #include <sys/systm.h> | | 141 | #include <sys/systm.h> |
142 | #include <sys/kernel.h> | | 142 | #include <sys/kernel.h> |
143 | #include <sys/proc.h> | | 143 | #include <sys/proc.h> |
144 | #include <sys/malloc.h> | | 144 | #include <sys/malloc.h> |
145 | #include <sys/pool.h> | | 145 | #include <sys/pool.h> |
146 | #include <sys/buf.h> | | 146 | #include <sys/buf.h> |
147 | #include <sys/evcnt.h> | | 147 | #include <sys/evcnt.h> |
148 | #include <sys/atomic.h> | | 148 | #include <sys/atomic.h> |
149 | #include <sys/cpu.h> | | 149 | #include <sys/cpu.h> |
150 | | | 150 | |
151 | #include <uvm/uvm.h> | | 151 | #include <uvm/uvm.h> |
| @@ -1374,26 +1374,27 @@ pmap_bootstrap(paddr_t ptaddr, u_int max | | | @@ -1374,26 +1374,27 @@ pmap_bootstrap(paddr_t ptaddr, u_int max |
1374 | * could be issued, but must NOT block IPIs. | | 1374 | * could be issued, but must NOT block IPIs. |
1375 | */ | | 1375 | */ |
1376 | mutex_init(&tlb_lock, MUTEX_SPIN, IPL_VM); | | 1376 | mutex_init(&tlb_lock, MUTEX_SPIN, IPL_VM); |
1377 | | | 1377 | |
1378 | /* | | 1378 | /* |
1379 | * Initialize kernel pmap. Note that all kernel mappings | | 1379 | * Initialize kernel pmap. Note that all kernel mappings |
1380 | * have PG_ASM set, so the ASN doesn't really matter for | | 1380 | * have PG_ASM set, so the ASN doesn't really matter for |
1381 | * the kernel pmap. Also, since the kernel pmap always | | 1381 | * the kernel pmap. Also, since the kernel pmap always |
1382 | * references kernel_lev1map, it always has an invalid ASN | | 1382 | * references kernel_lev1map, it always has an invalid ASN |
1383 | * generation. | | 1383 | * generation. |
1384 | */ | | 1384 | */ |
1385 | memset(pmap_kernel(), 0, sizeof(struct pmap)); | | 1385 | memset(pmap_kernel(), 0, sizeof(struct pmap)); |
1386 | LIST_INIT(&pmap_kernel()->pm_ptpages); | | 1386 | LIST_INIT(&pmap_kernel()->pm_ptpages); |
| | | 1387 | LIST_INIT(&pmap_kernel()->pm_pvents); |
1387 | atomic_store_relaxed(&pmap_kernel()->pm_count, 1); | | 1388 | atomic_store_relaxed(&pmap_kernel()->pm_count, 1); |
1388 | /* Kernel pmap does not have per-CPU info. */ | | 1389 | /* Kernel pmap does not have per-CPU info. */ |
1389 | TAILQ_INSERT_TAIL(&pmap_all_pmaps, pmap_kernel(), pm_list); | | 1390 | TAILQ_INSERT_TAIL(&pmap_all_pmaps, pmap_kernel(), pm_list); |
1390 | | | 1391 | |
1391 | /* | | 1392 | /* |
1392 | * Set up lwp0's PCB such that the ptbr points to the right place | | 1393 | * Set up lwp0's PCB such that the ptbr points to the right place |
1393 | * and has the kernel pmap's (really unused) ASN. | | 1394 | * and has the kernel pmap's (really unused) ASN. |
1394 | */ | | 1395 | */ |
1395 | pcb = lwp_getpcb(&lwp0); | | 1396 | pcb = lwp_getpcb(&lwp0); |
1396 | pcb->pcb_hw.apcb_ptbr = | | 1397 | pcb->pcb_hw.apcb_ptbr = |
1397 | ALPHA_K0SEG_TO_PHYS((vaddr_t)kernel_lev1map) >> PGSHIFT; | | 1398 | ALPHA_K0SEG_TO_PHYS((vaddr_t)kernel_lev1map) >> PGSHIFT; |
1398 | pcb->pcb_hw.apcb_asn = PMAP_ASN_KERNEL; | | 1399 | pcb->pcb_hw.apcb_asn = PMAP_ASN_KERNEL; |
1399 | | | 1400 | |
| @@ -1558,26 +1559,27 @@ pmap_create(void) | | | @@ -1558,26 +1559,27 @@ pmap_create(void) |
1558 | { | | 1559 | { |
1559 | pmap_t pmap; | | 1560 | pmap_t pmap; |
1560 | pt_entry_t *lev1map; | | 1561 | pt_entry_t *lev1map; |
1561 | int i; | | 1562 | int i; |
1562 | | | 1563 | |
1563 | #ifdef DEBUG | | 1564 | #ifdef DEBUG |
1564 | if (pmapdebug & (PDB_FOLLOW|PDB_CREATE)) | | 1565 | if (pmapdebug & (PDB_FOLLOW|PDB_CREATE)) |
1565 | printf("pmap_create()\n"); | | 1566 | printf("pmap_create()\n"); |
1566 | #endif | | 1567 | #endif |
1567 | | | 1568 | |
1568 | pmap = pool_cache_get(&pmap_pmap_cache, PR_WAITOK); | | 1569 | pmap = pool_cache_get(&pmap_pmap_cache, PR_WAITOK); |
1569 | memset(pmap, 0, sizeof(*pmap)); | | 1570 | memset(pmap, 0, sizeof(*pmap)); |
1570 | LIST_INIT(&pmap->pm_ptpages); | | 1571 | LIST_INIT(&pmap->pm_ptpages); |
| | | 1572 | LIST_INIT(&pmap->pm_pvents); |
1571 | | | 1573 | |
1572 | atomic_store_relaxed(&pmap->pm_count, 1); | | 1574 | atomic_store_relaxed(&pmap->pm_count, 1); |
1573 | | | 1575 | |
1574 | try_again: | | 1576 | try_again: |
1575 | rw_enter(&pmap_growkernel_lock, RW_READER); | | 1577 | rw_enter(&pmap_growkernel_lock, RW_READER); |
1576 | | | 1578 | |
1577 | lev1map = pool_cache_get(&pmap_l1pt_cache, PR_NOWAIT); | | 1579 | lev1map = pool_cache_get(&pmap_l1pt_cache, PR_NOWAIT); |
1578 | if (__predict_false(lev1map == NULL)) { | | 1580 | if (__predict_false(lev1map == NULL)) { |
1579 | rw_exit(&pmap_growkernel_lock); | | 1581 | rw_exit(&pmap_growkernel_lock); |
1580 | (void) kpause("pmap_create", false, hz >> 2, NULL); | | 1582 | (void) kpause("pmap_create", false, hz >> 2, NULL); |
1581 | goto try_again; | | 1583 | goto try_again; |
1582 | } | | 1584 | } |
1583 | | | 1585 | |
| @@ -3268,26 +3270,27 @@ pmap_pv_enter(pmap_t pmap, struct vm_pag | | | @@ -3268,26 +3270,27 @@ pmap_pv_enter(pmap_t pmap, struct vm_pag |
3268 | printf("pmap = %p, va = 0x%lx\n", pmap, va); | | 3270 | printf("pmap = %p, va = 0x%lx\n", pmap, va); |
3269 | panic("pmap_pv_enter: already in pv table"); | | 3271 | panic("pmap_pv_enter: already in pv table"); |
3270 | } | | 3272 | } |
3271 | } | | 3273 | } |
3272 | } | | 3274 | } |
3273 | #endif | | 3275 | #endif |
3274 | | | 3276 | |
3275 | /* | | 3277 | /* |
3276 | * ...and put it in the list. | | 3278 | * ...and put it in the list. |
3277 | */ | | 3279 | */ |
3278 | uintptr_t const attrs = md->pvh_listx & PGA_ATTRS; | | 3280 | uintptr_t const attrs = md->pvh_listx & PGA_ATTRS; |
3279 | newpv->pv_next = (struct pv_entry *)(md->pvh_listx & ~PGA_ATTRS); | | 3281 | newpv->pv_next = (struct pv_entry *)(md->pvh_listx & ~PGA_ATTRS); |
3280 | md->pvh_listx = (uintptr_t)newpv | attrs; | | 3282 | md->pvh_listx = (uintptr_t)newpv | attrs; |
| | | 3283 | LIST_INSERT_HEAD(&pmap->pm_pvents, newpv, pv_link); |
3281 | | | 3284 | |
3282 | if (dolock) { | | 3285 | if (dolock) { |
3283 | mutex_exit(lock); | | 3286 | mutex_exit(lock); |
3284 | } | | 3287 | } |
3285 | | | 3288 | |
3286 | return 0; | | 3289 | return 0; |
3287 | } | | 3290 | } |
3288 | | | 3291 | |
3289 | /* | | 3292 | /* |
3290 | * pmap_pv_remove: | | 3293 | * pmap_pv_remove: |
3291 | * | | 3294 | * |
3292 | * Remove a physical->virtual entry from the pv_table. | | 3295 | * Remove a physical->virtual entry from the pv_table. |
3293 | */ | | 3296 | */ |
| @@ -3306,28 +3309,35 @@ pmap_pv_remove(pmap_t pmap, struct vm_pa | | | @@ -3306,28 +3309,35 @@ pmap_pv_remove(pmap_t pmap, struct vm_pa |
3306 | lock = NULL; /* XXX stupid gcc */ | | 3309 | lock = NULL; /* XXX stupid gcc */ |
3307 | } | | 3310 | } |
3308 | | | 3311 | |
3309 | /* | | 3312 | /* |
3310 | * Find the entry to remove. | | 3313 | * Find the entry to remove. |
3311 | */ | | 3314 | */ |
3312 | for (pvp = (struct pv_entry **)&md->pvh_listx, pv = VM_MDPAGE_PVS(pg); | | 3315 | for (pvp = (struct pv_entry **)&md->pvh_listx, pv = VM_MDPAGE_PVS(pg); |
3313 | pv != NULL; pvp = &pv->pv_next, pv = *pvp) | | 3316 | pv != NULL; pvp = &pv->pv_next, pv = *pvp) |
3314 | if (pmap == pv->pv_pmap && va == pv->pv_va) | | 3317 | if (pmap == pv->pv_pmap && va == pv->pv_va) |
3315 | break; | | 3318 | break; |
3316 | | | 3319 | |
3317 | KASSERT(pv != NULL); | | 3320 | KASSERT(pv != NULL); |
3318 | | | 3321 | |
| | | 3322 | /* |
| | | 3323 | * The page attributes are in the lower 2 bits of the first |
| | | 3324 | * PV entry pointer. Rather than comparing the pointer address |
| | | 3325 | * and branching, we just always preserve what might be there |
| | | 3326 | * (either attribute bits or zero bits). |
| | | 3327 | */ |
3319 | *pvp = (pv_entry_t)((uintptr_t)pv->pv_next | | | 3328 | *pvp = (pv_entry_t)((uintptr_t)pv->pv_next | |
3320 | (((uintptr_t)*pvp) & PGA_ATTRS)); | | 3329 | (((uintptr_t)*pvp) & PGA_ATTRS)); |
| | | 3330 | LIST_REMOVE(pv, pv_link); |
3321 | | | 3331 | |
3322 | if (dolock) { | | 3332 | if (dolock) { |
3323 | mutex_exit(lock); | | 3333 | mutex_exit(lock); |
3324 | } | | 3334 | } |
3325 | | | 3335 | |
3326 | if (opvp != NULL) | | 3336 | if (opvp != NULL) |
3327 | *opvp = pv; | | 3337 | *opvp = pv; |
3328 | else | | 3338 | else |
3329 | pmap_pv_free(pv); | | 3339 | pmap_pv_free(pv); |
3330 | } | | 3340 | } |
3331 | | | 3341 | |
3332 | /* | | 3342 | /* |
3333 | * pmap_pv_page_alloc: | | 3343 | * pmap_pv_page_alloc: |