Use 4K pages on ARM_MMU_EXTENDED platforms (all armv[67] except RPI) by

creating a new pool l1ttpl for the userland L1 translation table which
needs to be 8KB and 8KB aligned.

Limit the pool to maxproc and add hooks to allow the sysctl changing of
maxproc to adjust the pool.

This comes at a 5% performance penalty for build.sh -j8 kernel on a
Tegra TK1.
This commit is contained in:
skrll 2020-01-18 14:40:03 +00:00
parent 8903567a14
commit 170f9641df
8 changed files with 179 additions and 46 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.c,v 1.140 2020/01/15 08:34:04 mrg Exp $ */
/* $NetBSD: cpu.c,v 1.141 2020/01/18 14:40:04 skrll Exp $ */
/*
* Copyright (c) 1995 Mark Brinicombe.
@ -46,7 +46,7 @@
#include "opt_multiprocessor.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.140 2020/01/15 08:34:04 mrg Exp $");
__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.141 2020/01/18 14:40:04 skrll Exp $");
#include <sys/param.h>
#include <sys/conf.h>
@ -886,3 +886,12 @@ identify_features(device_t dv)
"pfr: [0]=%#x [1]=%#x\n",
cpu_processor_features[0], cpu_processor_features[1]);
}
#ifdef _ARM_ARCH_6
int
cpu_maxproc_hook(int nmaxproc)
{
return pmap_maxproc_set(nmaxproc);
}
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: pmap.c,v 1.379 2020/01/18 07:52:33 skrll Exp $ */
/* $NetBSD: pmap.c,v 1.380 2020/01/18 14:40:04 skrll Exp $ */
/*
* Copyright 2003 Wasabi Systems, Inc.
@ -221,7 +221,7 @@
#include <arm/db_machdep.h>
#endif
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.379 2020/01/18 07:52:33 skrll Exp $");
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.380 2020/01/18 14:40:04 skrll Exp $");
//#define PMAP_DEBUG
#ifdef PMAP_DEBUG
@ -745,6 +745,7 @@ static void pmap_use_l1(pmap_t);
static struct l2_bucket *pmap_get_l2_bucket(pmap_t, vaddr_t);
static struct l2_bucket *pmap_alloc_l2_bucket(pmap_t, vaddr_t);
static int pmap_l1tt_ctor(void *, void *, int);
static void pmap_free_l2_bucket(pmap_t, struct l2_bucket *, u_int);
static int pmap_l2ptp_ctor(void *, void *, int);
static int pmap_l2dtable_ctor(void *, void *, int);
@ -778,6 +779,20 @@ static void pmap_init_l1(struct l1_ttable *, pd_entry_t *);
#endif
static vaddr_t kernel_pt_lookup(paddr_t);
#ifdef ARM_MMU_EXTENDED
static struct pool_cache pmap_l1tt_cache;
static void *pmap_l1tt_alloc(struct pool *, int);
static void pmap_l1tt_free(struct pool *, void *);
static struct pool_allocator pmap_l1tt_allocator = {
.pa_alloc = pmap_l1tt_alloc,
.pa_free = pmap_l1tt_free,
.pa_pagesz = L1TT_SIZE,
};
#endif
/*
* Misc variables
@ -1290,6 +1305,29 @@ pmap_modify_pv(struct vm_page_md *md, paddr_t pa, pmap_t pm, vaddr_t va,
return (oflags);
}
#if defined(ARM_MMU_EXTENDED)
int
pmap_maxproc_set(int nmaxproc)
{
static const char pmap_l1ttpool_warnmsg[] =
"WARNING: l1ttpool limit reached; increase kern.maxproc";
// pool_cache_setlowat(&pmap_l1tt_cache, nmaxproc);
/*
* Set the hard limit on the pmap_l1tt_cache to the number
* of processes the kernel is to support. Log the limit
* reached message max once a minute.
*/
pool_cache_sethardlimit(&pmap_l1tt_cache, nmaxproc,
pmap_l1ttpool_warnmsg, 60);
return 0;
}
#endif
/*
* Allocate an L1 translation table for the specified pmap.
* This is called at pmap creation time.
@ -1298,33 +1336,11 @@ static void
pmap_alloc_l1(pmap_t pm)
{
#ifdef ARM_MMU_EXTENDED
#ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS
struct vm_page *pg;
bool ok __diagused;
for (;;) {
#ifdef PMAP_NEED_ALLOC_POOLPAGE
pg = arm_pmap_alloc_poolpage(UVM_PGA_ZERO);
#else
pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO);
#endif
if (pg != NULL)
break;
uvm_wait("pmapl1alloc");
}
pm->pm_l1_pa = VM_PAGE_TO_PHYS(pg);
vaddr_t va = pmap_direct_mapped_phys(pm->pm_l1_pa, &ok, 0);
KASSERT(ok);
KASSERT(va >= KERNEL_BASE);
vaddr_t va = (vaddr_t)pool_cache_get_paddr(&pmap_l1tt_cache, PR_WAITOK,
&pm->pm_l1_pa);
#else
KASSERTMSG(kernel_map != NULL, "pm %p", pm);
vaddr_t va = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
UVM_KMF_WIRED|UVM_KMF_ZERO);
KASSERT(va);
pmap_extract(pmap_kernel(), va, &pm->pm_l1_pa);
#endif
pm->pm_l1 = (pd_entry_t *)va;
PTE_SYNC_RANGE(pm->pm_l1, PAGE_SIZE / sizeof(pt_entry_t));
PTE_SYNC_RANGE(pm->pm_l1, L1TT_SIZE / sizeof(pt_entry_t));
#else
struct l1_ttable *l1;
uint8_t domain;
@ -1369,12 +1385,8 @@ static void
pmap_free_l1(pmap_t pm)
{
#ifdef ARM_MMU_EXTENDED
#ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS
struct vm_page *pg = PHYS_TO_VM_PAGE(pm->pm_l1_pa);
uvm_pagefree(pg);
#else
uvm_km_free(kernel_map, (vaddr_t)pm->pm_l1, PAGE_SIZE, UVM_KMF_WIRED);
#endif
pool_cache_put_paddr(&pmap_l1tt_cache, (void *)pm->pm_l1, pm->pm_l1_pa);
pm->pm_l1 = NULL;
pm->pm_l1_pa = 0;
#else
@ -1671,6 +1683,24 @@ pmap_free_l2_bucket(pmap_t pm, struct l2_bucket *l2b, u_int count)
pmap_free_l2_dtable(l2);
}
#if defined(ARM_MMU_EXTENDED)
/*
* Pool cache constructors for L1 translation tables
*/
static int
pmap_l1tt_ctor(void *arg, void *v, int flags)
{
#ifndef PMAP_INCLUDE_PTE_SYNC
#error not supported
#endif
memset(v, 0, L1TT_SIZE);
PTE_SYNC_RANGE(v, L1TT_SIZE / sizeof(pt_entry_t));
return 0;
}
#endif
/*
* Pool cache constructors for L2 descriptor tables, metadata and pmap
* structures.
@ -6484,6 +6514,17 @@ pmap_init(void)
pool_setlowat(&pmap_pv_pool, (PAGE_SIZE / sizeof(struct pv_entry)) * 2);
#ifdef ARM_MMU_EXTENDED
/*
* Initialise the L1 pool and cache.
*/
pool_cache_bootstrap(&pmap_l1tt_cache, L1TT_SIZE, L1TT_SIZE,
0, 0, "l1ttpl", &pmap_l1tt_allocator, IPL_NONE, pmap_l1tt_ctor,
NULL, NULL);
int error __diagused = pmap_maxproc_set(maxproc);
KASSERT(error == 0);
pmap_tlb_info_evcnt_attach(&pmap_tlb0_info);
#endif
@ -6535,6 +6576,75 @@ pmap_bootstrap_pv_page_free(struct pool *pp, void *v)
}
}
#if defined(ARM_MMU_EXTENDED)
static void *
pmap_l1tt_alloc(struct pool *pp, int flags)
{
struct pglist plist;
vaddr_t va;
const int waitok = flags & PR_WAITOK;
int error = uvm_pglistalloc(L1TT_SIZE, 0, -1, L1TT_SIZE, 0, &plist, 1,
waitok);
if (error)
panic("Cannot allocate L1TT physical pages, %d", error);
struct vm_page *pg = TAILQ_FIRST(&plist);
#if !defined( __HAVE_MM_MD_DIRECT_MAPPED_PHYS)
/* Allocate a L1 translation table VA */
va = uvm_km_alloc(kernel_map, L1TT_SIZE, L1TT_SIZE, UVM_KMF_VAONLY);
if (va == 0)
panic("Cannot allocate L1TT KVA");
const vaddr_t eva = va + L1TT_SIZE;
vaddr_t mva = va;
while (pg && mva < eva) {
paddr_t pa = VM_PAGE_TO_PHYS(pg);
pmap_kenter_pa(mva, pa,
VM_PROT_READ|VM_PROT_WRITE, PMAP_KMPAGE|PMAP_PTE);
mva += PAGE_SIZE;
pg = TAILQ_NEXT(pg, pageq.queue);
}
KASSERTMSG(pg == NULL && mva == eva, "pg %p mva %" PRIxVADDR
" eva %" PRIxVADDR, pg, mva, eva);
#else
bool ok;
paddr_t pa = VM_PAGE_TO_PHYS(pg);
va = pmap_direct_mapped_phys(pa, &ok, 0);
KASSERT(ok);
KASSERT(va >= KERNEL_BASE);
#endif
return (void *)va;
}
static void
pmap_l1tt_free(struct pool *pp, void *v)
{
vaddr_t va = (vaddr_t)v;
#if !defined( __HAVE_MM_MD_DIRECT_MAPPED_PHYS)
uvm_km_free(kernel_map, va, L1TT_SIZE, 0);
#else
paddr_t pa;
bool ok = pmap_extract(pmap_kernel(), va, &pa);
KASSERT(ok);
const paddr_t epa = pa + L1TT_SIZE;
for (; pa < epa; pa += PAGE_SIZE) {
struct vm_page *pg = PHYS_TO_VM_PAGE(pa);
uvm_pagefree(pg);
}
#endif
}
#endif
/*
* pmap_postinit()
*

View File

@ -1,4 +1,4 @@
/* $NetBSD: param.h,v 1.27 2019/06/19 09:53:39 skrll Exp $ */
/* $NetBSD: param.h,v 1.28 2020/01/18 14:40:04 skrll Exp $ */
/*
* Copyright (c) 1994,1995 Mark Brinicombe.
@ -46,12 +46,8 @@
* this file. */
#ifndef PGSHIFT
#if defined(_ARM_ARCH_6)
#define PGSHIFT 13 /* LOG2(NBPG) */
#else
#define PGSHIFT 12 /* LOG2(NBPG) */
#endif
#endif
#define NBPG (1 << PGSHIFT) /* bytes/page */
#define PGOFSET (NBPG - 1) /* byte offset into page */
#define NPTEPG (NBPG / sizeof(pt_entry_t)) /* PTEs per Page */

