When an OEA kernel is configured for multiple MMU types, use the new

powerpc fixup mechanism to bind the kernel to a particular MMU.  This
avoids an indirect call for every pmap call.
This commit is contained in:
matt 2011-02-12 18:23:09 +00:00
parent e8a328b2a2
commit e13c032f64
9 changed files with 332 additions and 90 deletions

View File

@ -38,7 +38,7 @@
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: booke_stubs.c,v 1.2 2011/01/18 01:02:52 matt Exp $");
__KERNEL_RCSID(0, "$NetBSD: booke_stubs.c,v 1.3 2011/02/12 18:23:09 matt Exp $");
#include <sys/param.h>
#include <sys/cpu.h>
@ -270,5 +270,5 @@ booke_fixup_stubs(void)
extern uint32_t _ftext[];
extern uint32_t _etext[];
powerpc_fixup_stubs(_ftext, _etext);
powerpc_fixup_stubs(_ftext, _etext, NULL, NULL);
}

View File

@ -1,4 +1,4 @@
# $NetBSD: files.powerpc,v 1.73 2011/01/18 01:02:53 matt Exp $
# $NetBSD: files.powerpc,v 1.74 2011/02/12 18:23:09 matt Exp $
defflag opt_altivec.h ALTIVEC K_ALTIVEC PPC_HAVE_SPE
defflag opt_openpic.h OPENPIC OPENPIC_SERIAL_MODE
@ -9,7 +9,7 @@ defparam opt_pmap.h PTEGCOUNT PMAP_MEMLIMIT
file arch/powerpc/powerpc/copystr.c
file arch/powerpc/powerpc/core_machdep.c coredump
file arch/powerpc/powerpc/fixup.c ppc_booke
file arch/powerpc/powerpc/fixup.c ppc_booke | (ppc_oea & ppc_oea64) | (ppc_oea & ppc_oea64_bridge) | (ppc_oea64 & ppc_oea64_bridge)
file arch/powerpc/powerpc/fubyte.c
file arch/powerpc/powerpc/fuswintr.c
file arch/powerpc/powerpc/ipkdb_glue.c ipkdb

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern.ldscript,v 1.3 2011/01/23 17:38:37 matt Exp $ */
/* $NetBSD: kern.ldscript,v 1.4 2011/02/12 18:23:09 matt Exp $ */
/* ldscript for NetBSD/powerpc kernels and LKMs */
OUTPUT_ARCH(powerpc)
@ -18,6 +18,9 @@ SECTIONS
__stub_start = .;
*(.stub)
__stub_end = .;
__stub_pmap_start = .;
*(.stub.pmap)
__stub_pmap_end = .;
*(.gnu.warning)
} =0
_etext = .;

View File

