Sun May 30 04:04:27 2021 UTC ()
Pages that are in-use as page table pages should never be part of a
UVM loan transaction, so use the vm_page::loan_count field as the PT
page reference count.


(thorpej)
diff -r1.284 -r1.285 src/sys/arch/alpha/alpha/pmap.c
diff -r1.90 -r1.91 src/sys/arch/alpha/include/pmap.h

cvs diff -r1.284 -r1.285 src/sys/arch/alpha/alpha/pmap.c (expand / switch to unified diff)

--- src/sys/arch/alpha/alpha/pmap.c 2021/05/30 01:41:45 1.284
+++ src/sys/arch/alpha/alpha/pmap.c 2021/05/30 04:04:26 1.285
@@ -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 */
3351static void 3351static void
3352pmap_pv_page_free(struct pool *pp, void *v) 3352pmap_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 */
3366static struct vm_page * 3375static struct vm_page *
3367pmap_physpage_alloc(int usage) 3376pmap_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 */
3396static void 3398static void
3397pmap_physpage_free(paddr_t pa) 3399pmap_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 */
3418static int 3416static int
3419pmap_physpage_addref(void *kva) 3417pmap_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 */
3439static int 3435static int
3440pmap_physpage_delref(void *kva) 3436pmap_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
3457static bool 3451static bool
3458pmap_kptpage_alloc(paddr_t *pap) 3452pmap_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 *

cvs diff -r1.90 -r1.91 src/sys/arch/alpha/include/pmap.h (expand / switch to unified diff)

--- src/sys/arch/alpha/include/pmap.h 2021/05/30 01:41:45 1.90
+++ src/sys/arch/alpha/include/pmap.h 2021/05/30 04:04:26 1.91
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: pmap.h,v 1.90 2021/05/30 01:41:45 thorpej Exp $ */ 1/* $NetBSD: pmap.h,v 1.91 2021/05/30 04:04:26 thorpej Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1998, 1999, 2000, 2001, 2007 The NetBSD Foundation, Inc. 4 * Copyright (c) 1998, 1999, 2000, 2001, 2007 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 Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center and by Chris G. Demetriou. 9 * NASA Ames Research Center and by Chris G. Demetriou.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
@@ -351,25 +351,24 @@ do { \ @@ -351,25 +351,24 @@ do { \
351 if ((pmap)->pm_percpu[cpu_id].pmc_needisync) { \ 351 if ((pmap)->pm_percpu[cpu_id].pmc_needisync) { \
352 (pmap)->pm_percpu[cpu_id].pmc_needisync = 0; \ 352 (pmap)->pm_percpu[cpu_id].pmc_needisync = 0; \
353 alpha_pal_imb(); \ 353 alpha_pal_imb(); \
354 } \ 354 } \
355} while (0) 355} while (0)
356 356
357/* 357/*
358 * pmap-specific data store in the vm_page structure. 358 * pmap-specific data store in the vm_page structure.
359 */ 359 */
360#define __HAVE_VM_PAGE_MD 360#define __HAVE_VM_PAGE_MD
361struct vm_page_md { 361struct vm_page_md {
362 struct pv_entry *pvh_list; /* pv_entry list */ 362 struct pv_entry *pvh_list; /* pv_entry list */
363 int pvh_attrs; /* page attributes */ 363 int pvh_attrs; /* page attributes */
364 unsigned pvh_refcnt; 
365}; 364};
366 365
367#define VM_MDPAGE_INIT(pg) \ 366#define VM_MDPAGE_INIT(pg) \
368do { \ 367do { \
369 (pg)->mdpage.pvh_list = NULL; \ 368 (pg)->mdpage.pvh_list = NULL; \
370 (pg)->mdpage.pvh_refcnt = 0; \ 369 (pg)->mdpage.pvh_attrs = 0; \
371} while (/*CONSTCOND*/0) 370} while (/*CONSTCOND*/0)
372 371
373#endif /* _KERNEL */ 372#endif /* _KERNEL */
374 373
375#endif /* _PMAP_MACHINE_ */ 374#endif /* _PMAP_MACHINE_ */