View File

@ -1,4 +1,4 @@
/* $NetBSD: pmap.h,v 1.158 2020/01/12 20:06:52 christos Exp $ */
/* $NetBSD: pmap.h,v 1.159 2020/01/18 14:40:04 skrll Exp $ */
/*
* Copyright (c) 2002, 2003 Wasabi Systems, Inc.
@ -383,6 +383,10 @@ bool pmap_extract(pmap_t, vaddr_t, paddr_t *);
void pmap_prefer(vaddr_t, vaddr_t *, int);
#endif
#ifdef _ARM_ARCH_6
int pmap_maxproc_set(int);
#endif
void pmap_icache_sync_range(pmap_t, vaddr_t, vaddr_t);
/* Functions we use internally. */

View File

@ -1,4 +1,4 @@
/* $NetBSD: pte.h,v 1.20 2019/06/19 09:54:15 skrll Exp $ */
/* $NetBSD: pte.h,v 1.21 2020/01/18 14:40:04 skrll Exp $ */
/*
* Copyright (c) 2001, 2002 Wasabi Systems, Inc.
@ -141,6 +141,8 @@ typedef uint32_t pt_entry_t; /* L2 table entry */
#define L1_TABLE_SIZE_REAL 0x4000 /* 16K */
#define L2_TABLE_SIZE_REAL 0x400 /* 1K */
#define L1TT_SIZE 0x2000 /* 8K */
/*
* ARM L1 Descriptors
*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.h,v 1.104 2020/01/15 08:34:04 mrg Exp $ */
/* $NetBSD: cpu.h,v 1.105 2020/01/18 14:40:04 skrll Exp $ */
/*
* Copyright (c) 1994-1996 Mark Brinicombe.
@ -329,6 +329,10 @@ vaddr_t cpu_uarea_alloc_idlelwp(struct cpu_info *);
*/
void cpu_attach(device_t, cpuid_t);
#ifdef _ARM_ARCH_6
int cpu_maxproc_hook(int);
#endif
#endif /* !_LOCORE */
#endif /* _KERNEL */