@ -1,4 +1,4 @@
/* $NetBSD: instr.h,v 1.5 2011/01/18 01:02:54 matt Exp $ */
/* $NetBSD: instr.h,v 1.6 2011/02/12 18:23:09 matt Exp $ */
/*
* Copyright (c) 1992, 1993
@ -438,7 +438,7 @@ struct powerpc_jump_fixup_info {
uint32_t jfi_real;
};
void powerpc_fixup_stubs(uint32_t *, uint32_t *);
void powerpc_fixup_stubs(uint32_t *, uint32_t *, uint32_t *, uint32_t *);
#endif /* !_POWERPC_INSTR_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: pmap.h,v 1.20 2011/01/18 01:02:55 matt Exp $ */
/* $NetBSD: pmap.h,v 1.21 2011/02/12 18:23:10 matt Exp $ */
/*-
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
@ -130,12 +130,9 @@ pmap_remove_all(struct pmap *pmap)
}
#if (defined(PPC_OEA) + defined(PPC_OEA64) + defined(PPC_OEA64_BRIDGE)) != 1
#define PMAP_EXCLUDE_DECLS
#define PMAP_NEEDS_FIXUP
#endif
#ifndef PMAP_NOOPNAMES
#if !defined(PMAP_EXCLUDE_DECLS)
void pmap_bootstrap(vaddr_t, vaddr_t);
bool pmap_extract(pmap_t, vaddr_t, paddr_t *);
bool pmap_query_bit(struct vm_page *, int);
@ -145,45 +142,6 @@ void pmap_procwr(struct proc *, vaddr_t, size_t);
int pmap_pte_spill(pmap_t, vaddr_t, bool);
void pmap_pinit(pmap_t);
#else
#define PMAPOPNAME(name) (*pmapops->pmapop_##name)
extern const struct pmap_ops *pmapops;
#define pmap_pte_spill PMAPOPNAME(pte_spill)
#define pmap_real_memory PMAPOPNAME(real_memory)
#define pmap_init PMAPOPNAME(init)
#define pmap_virtual_space PMAPOPNAME(virtual_space)
#define pmap_create PMAPOPNAME(create)
#define pmap_reference PMAPOPNAME(reference)
#define pmap_destroy PMAPOPNAME(destroy)
#define pmap_copy PMAPOPNAME(copy)
#define pmap_update PMAPOPNAME(update)
#define pmap_enter PMAPOPNAME(enter)
#define pmap_remove PMAPOPNAME(remove)
#define pmap_kenter_pa PMAPOPNAME(kenter_pa)
#define pmap_kremove PMAPOPNAME(kremove)
#define pmap_extract PMAPOPNAME(extract)
#define pmap_protect PMAPOPNAME(protect)
#define pmap_unwire PMAPOPNAME(unwire)
#define pmap_page_protect PMAPOPNAME(page_protect)
#define pmap_query_bit PMAPOPNAME(query_bit)
#define pmap_clear_bit PMAPOPNAME(clear_bit)
#define pmap_activate PMAPOPNAME(activate)
#define pmap_deactivate PMAPOPNAME(deactivate)
#define pmap_pinit PMAPOPNAME(pinit)
#define pmap_procwr PMAPOPNAME(procwr)
#define pmap_pte_print PMAPOPNAME(pte_print)
#define pmap_pteg_check PMAPOPNAME(pteg_check)
#define pmap_print_mmuregs PMAPOPNAME(print_mmuregs)
#define pmap_print_pte PMAPOPNAME(print_pte)
#define pmap_pteg_dist PMAPOPNAME(pteg_dist)
#define pmap_pvo_verify PMAPOPNAME(pvo_verify)
#define pmap_steal_memory PMAPOPNAME(steal_memory)
#define pmap_bootstrap PMAPOPNAME(bootstrap)
#endif /* PMAP_EXCLUDE_DECLS */
static inline paddr_t vtophys (vaddr_t);
/*
@ -206,34 +164,37 @@ vtophys(vaddr_t va)
if (pmap_extract(pmap_kernel(), va, &pa))
return pa;
KASSERT(0);
KASSERTMSG(0, ("vtophys: pmap_extract of %#"PRIxVADDR" failed", va));
return (paddr_t) -1;
}
#ifdef PMAP_NEEDS_FIXUP
extern const struct pmap_ops *pmapops;
extern const struct pmap_ops pmap32_ops;
extern const struct pmap_ops pmap64_ops;
extern const struct pmap_ops pmap64bridge_ops;
void pmap_fixup_stubs(const struct pmap_ops *);
static inline void
pmap_setup32(void)
{
pmapops = &pmap32_ops;
pmap_fixup_stubs(&pmap32_ops);
}
static inline void
pmap_setup64(void)
{
pmapops = &pmap64_ops;
pmap_fixup_stubs(&pmap64_ops);
}
static inline void
pmap_setup64bridge(void)
{
pmapops = &pmap64bridge_ops;
pmap_fixup_stubs(&pmap64bridge_ops);
}
#endif /* !PMAP_NOOPNAMES */
#endif
bool pmap_pageidlezero (paddr_t);
void pmap_syncicache (paddr_t, psize_t);

View File

