| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: pmap.c,v 1.284 2021/05/30 01:41:45 thorpej Exp $ */ | | 1 | /* $NetBSD: pmap.c,v 1.285 2021/05/30 04:04:26 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.284 2021/05/30 01:41:45 thorpej Exp $"); | | 138 | __KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.285 2021/05/30 04:04:26 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> |
| @@ -3348,118 +3348,112 @@ pmap_pv_page_alloc(struct pool *pp, int | | | @@ -3348,118 +3348,112 @@ pmap_pv_page_alloc(struct pool *pp, int |
3348 | * | | 3348 | * |
3349 | * Free a pv_entry pool page. | | 3349 | * Free a pv_entry pool page. |
3350 | */ | | 3350 | */ |
3351 | static void | | 3351 | static void |
3352 | pmap_pv_page_free(struct pool *pp, void *v) | | 3352 | pmap_pv_page_free(struct pool *pp, void *v) |
3353 | { | | 3353 | { |
3354 | | | 3354 | |
3355 | pmap_physpage_free(ALPHA_K0SEG_TO_PHYS((vaddr_t)v)); | | 3355 | pmap_physpage_free(ALPHA_K0SEG_TO_PHYS((vaddr_t)v)); |
3356 | } | | 3356 | } |
3357 | | | 3357 | |
3358 | /******************** misc. functions ********************/ | | 3358 | /******************** misc. functions ********************/ |
3359 | | | 3359 | |
3360 | /* | | 3360 | /* |
| | | 3361 | * Pages that are in-use as page table pages should never be part |
| | | 3362 | * of a UVM loan, so we'll use that field for our PT page reference |
| | | 3363 | * count. |
| | | 3364 | */ |
| | | 3365 | #define PHYSPAGE_REFCNT(pg) atomic_load_relaxed(&(pg)->loan_count) |
| | | 3366 | #define PHYSPAGE_REFCNT_INC(pg) atomic_inc_uint_nv(&(pg)->loan_count) |
| | | 3367 | #define PHYSPAGE_REFCNT_DEC(pg) atomic_dec_uint_nv(&(pg)->loan_count) |
| | | 3368 | |
| | | 3369 | /* |
3361 | * pmap_physpage_alloc: | | 3370 | * pmap_physpage_alloc: |
3362 | * | | 3371 | * |
3363 | * Allocate a single page from the VM system and return the | | 3372 | * Allocate a single page from the VM system and return the |
3364 | * physical address for that page. | | 3373 | * physical address for that page. |
3365 | */ | | 3374 | */ |
3366 | static struct vm_page * | | 3375 | static struct vm_page * |
3367 | pmap_physpage_alloc(int usage) | | 3376 | pmap_physpage_alloc(int usage) |
3368 | { | | 3377 | { |
3369 | struct vm_page *pg; | | 3378 | struct vm_page *pg; |
3370 | | | 3379 | |
3371 | /* | | 3380 | /* |
3372 | * Don't ask for a zero'd page in the L1PT case -- we will | | 3381 | * Don't ask for a zero'd page in the L1PT case -- we will |
3373 | * properly initialize it in the constructor. | | 3382 | * properly initialize it in the constructor. |
3374 | */ | | 3383 | */ |
3375 | | | 3384 | |
3376 | pg = uvm_pagealloc(NULL, 0, NULL, usage == PGU_L1PT ? | | 3385 | pg = uvm_pagealloc(NULL, 0, NULL, usage == PGU_L1PT ? |
3377 | UVM_PGA_USERESERVE : UVM_PGA_USERESERVE|UVM_PGA_ZERO); | | 3386 | UVM_PGA_USERESERVE : UVM_PGA_USERESERVE|UVM_PGA_ZERO); |
3378 | if (pg != NULL) { | | 3387 | if (pg != NULL) { |
3379 | #ifdef DEBUG | | 3388 | KASSERT(PHYSPAGE_REFCNT(pg) == 0); |
3380 | struct vm_page_md * const md = VM_PAGE_TO_MD(pg); | | | |
3381 | if (md->pvh_refcnt != 0) { | | | |
3382 | printf("pmap_physpage_alloc: page 0x%lx has " | | | |
3383 | "%d references\n", pa, md->pvh_refcnt); | | | |
3384 | panic("pmap_physpage_alloc"); | | | |
3385 | } | | | |
3386 | #endif | | | |
3387 | } | | 3389 | } |
3388 | return pg; | | 3390 | return pg; |
3389 | } | | 3391 | } |
3390 | | | 3392 | |
3391 | /* | | 3393 | /* |
3392 | * pmap_physpage_free: | | 3394 | * pmap_physpage_free: |
3393 | * | | 3395 | * |
3394 | * Free the single page table page at the specified physical address. | | 3396 | * Free the single page table page at the specified physical address. |
3395 | */ | | 3397 | */ |
3396 | static void | | 3398 | static void |
3397 | pmap_physpage_free(paddr_t pa) | | 3399 | pmap_physpage_free(paddr_t pa) |
3398 | { | | 3400 | { |
3399 | struct vm_page *pg; | | 3401 | struct vm_page *pg; |
3400 | | | 3402 | |
3401 | if ((pg = PHYS_TO_VM_PAGE(pa)) == NULL) | | 3403 | if ((pg = PHYS_TO_VM_PAGE(pa)) == NULL) |
3402 | panic("pmap_physpage_free: bogus physical page address"); | | 3404 | panic("pmap_physpage_free: bogus physical page address"); |
3403 | | | 3405 | |
3404 | #ifdef DEBUG | | 3406 | KASSERT(PHYSPAGE_REFCNT(pg) == 0); |
3405 | struct vm_page_md * const md = VM_PAGE_TO_MD(pg); | | | |
3406 | if (md->pvh_refcnt != 0) | | | |
3407 | panic("pmap_physpage_free: page still has references"); | | | |
3408 | #endif | | | |
3409 | | | 3407 | |
3410 | uvm_pagefree(pg); | | 3408 | uvm_pagefree(pg); |
3411 | } | | 3409 | } |
3412 | | | 3410 | |
3413 | /* | | 3411 | /* |
3414 | * pmap_physpage_addref: | | 3412 | * pmap_physpage_addref: |
3415 | * | | 3413 | * |
3416 | * Add a reference to the specified special use page. | | 3414 | * Add a reference to the specified special use page. |
3417 | */ | | 3415 | */ |
3418 | static int | | 3416 | static int |
3419 | pmap_physpage_addref(void *kva) | | 3417 | pmap_physpage_addref(void *kva) |
3420 | { | | 3418 | { |
3421 | struct vm_page *pg; | | 3419 | struct vm_page *pg; |
3422 | struct vm_page_md *md; | | | |
3423 | paddr_t pa; | | 3420 | paddr_t pa; |
3424 | | | 3421 | |
3425 | pa = ALPHA_K0SEG_TO_PHYS(trunc_page((vaddr_t)kva)); | | 3422 | pa = ALPHA_K0SEG_TO_PHYS(trunc_page((vaddr_t)kva)); |
3426 | pg = PHYS_TO_VM_PAGE(pa); | | 3423 | pg = PHYS_TO_VM_PAGE(pa); |
3427 | md = VM_PAGE_TO_MD(pg); | | | |
3428 | | | 3424 | |
3429 | KASSERT((int)md->pvh_refcnt >= 0); | | 3425 | KASSERT(PHYSPAGE_REFCNT(pg) < UINT32_MAX); |
3430 | | | 3426 | |
3431 | return atomic_inc_uint_nv(&md->pvh_refcnt); | | 3427 | return PHYSPAGE_REFCNT_INC(pg); |
3432 | } | | 3428 | } |
3433 | | | 3429 | |
3434 | /* | | 3430 | /* |
3435 | * pmap_physpage_delref: | | 3431 | * pmap_physpage_delref: |
3436 | * | | 3432 | * |
3437 | * Delete a reference to the specified special use page. | | 3433 | * Delete a reference to the specified special use page. |
3438 | */ | | 3434 | */ |
3439 | static int | | 3435 | static int |
3440 | pmap_physpage_delref(void *kva) | | 3436 | pmap_physpage_delref(void *kva) |
3441 | { | | 3437 | { |
3442 | struct vm_page *pg; | | 3438 | struct vm_page *pg; |
3443 | struct vm_page_md *md; | | | |
3444 | paddr_t pa; | | 3439 | paddr_t pa; |
3445 | | | 3440 | |
3446 | pa = ALPHA_K0SEG_TO_PHYS(trunc_page((vaddr_t)kva)); | | 3441 | pa = ALPHA_K0SEG_TO_PHYS(trunc_page((vaddr_t)kva)); |
3447 | pg = PHYS_TO_VM_PAGE(pa); | | 3442 | pg = PHYS_TO_VM_PAGE(pa); |
3448 | md = VM_PAGE_TO_MD(pg); | | | |
3449 | | | 3443 | |
3450 | KASSERT((int)md->pvh_refcnt > 0); | | 3444 | KASSERT(PHYSPAGE_REFCNT(pg) != 0); |
3451 | | | 3445 | |
3452 | return atomic_dec_uint_nv(&md->pvh_refcnt); | | 3446 | return PHYSPAGE_REFCNT_DEC(pg); |
3453 | } | | 3447 | } |
3454 | | | 3448 | |
3455 | /******************** page table page management ********************/ | | 3449 | /******************** page table page management ********************/ |
3456 | | | 3450 | |
3457 | static bool | | 3451 | static bool |
3458 | pmap_kptpage_alloc(paddr_t *pap) | | 3452 | pmap_kptpage_alloc(paddr_t *pap) |
3459 | { | | 3453 | { |
3460 | if (uvm.page_init_done == false) { | | 3454 | if (uvm.page_init_done == false) { |
3461 | /* | | 3455 | /* |
3462 | * We're growing the kernel pmap early (from | | 3456 | * We're growing the kernel pmap early (from |
3463 | * uvm_pageboot_alloc()). This case must | | 3457 | * uvm_pageboot_alloc()). This case must |
3464 | * be handled a little differently. | | 3458 | * be handled a little differently. |
3465 | */ | | 3459 | */ |
| @@ -3675,30 +3669,28 @@ pmap_ptpage_free(pmap_t pmap, pt_entry_t | | | @@ -3675,30 +3669,28 @@ pmap_ptpage_free(pmap_t pmap, pt_entry_t |
3675 | struct pmap_tlb_context * const tlbctx) | | 3669 | struct pmap_tlb_context * const tlbctx) |
3676 | { | | 3670 | { |
3677 | | | 3671 | |
3678 | /* | | 3672 | /* |
3679 | * Extract the physical address of the page from the PTE | | 3673 | * Extract the physical address of the page from the PTE |
3680 | * and clear the entry. | | 3674 | * and clear the entry. |
3681 | */ | | 3675 | */ |
3682 | const paddr_t ptpa = pmap_pte_pa(pte); | | 3676 | const paddr_t ptpa = pmap_pte_pa(pte); |
3683 | atomic_store_relaxed(pte, PG_NV); | | 3677 | atomic_store_relaxed(pte, PG_NV); |
3684 | | | 3678 | |
3685 | struct vm_page * const pg = PHYS_TO_VM_PAGE(ptpa); | | 3679 | struct vm_page * const pg = PHYS_TO_VM_PAGE(ptpa); |
3686 | KASSERT(pg != NULL); | | 3680 | KASSERT(pg != NULL); |
3687 | | | 3681 | |
| | | 3682 | KASSERT(PHYSPAGE_REFCNT(pg) == 0); |
3688 | #ifdef DEBUG | | 3683 | #ifdef DEBUG |
3689 | struct vm_page_md * const md = VM_PAGE_TO_MD(pg); | | | |
3690 | KDASSERT(md->pvh_refcnt == 0); | | | |
3691 | | | | |
3692 | pmap_zero_page(ptpa); | | 3684 | pmap_zero_page(ptpa); |
3693 | #endif | | 3685 | #endif |
3694 | | | 3686 | |
3695 | LIST_REMOVE(pg, pageq.list); | | 3687 | LIST_REMOVE(pg, pageq.list); |
3696 | LIST_INSERT_HEAD(&tlbctx->t_freeptq, pg, pageq.list); | | 3688 | LIST_INSERT_HEAD(&tlbctx->t_freeptq, pg, pageq.list); |
3697 | } | | 3689 | } |
3698 | | | 3690 | |
3699 | /* | | 3691 | /* |
3700 | * pmap_l3pt_delref: | | 3692 | * pmap_l3pt_delref: |
3701 | * | | 3693 | * |
3702 | * Delete a reference on a level 3 PT page. If the reference drops | | 3694 | * Delete a reference on a level 3 PT page. If the reference drops |
3703 | * to zero, free it. | | 3695 | * to zero, free it. |
3704 | * | | 3696 | * |