View File

@ -1,4 +1,4 @@
/* $NetBSD: types.h,v 1.39 2020/01/17 20:28:14 skrll Exp $ */
/* $NetBSD: types.h,v 1.40 2020/01/18 14:40:04 skrll Exp $ */
/*
* Copyright (c) 1990 The Regents of the University of California.
@ -91,6 +91,7 @@ typedef int __register_t;
#define __HAVE_ATOMIC64_OPS
#endif
#if defined(_ARM_ARCH_6)
#define __HAVE_MAXPROC_HOOK
#define __HAVE_UCAS_MP
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: init_sysctl.c,v 1.223 2020/01/02 15:42:27 thorpej Exp $ */
/* $NetBSD: init_sysctl.c,v 1.224 2020/01/18 14:40:03 skrll Exp $ */
/*-
* Copyright (c) 2003, 2007, 2008, 2009 The NetBSD Foundation, Inc.
@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: init_sysctl.c,v 1.223 2020/01/02 15:42:27 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: init_sysctl.c,v 1.224 2020/01/18 14:40:03 skrll Exp $");
#include "opt_sysv.h"
#include "opt_compat_netbsd.h"
@ -874,6 +874,13 @@ sysctl_kern_maxproc(SYSCTLFN_ARGS)
if (nmaxproc > cpu_maxproc())
return (EINVAL);
#endif
error = 0;
#ifdef __HAVE_MAXPROC_HOOK
error = cpu_maxproc_hook(nmaxproc);
#endif
if (error)
return error;
maxproc = nmaxproc;
return (0);