@ -1,4 +1,4 @@
/* $NetBSD: pmap.c,v 1.75 2011/01/18 01:02:55 matt Exp $ */
/* $NetBSD: pmap.c,v 1.76 2011/02/12 18:23:10 matt Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
@ -63,7 +63,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.75 2011/01/18 01:02:55 matt Exp $");
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.76 2011/02/12 18:23:10 matt Exp $");
#define PMAP_NOOPNAMES
@ -121,21 +121,6 @@ static u_int mem_cnt, avail_cnt;
#if !defined(PMAP_OEA64) && !defined(PMAP_OEA64_BRIDGE)
# define PMAP_OEA 1
# if defined(PMAP_EXCLUDE_DECLS) && !defined(PPC_OEA64) && !defined(PPC_OEA64_BRIDGE)
# define PMAPNAME(name) pmap_##name
# endif
#endif
#if defined(PMAP_OEA64)
# if defined(PMAP_EXCLUDE_DECLS) && !defined(PPC_OEA) && !defined(PPC_OEA64_BRIDGE)
# define PMAPNAME(name) pmap_##name
# endif
#endif
#if defined(PMAP_OEA64_BRIDGE)
# if defined(PMAP_EXCLUDE_DECLS) && !defined(PPC_OEA) && !defined(PPC_OEA64)
# define PMAPNAME(name) pmap_##name
# endif
#endif
#if defined(PMAP_OEA)
@ -147,7 +132,7 @@ static u_int mem_cnt, avail_cnt;
#define _PRIxva "lx"
#define _PRIsr "lx"
#if defined(PMAP_EXCLUDE_DECLS) && !defined(PMAPNAME)
#ifdef PMAP_NEEDS_FIXUP
#if defined(PMAP_OEA)
#define PMAPNAME(name) pmap32_##name
#elif defined(PMAP_OEA64)
@ -157,9 +142,9 @@ static u_int mem_cnt, avail_cnt;
#else
#error unknown variant for pmap
#endif
#endif /* PMAP_EXLCUDE_DECLS && !PMAPNAME */
#endif /* PMAP_NEEDS_FIXUP */
#if defined(PMAPNAME)
#ifdef PMAPNAME
#define STATIC static
#define pmap_pte_spill PMAPNAME(pte_spill)
#define pmap_real_memory PMAPNAME(real_memory)

View File

@ -1,6 +1,292 @@
/* $NetBSD: pmap_kernel.c,v 1.2 2008/12/11 19:33:12 pooka Exp $ */
/* $NetBSD: pmap_kernel.c,v 1.3 2011/02/12 18:23:10 matt Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Matt Thomas of 3am Software Foundry.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(1, "$NetBSD: pmap_kernel.c,v 1.3 2011/02/12 18:23:10 matt Exp $");
#include "opt_ddb.h"
#include "opt_pmap.h"
#include <sys/param.h>
#include <uvm/uvm_extern.h>
extern struct pmap kernel_pmap_;
struct pmap *const kernel_pmap_ptr = &kernel_pmap_;
#ifdef PMAP_NEEDS_FIXUP
#include <powerpc/instr.h>
const struct pmap_ops *pmapops;
void
pmap_fixup_stubs(const struct pmap_ops *ops)
{
extern uint32_t _ftext[], _etext[];
extern uint32_t __stub_pmap_start[], __stub_pmap_end[];
pmapops = ops;
powerpc_fixup_stubs(_ftext, _etext, __stub_pmap_start, __stub_pmap_end);
}
#define __stub __section(".stub.pmap")
int pmap_pte_spill(struct pmap *, vaddr_t, bool) __stub;
void pmap_real_memory(paddr_t *, psize_t *) __stub;
void pmap_init(void) __stub;
void pmap_virtual_space(vaddr_t *, vaddr_t *) __stub;
pmap_t pmap_create(void) __stub;
void pmap_reference(pmap_t) __stub;
void pmap_destroy(pmap_t) __stub;
void pmap_copy(pmap_t, pmap_t, vaddr_t, vsize_t, vaddr_t) __stub;
void pmap_update(pmap_t) __stub;
int pmap_enter(pmap_t, vaddr_t, paddr_t, vm_prot_t, u_int) __stub;
void pmap_remove(pmap_t, vaddr_t, vaddr_t) __stub;
void pmap_kenter_pa(vaddr_t, paddr_t, vm_prot_t, u_int) __stub;
void pmap_kremove(vaddr_t, vsize_t) __stub;
bool pmap_extract(pmap_t, vaddr_t, paddr_t *) __stub;
void pmap_protect(pmap_t, vaddr_t, vaddr_t, vm_prot_t) __stub;
void pmap_unwire(pmap_t, vaddr_t) __stub;
void pmap_page_protect(struct vm_page *, vm_prot_t) __stub;
bool pmap_query_bit(struct vm_page *, int) __stub;
bool pmap_clear_bit(struct vm_page *, int) __stub;
void pmap_activate(struct lwp *) __stub;
void pmap_deactivate(struct lwp *) __stub;
void pmap_pinit(pmap_t) __stub;
void pmap_procwr(struct proc *, vaddr_t, size_t) __stub;
#if defined(DEBUG) || defined(PMAPCHECK) || defined(DDB)
void pmap_pte_print(volatile struct pte *) __stub;
void pmap_pteg_check(void) __stub;
void pmap_print_mmuregs(void) __stub;
void pmap_print_pte(pmap_t, vaddr_t) __stub;
void pmap_pteg_dist(void) __stub;
#endif
#if defined(DEBUG) || defined(PMAPCHECK)
void pmap_pvo_verify(void) __stub;
#endif
vaddr_t pmap_steal_memory(vsize_t, vaddr_t *, vaddr_t *) __stub;
void pmap_bootstrap(paddr_t, paddr_t) __stub;
int
pmap_pte_spill(struct pmap *pm, vaddr_t va, bool exec)
{
return (*pmapops->pmapop_pte_spill)(pm, va, exec);
}
void
pmap_real_memory(paddr_t *start, psize_t *size)
{
(*pmapops->pmapop_real_memory)(start, size);
}
void
pmap_init(void)
{
(*pmapops->pmapop_init)();
}
void
pmap_virtual_space(vaddr_t *startp, vaddr_t *endp)
{
(*pmapops->pmapop_virtual_space)(startp, endp);
}
pmap_t
pmap_create(void)
{
return (*pmapops->pmapop_create)();
}
void
pmap_reference(pmap_t pm)
{
(*pmapops->pmapop_reference)(pm);
}
void
pmap_destroy(pmap_t pm)
{
(*pmapops->pmapop_destroy)(pm);
}
void
pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vaddr_t dst_va, vsize_t len,
vaddr_t src_va)
{
(*pmapops->pmapop_copy)(dst_pmap, src_pmap, dst_va, len, src_va);
}
void
pmap_update(pmap_t pm)
{
(*pmapops->pmapop_update)(pm);
}
int
pmap_enter(pmap_t pm, vaddr_t va, paddr_t pa, vm_prot_t prot, u_int flags)
{
return (*pmapops->pmapop_enter)(pm, va, pa, prot, flags);
}
void
pmap_remove(pmap_t pm, vaddr_t start, vaddr_t end)
{
(*pmapops->pmapop_remove)(pm, start, end);
}
void
pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot, u_int flags)
{
(*pmapops->pmapop_kenter_pa)(va, pa, prot, flags);
}
void
pmap_kremove(vaddr_t start, vsize_t end)
{
(*pmapops->pmapop_kremove)(start, end);
}
bool
pmap_extract(pmap_t pm, vaddr_t va, paddr_t *pap)
{
return (*pmapops->pmapop_extract)(pm, va, pap);
}
void
pmap_protect(pmap_t pm, vaddr_t start, vaddr_t end, vm_prot_t prot)
{
(*pmapops->pmapop_protect)(pm, start, end, prot);
}
void
pmap_unwire(pmap_t pm, vaddr_t va)
{
(*pmapops->pmapop_unwire)(pm, va);
}
void
pmap_page_protect(struct vm_page *pg, vm_prot_t prot)
{
(*pmapops->pmapop_page_protect)(pg, prot);
}
bool
pmap_query_bit(struct vm_page *pg, int ptebit)
{
return (*pmapops->pmapop_query_bit)(pg, ptebit);
}
bool
pmap_clear_bit(struct vm_page *pg, int ptebit)
{
return (*pmapops->pmapop_clear_bit)(pg, ptebit);
}
void
pmap_activate(struct lwp *l)
{
(*pmapops->pmapop_activate)(l);
}
void
pmap_deactivate(struct lwp *l)
{
(*pmapops->pmapop_deactivate)(l);
}
void
pmap_pinit(pmap_t pm)
{
(*pmapops->pmapop_pinit)(pm);
}
void
pmap_procwr(struct proc *p, vaddr_t va, size_t len)
{
(*pmapops->pmapop_procwr)(p, va, len);
}
#if defined(DEBUG) || defined(PMAPCHECK) || defined(DDB)
void
pmap_pte_print(volatile struct pte *ptep)
{
(*pmapops->pmapop_pte_print)(ptep);
}
void
pmap_pteg_check(void)
{
(*pmapops->pmapop_pteg_check)();
}
void
pmap_print_mmuregs(void)
{
(*pmapops->pmapop_print_mmuregs)();
}
void
pmap_print_pte(pmap_t pm, vaddr_t va)
{
(*pmapops->pmapop_print_pte)(pm, va);
}
void
pmap_pteg_dist(void)
{
(*pmapops->pmapop_pteg_dist)();
}
#endif
#if defined(DEBUG) || defined(PMAPCHECK)
void
pmap_pvo_verify(void)
{
(*pmapops->pmapop_pvo_verify)(void)
}
#endif
vaddr_t
pmap_steal_memory(vsize_t vsize, vaddr_t *vstartp, vaddr_t *vendp)
{
return (*pmapops->pmapop_steal_memory)(vsize, vstartp, vendp);
}
void
pmap_bootstrap(paddr_t startkernel, paddr_t endkernel)
{
(*pmapops->pmapop_bootstrap)(startkernel, endkernel);
}
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: fixup.c,v 1.2 2011/01/18 01:02:55 matt Exp $ */
/* $NetBSD: fixup.c,v 1.3 2011/02/12 18:23:10 matt Exp $ */
/*-
* Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
* All rights reserved.
@ -36,7 +36,7 @@
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: fixup.c,v 1.2 2011/01/18 01:02:55 matt Exp $");
__KERNEL_RCSID(0, "$NetBSD: fixup.c,v 1.3 2011/02/12 18:23:10 matt Exp $");
#include <sys/param.h>
#include <sys/types.h>
@ -65,7 +65,8 @@ fixup_jump(uint32_t *insnp, const struct powerpc_jump_fixup_info *jfi)
}
void
powerpc_fixup_stubs(uint32_t *start, uint32_t *end)
powerpc_fixup_stubs(uint32_t *start, uint32_t *end,
uint32_t *stub_start, uint32_t *stub_end)
{
extern uint32_t __stub_start[], __stub_end[];
#ifdef DEBUG
@ -73,6 +74,11 @@ powerpc_fixup_stubs(uint32_t *start, uint32_t *end)
uint64_t cycles = mftb();
#endif
if (stub_start == NULL) {
stub_start = __stub_start;
stub_end = __stub_end;
}
if (end > __stub_start)
end = __stub_start;
@ -86,8 +92,7 @@ powerpc_fixup_stubs(uint32_t *start, uint32_t *end)
* First we check to see if this is a jump and whether it is
* within the range we are interested in.
*/
if (opcode != OPC_B || stub < __stub_start
|| __stub_end <= stub)
if (opcode != OPC_B || stub < stub_start || stub_end <= stub)
continue;
fixup.jfi_stub = fixup_addr2offset(stub);
@ -100,26 +105,32 @@ powerpc_fixup_stubs(uint32_t *start, uint32_t *end)
register_t ctr = 0;
uint32_t valid_mask = (1 << 1);
int r_lr = -1;
for (; stub < __stub_end && fixup.jfi_real == 0; stub++) {
for (; stub < stub_end && fixup.jfi_real == 0; stub++) {
const union instr i = { .i_int = *stub };
switch (i.i_any.i_opcd) {
case OPC_integer_31: {
const u_int rs = i.i_x.i_rs;
#ifdef DIAGNOSTIC
const u_int ra = i.i_x.i_ra;
const u_int rb = i.i_x.i_rb;
#endif
switch (i.i_x.i_xo) {
case OPC31_MFSPR: {
#ifdef DIAGNOSTIC
const u_int spr = (rb << 5) | ra;
KASSERT(spr == SPR_LR);
#endif
valid_mask |= (1 << rs);
r_lr = rs;
break;
}
case OPC31_MTSPR: {
#ifdef DIAGNOSTIC
const u_int spr = (rb << 5) | ra;
KASSERT(valid_mask & (1 << rs));
KASSERT(spr == SPR_CTR);
#endif
ctr = fixreg[rs];
break;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: pmap_subr.c,v 1.25 2010/11/12 07:59:27 uebayasi Exp $ */
/* $NetBSD: pmap_subr.c,v 1.26 2011/02/12 18:23:10 matt Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: pmap_subr.c,v 1.25 2010/11/12 07:59:27 uebayasi Exp $");
__KERNEL_RCSID(0, "$NetBSD: pmap_subr.c,v 1.26 2011/02/12 18:23:10 matt Exp $");
#include "opt_multiprocessor.h"
#include "opt_altivec.h"
@ -54,10 +54,6 @@ __KERNEL_RCSID(0, "$NetBSD: pmap_subr.c,v 1.25 2010/11/12 07:59:27 uebayasi Exp
#define MFMSR() mfmsr()
#define MTMSR(psl) __asm volatile("sync; mtmsr %0; isync" :: "r"(psl))
#ifdef PMAP_EXCLUDE_DECLS
const struct pmap_ops *pmapops;
#endif
#ifdef PMAPCOUNTERS
#define PMAPCOUNT(ev) ((pmap_evcnt_ ## ev).ev_count++)
#define PMAPCOUNT2(ev) ((ev).ev_count++)