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:
parent
8903567a14
commit
170f9641df
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
*
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue