Remove now unused armv4 and not-INTRNG files.
This commit is contained in:
parent
412ef5da8a
commit
b88b275145
@ -256,9 +256,6 @@ struct cpu_functions cortexa_cpufuncs = {
|
||||
|
||||
struct cpu_functions cpufuncs;
|
||||
u_int cputype;
|
||||
#if __ARM_ARCH <= 5
|
||||
u_int cpu_reset_needs_v4_MMU_disable; /* flag used in locore-v4.s */
|
||||
#endif
|
||||
|
||||
#if defined (CPU_ARM9E) || \
|
||||
defined(CPU_ARM1176) || \
|
||||
|
@ -1,341 +0,0 @@
|
||||
/* $NetBSD: cpu.c,v 1.55 2004/02/13 11:36:10 wiz Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995 Mark Brinicombe.
|
||||
* Copyright (c) 1995 Brini.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Brini.
|
||||
* 4. The name of the company nor the name of the author may be used to
|
||||
* endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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.
|
||||
*
|
||||
* RiscBSD kernel project
|
||||
*
|
||||
* cpu.c
|
||||
*
|
||||
* Probing and configuration for the master CPU
|
||||
*
|
||||
* Created : 10/10/95
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/endian.h>
|
||||
|
||||
#include <machine/md_var.h>
|
||||
|
||||
char machine[] = "arm";
|
||||
|
||||
SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD,
|
||||
machine, 0, "Machine class");
|
||||
|
||||
static const char * const generic_steppings[16] = {
|
||||
"rev 0", "rev 1", "rev 2", "rev 3",
|
||||
"rev 4", "rev 5", "rev 6", "rev 7",
|
||||
"rev 8", "rev 9", "rev 10", "rev 11",
|
||||
"rev 12", "rev 13", "rev 14", "rev 15",
|
||||
};
|
||||
|
||||
static const char * const xscale_steppings[16] = {
|
||||
"step A-0", "step A-1", "step B-0", "step C-0",
|
||||
"step D-0", "rev 5", "rev 6", "rev 7",
|
||||
"rev 8", "rev 9", "rev 10", "rev 11",
|
||||
"rev 12", "rev 13", "rev 14", "rev 15",
|
||||
};
|
||||
|
||||
static const char * const i80219_steppings[16] = {
|
||||
"step A-0", "rev 1", "rev 2", "rev 3",
|
||||
"rev 4", "rev 5", "rev 6", "rev 7",
|
||||
"rev 8", "rev 9", "rev 10", "rev 11",
|
||||
"rev 12", "rev 13", "rev 14", "rev 15",
|
||||
};
|
||||
|
||||
static const char * const i80321_steppings[16] = {
|
||||
"step A-0", "step B-0", "rev 2", "rev 3",
|
||||
"rev 4", "rev 5", "rev 6", "rev 7",
|
||||
"rev 8", "rev 9", "rev 10", "rev 11",
|
||||
"rev 12", "rev 13", "rev 14", "rev 15",
|
||||
};
|
||||
|
||||
static const char * const i81342_steppings[16] = {
|
||||
"step A-0", "rev 1", "rev 2", "rev 3",
|
||||
"rev 4", "rev 5", "rev 6", "rev 7",
|
||||
"rev 8", "rev 9", "rev 10", "rev 11",
|
||||
"rev 12", "rev 13", "rev 14", "rev 15",
|
||||
};
|
||||
|
||||
/* Steppings for PXA2[15]0 */
|
||||
static const char * const pxa2x0_steppings[16] = {
|
||||
"step A-0", "step A-1", "step B-0", "step B-1",
|
||||
"step B-2", "step C-0", "rev 6", "rev 7",
|
||||
"rev 8", "rev 9", "rev 10", "rev 11",
|
||||
"rev 12", "rev 13", "rev 14", "rev 15",
|
||||
};
|
||||
|
||||
/* Steppings for PXA255/26x.
|
||||
* rev 5: PXA26x B0, rev 6: PXA255 A0
|
||||
*/
|
||||
static const char * const pxa255_steppings[16] = {
|
||||
"rev 0", "rev 1", "rev 2", "step A-0",
|
||||
"rev 4", "step B-0", "step A-0", "rev 7",
|
||||
"rev 8", "rev 9", "rev 10", "rev 11",
|
||||
"rev 12", "rev 13", "rev 14", "rev 15",
|
||||
};
|
||||
|
||||
/* Stepping for PXA27x */
|
||||
static const char * const pxa27x_steppings[16] = {
|
||||
"step A-0", "step A-1", "step B-0", "step B-1",
|
||||
"step C-0", "rev 5", "rev 6", "rev 7",
|
||||
"rev 8", "rev 9", "rev 10", "rev 11",
|
||||
"rev 12", "rev 13", "rev 14", "rev 15",
|
||||
};
|
||||
|
||||
struct cpuidtab {
|
||||
u_int32_t cpuid;
|
||||
enum cpu_class cpu_class;
|
||||
const char *cpu_name;
|
||||
const char * const *cpu_steppings;
|
||||
};
|
||||
|
||||
const struct cpuidtab cpuids[] = {
|
||||
{ CPU_ID_ARM920T, CPU_CLASS_ARM9TDMI, "ARM920T",
|
||||
generic_steppings },
|
||||
{ CPU_ID_ARM920T_ALT, CPU_CLASS_ARM9TDMI, "ARM920T",
|
||||
generic_steppings },
|
||||
{ CPU_ID_ARM922T, CPU_CLASS_ARM9TDMI, "ARM922T",
|
||||
generic_steppings },
|
||||
{ CPU_ID_ARM926EJS, CPU_CLASS_ARM9EJS, "ARM926EJ-S",
|
||||
generic_steppings },
|
||||
{ CPU_ID_ARM940T, CPU_CLASS_ARM9TDMI, "ARM940T",
|
||||
generic_steppings },
|
||||
{ CPU_ID_ARM946ES, CPU_CLASS_ARM9ES, "ARM946E-S",
|
||||
generic_steppings },
|
||||
{ CPU_ID_ARM966ES, CPU_CLASS_ARM9ES, "ARM966E-S",
|
||||
generic_steppings },
|
||||
{ CPU_ID_ARM966ESR1, CPU_CLASS_ARM9ES, "ARM966E-S",
|
||||
generic_steppings },
|
||||
{ CPU_ID_FA526, CPU_CLASS_ARM9TDMI, "FA526",
|
||||
generic_steppings },
|
||||
{ CPU_ID_FA626TE, CPU_CLASS_ARM9ES, "FA626TE",
|
||||
generic_steppings },
|
||||
|
||||
{ CPU_ID_TI925T, CPU_CLASS_ARM9TDMI, "TI ARM925T",
|
||||
generic_steppings },
|
||||
|
||||
{ CPU_ID_ARM1020E, CPU_CLASS_ARM10E, "ARM1020E",
|
||||
generic_steppings },
|
||||
{ CPU_ID_ARM1022ES, CPU_CLASS_ARM10E, "ARM1022E-S",
|
||||
generic_steppings },
|
||||
{ CPU_ID_ARM1026EJS, CPU_CLASS_ARM10EJ, "ARM1026EJ-S",
|
||||
generic_steppings },
|
||||
|
||||
{ CPU_ID_80200, CPU_CLASS_XSCALE, "i80200",
|
||||
xscale_steppings },
|
||||
|
||||
{ CPU_ID_80321_400, CPU_CLASS_XSCALE, "i80321 400MHz",
|
||||
i80321_steppings },
|
||||
{ CPU_ID_80321_600, CPU_CLASS_XSCALE, "i80321 600MHz",
|
||||
i80321_steppings },
|
||||
{ CPU_ID_80321_400_B0, CPU_CLASS_XSCALE, "i80321 400MHz",
|
||||
i80321_steppings },
|
||||
{ CPU_ID_80321_600_B0, CPU_CLASS_XSCALE, "i80321 600MHz",
|
||||
i80321_steppings },
|
||||
|
||||
{ CPU_ID_81342, CPU_CLASS_XSCALE, "i81342",
|
||||
i81342_steppings },
|
||||
|
||||
{ CPU_ID_80219_400, CPU_CLASS_XSCALE, "i80219 400MHz",
|
||||
i80219_steppings },
|
||||
{ CPU_ID_80219_600, CPU_CLASS_XSCALE, "i80219 600MHz",
|
||||
i80219_steppings },
|
||||
|
||||
{ CPU_ID_PXA27X, CPU_CLASS_XSCALE, "PXA27x",
|
||||
pxa27x_steppings },
|
||||
{ CPU_ID_PXA250A, CPU_CLASS_XSCALE, "PXA250",
|
||||
pxa2x0_steppings },
|
||||
{ CPU_ID_PXA210A, CPU_CLASS_XSCALE, "PXA210",
|
||||
pxa2x0_steppings },
|
||||
{ CPU_ID_PXA250B, CPU_CLASS_XSCALE, "PXA250",
|
||||
pxa2x0_steppings },
|
||||
{ CPU_ID_PXA210B, CPU_CLASS_XSCALE, "PXA210",
|
||||
pxa2x0_steppings },
|
||||
{ CPU_ID_PXA250C, CPU_CLASS_XSCALE, "PXA255",
|
||||
pxa255_steppings },
|
||||
{ CPU_ID_PXA210C, CPU_CLASS_XSCALE, "PXA210",
|
||||
pxa2x0_steppings },
|
||||
|
||||
{ CPU_ID_MV88FR131, CPU_CLASS_MARVELL, "Feroceon 88FR131",
|
||||
generic_steppings },
|
||||
|
||||
{ CPU_ID_MV88FR571_VD, CPU_CLASS_MARVELL, "Feroceon 88FR571-VD",
|
||||
generic_steppings },
|
||||
{ 0, CPU_CLASS_NONE, NULL, NULL }
|
||||
};
|
||||
|
||||
struct cpu_classtab {
|
||||
const char *class_name;
|
||||
const char *class_option;
|
||||
};
|
||||
|
||||
const struct cpu_classtab cpu_classes[] = {
|
||||
{ "unknown", NULL }, /* CPU_CLASS_NONE */
|
||||
{ "ARM9TDMI", "CPU_ARM9TDMI" }, /* CPU_CLASS_ARM9TDMI */
|
||||
{ "ARM9E-S", "CPU_ARM9E" }, /* CPU_CLASS_ARM9ES */
|
||||
{ "ARM9EJ-S", "CPU_ARM9E" }, /* CPU_CLASS_ARM9EJS */
|
||||
{ "ARM10E", "CPU_ARM10" }, /* CPU_CLASS_ARM10E */
|
||||
{ "ARM10EJ", "CPU_ARM10" }, /* CPU_CLASS_ARM10EJ */
|
||||
{ "XScale", "CPU_XSCALE_..." }, /* CPU_CLASS_XSCALE */
|
||||
{ "Marvell", "CPU_MARVELL" }, /* CPU_CLASS_MARVELL */
|
||||
};
|
||||
|
||||
/*
|
||||
* Report the type of the specified arm processor. This uses the generic and
|
||||
* arm specific information in the cpu structure to identify the processor.
|
||||
* The remaining fields in the cpu structure are filled in appropriately.
|
||||
*/
|
||||
|
||||
static const char * const wtnames[] = {
|
||||
"write-through",
|
||||
"write-back",
|
||||
"write-back",
|
||||
"**unknown 3**",
|
||||
"**unknown 4**",
|
||||
"write-back-locking", /* XXX XScale-specific? */
|
||||
"write-back-locking-A",
|
||||
"write-back-locking-B",
|
||||
"**unknown 8**",
|
||||
"**unknown 9**",
|
||||
"**unknown 10**",
|
||||
"**unknown 11**",
|
||||
"**unknown 12**",
|
||||
"**unknown 13**",
|
||||
"write-back-locking-C",
|
||||
"**unknown 15**",
|
||||
};
|
||||
|
||||
static void
|
||||
print_enadis(int enadis, char *s)
|
||||
{
|
||||
|
||||
printf(" %s %sabled", s, (enadis == 0) ? "dis" : "en");
|
||||
}
|
||||
|
||||
enum cpu_class cpu_class = CPU_CLASS_NONE;
|
||||
|
||||
void
|
||||
identify_arm_cpu(void)
|
||||
{
|
||||
u_int cpuid, ctrl;
|
||||
int i;
|
||||
|
||||
ctrl = cp15_sctlr_get();
|
||||
cpuid = cp15_midr_get();
|
||||
|
||||
if (cpuid == 0) {
|
||||
printf("Processor failed probe - no CPU ID\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; cpuids[i].cpuid != 0; i++)
|
||||
if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
|
||||
cpu_class = cpuids[i].cpu_class;
|
||||
printf("CPU: %s %s (%s core)\n",
|
||||
cpuids[i].cpu_name,
|
||||
cpuids[i].cpu_steppings[cpuid &
|
||||
CPU_ID_REVISION_MASK],
|
||||
cpu_classes[cpu_class].class_name);
|
||||
break;
|
||||
}
|
||||
if (cpuids[i].cpuid == 0)
|
||||
printf("unknown CPU (ID = 0x%x)\n", cpuid);
|
||||
|
||||
printf(" ");
|
||||
|
||||
if (ctrl & CPU_CONTROL_BEND_ENABLE)
|
||||
printf(" Big-endian");
|
||||
else
|
||||
printf(" Little-endian");
|
||||
|
||||
switch (cpu_class) {
|
||||
case CPU_CLASS_ARM9TDMI:
|
||||
case CPU_CLASS_ARM9ES:
|
||||
case CPU_CLASS_ARM9EJS:
|
||||
case CPU_CLASS_ARM10E:
|
||||
case CPU_CLASS_ARM10EJ:
|
||||
case CPU_CLASS_XSCALE:
|
||||
case CPU_CLASS_MARVELL:
|
||||
print_enadis(ctrl & CPU_CONTROL_DC_ENABLE, "DC");
|
||||
print_enadis(ctrl & CPU_CONTROL_IC_ENABLE, "IC");
|
||||
#if defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY)
|
||||
i = sheeva_control_ext(0, 0);
|
||||
print_enadis(i & MV_WA_ENABLE, "WA");
|
||||
print_enadis(i & MV_DC_STREAM_ENABLE, "DC streaming");
|
||||
printf("\n ");
|
||||
print_enadis((i & MV_BTB_DISABLE) == 0, "BTB");
|
||||
print_enadis(i & MV_L2_ENABLE, "L2");
|
||||
print_enadis((i & MV_L2_PREFETCH_DISABLE) == 0,
|
||||
"L2 prefetch");
|
||||
printf("\n ");
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
print_enadis(ctrl & CPU_CONTROL_WBUF_ENABLE, "WB");
|
||||
if (ctrl & CPU_CONTROL_LABT_ENABLE)
|
||||
printf(" LABT");
|
||||
else
|
||||
printf(" EABT");
|
||||
|
||||
print_enadis(ctrl & CPU_CONTROL_BPRD_ENABLE, "branch prediction");
|
||||
printf("\n");
|
||||
|
||||
/* Print cache info. */
|
||||
if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0)
|
||||
return;
|
||||
|
||||
if (arm_pcache_unified) {
|
||||
printf(" %dKB/%dB %d-way %s unified cache\n",
|
||||
arm_pdcache_size / 1024,
|
||||
arm_pdcache_line_size, arm_pdcache_ways,
|
||||
wtnames[arm_pcache_type]);
|
||||
} else {
|
||||
printf(" %dKB/%dB %d-way instruction cache\n",
|
||||
arm_picache_size / 1024,
|
||||
arm_picache_line_size, arm_picache_ways);
|
||||
printf(" %dKB/%dB %d-way %s data cache\n",
|
||||
arm_pdcache_size / 1024,
|
||||
arm_pdcache_line_size, arm_pdcache_ways,
|
||||
wtnames[arm_pcache_type]);
|
||||
}
|
||||
}
|
@ -1,204 +0,0 @@
|
||||
/* $NetBSD: intr.c,v 1.12 2003/07/15 00:24:41 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-4-Clause
|
||||
*
|
||||
* Copyright (c) 2004 Olivier Houchard.
|
||||
* Copyright (c) 1994-1998 Mark Brinicombe.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Mark Brinicombe
|
||||
* for the NetBSD Project.
|
||||
* 4. The name of the company nor the name of the author may be used to
|
||||
* endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*
|
||||
* Soft interrupt and other generic interrupt functions.
|
||||
*/
|
||||
|
||||
#include "opt_platform.h"
|
||||
#include "opt_hwpmc_hooks.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/interrupt.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/pmc.h>
|
||||
#include <sys/pmckern.h>
|
||||
#include <sys/vmmeter.h>
|
||||
|
||||
#include <machine/atomic.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/intr.h>
|
||||
#include <machine/cpu.h>
|
||||
|
||||
#ifdef FDT
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <machine/fdt.h>
|
||||
#endif
|
||||
|
||||
#define INTRNAME_LEN (MAXCOMLEN + 1)
|
||||
|
||||
typedef void (*mask_fn)(void *);
|
||||
|
||||
static struct intr_event *intr_events[NIRQ];
|
||||
|
||||
void intr_irq_handler(struct trapframe *);
|
||||
|
||||
void (*arm_post_filter)(void *) = NULL;
|
||||
int (*arm_config_irq)(int irq, enum intr_trigger trig,
|
||||
enum intr_polarity pol) = NULL;
|
||||
|
||||
/* Data for statistics reporting. */
|
||||
u_long intrcnt[NIRQ];
|
||||
char intrnames[(NIRQ * INTRNAME_LEN) + 1];
|
||||
size_t sintrcnt = sizeof(intrcnt);
|
||||
size_t sintrnames = sizeof(intrnames);
|
||||
|
||||
/*
|
||||
* Pre-format intrnames into an array of fixed-size strings containing spaces.
|
||||
* This allows us to avoid the need for an intermediate table of indices into
|
||||
* the names and counts arrays, while still meeting the requirements and
|
||||
* assumptions of vmstat(8) and the kdb "show intrcnt" command, the two
|
||||
* consumers of this data.
|
||||
*/
|
||||
static void
|
||||
intr_init(void *unused)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NIRQ; ++i) {
|
||||
snprintf(&intrnames[i * INTRNAME_LEN], INTRNAME_LEN, "%-*s",
|
||||
INTRNAME_LEN - 1, "");
|
||||
}
|
||||
}
|
||||
|
||||
SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL);
|
||||
|
||||
#ifdef FDT
|
||||
int
|
||||
intr_fdt_map_irq(phandle_t iparent, pcell_t *intr, int icells)
|
||||
{
|
||||
fdt_pic_decode_t intr_decode;
|
||||
phandle_t intr_parent;
|
||||
int i, rv, interrupt, trig, pol;
|
||||
|
||||
intr_parent = OF_node_from_xref(iparent);
|
||||
for (i = 0; i < icells; i++)
|
||||
intr[i] = cpu_to_fdt32(intr[i]);
|
||||
|
||||
for (i = 0; fdt_pic_table[i] != NULL; i++) {
|
||||
intr_decode = fdt_pic_table[i];
|
||||
rv = intr_decode(intr_parent, intr, &interrupt, &trig, &pol);
|
||||
|
||||
if (rv == 0) {
|
||||
/* This was recognized as our PIC and decoded. */
|
||||
interrupt = FDT_MAP_IRQ(intr_parent, interrupt);
|
||||
return (interrupt);
|
||||
}
|
||||
}
|
||||
|
||||
/* Not in table, so guess */
|
||||
interrupt = FDT_MAP_IRQ(intr_parent, fdt32_to_cpu(intr[0]));
|
||||
|
||||
return (interrupt);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
arm_setup_irqhandler(const char *name, driver_filter_t *filt,
|
||||
void (*hand)(void*), void *arg, int irq, int flags, void **cookiep)
|
||||
{
|
||||
struct intr_event *event;
|
||||
int error;
|
||||
|
||||
if (irq < 0 || irq >= NIRQ)
|
||||
return;
|
||||
event = intr_events[irq];
|
||||
if (event == NULL) {
|
||||
error = intr_event_create(&event, (void *)irq, 0, irq,
|
||||
(mask_fn)arm_mask_irq, (mask_fn)arm_unmask_irq,
|
||||
arm_post_filter, NULL, "intr%d:", irq);
|
||||
if (error)
|
||||
return;
|
||||
intr_events[irq] = event;
|
||||
snprintf(&intrnames[irq * INTRNAME_LEN], INTRNAME_LEN,
|
||||
"irq%d: %-*s", irq, INTRNAME_LEN - 1, name);
|
||||
}
|
||||
intr_event_add_handler(event, name, filt, hand, arg,
|
||||
intr_priority(flags), flags, cookiep);
|
||||
}
|
||||
|
||||
int
|
||||
arm_remove_irqhandler(int irq, void *cookie)
|
||||
{
|
||||
struct intr_event *event;
|
||||
int error;
|
||||
|
||||
event = intr_events[irq];
|
||||
arm_mask_irq(irq);
|
||||
|
||||
error = intr_event_remove_handler(cookie);
|
||||
|
||||
if (!CK_SLIST_EMPTY(&event->ie_handlers))
|
||||
arm_unmask_irq(irq);
|
||||
return (error);
|
||||
}
|
||||
|
||||
void dosoftints(void);
|
||||
void
|
||||
dosoftints(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
intr_irq_handler(struct trapframe *frame)
|
||||
{
|
||||
struct intr_event *event;
|
||||
int i;
|
||||
|
||||
VM_CNT_INC(v_intr);
|
||||
i = -1;
|
||||
while ((i = arm_get_next_irq(i)) != -1) {
|
||||
intrcnt[i]++;
|
||||
event = intr_events[i];
|
||||
if (intr_event_handle(event, frame) != 0) {
|
||||
/* XXX: Log stray IRQs */
|
||||
arm_mask_irq(i);
|
||||
}
|
||||
}
|
||||
#ifdef HWPMC_HOOKS
|
||||
if (pmc_hook && (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN))
|
||||
pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, frame);
|
||||
#endif
|
||||
}
|
@ -1,494 +0,0 @@
|
||||
/* $NetBSD: locore.S,v 1.14 2003/04/20 16:21:40 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright 2011 Semihalf
|
||||
* Copyright (C) 1994-1997 Mark Brinicombe
|
||||
* Copyright (C) 1994 Brini
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Brini.
|
||||
* 4. The name of Brini may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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 "assym.inc"
|
||||
#include <sys/syscall.h>
|
||||
#include <machine/asm.h>
|
||||
#include <machine/armreg.h>
|
||||
#include <machine/pte-v4.h>
|
||||
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/* 2K initial stack is plenty, it is only used by initarm() */
|
||||
#define INIT_ARM_STACK_SIZE 2048
|
||||
|
||||
#define CPWAIT_BRANCH \
|
||||
sub pc, pc, #4
|
||||
|
||||
#define CPWAIT(tmp) \
|
||||
mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\
|
||||
mov tmp, tmp /* wait for it to complete */ ;\
|
||||
CPWAIT_BRANCH /* branch to next insn */
|
||||
|
||||
/*
|
||||
* This is for libkvm, and should be the address of the beginning
|
||||
* of the kernel text segment (not necessarily the same as kernbase).
|
||||
*
|
||||
* These are being phased out. Newer copies of libkvm don't need these
|
||||
* values as the information is added to the core file by inspecting
|
||||
* the running kernel.
|
||||
*/
|
||||
.text
|
||||
.align 2
|
||||
|
||||
.globl kernbase
|
||||
.set kernbase,KERNVIRTADDR
|
||||
|
||||
#ifdef PHYSADDR
|
||||
.globl physaddr
|
||||
.set physaddr,PHYSADDR
|
||||
#endif
|
||||
|
||||
/*
|
||||
* On entry for FreeBSD boot ABI:
|
||||
* r0 - metadata pointer or 0 (boothowto on AT91's boot2)
|
||||
* r1 - if (r0 == 0) then metadata pointer
|
||||
* On entry for Linux boot ABI:
|
||||
* r0 - 0
|
||||
* r1 - machine type (passed as arg2 to initarm)
|
||||
* r2 - Pointer to a tagged list or dtb image (phys addr) (passed as arg1 initarm)
|
||||
*
|
||||
* For both types of boot we gather up the args, put them in a struct arm_boot_params
|
||||
* structure and pass that to initarm.
|
||||
*/
|
||||
.globl btext
|
||||
btext:
|
||||
ASENTRY_NP(_start)
|
||||
STOP_UNWINDING /* Can't unwind into the bootloader! */
|
||||
|
||||
mov r9, r0 /* 0 or boot mode from boot2 */
|
||||
mov r8, r1 /* Save Machine type */
|
||||
mov ip, r2 /* Save meta data */
|
||||
mov fp, r3 /* Future expansion */
|
||||
|
||||
/* Make sure interrupts are disabled. */
|
||||
mrs r7, cpsr
|
||||
orr r7, r7, #(PSR_I | PSR_F)
|
||||
msr cpsr_c, r7
|
||||
|
||||
#if defined (FLASHADDR) && defined(LOADERRAMADDR)
|
||||
/*
|
||||
* Sanity check the configuration.
|
||||
* FLASHADDR and LOADERRAMADDR depend on PHYSADDR in some cases.
|
||||
* ARMv4 and ARMv5 make assumptions on where they are loaded.
|
||||
* TODO: Fix the ARMv4/v5 case.
|
||||
*/
|
||||
#ifndef PHYSADDR
|
||||
#error PHYSADDR must be defined for this configuration
|
||||
#endif
|
||||
|
||||
/* Check if we're running from flash. */
|
||||
ldr r7, =FLASHADDR
|
||||
/*
|
||||
* If we're running with MMU disabled, test against the
|
||||
* physical address instead.
|
||||
*/
|
||||
mrc CP15_SCTLR(r2)
|
||||
ands r2, r2, #CPU_CONTROL_MMU_ENABLE
|
||||
ldreq r6, =PHYSADDR
|
||||
ldrne r6, =LOADERRAMADDR
|
||||
cmp r7, r6
|
||||
bls flash_lower
|
||||
cmp r7, pc
|
||||
bhi from_ram
|
||||
b do_copy
|
||||
|
||||
flash_lower:
|
||||
cmp r6, pc
|
||||
bls from_ram
|
||||
do_copy:
|
||||
ldr r7, =KERNBASE
|
||||
adr r1, _start
|
||||
ldr r0, Lreal_start
|
||||
ldr r2, Lend
|
||||
sub r2, r2, r0
|
||||
sub r0, r0, r7
|
||||
add r0, r0, r6
|
||||
mov r4, r0
|
||||
bl memcpy
|
||||
ldr r0, Lram_offset
|
||||
add pc, r4, r0
|
||||
Lram_offset: .word from_ram-_C_LABEL(_start)
|
||||
from_ram:
|
||||
nop
|
||||
#endif
|
||||
|
||||
disable_mmu:
|
||||
/* Disable MMU for a while */
|
||||
mrc CP15_SCTLR(r2)
|
||||
bic r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\
|
||||
CPU_CONTROL_WBUF_ENABLE)
|
||||
bic r2, r2, #(CPU_CONTROL_IC_ENABLE)
|
||||
bic r2, r2, #(CPU_CONTROL_BPRD_ENABLE)
|
||||
mcr CP15_SCTLR(r2)
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
CPWAIT(r0)
|
||||
|
||||
Lunmapped:
|
||||
/*
|
||||
* Build page table from scratch.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Figure out the physical address we're loaded at by assuming this
|
||||
* entry point code is in the first L1 section and so if we clear the
|
||||
* offset bits of the pc that will give us the section-aligned load
|
||||
* address, which remains in r5 throughout all the following code.
|
||||
*/
|
||||
ldr r2, =(L1_S_OFFSET)
|
||||
bic r5, pc, r2
|
||||
|
||||
/* Find the delta between VA and PA, result stays in r0 throughout. */
|
||||
adr r0, Lpagetable
|
||||
bl translate_va_to_pa
|
||||
|
||||
/*
|
||||
* First map the entire 4GB address space as VA=PA. It's mapped as
|
||||
* normal (cached) memory because it's for things like accessing the
|
||||
* parameters passed in from the bootloader, which might be at any
|
||||
* physical address, different for every platform.
|
||||
*/
|
||||
mov r1, #0
|
||||
mov r2, #0
|
||||
mov r3, #4096
|
||||
bl build_pagetables
|
||||
|
||||
/*
|
||||
* Next we do 64MiB starting at the physical load address, mapped to
|
||||
* the VA the kernel is linked for.
|
||||
*/
|
||||
mov r1, r5
|
||||
ldr r2, =(KERNVIRTADDR)
|
||||
mov r3, #64
|
||||
bl build_pagetables
|
||||
#if defined(PHYSADDR) && (KERNVIRTADDR != KERNBASE)
|
||||
/*
|
||||
* If the kernel wasn't loaded at the beginning of the ram, map the memory
|
||||
* before the kernel too, as some ports use that for pagetables, stack, etc...
|
||||
*/
|
||||
ldr r1, =PHYSADDR
|
||||
ldr r2, =KERNBASE
|
||||
ldr r3, =((KERNVIRTADDR - KERNBASE) / L1_S_SIZE)
|
||||
bl build_pagetables
|
||||
#endif
|
||||
|
||||
/* Create a device mapping for early_printf if specified. */
|
||||
#if defined(SOCDEV_PA) && defined(SOCDEV_VA)
|
||||
ldr r1, =SOCDEV_PA
|
||||
ldr r2, =SOCDEV_VA
|
||||
mov r3, #1
|
||||
bl build_device_pagetables
|
||||
#endif
|
||||
|
||||
mcr p15, 0, r0, c2, c0, 0 /* Set TTB */
|
||||
mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */
|
||||
|
||||
/* Set the Domain Access register. Very important! */
|
||||
mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
|
||||
mcr p15, 0, r0, c3, c0, 0
|
||||
/*
|
||||
* Enable MMU.
|
||||
*/
|
||||
mrc CP15_SCTLR(r0)
|
||||
orr r0, r0, #(CPU_CONTROL_MMU_ENABLE)
|
||||
mcr CP15_SCTLR(r0)
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
CPWAIT(r0)
|
||||
|
||||
/* Transition the PC from physical to virtual addressing. */
|
||||
ldr pc,=mmu_done
|
||||
|
||||
mmu_done:
|
||||
nop
|
||||
adr r1, .Lstart
|
||||
ldmia r1, {r1, r2, sp} /* Set initial stack and */
|
||||
sub r2, r2, r1 /* get zero init data */
|
||||
mov r3, #0
|
||||
.L1:
|
||||
str r3, [r1], #0x0004 /* get zero init data */
|
||||
subs r2, r2, #4
|
||||
bgt .L1
|
||||
|
||||
virt_done:
|
||||
mov r1, #28 /* loader info size is 28 bytes also second arg */
|
||||
subs sp, sp, r1 /* allocate arm_boot_params struct on stack */
|
||||
mov r0, sp /* loader info pointer is first arg */
|
||||
bic sp, sp, #7 /* align stack to 8 bytes */
|
||||
str r1, [r0] /* Store length of loader info */
|
||||
str r9, [r0, #4] /* Store r0 from boot loader */
|
||||
str r8, [r0, #8] /* Store r1 from boot loader */
|
||||
str ip, [r0, #12] /* store r2 from boot loader */
|
||||
str fp, [r0, #16] /* store r3 from boot loader */
|
||||
str r5, [r0, #20] /* store the physical address */
|
||||
adr r4, Lpagetable /* load the pagetable address */
|
||||
ldr r5, [r4, #4]
|
||||
str r5, [r0, #24] /* store the pagetable address */
|
||||
mov fp, #0 /* trace back starts here */
|
||||
bl _C_LABEL(initarm) /* Off we go */
|
||||
|
||||
/* init arm will return the new stack pointer. */
|
||||
mov sp, r0
|
||||
|
||||
bl _C_LABEL(mi_startup) /* call mi_startup()! */
|
||||
|
||||
adr r0, .Lmainreturned
|
||||
b _C_LABEL(panic)
|
||||
/* NOTREACHED */
|
||||
END(_start)
|
||||
|
||||
#define VA_TO_PA_POINTER(name, table) \
|
||||
name: ;\
|
||||
.word . ;\
|
||||
.word table
|
||||
|
||||
/*
|
||||
* Returns the physical address of a magic va to pa pointer.
|
||||
* r0 - The pagetable data pointer. This must be built using the
|
||||
* VA_TO_PA_POINTER macro.
|
||||
* e.g.
|
||||
* VA_TO_PA_POINTER(Lpagetable, pagetable)
|
||||
* ...
|
||||
* adr r0, Lpagetable
|
||||
* bl translate_va_to_pa
|
||||
* r0 will now contain the physical address of pagetable
|
||||
* r1, r2 - Trashed
|
||||
*/
|
||||
translate_va_to_pa:
|
||||
ldr r1, [r0]
|
||||
sub r2, r1, r0
|
||||
/* At this point: r2 = VA - PA */
|
||||
|
||||
/*
|
||||
* Find the physical address of the table. After these two
|
||||
* instructions:
|
||||
* r1 = va(pagetable)
|
||||
*
|
||||
* r0 = va(pagetable) - (VA - PA)
|
||||
* = va(pagetable) - VA + PA
|
||||
* = pa(pagetable)
|
||||
*/
|
||||
ldr r1, [r0, #4]
|
||||
sub r0, r1, r2
|
||||
RET
|
||||
|
||||
/*
|
||||
* Builds the page table
|
||||
* r0 - The table base address
|
||||
* r1 - The physical address (trashed)
|
||||
* r2 - The virtual address (trashed)
|
||||
* r3 - The number of 1MiB sections
|
||||
* r4 - Trashed
|
||||
*
|
||||
* Addresses must be 1MiB aligned
|
||||
*/
|
||||
build_device_pagetables:
|
||||
ldr r4, =(L1_TYPE_S|L1_S_AP(AP_KRW))
|
||||
b 1f
|
||||
build_pagetables:
|
||||
/* Set the required page attributed */
|
||||
ldr r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
|
||||
1:
|
||||
orr r1, r4
|
||||
|
||||
/* Move the virtual address to the correct bit location */
|
||||
lsr r2, #(L1_S_SHIFT - 2)
|
||||
|
||||
mov r4, r3
|
||||
2:
|
||||
str r1, [r0, r2]
|
||||
add r2, r2, #4
|
||||
add r1, r1, #(L1_S_SIZE)
|
||||
adds r4, r4, #-1
|
||||
bhi 2b
|
||||
|
||||
RET
|
||||
|
||||
VA_TO_PA_POINTER(Lpagetable, pagetable)
|
||||
|
||||
Lreal_start:
|
||||
.word _start
|
||||
Lend:
|
||||
.word _edata
|
||||
|
||||
.Lstart:
|
||||
.word _edata
|
||||
.word _ebss
|
||||
.word svcstk + INIT_ARM_STACK_SIZE
|
||||
|
||||
.Lvirt_done:
|
||||
.word virt_done
|
||||
|
||||
.Lmainreturned:
|
||||
.asciz "main() returned"
|
||||
.align 2
|
||||
|
||||
.bss
|
||||
svcstk:
|
||||
.space INIT_ARM_STACK_SIZE
|
||||
|
||||
/*
|
||||
* Memory for the initial pagetable. We are unable to place this in
|
||||
* the bss as this will be cleared after the table is loaded.
|
||||
*/
|
||||
.section ".init_pagetable", "aw", %nobits
|
||||
.align 14 /* 16KiB aligned */
|
||||
pagetable:
|
||||
.space L1_TABLE_SIZE
|
||||
|
||||
.text
|
||||
.align 2
|
||||
|
||||
.Lcpufuncs:
|
||||
.word _C_LABEL(cpufuncs)
|
||||
|
||||
ENTRY_NP(cpu_halt)
|
||||
mrs r2, cpsr
|
||||
bic r2, r2, #(PSR_MODE)
|
||||
orr r2, r2, #(PSR_SVC32_MODE)
|
||||
orr r2, r2, #(PSR_I | PSR_F)
|
||||
msr cpsr_fsxc, r2
|
||||
|
||||
ldr r4, .Lcpu_reset_address
|
||||
ldr r4, [r4]
|
||||
|
||||
ldr r0, .Lcpufuncs
|
||||
mov lr, pc
|
||||
ldr pc, [r0, #CF_IDCACHE_WBINV_ALL]
|
||||
mov lr, pc
|
||||
ldr pc, [r0, #CF_L2CACHE_WBINV_ALL]
|
||||
|
||||
/*
|
||||
* Load the cpu_reset_needs_v4_MMU_disable flag to determine if it's
|
||||
* necessary.
|
||||
*/
|
||||
|
||||
ldr r1, .Lcpu_reset_needs_v4_MMU_disable
|
||||
ldr r1, [r1]
|
||||
cmp r1, #0
|
||||
mov r2, #0
|
||||
|
||||
/*
|
||||
* MMU & IDC off, 32 bit program & data space
|
||||
* Hurl ourselves into the ROM
|
||||
*/
|
||||
mov r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE)
|
||||
mcr CP15_SCTLR(r0)
|
||||
mcrne p15, 0, r2, c8, c7, 0 /* nail I+D TLB on ARMv4 and greater */
|
||||
mov pc, r4
|
||||
|
||||
/*
|
||||
* _cpu_reset_address contains the address to branch to, to complete
|
||||
* the cpu reset after turning the MMU off
|
||||
* This variable is provided by the hardware specific code
|
||||
*/
|
||||
.Lcpu_reset_address:
|
||||
.word _C_LABEL(cpu_reset_address)
|
||||
|
||||
/*
|
||||
* cpu_reset_needs_v4_MMU_disable contains a flag that signals if the
|
||||
* v4 MMU disable instruction needs executing... it is an illegal instruction
|
||||
* on f.e. ARM6/7 that locks up the computer in an endless illegal
|
||||
* instruction / data-abort / reset loop.
|
||||
*/
|
||||
.Lcpu_reset_needs_v4_MMU_disable:
|
||||
.word _C_LABEL(cpu_reset_needs_v4_MMU_disable)
|
||||
END(cpu_halt)
|
||||
|
||||
|
||||
/*
|
||||
* setjump + longjmp
|
||||
*/
|
||||
ENTRY(setjmp)
|
||||
stmia r0, {r4-r14}
|
||||
mov r0, #0x00000000
|
||||
RET
|
||||
END(setjmp)
|
||||
|
||||
ENTRY(longjmp)
|
||||
ldmia r0, {r4-r14}
|
||||
mov r0, #0x00000001
|
||||
RET
|
||||
END(longjmp)
|
||||
|
||||
.data
|
||||
.global _C_LABEL(esym)
|
||||
_C_LABEL(esym): .word _C_LABEL(end)
|
||||
|
||||
ENTRY_NP(abort)
|
||||
b _C_LABEL(abort)
|
||||
END(abort)
|
||||
|
||||
ENTRY_NP(sigcode)
|
||||
mov r0, sp
|
||||
add r0, r0, #SIGF_UC
|
||||
|
||||
/*
|
||||
* Call the sigreturn system call.
|
||||
*
|
||||
* We have to load r7 manually rather than using
|
||||
* "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is
|
||||
* correct. Using the alternative places esigcode at the address
|
||||
* of the data rather than the address one past the data.
|
||||
*/
|
||||
|
||||
ldr r7, [pc, #12] /* Load SYS_sigreturn */
|
||||
swi SYS_sigreturn
|
||||
|
||||
/* Well if that failed we better exit quick ! */
|
||||
|
||||
ldr r7, [pc, #8] /* Load SYS_exit */
|
||||
swi SYS_exit
|
||||
|
||||
/* Branch back to retry SYS_sigreturn */
|
||||
b . - 16
|
||||
END(sigcode)
|
||||
.word SYS_sigreturn
|
||||
.word SYS_exit
|
||||
|
||||
.align 2
|
||||
.global _C_LABEL(esigcode)
|
||||
_C_LABEL(esigcode):
|
||||
|
||||
.data
|
||||
.global szsigcode
|
||||
szsigcode:
|
||||
.long esigcode-sigcode
|
||||
|
||||
/* End of locore.S */
|
@ -34,8 +34,4 @@
|
||||
|
||||
#include <machine/acle-compat.h>
|
||||
|
||||
#if __ARM_ARCH >= 6
|
||||
#include "locore-v6.S"
|
||||
#else
|
||||
#include "locore-v4.S"
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,376 +0,0 @@
|
||||
/* $NetBSD: cpuswitch.S,v 1.41 2003/11/15 08:44:18 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright 2003 Wasabi Systems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Written by Steve C. Woodford for Wasabi Systems, Inc.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed for the NetBSD Project by
|
||||
* Wasabi Systems, Inc.
|
||||
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
|
||||
* 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.
|
||||
*/
|
||||
/*-
|
||||
* Copyright (c) 1994-1998 Mark Brinicombe.
|
||||
* Copyright (c) 1994 Brini.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software written for Brini by Mark Brinicombe
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Brini.
|
||||
* 4. The name of the company nor the name of the author may be used to
|
||||
* endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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.
|
||||
*
|
||||
* RiscBSD kernel project
|
||||
*
|
||||
* cpuswitch.S
|
||||
*
|
||||
* cpu switching functions
|
||||
*
|
||||
* Created : 15/10/94
|
||||
*
|
||||
*/
|
||||
|
||||
#include "assym.inc"
|
||||
#include "opt_sched.h"
|
||||
|
||||
#include <machine/asm.h>
|
||||
#include <machine/asmacros.h>
|
||||
#include <machine/armreg.h>
|
||||
#include <machine/vfp.h>
|
||||
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
|
||||
#define GET_PCPU(tmp, tmp2) \
|
||||
ldr tmp, .Lcurpcpu
|
||||
|
||||
#ifdef VFP
|
||||
.fpu vfp /* allow VFP instructions */
|
||||
#endif
|
||||
|
||||
.Lcurpcpu:
|
||||
.word _C_LABEL(__pcpu)
|
||||
.Lblocked_lock:
|
||||
.word _C_LABEL(blocked_lock)
|
||||
|
||||
|
||||
#define DOMAIN_CLIENT 0x01
|
||||
|
||||
.Lcpufuncs:
|
||||
.word _C_LABEL(cpufuncs)
|
||||
|
||||
/*
|
||||
* cpu_throw(oldtd, newtd)
|
||||
*
|
||||
* Remove current thread state, then select the next thread to run
|
||||
* and load its state.
|
||||
* r0 = oldtd
|
||||
* r1 = newtd
|
||||
*/
|
||||
ENTRY(cpu_throw)
|
||||
mov r5, r1
|
||||
|
||||
/*
|
||||
* r0 = oldtd
|
||||
* r5 = newtd
|
||||
*/
|
||||
|
||||
#ifdef VFP /* This thread is dying, disable */
|
||||
bl _C_LABEL(vfp_discard) /* VFP without preserving state. */
|
||||
#endif
|
||||
|
||||
GET_PCPU(r7, r9)
|
||||
ldr r7, [r5, #(TD_PCB)] /* r7 = new thread's PCB */
|
||||
|
||||
/* Switch to lwp0 context */
|
||||
|
||||
ldr r9, .Lcpufuncs
|
||||
mov lr, pc
|
||||
ldr pc, [r9, #CF_IDCACHE_WBINV_ALL]
|
||||
ldr r0, [r7, #(PCB_PL1VEC)]
|
||||
ldr r1, [r7, #(PCB_DACR)]
|
||||
/*
|
||||
* r0 = Pointer to L1 slot for vector_page (or NULL)
|
||||
* r1 = lwp0's DACR
|
||||
* r5 = lwp0
|
||||
* r7 = lwp0's PCB
|
||||
* r9 = cpufuncs
|
||||
*/
|
||||
|
||||
/*
|
||||
* Ensure the vector table is accessible by fixing up lwp0's L1
|
||||
*/
|
||||
cmp r0, #0 /* No need to fixup vector table? */
|
||||
ldrne r3, [r0] /* But if yes, fetch current value */
|
||||
ldrne r2, [r7, #(PCB_L1VEC)] /* Fetch new vector_page value */
|
||||
mcr p15, 0, r1, c3, c0, 0 /* Update DACR for lwp0's context */
|
||||
cmpne r3, r2 /* Stuffing the same value? */
|
||||
strne r2, [r0] /* Store if not. */
|
||||
|
||||
#ifdef PMAP_INCLUDE_PTE_SYNC
|
||||
/*
|
||||
* Need to sync the cache to make sure that last store is
|
||||
* visible to the MMU.
|
||||
*/
|
||||
movne r1, #4
|
||||
movne lr, pc
|
||||
ldrne pc, [r9, #CF_DCACHE_WB_RANGE]
|
||||
#endif /* PMAP_INCLUDE_PTE_SYNC */
|
||||
|
||||
/*
|
||||
* Note: We don't do the same optimisation as cpu_switch() with
|
||||
* respect to avoiding flushing the TLB if we're switching to
|
||||
* the same L1 since this process' VM space may be about to go
|
||||
* away, so we don't want *any* turds left in the TLB.
|
||||
*/
|
||||
|
||||
/* Switch the memory to the new process */
|
||||
ldr r0, [r7, #(PCB_PAGEDIR)]
|
||||
mov lr, pc
|
||||
ldr pc, [r9, #CF_CONTEXT_SWITCH]
|
||||
|
||||
GET_PCPU(r6, r4)
|
||||
/* Hook in a new pcb */
|
||||
str r7, [r6, #PC_CURPCB]
|
||||
/* We have a new curthread now so make a note it */
|
||||
str r5, [r6, #PC_CURTHREAD]
|
||||
|
||||
/* Set the new tp */
|
||||
ldr r6, [r5, #(TD_MD + MD_TP)]
|
||||
ldr r4, =ARM_TP_ADDRESS
|
||||
str r6, [r4]
|
||||
ldr r6, [r5, #(TD_MD + MD_RAS_START)]
|
||||
str r6, [r4, #4] /* ARM_RAS_START */
|
||||
ldr r6, [r5, #(TD_MD + MD_RAS_END)]
|
||||
str r6, [r4, #8] /* ARM_RAS_END */
|
||||
|
||||
/* Restore all the saved registers and exit */
|
||||
add r3, r7, #PCB_R4
|
||||
ldmia r3, {r4-r12, sp, pc}
|
||||
END(cpu_throw)
|
||||
|
||||
/*
|
||||
* cpu_switch(oldtd, newtd, lock)
|
||||
*
|
||||
* Save the current thread state, then select the next thread to run
|
||||
* and load its state.
|
||||
* r0 = oldtd
|
||||
* r1 = newtd
|
||||
* r2 = lock (new lock for old thread)
|
||||
*/
|
||||
ENTRY(cpu_switch)
|
||||
/* Interrupts are disabled. */
|
||||
/* Save all the registers in the old thread's pcb. */
|
||||
ldr r3, [r0, #(TD_PCB)]
|
||||
|
||||
/* Restore all the saved registers and exit */
|
||||
add r3, #(PCB_R4)
|
||||
stmia r3, {r4-r12, sp, lr, pc}
|
||||
|
||||
mov r6, r2 /* Save the mutex */
|
||||
|
||||
/* rem: r0 = old lwp */
|
||||
/* rem: interrupts are disabled */
|
||||
|
||||
/* Process is now on a processor. */
|
||||
/* We have a new curthread now so make a note it */
|
||||
GET_PCPU(r7, r2)
|
||||
str r1, [r7, #PC_CURTHREAD]
|
||||
|
||||
/* Hook in a new pcb */
|
||||
ldr r2, [r1, #TD_PCB]
|
||||
str r2, [r7, #PC_CURPCB]
|
||||
|
||||
/* Stage two : Save old context */
|
||||
|
||||
/* Get the user structure for the old thread. */
|
||||
ldr r2, [r0, #(TD_PCB)]
|
||||
mov r4, r0 /* Save the old thread. */
|
||||
|
||||
/* Store the old tp; userland can change it on armv4. */
|
||||
ldr r3, =ARM_TP_ADDRESS
|
||||
ldr r9, [r3]
|
||||
str r9, [r0, #(TD_MD + MD_TP)]
|
||||
ldr r9, [r3, #4]
|
||||
str r9, [r0, #(TD_MD + MD_RAS_START)]
|
||||
ldr r9, [r3, #8]
|
||||
str r9, [r0, #(TD_MD + MD_RAS_END)]
|
||||
|
||||
/* Set the new tp */
|
||||
ldr r9, [r1, #(TD_MD + MD_TP)]
|
||||
str r9, [r3]
|
||||
ldr r9, [r1, #(TD_MD + MD_RAS_START)]
|
||||
str r9, [r3, #4]
|
||||
ldr r9, [r1, #(TD_MD + MD_RAS_END)]
|
||||
str r9, [r3, #8]
|
||||
|
||||
/* Get the user structure for the new process in r9 */
|
||||
ldr r9, [r1, #(TD_PCB)]
|
||||
|
||||
/* rem: r2 = old PCB */
|
||||
/* rem: r9 = new PCB */
|
||||
/* rem: interrupts are enabled */
|
||||
|
||||
#ifdef VFP
|
||||
fmrx r0, fpexc /* If the VFP is enabled */
|
||||
tst r0, #(VFPEXC_EN) /* the current thread has */
|
||||
movne r1, #1 /* used it, so go save */
|
||||
addne r0, r2, #(PCB_VFPSTATE) /* the state into the PCB */
|
||||
blne _C_LABEL(vfp_store) /* and disable the VFP. */
|
||||
#endif
|
||||
|
||||
/* r0-r3 now free! */
|
||||
|
||||
/* Third phase : restore saved context */
|
||||
|
||||
/* rem: r2 = old PCB */
|
||||
/* rem: r9 = new PCB */
|
||||
|
||||
ldr r5, [r9, #(PCB_DACR)] /* r5 = new DACR */
|
||||
mov r2, #DOMAIN_CLIENT
|
||||
cmp r5, r2, lsl #(PMAP_DOMAIN_KERNEL * 2) /* Sw to kernel thread? */
|
||||
beq .Lcs_context_switched /* Yup. Don't flush cache */
|
||||
mrc p15, 0, r0, c3, c0, 0 /* r0 = old DACR */
|
||||
/*
|
||||
* Get the new L1 table pointer into r11. If we're switching to
|
||||
* an LWP with the same address space as the outgoing one, we can
|
||||
* skip the cache purge and the TTB load.
|
||||
*
|
||||
* To avoid data dep stalls that would happen anyway, we try
|
||||
* and get some useful work done in the mean time.
|
||||
*/
|
||||
mrc p15, 0, r10, c2, c0, 0 /* r10 = old L1 */
|
||||
ldr r11, [r9, #(PCB_PAGEDIR)] /* r11 = new L1 */
|
||||
|
||||
teq r10, r11 /* Same L1? */
|
||||
cmpeq r0, r5 /* Same DACR? */
|
||||
beq .Lcs_context_switched /* yes! */
|
||||
|
||||
/*
|
||||
* Definitely need to flush the cache.
|
||||
*/
|
||||
|
||||
ldr r1, .Lcpufuncs
|
||||
mov lr, pc
|
||||
ldr pc, [r1, #CF_IDCACHE_WBINV_ALL]
|
||||
|
||||
.Lcs_cache_purge_skipped:
|
||||
/* rem: r6 = lock */
|
||||
/* rem: r9 = new PCB */
|
||||
/* rem: r10 = old L1 */
|
||||
/* rem: r11 = new L1 */
|
||||
|
||||
mov r2, #0x00000000
|
||||
ldr r7, [r9, #(PCB_PL1VEC)]
|
||||
|
||||
/*
|
||||
* Ensure the vector table is accessible by fixing up the L1
|
||||
*/
|
||||
cmp r7, #0 /* No need to fixup vector table? */
|
||||
ldrne r2, [r7] /* But if yes, fetch current value */
|
||||
ldrne r0, [r9, #(PCB_L1VEC)] /* Fetch new vector_page value */
|
||||
mcr p15, 0, r5, c3, c0, 0 /* Update DACR for new context */
|
||||
cmpne r2, r0 /* Stuffing the same value? */
|
||||
#ifndef PMAP_INCLUDE_PTE_SYNC
|
||||
strne r0, [r7] /* Nope, update it */
|
||||
#else
|
||||
beq .Lcs_same_vector
|
||||
str r0, [r7] /* Otherwise, update it */
|
||||
|
||||
/*
|
||||
* Need to sync the cache to make sure that last store is
|
||||
* visible to the MMU.
|
||||
*/
|
||||
ldr r2, .Lcpufuncs
|
||||
mov r0, r7
|
||||
mov r1, #4
|
||||
mov lr, pc
|
||||
ldr pc, [r2, #CF_DCACHE_WB_RANGE]
|
||||
|
||||
.Lcs_same_vector:
|
||||
#endif /* PMAP_INCLUDE_PTE_SYNC */
|
||||
|
||||
cmp r10, r11 /* Switching to the same L1? */
|
||||
ldr r10, .Lcpufuncs
|
||||
beq .Lcs_same_l1 /* Yup. */
|
||||
/*
|
||||
* Do a full context switch, including full TLB flush.
|
||||
*/
|
||||
mov r0, r11
|
||||
mov lr, pc
|
||||
ldr pc, [r10, #CF_CONTEXT_SWITCH]
|
||||
|
||||
b .Lcs_context_switched
|
||||
|
||||
/*
|
||||
* We're switching to a different process in the same L1.
|
||||
* In this situation, we only need to flush the TLB for the
|
||||
* vector_page mapping, and even then only if r7 is non-NULL.
|
||||
*/
|
||||
.Lcs_same_l1:
|
||||
cmp r7, #0
|
||||
movne r0, #0 /* We *know* vector_page's VA is 0x0 */
|
||||
movne lr, pc
|
||||
ldrne pc, [r10, #CF_TLB_FLUSHID_SE]
|
||||
|
||||
.Lcs_context_switched:
|
||||
|
||||
/* Release the old thread */
|
||||
str r6, [r4, #TD_LOCK]
|
||||
|
||||
/* XXXSCW: Safe to re-enable FIQs here */
|
||||
|
||||
/* rem: r9 = new PCB */
|
||||
|
||||
/* Restore all the saved registers and exit */
|
||||
add r3, r9, #PCB_R4
|
||||
ldmia r3, {r4-r12, sp, pc}
|
||||
END(cpu_switch)
|
@ -1,717 +0,0 @@
|
||||
/* $NetBSD: fault.c,v 1.45 2003/11/20 14:44:36 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright 2004 Olivier Houchard
|
||||
* Copyright 2003 Wasabi Systems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Written by Steve C. Woodford for Wasabi Systems, Inc.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed for the NetBSD Project by
|
||||
* Wasabi Systems, Inc.
|
||||
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
|
||||
* 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.
|
||||
*/
|
||||
/*-
|
||||
* Copyright (c) 1994-1997 Mark Brinicombe.
|
||||
* Copyright (c) 1994 Brini.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software written for Brini by Mark Brinicombe
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Brini.
|
||||
* 4. The name of the company nor the name of the author may be used to
|
||||
* endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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.
|
||||
*
|
||||
* RiscBSD kernel project
|
||||
*
|
||||
* fault.c
|
||||
*
|
||||
* Fault handlers
|
||||
*
|
||||
* Created : 28/11/94
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/vmmeter.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_kern.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <vm/vm_extern.h>
|
||||
#include <vm/vm_param.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/frame.h>
|
||||
#include <machine/machdep.h>
|
||||
#include <machine/pcb.h>
|
||||
|
||||
#ifdef KDB
|
||||
#include <sys/kdb.h>
|
||||
#endif
|
||||
|
||||
#ifdef KDTRACE_HOOKS
|
||||
#include <sys/dtrace_bsd.h>
|
||||
#endif
|
||||
|
||||
#define ReadWord(a) (*((volatile unsigned int *)(a)))
|
||||
|
||||
#ifdef DEBUG
|
||||
int last_fault_code; /* For the benefit of pmap_fault_fixup() */
|
||||
#endif
|
||||
|
||||
struct ksig {
|
||||
int signb;
|
||||
u_long code;
|
||||
};
|
||||
struct data_abort {
|
||||
int (*func)(struct trapframe *, u_int, u_int, struct thread *,
|
||||
struct ksig *);
|
||||
const char *desc;
|
||||
};
|
||||
|
||||
static int dab_fatal(struct trapframe *, u_int, u_int, struct thread *,
|
||||
struct ksig *);
|
||||
static int dab_align(struct trapframe *, u_int, u_int, struct thread *,
|
||||
struct ksig *);
|
||||
static int dab_buserr(struct trapframe *, u_int, u_int, struct thread *,
|
||||
struct ksig *);
|
||||
static void prefetch_abort_handler(struct trapframe *);
|
||||
|
||||
static const struct data_abort data_aborts[] = {
|
||||
{dab_fatal, "Vector Exception"},
|
||||
{dab_align, "Alignment Fault 1"},
|
||||
{dab_fatal, "Terminal Exception"},
|
||||
{dab_align, "Alignment Fault 3"},
|
||||
{dab_buserr, "External Linefetch Abort (S)"},
|
||||
{NULL, "Translation Fault (S)"},
|
||||
{dab_buserr, "External Linefetch Abort (P)"},
|
||||
{NULL, "Translation Fault (P)"},
|
||||
{dab_buserr, "External Non-Linefetch Abort (S)"},
|
||||
{NULL, "Domain Fault (S)"},
|
||||
{dab_buserr, "External Non-Linefetch Abort (P)"},
|
||||
{NULL, "Domain Fault (P)"},
|
||||
{dab_buserr, "External Translation Abort (L1)"},
|
||||
{NULL, "Permission Fault (S)"},
|
||||
{dab_buserr, "External Translation Abort (L2)"},
|
||||
{NULL, "Permission Fault (P)"}
|
||||
};
|
||||
|
||||
/* Determine if a fault came from user mode */
|
||||
#define TRAP_USERMODE(tf) ((tf->tf_spsr & PSR_MODE) == PSR_USR32_MODE)
|
||||
|
||||
/* Determine if 'x' is a permission fault */
|
||||
#define IS_PERMISSION_FAULT(x) \
|
||||
(((1 << ((x) & FAULT_TYPE_MASK)) & \
|
||||
((1 << FAULT_PERM_P) | (1 << FAULT_PERM_S))) != 0)
|
||||
|
||||
static __inline void
|
||||
call_trapsignal(struct thread *td, int sig, u_long code)
|
||||
{
|
||||
ksiginfo_t ksi;
|
||||
|
||||
ksiginfo_init_trap(&ksi);
|
||||
ksi.ksi_signo = sig;
|
||||
ksi.ksi_code = (int)code;
|
||||
trapsignal(td, &ksi);
|
||||
}
|
||||
|
||||
void
|
||||
abort_handler(struct trapframe *tf, int type)
|
||||
{
|
||||
struct vm_map *map;
|
||||
struct pcb *pcb;
|
||||
struct thread *td;
|
||||
u_int user, far, fsr;
|
||||
vm_prot_t ftype;
|
||||
void *onfault;
|
||||
vm_offset_t va;
|
||||
int error = 0, signo, ucode;
|
||||
struct ksig ksig;
|
||||
struct proc *p;
|
||||
|
||||
if (type == 1)
|
||||
return (prefetch_abort_handler(tf));
|
||||
|
||||
/* Grab FAR/FSR before enabling interrupts */
|
||||
far = cp15_dfar_get();
|
||||
fsr = cp15_dfsr_get();
|
||||
#if 0
|
||||
printf("data abort: fault address=%p (from pc=%p lr=%p)\n",
|
||||
(void*)far, (void*)tf->tf_pc, (void*)tf->tf_svc_lr);
|
||||
#endif
|
||||
|
||||
/* Update vmmeter statistics */
|
||||
#if 0
|
||||
vmexp.traps++;
|
||||
#endif
|
||||
|
||||
td = curthread;
|
||||
p = td->td_proc;
|
||||
|
||||
VM_CNT_INC(v_trap);
|
||||
/* Data abort came from user mode? */
|
||||
user = TRAP_USERMODE(tf);
|
||||
|
||||
if (user) {
|
||||
td->td_pticks = 0;
|
||||
td->td_frame = tf;
|
||||
if (td->td_cowgen != td->td_proc->p_cowgen)
|
||||
thread_cow_update(td);
|
||||
}
|
||||
/* Grab the current pcb */
|
||||
pcb = td->td_pcb;
|
||||
/* Re-enable interrupts if they were enabled previously */
|
||||
if (td->td_md.md_spinlock_count == 0) {
|
||||
if (__predict_true(tf->tf_spsr & PSR_I) == 0)
|
||||
enable_interrupts(PSR_I);
|
||||
if (__predict_true(tf->tf_spsr & PSR_F) == 0)
|
||||
enable_interrupts(PSR_F);
|
||||
}
|
||||
|
||||
/* Invoke the appropriate handler, if necessary */
|
||||
if (__predict_false(data_aborts[fsr & FAULT_TYPE_MASK].func != NULL)) {
|
||||
if ((data_aborts[fsr & FAULT_TYPE_MASK].func)(tf, fsr, far,
|
||||
td, &ksig)) {
|
||||
signo = ksig.signb;
|
||||
ucode = ksig.code;
|
||||
goto do_trapsignal;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, we're dealing with one of the following data aborts:
|
||||
*
|
||||
* FAULT_TRANS_S - Translation -- Section
|
||||
* FAULT_TRANS_P - Translation -- Page
|
||||
* FAULT_DOMAIN_S - Domain -- Section
|
||||
* FAULT_DOMAIN_P - Domain -- Page
|
||||
* FAULT_PERM_S - Permission -- Section
|
||||
* FAULT_PERM_P - Permission -- Page
|
||||
*
|
||||
* These are the main virtual memory-related faults signalled by
|
||||
* the MMU.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Make sure the Program Counter is sane. We could fall foul of
|
||||
* someone executing Thumb code, in which case the PC might not
|
||||
* be word-aligned. This would cause a kernel alignment fault
|
||||
* further down if we have to decode the current instruction.
|
||||
* XXX: It would be nice to be able to support Thumb at some point.
|
||||
*/
|
||||
if (__predict_false((tf->tf_pc & 3) != 0)) {
|
||||
if (user) {
|
||||
/*
|
||||
* Give the user an illegal instruction signal.
|
||||
*/
|
||||
/* Deliver a SIGILL to the process */
|
||||
signo = SIGILL;
|
||||
ucode = 0;
|
||||
goto do_trapsignal;
|
||||
}
|
||||
|
||||
/*
|
||||
* The kernel never executes Thumb code.
|
||||
*/
|
||||
printf("\ndata_abort_fault: Misaligned Kernel-mode "
|
||||
"Program Counter\n");
|
||||
dab_fatal(tf, fsr, far, td, &ksig);
|
||||
}
|
||||
|
||||
va = trunc_page((vm_offset_t)far);
|
||||
|
||||
/*
|
||||
* It is only a kernel address space fault iff:
|
||||
* 1. user == 0 and
|
||||
* 2. pcb_onfault not set or
|
||||
* 3. pcb_onfault set and not LDRT/LDRBT/STRT/STRBT instruction.
|
||||
*/
|
||||
if (user == 0 && (va >= VM_MIN_KERNEL_ADDRESS ||
|
||||
(va < VM_MIN_ADDRESS && vector_page == ARM_VECTORS_LOW)) &&
|
||||
__predict_true((pcb->pcb_onfault == NULL ||
|
||||
(ReadWord(tf->tf_pc) & 0x05200000) != 0x04200000))) {
|
||||
map = kernel_map;
|
||||
|
||||
/* Was the fault due to the FPE/IPKDB ? */
|
||||
if (__predict_false((tf->tf_spsr & PSR_MODE)==PSR_UND32_MODE)) {
|
||||
/*
|
||||
* Force exit via userret()
|
||||
* This is necessary as the FPE is an extension to
|
||||
* userland that actually runs in a priveledged mode
|
||||
* but uses USR mode permissions for its accesses.
|
||||
*/
|
||||
user = 1;
|
||||
signo = SIGSEGV;
|
||||
ucode = 0;
|
||||
goto do_trapsignal;
|
||||
}
|
||||
} else {
|
||||
map = &td->td_proc->p_vmspace->vm_map;
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to know whether the page should be mapped as R or R/W.
|
||||
* On armv4, the fault status register does not indicate whether
|
||||
* the access was a read or write. We know that a permission fault
|
||||
* can only be the result of a write to a read-only location, so we
|
||||
* can deal with those quickly. Otherwise we need to disassemble
|
||||
* the faulting instruction to determine if it was a write.
|
||||
*/
|
||||
if (IS_PERMISSION_FAULT(fsr))
|
||||
ftype = VM_PROT_WRITE;
|
||||
else {
|
||||
u_int insn = ReadWord(tf->tf_pc);
|
||||
|
||||
if (((insn & 0x0c100000) == 0x04000000) || /* STR/STRB */
|
||||
((insn & 0x0e1000b0) == 0x000000b0) || /* STRH/STRD */
|
||||
((insn & 0x0a100000) == 0x08000000)) { /* STM/CDT */
|
||||
ftype = VM_PROT_WRITE;
|
||||
} else {
|
||||
if ((insn & 0x0fb00ff0) == 0x01000090) /* SWP */
|
||||
ftype = VM_PROT_READ | VM_PROT_WRITE;
|
||||
else
|
||||
ftype = VM_PROT_READ;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* See if the fault is as a result of ref/mod emulation,
|
||||
* or domain mismatch.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
last_fault_code = fsr;
|
||||
#endif
|
||||
if (td->td_critnest != 0 || WITNESS_CHECK(WARN_SLEEPOK | WARN_GIANTOK,
|
||||
NULL, "Kernel page fault") != 0)
|
||||
goto fatal_pagefault;
|
||||
|
||||
if (pmap_fault_fixup(vmspace_pmap(td->td_proc->p_vmspace), va, ftype,
|
||||
user)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
onfault = pcb->pcb_onfault;
|
||||
pcb->pcb_onfault = NULL;
|
||||
error = vm_fault_trap(map, va, ftype, VM_FAULT_NORMAL, &signo, &ucode);
|
||||
pcb->pcb_onfault = onfault;
|
||||
if (__predict_true(error == KERN_SUCCESS))
|
||||
goto out;
|
||||
fatal_pagefault:
|
||||
if (user == 0) {
|
||||
if (pcb->pcb_onfault) {
|
||||
tf->tf_r0 = error;
|
||||
tf->tf_pc = (register_t)(intptr_t) pcb->pcb_onfault;
|
||||
return;
|
||||
}
|
||||
|
||||
printf("\nvm_fault(%p, %x, %x, 0) -> %x\n", map, va, ftype,
|
||||
error);
|
||||
dab_fatal(tf, fsr, far, td, &ksig);
|
||||
}
|
||||
|
||||
do_trapsignal:
|
||||
call_trapsignal(td, signo, ucode);
|
||||
out:
|
||||
/* If returning to user mode, make sure to invoke userret() */
|
||||
if (user)
|
||||
userret(td, tf);
|
||||
}
|
||||
|
||||
/*
|
||||
* dab_fatal() handles the following data aborts:
|
||||
*
|
||||
* FAULT_WRTBUF_0 - Vector Exception
|
||||
* FAULT_WRTBUF_1 - Terminal Exception
|
||||
*
|
||||
* We should never see these on a properly functioning system.
|
||||
*
|
||||
* This function is also called by the other handlers if they
|
||||
* detect a fatal problem.
|
||||
*
|
||||
* Note: If 'l' is NULL, we assume we're dealing with a prefetch abort.
|
||||
*/
|
||||
static int
|
||||
dab_fatal(struct trapframe *tf, u_int fsr, u_int far, struct thread *td,
|
||||
struct ksig *ksig)
|
||||
{
|
||||
const char *mode;
|
||||
#ifdef KDB
|
||||
bool handled;
|
||||
#endif
|
||||
|
||||
#ifdef KDB
|
||||
if (kdb_active) {
|
||||
kdb_reenter();
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
#ifdef KDTRACE_HOOKS
|
||||
if (!TRAP_USERMODE(tf)) {
|
||||
if (dtrace_trap_func != NULL && (*dtrace_trap_func)(tf, far & FAULT_TYPE_MASK))
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
mode = TRAP_USERMODE(tf) ? "user" : "kernel";
|
||||
|
||||
disable_interrupts(PSR_I|PSR_F);
|
||||
if (td != NULL) {
|
||||
printf("Fatal %s mode data abort: '%s'\n", mode,
|
||||
data_aborts[fsr & FAULT_TYPE_MASK].desc);
|
||||
printf("trapframe: %p\nFSR=%08x, FAR=", tf, fsr);
|
||||
if ((fsr & FAULT_IMPRECISE) == 0)
|
||||
printf("%08x, ", far);
|
||||
else
|
||||
printf("Invalid, ");
|
||||
printf("spsr=%08x\n", tf->tf_spsr);
|
||||
} else {
|
||||
printf("Fatal %s mode prefetch abort at 0x%08x\n",
|
||||
mode, tf->tf_pc);
|
||||
printf("trapframe: %p, spsr=%08x\n", tf, tf->tf_spsr);
|
||||
}
|
||||
|
||||
printf("r0 =%08x, r1 =%08x, r2 =%08x, r3 =%08x\n",
|
||||
tf->tf_r0, tf->tf_r1, tf->tf_r2, tf->tf_r3);
|
||||
printf("r4 =%08x, r5 =%08x, r6 =%08x, r7 =%08x\n",
|
||||
tf->tf_r4, tf->tf_r5, tf->tf_r6, tf->tf_r7);
|
||||
printf("r8 =%08x, r9 =%08x, r10=%08x, r11=%08x\n",
|
||||
tf->tf_r8, tf->tf_r9, tf->tf_r10, tf->tf_r11);
|
||||
printf("r12=%08x, ", tf->tf_r12);
|
||||
|
||||
if (TRAP_USERMODE(tf))
|
||||
printf("usp=%08x, ulr=%08x",
|
||||
tf->tf_usr_sp, tf->tf_usr_lr);
|
||||
else
|
||||
printf("ssp=%08x, slr=%08x",
|
||||
tf->tf_svc_sp, tf->tf_svc_lr);
|
||||
printf(", pc =%08x\n\n", tf->tf_pc);
|
||||
|
||||
#ifdef KDB
|
||||
if (debugger_on_trap) {
|
||||
kdb_why = KDB_WHY_TRAP;
|
||||
handled = kdb_trap(fsr, 0, tf);
|
||||
kdb_why = KDB_WHY_UNSET;
|
||||
if (handled)
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
panic("Fatal abort");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* dab_align() handles the following data aborts:
|
||||
*
|
||||
* FAULT_ALIGN_0 - Alignment fault
|
||||
* FAULT_ALIGN_1 - Alignment fault
|
||||
*
|
||||
* These faults are fatal if they happen in kernel mode. Otherwise, we
|
||||
* deliver a bus error to the process.
|
||||
*/
|
||||
static int
|
||||
dab_align(struct trapframe *tf, u_int fsr, u_int far, struct thread *td,
|
||||
struct ksig *ksig)
|
||||
{
|
||||
|
||||
/* Alignment faults are always fatal if they occur in kernel mode */
|
||||
if (!TRAP_USERMODE(tf)) {
|
||||
if (!td || !td->td_pcb->pcb_onfault)
|
||||
dab_fatal(tf, fsr, far, td, ksig);
|
||||
tf->tf_r0 = EFAULT;
|
||||
tf->tf_pc = (int)td->td_pcb->pcb_onfault;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* pcb_onfault *must* be NULL at this point */
|
||||
|
||||
/* Deliver a bus error signal to the process */
|
||||
ksig->code = 0;
|
||||
ksig->signb = SIGBUS;
|
||||
td->td_frame = tf;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* dab_buserr() handles the following data aborts:
|
||||
*
|
||||
* FAULT_BUSERR_0 - External Abort on Linefetch -- Section
|
||||
* FAULT_BUSERR_1 - External Abort on Linefetch -- Page
|
||||
* FAULT_BUSERR_2 - External Abort on Non-linefetch -- Section
|
||||
* FAULT_BUSERR_3 - External Abort on Non-linefetch -- Page
|
||||
* FAULT_BUSTRNL1 - External abort on Translation -- Level 1
|
||||
* FAULT_BUSTRNL2 - External abort on Translation -- Level 2
|
||||
*
|
||||
* If pcb_onfault is set, flag the fault and return to the handler.
|
||||
* If the fault occurred in user mode, give the process a SIGBUS.
|
||||
*
|
||||
* Note: On XScale, FAULT_BUSERR_0, FAULT_BUSERR_1, and FAULT_BUSERR_2
|
||||
* can be flagged as imprecise in the FSR. This causes a real headache
|
||||
* since some of the machine state is lost. In this case, tf->tf_pc
|
||||
* may not actually point to the offending instruction. In fact, if
|
||||
* we've taken a double abort fault, it generally points somewhere near
|
||||
* the top of "data_abort_entry" in exception.S.
|
||||
*
|
||||
* In all other cases, these data aborts are considered fatal.
|
||||
*/
|
||||
static int
|
||||
dab_buserr(struct trapframe *tf, u_int fsr, u_int far, struct thread *td,
|
||||
struct ksig *ksig)
|
||||
{
|
||||
struct pcb *pcb = td->td_pcb;
|
||||
|
||||
#ifdef __XSCALE__
|
||||
if ((fsr & FAULT_IMPRECISE) != 0 &&
|
||||
(tf->tf_spsr & PSR_MODE) == PSR_ABT32_MODE) {
|
||||
/*
|
||||
* Oops, an imprecise, double abort fault. We've lost the
|
||||
* r14_abt/spsr_abt values corresponding to the original
|
||||
* abort, and the spsr saved in the trapframe indicates
|
||||
* ABT mode.
|
||||
*/
|
||||
tf->tf_spsr &= ~PSR_MODE;
|
||||
|
||||
/*
|
||||
* We use a simple heuristic to determine if the double abort
|
||||
* happened as a result of a kernel or user mode access.
|
||||
* If the current trapframe is at the top of the kernel stack,
|
||||
* the fault _must_ have come from user mode.
|
||||
*/
|
||||
if (tf != ((struct trapframe *)pcb->pcb_regs.sf_sp) - 1) {
|
||||
/*
|
||||
* Kernel mode. We're either about to die a
|
||||
* spectacular death, or pcb_onfault will come
|
||||
* to our rescue. Either way, the current value
|
||||
* of tf->tf_pc is irrelevant.
|
||||
*/
|
||||
tf->tf_spsr |= PSR_SVC32_MODE;
|
||||
if (pcb->pcb_onfault == NULL)
|
||||
printf("\nKernel mode double abort!\n");
|
||||
} else {
|
||||
/*
|
||||
* User mode. We've lost the program counter at the
|
||||
* time of the fault (not that it was accurate anyway;
|
||||
* it's not called an imprecise fault for nothing).
|
||||
* About all we can do is copy r14_usr to tf_pc and
|
||||
* hope for the best. The process is about to get a
|
||||
* SIGBUS, so it's probably history anyway.
|
||||
*/
|
||||
tf->tf_spsr |= PSR_USR32_MODE;
|
||||
tf->tf_pc = tf->tf_usr_lr;
|
||||
}
|
||||
}
|
||||
|
||||
/* FAR is invalid for imprecise exceptions */
|
||||
if ((fsr & FAULT_IMPRECISE) != 0)
|
||||
far = 0;
|
||||
#endif /* __XSCALE__ */
|
||||
|
||||
if (pcb->pcb_onfault) {
|
||||
tf->tf_r0 = EFAULT;
|
||||
tf->tf_pc = (register_t)(intptr_t) pcb->pcb_onfault;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, if the fault happened in kernel mode, we're toast
|
||||
*/
|
||||
if (!TRAP_USERMODE(tf))
|
||||
dab_fatal(tf, fsr, far, td, ksig);
|
||||
|
||||
/* Deliver a bus error signal to the process */
|
||||
ksig->signb = SIGBUS;
|
||||
ksig->code = 0;
|
||||
td->td_frame = tf;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* void prefetch_abort_handler(struct trapframe *tf)
|
||||
*
|
||||
* Abort handler called when instruction execution occurs at
|
||||
* a non existent or restricted (access permissions) memory page.
|
||||
* If the address is invalid and we were in SVC mode then panic as
|
||||
* the kernel should never prefetch abort.
|
||||
* If the address is invalid and the page is mapped then the user process
|
||||
* does no have read permission so send it a signal.
|
||||
* Otherwise fault the page in and try again.
|
||||
*/
|
||||
static void
|
||||
prefetch_abort_handler(struct trapframe *tf)
|
||||
{
|
||||
struct thread *td;
|
||||
struct proc * p;
|
||||
struct vm_map *map;
|
||||
vm_offset_t fault_pc, va;
|
||||
int error = 0, signo, ucode;
|
||||
struct ksig ksig;
|
||||
|
||||
#if 0
|
||||
/* Update vmmeter statistics */
|
||||
uvmexp.traps++;
|
||||
#endif
|
||||
#if 0
|
||||
printf("prefetch abort handler: %p %p\n", (void*)tf->tf_pc,
|
||||
(void*)tf->tf_usr_lr);
|
||||
#endif
|
||||
|
||||
td = curthread;
|
||||
p = td->td_proc;
|
||||
VM_CNT_INC(v_trap);
|
||||
|
||||
if (TRAP_USERMODE(tf)) {
|
||||
td->td_frame = tf;
|
||||
if (td->td_cowgen != td->td_proc->p_cowgen)
|
||||
thread_cow_update(td);
|
||||
}
|
||||
fault_pc = tf->tf_pc;
|
||||
if (td->td_md.md_spinlock_count == 0) {
|
||||
if (__predict_true(tf->tf_spsr & PSR_I) == 0)
|
||||
enable_interrupts(PSR_I);
|
||||
if (__predict_true(tf->tf_spsr & PSR_F) == 0)
|
||||
enable_interrupts(PSR_F);
|
||||
}
|
||||
|
||||
/* Prefetch aborts cannot happen in kernel mode */
|
||||
if (__predict_false(!TRAP_USERMODE(tf)))
|
||||
dab_fatal(tf, 0, tf->tf_pc, NULL, &ksig);
|
||||
td->td_pticks = 0;
|
||||
|
||||
/* Ok validate the address, can only execute in USER space */
|
||||
if (__predict_false(fault_pc >= VM_MAXUSER_ADDRESS ||
|
||||
(fault_pc < VM_MIN_ADDRESS && vector_page == ARM_VECTORS_LOW))) {
|
||||
signo = SIGSEGV;
|
||||
ucode = 0;
|
||||
goto do_trapsignal;
|
||||
}
|
||||
|
||||
map = &td->td_proc->p_vmspace->vm_map;
|
||||
va = trunc_page(fault_pc);
|
||||
|
||||
/*
|
||||
* See if the pmap can handle this fault on its own...
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
last_fault_code = -1;
|
||||
#endif
|
||||
if (pmap_fault_fixup(map->pmap, va, VM_PROT_READ, 1))
|
||||
goto out;
|
||||
|
||||
error = vm_fault_trap(map, va, VM_PROT_READ | VM_PROT_EXECUTE,
|
||||
VM_FAULT_NORMAL, &signo, &ucode);
|
||||
if (__predict_true(error == KERN_SUCCESS))
|
||||
goto out;
|
||||
|
||||
do_trapsignal:
|
||||
call_trapsignal(td, signo, ucode);
|
||||
|
||||
out:
|
||||
userret(td, tf);
|
||||
|
||||
}
|
||||
|
||||
extern int badaddr_read_1(const uint8_t *, uint8_t *);
|
||||
extern int badaddr_read_2(const uint16_t *, uint16_t *);
|
||||
extern int badaddr_read_4(const uint32_t *, uint32_t *);
|
||||
/*
|
||||
* Tentatively read an 8, 16, or 32-bit value from 'addr'.
|
||||
* If the read succeeds, the value is written to 'rptr' and zero is returned.
|
||||
* Else, return EFAULT.
|
||||
*/
|
||||
int
|
||||
badaddr_read(void *addr, size_t size, void *rptr)
|
||||
{
|
||||
union {
|
||||
uint8_t v1;
|
||||
uint16_t v2;
|
||||
uint32_t v4;
|
||||
} u;
|
||||
int rv;
|
||||
|
||||
cpu_drain_writebuf();
|
||||
|
||||
/* Read from the test address. */
|
||||
switch (size) {
|
||||
case sizeof(uint8_t):
|
||||
rv = badaddr_read_1(addr, &u.v1);
|
||||
if (rv == 0 && rptr)
|
||||
*(uint8_t *) rptr = u.v1;
|
||||
break;
|
||||
|
||||
case sizeof(uint16_t):
|
||||
rv = badaddr_read_2(addr, &u.v2);
|
||||
if (rv == 0 && rptr)
|
||||
*(uint16_t *) rptr = u.v2;
|
||||
break;
|
||||
|
||||
case sizeof(uint32_t):
|
||||
rv = badaddr_read_4(addr, &u.v4);
|
||||
if (rv == 0 && rptr)
|
||||
*(uint32_t *) rptr = u.v4;
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("badaddr: invalid size (%lu)", (u_long) size);
|
||||
}
|
||||
|
||||
/* Return EFAULT if the address was invalid, else zero */
|
||||
return (rv);
|
||||
}
|
@ -1,660 +0,0 @@
|
||||
/* $NetBSD: atomic.h,v 1.1 2002/10/19 12:22:34 bsh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (C) 2003-2004 Olivier Houchard
|
||||
* Copyright (C) 1994-1997 Mark Brinicombe
|
||||
* Copyright (C) 1994 Brini
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software written for Brini by Mark Brinicombe
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Brini.
|
||||
* 4. The name of Brini may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _MACHINE_ATOMIC_V4_H_
|
||||
#define _MACHINE_ATOMIC_V4_H_
|
||||
|
||||
#ifndef _MACHINE_ATOMIC_H_
|
||||
#error Do not include this file directly, use <machine/atomic.h>
|
||||
#endif
|
||||
|
||||
#if __ARM_ARCH <= 5
|
||||
#define isb() __asm __volatile("mcr p15, 0, %0, c7, c5, 4" : : "r" (0) : "memory")
|
||||
#define dsb() __asm __volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (0) : "memory")
|
||||
#define dmb() dsb()
|
||||
#else
|
||||
#error Only use this file with ARMv5 and earlier
|
||||
#endif
|
||||
|
||||
#define mb() dmb()
|
||||
#define wmb() dmb()
|
||||
#define rmb() dmb()
|
||||
|
||||
#define __with_interrupts_disabled(expr) \
|
||||
do { \
|
||||
u_int cpsr_save, tmp; \
|
||||
\
|
||||
__asm __volatile( \
|
||||
"mrs %0, cpsr;" \
|
||||
"orr %1, %0, %2;" \
|
||||
"msr cpsr_fsxc, %1;" \
|
||||
: "=r" (cpsr_save), "=r" (tmp) \
|
||||
: "I" (PSR_I | PSR_F) \
|
||||
: "cc" ); \
|
||||
(expr); \
|
||||
__asm __volatile( \
|
||||
"msr cpsr_fsxc, %0" \
|
||||
: /* no output */ \
|
||||
: "r" (cpsr_save) \
|
||||
: "cc" ); \
|
||||
} while(0)
|
||||
|
||||
static __inline uint32_t
|
||||
__swp(uint32_t val, volatile uint32_t *ptr)
|
||||
{
|
||||
__asm __volatile("swp %0, %2, [%3]"
|
||||
: "=&r" (val), "=m" (*ptr)
|
||||
: "r" (val), "r" (ptr), "m" (*ptr)
|
||||
: "memory");
|
||||
return (val);
|
||||
}
|
||||
|
||||
#ifdef _KERNEL
|
||||
#define ARM_HAVE_ATOMIC64
|
||||
|
||||
static __inline void
|
||||
atomic_add_32(volatile u_int32_t *p, u_int32_t val)
|
||||
{
|
||||
__with_interrupts_disabled(*p += val);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
atomic_add_64(volatile u_int64_t *p, u_int64_t val)
|
||||
{
|
||||
__with_interrupts_disabled(*p += val);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
atomic_clear_32(volatile uint32_t *address, uint32_t clearmask)
|
||||
{
|
||||
__with_interrupts_disabled(*address &= ~clearmask);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
atomic_clear_64(volatile uint64_t *address, uint64_t clearmask)
|
||||
{
|
||||
__with_interrupts_disabled(*address &= ~clearmask);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
atomic_fcmpset_8(volatile uint8_t *p, volatile uint8_t *cmpval, volatile uint8_t newval)
|
||||
{
|
||||
int ret;
|
||||
|
||||
__with_interrupts_disabled(
|
||||
{
|
||||
ret = *p;
|
||||
if (*p == *cmpval) {
|
||||
*p = newval;
|
||||
ret = 1;
|
||||
} else {
|
||||
*cmpval = *p;
|
||||
ret = 0;
|
||||
}
|
||||
});
|
||||
return (ret);
|
||||
}
|
||||
static __inline int
|
||||
atomic_fcmpset_16(volatile uint16_t *p, volatile uint16_t *cmpval, volatile uint16_t newval)
|
||||
{
|
||||
int ret;
|
||||
|
||||
__with_interrupts_disabled(
|
||||
{
|
||||
ret = *p;
|
||||
if (*p == *cmpval) {
|
||||
*p = newval;
|
||||
ret = 1;
|
||||
} else {
|
||||
*cmpval = *p;
|
||||
ret = 0;
|
||||
}
|
||||
});
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
atomic_fcmpset_32(volatile u_int32_t *p, volatile u_int32_t *cmpval, volatile u_int32_t newval)
|
||||
{
|
||||
int ret;
|
||||
|
||||
__with_interrupts_disabled(
|
||||
{
|
||||
ret = *p;
|
||||
if (*p == *cmpval) {
|
||||
*p = newval;
|
||||
ret = 1;
|
||||
} else {
|
||||
*cmpval = *p;
|
||||
ret = 0;
|
||||
}
|
||||
});
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
atomic_fcmpset_64(volatile u_int64_t *p, volatile u_int64_t *cmpval, volatile u_int64_t newval)
|
||||
{
|
||||
int ret;
|
||||
|
||||
__with_interrupts_disabled(
|
||||
{
|
||||
if (*p == *cmpval) {
|
||||
*p = newval;
|
||||
ret = 1;
|
||||
} else {
|
||||
*cmpval = *p;
|
||||
ret = 0;
|
||||
}
|
||||
});
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
atomic_cmpset_8(volatile uint8_t *p, volatile uint8_t cmpval, volatile uint8_t newval)
|
||||
{
|
||||
int ret;
|
||||
|
||||
__with_interrupts_disabled(
|
||||
{
|
||||
if (*p == cmpval) {
|
||||
*p = newval;
|
||||
ret = 1;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
});
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
atomic_cmpset_16(volatile uint16_t *p, volatile uint16_t cmpval, volatile uint16_t newval)
|
||||
{
|
||||
int ret;
|
||||
|
||||
__with_interrupts_disabled(
|
||||
{
|
||||
if (*p == cmpval) {
|
||||
*p = newval;
|
||||
ret = 1;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
});
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
atomic_cmpset_32(volatile u_int32_t *p, volatile u_int32_t cmpval, volatile u_int32_t newval)
|
||||
{
|
||||
int ret;
|
||||
|
||||
__with_interrupts_disabled(
|
||||
{
|
||||
if (*p == cmpval) {
|
||||
*p = newval;
|
||||
ret = 1;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
});
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
atomic_cmpset_64(volatile u_int64_t *p, volatile u_int64_t cmpval, volatile u_int64_t newval)
|
||||
{
|
||||
int ret;
|
||||
|
||||
__with_interrupts_disabled(
|
||||
{
|
||||
if (*p == cmpval) {
|
||||
*p = newval;
|
||||
ret = 1;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
});
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static __inline uint32_t
|
||||
atomic_fetchadd_32(volatile uint32_t *p, uint32_t v)
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
__with_interrupts_disabled(
|
||||
{
|
||||
value = *p;
|
||||
*p += v;
|
||||
});
|
||||
return (value);
|
||||
}
|
||||
|
||||
static __inline uint64_t
|
||||
atomic_fetchadd_64(volatile uint64_t *p, uint64_t v)
|
||||
{
|
||||
uint64_t value;
|
||||
|
||||
__with_interrupts_disabled(
|
||||
{
|
||||
value = *p;
|
||||
*p += v;
|
||||
});
|
||||
return (value);
|
||||
}
|
||||
|
||||
static __inline uint64_t
|
||||
atomic_load_64(volatile uint64_t *p)
|
||||
{
|
||||
uint64_t value;
|
||||
|
||||
__with_interrupts_disabled(value = *p);
|
||||
return (value);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
atomic_set_32(volatile uint32_t *address, uint32_t setmask)
|
||||
{
|
||||
__with_interrupts_disabled(*address |= setmask);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
atomic_set_64(volatile uint64_t *address, uint64_t setmask)
|
||||
{
|
||||
__with_interrupts_disabled(*address |= setmask);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
atomic_store_64(volatile uint64_t *p, uint64_t value)
|
||||
{
|
||||
__with_interrupts_disabled(*p = value);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
atomic_subtract_32(volatile u_int32_t *p, u_int32_t val)
|
||||
{
|
||||
__with_interrupts_disabled(*p -= val);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
atomic_subtract_64(volatile u_int64_t *p, u_int64_t val)
|
||||
{
|
||||
__with_interrupts_disabled(*p -= val);
|
||||
}
|
||||
|
||||
static __inline uint64_t
|
||||
atomic_swap_64(volatile uint64_t *p, uint64_t v)
|
||||
{
|
||||
uint64_t value;
|
||||
|
||||
__with_interrupts_disabled(
|
||||
{
|
||||
value = *p;
|
||||
*p = v;
|
||||
});
|
||||
return (value);
|
||||
}
|
||||
|
||||
#else /* !_KERNEL */
|
||||
|
||||
static __inline void
|
||||
atomic_add_32(volatile u_int32_t *p, u_int32_t val)
|
||||
{
|
||||
int start, ras_start = ARM_RAS_START;
|
||||
|
||||
__asm __volatile("1:\n"
|
||||
"adr %1, 1b\n"
|
||||
"str %1, [%0]\n"
|
||||
"adr %1, 2f\n"
|
||||
"str %1, [%0, #4]\n"
|
||||
"ldr %1, [%2]\n"
|
||||
"add %1, %1, %3\n"
|
||||
"str %1, [%2]\n"
|
||||
"2:\n"
|
||||
"mov %1, #0\n"
|
||||
"str %1, [%0]\n"
|
||||
"mov %1, #0xffffffff\n"
|
||||
"str %1, [%0, #4]\n"
|
||||
: "+r" (ras_start), "=r" (start), "+r" (p), "+r" (val)
|
||||
: : "memory");
|
||||
}
|
||||
|
||||
static __inline void
|
||||
atomic_clear_32(volatile uint32_t *address, uint32_t clearmask)
|
||||
{
|
||||
int start, ras_start = ARM_RAS_START;
|
||||
|
||||
__asm __volatile("1:\n"
|
||||
"adr %1, 1b\n"
|
||||
"str %1, [%0]\n"
|
||||
"adr %1, 2f\n"
|
||||
"str %1, [%0, #4]\n"
|
||||
"ldr %1, [%2]\n"
|
||||
"bic %1, %1, %3\n"
|
||||
"str %1, [%2]\n"
|
||||
"2:\n"
|
||||
"mov %1, #0\n"
|
||||
"str %1, [%0]\n"
|
||||
"mov %1, #0xffffffff\n"
|
||||
"str %1, [%0, #4]\n"
|
||||
: "+r" (ras_start), "=r" (start), "+r" (address), "+r" (clearmask)
|
||||
: : "memory");
|
||||
|
||||
}
|
||||
|
||||
static __inline int
|
||||
atomic_cmpset_32(volatile u_int32_t *p, volatile u_int32_t cmpval, volatile u_int32_t newval)
|
||||
{
|
||||
int done, ras_start = ARM_RAS_START;
|
||||
|
||||
__asm __volatile("1:\n"
|
||||
"adr %1, 1b\n"
|
||||
"str %1, [%0]\n"
|
||||
"adr %1, 2f\n"
|
||||
"str %1, [%0, #4]\n"
|
||||
"ldr %1, [%2]\n"
|
||||
"cmp %1, %3\n"
|
||||
"streq %4, [%2]\n"
|
||||
"2:\n"
|
||||
"mov %1, #0\n"
|
||||
"str %1, [%0]\n"
|
||||
"mov %1, #0xffffffff\n"
|
||||
"str %1, [%0, #4]\n"
|
||||
"moveq %1, #1\n"
|
||||
"movne %1, #0\n"
|
||||
: "+r" (ras_start), "=r" (done)
|
||||
,"+r" (p), "+r" (cmpval), "+r" (newval) : : "cc", "memory");
|
||||
return (done);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
atomic_fcmpset_32(volatile u_int32_t *p, volatile u_int32_t *cmpval, volatile u_int32_t newval)
|
||||
{
|
||||
int done, oldval, ras_start = ARM_RAS_START;
|
||||
|
||||
__asm __volatile("1:\n"
|
||||
"adr %1, 1b\n"
|
||||
"str %1, [%0]\n"
|
||||
"adr %1, 2f\n"
|
||||
"str %1, [%0, #4]\n"
|
||||
"ldr %1, [%2]\n"
|
||||
"ldr %5, [%3]\n"
|
||||
"cmp %1, %5\n"
|
||||
"streq %4, [%2]\n"
|
||||
"2:\n"
|
||||
"mov %5, #0\n"
|
||||
"str %5, [%0]\n"
|
||||
"mov %5, #0xffffffff\n"
|
||||
"str %5, [%0, #4]\n"
|
||||
"strne %1, [%3]\n"
|
||||
"moveq %1, #1\n"
|
||||
"movne %1, #0\n"
|
||||
: "+r" (ras_start), "=r" (done) ,"+r" (p)
|
||||
, "+r" (cmpval), "+r" (newval), "+r" (oldval) : : "cc", "memory");
|
||||
return (done);
|
||||
}
|
||||
|
||||
static __inline uint32_t
|
||||
atomic_fetchadd_32(volatile uint32_t *p, uint32_t v)
|
||||
{
|
||||
uint32_t start, tmp, ras_start = ARM_RAS_START;
|
||||
|
||||
__asm __volatile("1:\n"
|
||||
"adr %1, 1b\n"
|
||||
"str %1, [%0]\n"
|
||||
"adr %1, 2f\n"
|
||||
"str %1, [%0, #4]\n"
|
||||
"ldr %1, [%3]\n"
|
||||
"mov %2, %1\n"
|
||||
"add %2, %2, %4\n"
|
||||
"str %2, [%3]\n"
|
||||
"2:\n"
|
||||
"mov %2, #0\n"
|
||||
"str %2, [%0]\n"
|
||||
"mov %2, #0xffffffff\n"
|
||||
"str %2, [%0, #4]\n"
|
||||
: "+r" (ras_start), "=r" (start), "=r" (tmp), "+r" (p), "+r" (v)
|
||||
: : "memory");
|
||||
return (start);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
atomic_set_32(volatile uint32_t *address, uint32_t setmask)
|
||||
{
|
||||
int start, ras_start = ARM_RAS_START;
|
||||
|
||||
__asm __volatile("1:\n"
|
||||
"adr %1, 1b\n"
|
||||
"str %1, [%0]\n"
|
||||
"adr %1, 2f\n"
|
||||
"str %1, [%0, #4]\n"
|
||||
"ldr %1, [%2]\n"
|
||||
"orr %1, %1, %3\n"
|
||||
"str %1, [%2]\n"
|
||||
"2:\n"
|
||||
"mov %1, #0\n"
|
||||
"str %1, [%0]\n"
|
||||
"mov %1, #0xffffffff\n"
|
||||
"str %1, [%0, #4]\n"
|
||||
|
||||
: "+r" (ras_start), "=r" (start), "+r" (address), "+r" (setmask)
|
||||
: : "memory");
|
||||
}
|
||||
|
||||
static __inline void
|
||||
atomic_subtract_32(volatile u_int32_t *p, u_int32_t val)
|
||||
{
|
||||
int start, ras_start = ARM_RAS_START;
|
||||
|
||||
__asm __volatile("1:\n"
|
||||
"adr %1, 1b\n"
|
||||
"str %1, [%0]\n"
|
||||
"adr %1, 2f\n"
|
||||
"str %1, [%0, #4]\n"
|
||||
"ldr %1, [%2]\n"
|
||||
"sub %1, %1, %3\n"
|
||||
"str %1, [%2]\n"
|
||||
"2:\n"
|
||||
"mov %1, #0\n"
|
||||
"str %1, [%0]\n"
|
||||
"mov %1, #0xffffffff\n"
|
||||
"str %1, [%0, #4]\n"
|
||||
|
||||
: "+r" (ras_start), "=r" (start), "+r" (p), "+r" (val)
|
||||
: : "memory");
|
||||
}
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
static __inline uint32_t
|
||||
atomic_readandclear_32(volatile u_int32_t *p)
|
||||
{
|
||||
|
||||
return (__swp(0, p));
|
||||
}
|
||||
|
||||
static __inline uint32_t
|
||||
atomic_swap_32(volatile u_int32_t *p, u_int32_t v)
|
||||
{
|
||||
|
||||
return (__swp(v, p));
|
||||
}
|
||||
|
||||
#define atomic_fcmpset_rel_32 atomic_fcmpset_32
|
||||
#define atomic_fcmpset_acq_32 atomic_fcmpset_32
|
||||
#ifdef _KERNEL
|
||||
#define atomic_fcmpset_8 atomic_fcmpset_8
|
||||
#define atomic_fcmpset_rel_8 atomic_fcmpset_8
|
||||
#define atomic_fcmpset_acq_8 atomic_fcmpset_8
|
||||
#define atomic_fcmpset_16 atomic_fcmpset_16
|
||||
#define atomic_fcmpset_rel_16 atomic_fcmpset_16
|
||||
#define atomic_fcmpset_acq_16 atomic_fcmpset_16
|
||||
#define atomic_fcmpset_rel_64 atomic_fcmpset_64
|
||||
#define atomic_fcmpset_acq_64 atomic_fcmpset_64
|
||||
#endif
|
||||
#define atomic_fcmpset_acq_long atomic_fcmpset_long
|
||||
#define atomic_fcmpset_rel_long atomic_fcmpset_long
|
||||
#define atomic_cmpset_rel_32 atomic_cmpset_32
|
||||
#define atomic_cmpset_acq_32 atomic_cmpset_32
|
||||
#ifdef _KERNEL
|
||||
#define atomic_cmpset_8 atomic_cmpset_8
|
||||
#define atomic_cmpset_rel_8 atomic_cmpset_8
|
||||
#define atomic_cmpset_acq_8 atomic_cmpset_8
|
||||
#define atomic_cmpset_16 atomic_cmpset_16
|
||||
#define atomic_cmpset_rel_16 atomic_cmpset_16
|
||||
#define atomic_cmpset_acq_16 atomic_cmpset_16
|
||||
#define atomic_cmpset_rel_64 atomic_cmpset_64
|
||||
#define atomic_cmpset_acq_64 atomic_cmpset_64
|
||||
#endif
|
||||
#define atomic_set_rel_32 atomic_set_32
|
||||
#define atomic_set_acq_32 atomic_set_32
|
||||
#define atomic_clear_rel_32 atomic_clear_32
|
||||
#define atomic_clear_acq_32 atomic_clear_32
|
||||
#define atomic_add_rel_32 atomic_add_32
|
||||
#define atomic_add_acq_32 atomic_add_32
|
||||
#define atomic_subtract_rel_32 atomic_subtract_32
|
||||
#define atomic_subtract_acq_32 atomic_subtract_32
|
||||
#define atomic_store_rel_32 atomic_store_32
|
||||
#define atomic_store_rel_long atomic_store_long
|
||||
#define atomic_load_acq_32 atomic_load_32
|
||||
#define atomic_load_acq_long atomic_load_long
|
||||
#define atomic_add_acq_long atomic_add_long
|
||||
#define atomic_add_rel_long atomic_add_long
|
||||
#define atomic_subtract_acq_long atomic_subtract_long
|
||||
#define atomic_subtract_rel_long atomic_subtract_long
|
||||
#define atomic_clear_acq_long atomic_clear_long
|
||||
#define atomic_clear_rel_long atomic_clear_long
|
||||
#define atomic_set_acq_long atomic_set_long
|
||||
#define atomic_set_rel_long atomic_set_long
|
||||
#define atomic_cmpset_acq_long atomic_cmpset_long
|
||||
#define atomic_cmpset_rel_long atomic_cmpset_long
|
||||
#define atomic_load_acq_long atomic_load_long
|
||||
#undef __with_interrupts_disabled
|
||||
|
||||
static __inline void
|
||||
atomic_add_long(volatile u_long *p, u_long v)
|
||||
{
|
||||
|
||||
atomic_add_32((volatile uint32_t *)p, v);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
atomic_clear_long(volatile u_long *p, u_long v)
|
||||
{
|
||||
|
||||
atomic_clear_32((volatile uint32_t *)p, v);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
atomic_cmpset_long(volatile u_long *dst, u_long old, u_long newe)
|
||||
{
|
||||
|
||||
return (atomic_cmpset_32((volatile uint32_t *)dst, old, newe));
|
||||
}
|
||||
|
||||
static __inline u_long
|
||||
atomic_fcmpset_long(volatile u_long *dst, u_long *old, u_long newe)
|
||||
{
|
||||
|
||||
return (atomic_fcmpset_32((volatile uint32_t *)dst,
|
||||
(uint32_t *)old, newe));
|
||||
}
|
||||
|
||||
static __inline u_long
|
||||
atomic_fetchadd_long(volatile u_long *p, u_long v)
|
||||
{
|
||||
|
||||
return (atomic_fetchadd_32((volatile uint32_t *)p, v));
|
||||
}
|
||||
|
||||
static __inline void
|
||||
atomic_readandclear_long(volatile u_long *p)
|
||||
{
|
||||
|
||||
atomic_readandclear_32((volatile uint32_t *)p);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
atomic_set_long(volatile u_long *p, u_long v)
|
||||
{
|
||||
|
||||
atomic_set_32((volatile uint32_t *)p, v);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
atomic_subtract_long(volatile u_long *p, u_long v)
|
||||
{
|
||||
|
||||
atomic_subtract_32((volatile uint32_t *)p, v);
|
||||
}
|
||||
|
||||
/*
|
||||
* ARMv5 does not support SMP. For both kernel and user modes, only a
|
||||
* compiler barrier is needed for fences, since CPU is always
|
||||
* self-consistent.
|
||||
*/
|
||||
static __inline void
|
||||
atomic_thread_fence_acq(void)
|
||||
{
|
||||
|
||||
__compiler_membar();
|
||||
}
|
||||
|
||||
static __inline void
|
||||
atomic_thread_fence_rel(void)
|
||||
{
|
||||
|
||||
__compiler_membar();
|
||||
}
|
||||
|
||||
static __inline void
|
||||
atomic_thread_fence_acq_rel(void)
|
||||
{
|
||||
|
||||
__compiler_membar();
|
||||
}
|
||||
|
||||
static __inline void
|
||||
atomic_thread_fence_seq_cst(void)
|
||||
{
|
||||
|
||||
__compiler_membar();
|
||||
}
|
||||
|
||||
#endif /* _MACHINE_ATOMIC_H_ */
|
@ -49,11 +49,7 @@
|
||||
#include <machine/sysarch.h>
|
||||
#endif
|
||||
|
||||
#if __ARM_ARCH >= 6
|
||||
#include <machine/atomic-v6.h>
|
||||
#else /* < armv6 */
|
||||
#include <machine/atomic-v4.h>
|
||||
#endif /* Arch >= v6 */
|
||||
|
||||
static __inline u_long
|
||||
atomic_swap_long(volatile u_long *p, u_long v)
|
||||
|
@ -1,183 +0,0 @@
|
||||
/*-
|
||||
* Copyright 2016 Svatopluk Kraus <skra@FreeBSD.org>
|
||||
* Copyright 2016 Michal Meloun <mmel@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 AUTHOR 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 AUTHOR 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
#ifndef MACHINE_CPU_V4_H
|
||||
#define MACHINE_CPU_V4_H
|
||||
|
||||
/* There are no user serviceable parts here, they may change without notice */
|
||||
#ifndef _KERNEL
|
||||
#error Only include this file in the kernel
|
||||
#endif
|
||||
|
||||
#include <machine/atomic.h>
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/cpuinfo.h>
|
||||
#include <machine/sysreg.h>
|
||||
|
||||
#if __ARM_ARCH >= 6
|
||||
#error Never include this file for ARMv6
|
||||
#else
|
||||
|
||||
#define CPU_ASID_KERNEL 0
|
||||
|
||||
/*
|
||||
* Macros to generate CP15 (system control processor) read/write functions.
|
||||
*/
|
||||
#define _FX(s...) #s
|
||||
|
||||
#define _RF0(fname, aname...) \
|
||||
static __inline uint32_t \
|
||||
fname(void) \
|
||||
{ \
|
||||
uint32_t reg; \
|
||||
__asm __volatile("mrc\t" _FX(aname): "=r" (reg)); \
|
||||
return(reg); \
|
||||
}
|
||||
|
||||
#define _R64F0(fname, aname) \
|
||||
static __inline uint64_t \
|
||||
fname(void) \
|
||||
{ \
|
||||
uint64_t reg; \
|
||||
__asm __volatile("mrrc\t" _FX(aname): "=r" (reg)); \
|
||||
return(reg); \
|
||||
}
|
||||
|
||||
#define _WF0(fname, aname...) \
|
||||
static __inline void \
|
||||
fname(void) \
|
||||
{ \
|
||||
__asm __volatile("mcr\t" _FX(aname)); \
|
||||
}
|
||||
|
||||
#define _WF1(fname, aname...) \
|
||||
static __inline void \
|
||||
fname(uint32_t reg) \
|
||||
{ \
|
||||
__asm __volatile("mcr\t" _FX(aname):: "r" (reg)); \
|
||||
}
|
||||
|
||||
/*
|
||||
* Publicly accessible functions
|
||||
*/
|
||||
|
||||
/* Various control registers */
|
||||
|
||||
_RF0(cp15_cpacr_get, CP15_CPACR(%0))
|
||||
_WF1(cp15_cpacr_set, CP15_CPACR(%0))
|
||||
_RF0(cp15_dfsr_get, CP15_DFSR(%0))
|
||||
_RF0(cp15_ttbr_get, CP15_TTBR0(%0))
|
||||
_RF0(cp15_dfar_get, CP15_DFAR(%0))
|
||||
/* XScale */
|
||||
_RF0(cp15_actlr_get, CP15_ACTLR(%0))
|
||||
_WF1(cp15_actlr_set, CP15_ACTLR(%0))
|
||||
|
||||
/*CPU id registers */
|
||||
_RF0(cp15_midr_get, CP15_MIDR(%0))
|
||||
_RF0(cp15_ctr_get, CP15_CTR(%0))
|
||||
_RF0(cp15_tcmtr_get, CP15_TCMTR(%0))
|
||||
_RF0(cp15_tlbtr_get, CP15_TLBTR(%0))
|
||||
_RF0(cp15_sctlr_get, CP15_SCTLR(%0))
|
||||
|
||||
#undef _FX
|
||||
#undef _RF0
|
||||
#undef _WF0
|
||||
#undef _WF1
|
||||
|
||||
/*
|
||||
* armv4/5 compatibility shims.
|
||||
*
|
||||
* These functions provide armv4 cache maintenance using the new armv6 names.
|
||||
* Included here are just the functions actually used now in common code; it may
|
||||
* be necessary to add things here over time.
|
||||
*
|
||||
* The callers of the dcache functions expect these routines to handle address
|
||||
* and size values which are not aligned to cacheline boundaries; the armv4 and
|
||||
* armv5 asm code handles that.
|
||||
*/
|
||||
|
||||
static __inline void
|
||||
tlb_flush_all(void)
|
||||
{
|
||||
cpu_tlb_flushID();
|
||||
cpu_cpwait();
|
||||
}
|
||||
|
||||
static __inline void
|
||||
icache_sync(vm_offset_t va, vm_size_t size)
|
||||
{
|
||||
cpu_icache_sync_range(va, size);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
dcache_inv_poc(vm_offset_t va, vm_paddr_t pa, vm_size_t size)
|
||||
{
|
||||
|
||||
cpu_dcache_inv_range(va, size);
|
||||
#ifdef ARM_L2_PIPT
|
||||
cpu_l2cache_inv_range(pa, size);
|
||||
#else
|
||||
cpu_l2cache_inv_range(va, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline void
|
||||
dcache_inv_poc_dma(vm_offset_t va, vm_paddr_t pa, vm_size_t size)
|
||||
{
|
||||
|
||||
/* See armv6 code, above, for why we do L2 before L1 in this case. */
|
||||
#ifdef ARM_L2_PIPT
|
||||
cpu_l2cache_inv_range(pa, size);
|
||||
#else
|
||||
cpu_l2cache_inv_range(va, size);
|
||||
#endif
|
||||
cpu_dcache_inv_range(va, size);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
dcache_wb_poc(vm_offset_t va, vm_paddr_t pa, vm_size_t size)
|
||||
{
|
||||
|
||||
cpu_dcache_wb_range(va, size);
|
||||
#ifdef ARM_L2_PIPT
|
||||
cpu_l2cache_wb_range(pa, size);
|
||||
#else
|
||||
cpu_l2cache_wb_range(va, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline void
|
||||
dcache_wbinv_poc_all(void)
|
||||
{
|
||||
cpu_idcache_wbinv_all();
|
||||
cpu_l2cache_wbinv_all();
|
||||
}
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* MACHINE_CPU_V4_H */
|
@ -11,11 +11,7 @@ void cpu_halt(void);
|
||||
void swi_vm(void *);
|
||||
|
||||
#ifdef _KERNEL
|
||||
#if __ARM_ARCH >= 6
|
||||
#include <machine/cpu-v6.h>
|
||||
#else
|
||||
#include <machine/cpu-v4.h>
|
||||
#endif /* __ARM_ARCH >= 6 */
|
||||
|
||||
static __inline uint64_t
|
||||
get_cyclecount(void)
|
||||
|
@ -1,381 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Systems Programming Group of the University of Utah Computer
|
||||
* Science Department and William Jolitz of UUNET Technologies Inc.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* Derived from hp300 version by Mike Hibler, this version by William
|
||||
* Jolitz uses a recursive map [a pde points to the page directory] to
|
||||
* map the page tables using the pagetables themselves. This is done to
|
||||
* reduce the impact on kernel virtual memory for lots of sparse address
|
||||
* space, and to reduce the cost of memory to each process.
|
||||
*
|
||||
* from: hp300: @(#)pmap.h 7.2 (Berkeley) 12/16/90
|
||||
* from: @(#)pmap.h 7.4 (Berkeley) 5/12/91
|
||||
* from: FreeBSD: src/sys/i386/include/pmap.h,v 1.70 2000/11/30
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _MACHINE_PMAP_V4_H_
|
||||
#define _MACHINE_PMAP_V4_H_
|
||||
|
||||
#include <machine/pte-v4.h>
|
||||
|
||||
/*
|
||||
* Pte related macros
|
||||
*/
|
||||
#define PTE_NOCACHE 1
|
||||
#define PTE_CACHE 2
|
||||
#define PTE_DEVICE PTE_NOCACHE
|
||||
#define PTE_PAGETABLE 3
|
||||
|
||||
enum mem_type {
|
||||
STRONG_ORD = 0,
|
||||
DEVICE_NOSHARE,
|
||||
DEVICE_SHARE,
|
||||
NRML_NOCACHE,
|
||||
NRML_IWT_OWT,
|
||||
NRML_IWB_OWB,
|
||||
NRML_IWBA_OWBA
|
||||
};
|
||||
|
||||
#ifndef LOCORE
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <sys/_cpuset.h>
|
||||
#include <sys/_lock.h>
|
||||
#include <sys/_mutex.h>
|
||||
|
||||
#define PDESIZE sizeof(pd_entry_t) /* for assembly files */
|
||||
#define PTESIZE sizeof(pt_entry_t) /* for assembly files */
|
||||
|
||||
#define pmap_page_get_memattr(m) ((m)->md.pv_memattr)
|
||||
#define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list))
|
||||
|
||||
/*
|
||||
* Pmap stuff
|
||||
*/
|
||||
|
||||
/*
|
||||
* This structure is used to hold a virtual<->physical address
|
||||
* association and is used mostly by bootstrap code
|
||||
*/
|
||||
struct pv_addr {
|
||||
SLIST_ENTRY(pv_addr) pv_list;
|
||||
vm_offset_t pv_va;
|
||||
vm_paddr_t pv_pa;
|
||||
};
|
||||
|
||||
struct pv_entry;
|
||||
struct pv_chunk;
|
||||
|
||||
struct md_page {
|
||||
int pvh_attrs;
|
||||
vm_memattr_t pv_memattr;
|
||||
vm_offset_t pv_kva; /* first kernel VA mapping */
|
||||
TAILQ_HEAD(,pv_entry) pv_list;
|
||||
};
|
||||
|
||||
struct l1_ttable;
|
||||
struct l2_dtable;
|
||||
|
||||
/*
|
||||
* The number of L2 descriptor tables which can be tracked by an l2_dtable.
|
||||
* A bucket size of 16 provides for 16MB of contiguous virtual address
|
||||
* space per l2_dtable. Most processes will, therefore, require only two or
|
||||
* three of these to map their whole working set.
|
||||
*/
|
||||
#define L2_BUCKET_LOG2 4
|
||||
#define L2_BUCKET_SIZE (1 << L2_BUCKET_LOG2)
|
||||
/*
|
||||
* Given the above "L2-descriptors-per-l2_dtable" constant, the number
|
||||
* of l2_dtable structures required to track all possible page descriptors
|
||||
* mappable by an L1 translation table is given by the following constants:
|
||||
*/
|
||||
#define L2_LOG2 ((32 - L1_S_SHIFT) - L2_BUCKET_LOG2)
|
||||
#define L2_SIZE (1 << L2_LOG2)
|
||||
|
||||
struct pmap {
|
||||
struct mtx pm_mtx;
|
||||
u_int8_t pm_domain;
|
||||
struct l1_ttable *pm_l1;
|
||||
struct l2_dtable *pm_l2[L2_SIZE];
|
||||
cpuset_t pm_active; /* active on cpus */
|
||||
struct pmap_statistics pm_stats; /* pmap statictics */
|
||||
TAILQ_HEAD(,pv_entry) pm_pvlist; /* list of mappings in pmap */
|
||||
};
|
||||
|
||||
typedef struct pmap *pmap_t;
|
||||
|
||||
#ifdef _KERNEL
|
||||
extern struct pmap kernel_pmap_store;
|
||||
#define kernel_pmap (&kernel_pmap_store)
|
||||
|
||||
#define PMAP_ASSERT_LOCKED(pmap) \
|
||||
mtx_assert(&(pmap)->pm_mtx, MA_OWNED)
|
||||
#define PMAP_LOCK(pmap) mtx_lock(&(pmap)->pm_mtx)
|
||||
#define PMAP_LOCK_DESTROY(pmap) mtx_destroy(&(pmap)->pm_mtx)
|
||||
#define PMAP_LOCK_INIT(pmap) mtx_init(&(pmap)->pm_mtx, "pmap", \
|
||||
NULL, MTX_DEF | MTX_DUPOK)
|
||||
#define PMAP_OWNED(pmap) mtx_owned(&(pmap)->pm_mtx)
|
||||
#define PMAP_MTX(pmap) (&(pmap)->pm_mtx)
|
||||
#define PMAP_TRYLOCK(pmap) mtx_trylock(&(pmap)->pm_mtx)
|
||||
#define PMAP_UNLOCK(pmap) mtx_unlock(&(pmap)->pm_mtx)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* For each vm_page_t, there is a list of all currently valid virtual
|
||||
* mappings of that page. An entry is a pv_entry_t, the list is pv_list.
|
||||
*/
|
||||
typedef struct pv_entry {
|
||||
vm_offset_t pv_va; /* virtual address for mapping */
|
||||
TAILQ_ENTRY(pv_entry) pv_list;
|
||||
int pv_flags; /* flags (wired, etc...) */
|
||||
pmap_t pv_pmap; /* pmap where mapping lies */
|
||||
TAILQ_ENTRY(pv_entry) pv_plist;
|
||||
} *pv_entry_t;
|
||||
|
||||
/*
|
||||
* pv_entries are allocated in chunks per-process. This avoids the
|
||||
* need to track per-pmap assignments.
|
||||
*/
|
||||
#define _NPCM 8
|
||||
#define _NPCPV 252
|
||||
|
||||
struct pv_chunk {
|
||||
pmap_t pc_pmap;
|
||||
TAILQ_ENTRY(pv_chunk) pc_list;
|
||||
uint32_t pc_map[_NPCM]; /* bitmap; 1 = free */
|
||||
uint32_t pc_dummy[3]; /* aligns pv_chunk to 4KB */
|
||||
TAILQ_ENTRY(pv_chunk) pc_lru;
|
||||
struct pv_entry pc_pventry[_NPCPV];
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
boolean_t pmap_get_pde_pte(pmap_t, vm_offset_t, pd_entry_t **, pt_entry_t **);
|
||||
|
||||
/*
|
||||
* virtual address to page table entry and
|
||||
* to physical address. Likewise for alternate address space.
|
||||
* Note: these work recursively, thus vtopte of a pte will give
|
||||
* the corresponding pde that in turn maps it.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The current top of kernel VM.
|
||||
*/
|
||||
extern vm_offset_t pmap_curmaxkvaddr;
|
||||
|
||||
/* Virtual address to page table entry */
|
||||
static __inline pt_entry_t *
|
||||
vtopte(vm_offset_t va)
|
||||
{
|
||||
pd_entry_t *pdep;
|
||||
pt_entry_t *ptep;
|
||||
|
||||
if (pmap_get_pde_pte(kernel_pmap, va, &pdep, &ptep) == FALSE)
|
||||
return (NULL);
|
||||
return (ptep);
|
||||
}
|
||||
|
||||
void pmap_bootstrap(vm_offset_t firstaddr, struct pv_addr *l1pt);
|
||||
int pmap_change_attr(vm_offset_t, vm_size_t, int);
|
||||
void pmap_kenter(vm_offset_t va, vm_paddr_t pa);
|
||||
void pmap_kenter_nocache(vm_offset_t va, vm_paddr_t pa);
|
||||
void pmap_kenter_user(vm_offset_t va, vm_paddr_t pa);
|
||||
vm_paddr_t pmap_dump_kextract(vm_offset_t, pt2_entry_t *);
|
||||
void pmap_kremove(vm_offset_t);
|
||||
vm_page_t pmap_use_pt(pmap_t, vm_offset_t);
|
||||
void pmap_debug(int);
|
||||
void pmap_map_section(vm_offset_t, vm_offset_t, vm_offset_t, int, int);
|
||||
void pmap_link_l2pt(vm_offset_t, vm_offset_t, struct pv_addr *);
|
||||
vm_size_t pmap_map_chunk(vm_offset_t, vm_offset_t, vm_offset_t, vm_size_t, int, int);
|
||||
void
|
||||
pmap_map_entry(vm_offset_t l1pt, vm_offset_t va, vm_offset_t pa, int prot,
|
||||
int cache);
|
||||
int pmap_fault_fixup(pmap_t, vm_offset_t, vm_prot_t, int);
|
||||
|
||||
/*
|
||||
* Definitions for MMU domains
|
||||
*/
|
||||
#define PMAP_DOMAINS 15 /* 15 'user' domains (1-15) */
|
||||
#define PMAP_DOMAIN_KERNEL 0 /* The kernel uses domain #0 */
|
||||
|
||||
/*
|
||||
* The new pmap ensures that page-tables are always mapping Write-Thru.
|
||||
* Thus, on some platforms we can run fast and loose and avoid syncing PTEs
|
||||
* on every change.
|
||||
*
|
||||
* Unfortunately, not all CPUs have a write-through cache mode. So we
|
||||
* define PMAP_NEEDS_PTE_SYNC for C code to conditionally do PTE syncs,
|
||||
* and if there is the chance for PTE syncs to be needed, we define
|
||||
* PMAP_INCLUDE_PTE_SYNC so e.g. assembly code can include (and run)
|
||||
* the code.
|
||||
*/
|
||||
extern int pmap_needs_pte_sync;
|
||||
|
||||
/*
|
||||
* These macros define the various bit masks in the PTE.
|
||||
*/
|
||||
|
||||
#define L1_S_CACHE_MASK (L1_S_B|L1_S_C)
|
||||
#define L2_L_CACHE_MASK (L2_B|L2_C)
|
||||
#define L2_S_PROT_U (L2_AP(AP_U))
|
||||
#define L2_S_PROT_W (L2_AP(AP_W))
|
||||
#define L2_S_PROT_MASK (L2_S_PROT_U|L2_S_PROT_W)
|
||||
#define L2_S_CACHE_MASK (L2_B|L2_C)
|
||||
#define L1_S_PROTO (L1_TYPE_S | L1_S_IMP)
|
||||
#define L1_C_PROTO (L1_TYPE_C | L1_C_IMP2)
|
||||
#define L2_L_PROTO (L2_TYPE_L)
|
||||
#define L2_S_PROTO (L2_TYPE_S)
|
||||
|
||||
/*
|
||||
* User-visible names for the ones that vary with MMU class.
|
||||
*/
|
||||
#define L2_AP(x) (L2_AP0(x) | L2_AP1(x) | L2_AP2(x) | L2_AP3(x))
|
||||
|
||||
#if defined(CPU_XSCALE_81342)
|
||||
#define CPU_XSCALE_CORE3
|
||||
#define PMAP_NEEDS_PTE_SYNC 1
|
||||
#define PMAP_INCLUDE_PTE_SYNC
|
||||
#else
|
||||
#define PMAP_NEEDS_PTE_SYNC 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These macros return various bits based on kernel/user and protection.
|
||||
* Note that the compiler will usually fold these at compile time.
|
||||
*/
|
||||
#define L1_S_PROT_U (L1_S_AP(AP_U))
|
||||
#define L1_S_PROT_W (L1_S_AP(AP_W))
|
||||
#define L1_S_PROT_MASK (L1_S_PROT_U|L1_S_PROT_W)
|
||||
#define L1_S_WRITABLE(pd) ((pd) & L1_S_PROT_W)
|
||||
|
||||
#define L1_S_PROT(ku, pr) ((((ku) == PTE_USER) ? L1_S_PROT_U : 0) | \
|
||||
(((pr) & VM_PROT_WRITE) ? L1_S_PROT_W : 0))
|
||||
|
||||
#define L2_L_PROT_U (L2_AP(AP_U))
|
||||
#define L2_L_PROT_W (L2_AP(AP_W))
|
||||
#define L2_L_PROT_MASK (L2_L_PROT_U|L2_L_PROT_W)
|
||||
|
||||
#define L2_L_PROT(ku, pr) ((((ku) == PTE_USER) ? L2_L_PROT_U : 0) | \
|
||||
(((pr) & VM_PROT_WRITE) ? L2_L_PROT_W : 0))
|
||||
|
||||
#define L2_S_PROT(ku, pr) ((((ku) == PTE_USER) ? L2_S_PROT_U : 0) | \
|
||||
(((pr) & VM_PROT_WRITE) ? L2_S_PROT_W : 0))
|
||||
|
||||
/*
|
||||
* Macros to test if a mapping is mappable with an L1 Section mapping
|
||||
* or an L2 Large Page mapping.
|
||||
*/
|
||||
#define L1_S_MAPPABLE_P(va, pa, size) \
|
||||
((((va) | (pa)) & L1_S_OFFSET) == 0 && (size) >= L1_S_SIZE)
|
||||
|
||||
#define L2_L_MAPPABLE_P(va, pa, size) \
|
||||
((((va) | (pa)) & L2_L_OFFSET) == 0 && (size) >= L2_L_SIZE)
|
||||
|
||||
/*
|
||||
* Provide a fallback in case we were not able to determine it at
|
||||
* compile-time.
|
||||
*/
|
||||
#ifndef PMAP_NEEDS_PTE_SYNC
|
||||
#define PMAP_NEEDS_PTE_SYNC pmap_needs_pte_sync
|
||||
#define PMAP_INCLUDE_PTE_SYNC
|
||||
#endif
|
||||
|
||||
#ifdef ARM_L2_PIPT
|
||||
#define _sync_l2(pte, size) cpu_l2cache_wb_range(vtophys(pte), size)
|
||||
#else
|
||||
#define _sync_l2(pte, size) cpu_l2cache_wb_range(pte, size)
|
||||
#endif
|
||||
|
||||
#define PTE_SYNC(pte) \
|
||||
do { \
|
||||
if (PMAP_NEEDS_PTE_SYNC) { \
|
||||
cpu_dcache_wb_range((vm_offset_t)(pte), sizeof(pt_entry_t));\
|
||||
cpu_drain_writebuf(); \
|
||||
_sync_l2((vm_offset_t)(pte), sizeof(pt_entry_t));\
|
||||
} else \
|
||||
cpu_drain_writebuf(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define PTE_SYNC_RANGE(pte, cnt) \
|
||||
do { \
|
||||
if (PMAP_NEEDS_PTE_SYNC) { \
|
||||
cpu_dcache_wb_range((vm_offset_t)(pte), \
|
||||
(cnt) << 2); /* * sizeof(pt_entry_t) */ \
|
||||
cpu_drain_writebuf(); \
|
||||
_sync_l2((vm_offset_t)(pte), \
|
||||
(cnt) << 2); /* * sizeof(pt_entry_t) */ \
|
||||
} else \
|
||||
cpu_drain_writebuf(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
void pmap_pte_init_generic(void);
|
||||
|
||||
#define PTE_KERNEL 0
|
||||
#define PTE_USER 1
|
||||
|
||||
/*
|
||||
* Flags that indicate attributes of pages or mappings of pages.
|
||||
*
|
||||
* The PVF_MOD and PVF_REF flags are stored in the mdpage for each
|
||||
* page. PVF_WIRED, PVF_WRITE, and PVF_NC are kept in individual
|
||||
* pv_entry's for each page. They live in the same "namespace" so
|
||||
* that we can clear multiple attributes at a time.
|
||||
*
|
||||
* Note the "non-cacheable" flag generally means the page has
|
||||
* multiple mappings in a given address space.
|
||||
*/
|
||||
#define PVF_MOD 0x01 /* page is modified */
|
||||
#define PVF_REF 0x02 /* page is referenced */
|
||||
#define PVF_WIRED 0x04 /* mapping is wired */
|
||||
#define PVF_WRITE 0x08 /* mapping is writable */
|
||||
#define PVF_EXEC 0x10 /* mapping is executable */
|
||||
#define PVF_NC 0x20 /* mapping is non-cacheable */
|
||||
#define PVF_MWC 0x40 /* mapping is used multiple times in userland */
|
||||
#define PVF_UNMAN 0x80 /* mapping is unmanaged */
|
||||
|
||||
void vector_page_setprot(int);
|
||||
|
||||
#define SECTION_CACHE 0x1
|
||||
#define SECTION_PT 0x2
|
||||
void pmap_postinit(void);
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !LOCORE */
|
||||
|
||||
#endif /* !_MACHINE_PMAP_V4_H_ */
|
@ -32,11 +32,7 @@
|
||||
#ifndef _MACHINE_PMAP_H_
|
||||
#define _MACHINE_PMAP_H_
|
||||
|
||||
#if __ARM_ARCH >= 6
|
||||
#include <machine/pmap-v6.h>
|
||||
#else
|
||||
#include <machine/pmap-v4.h>
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/systm.h>
|
||||
|
@ -1,350 +0,0 @@
|
||||
/* $NetBSD: pte.h,v 1.1 2001/11/23 17:39:04 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1994 Mark Brinicombe.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the RiscBSD team.
|
||||
* 4. The name "RiscBSD" nor the name of the author may be used to
|
||||
* endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY RISCBSD ``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 RISCBSD 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _MACHINE_PTE_V4_H_
|
||||
#define _MACHINE_PTE_V4_H_
|
||||
|
||||
#ifndef LOCORE
|
||||
typedef uint32_t pd_entry_t; /* page directory entry */
|
||||
typedef uint32_t pt_entry_t; /* page table entry */
|
||||
typedef pt_entry_t pt2_entry_t; /* compatibility with v6 */
|
||||
#endif
|
||||
|
||||
#define PG_FRAME 0xfffff000
|
||||
|
||||
/* The PT_SIZE definition is misleading... A page table is only 0x400
|
||||
* bytes long. But since VM mapping can only be done to 0x1000 a single
|
||||
* 1KB blocks cannot be steered to a va by itself. Therefore the
|
||||
* pages tables are allocated in blocks of 4. i.e. if a 1 KB block
|
||||
* was allocated for a PT then the other 3KB would also get mapped
|
||||
* whenever the 1KB was mapped.
|
||||
*/
|
||||
|
||||
#define PT_RSIZE 0x0400 /* Real page table size */
|
||||
#define PT_SIZE 0x1000
|
||||
#define PD_SIZE 0x4000
|
||||
|
||||
/* Page table types and masks */
|
||||
#define L1_PAGE 0x01 /* L1 page table mapping */
|
||||
#define L1_SECTION 0x02 /* L1 section mapping */
|
||||
#define L1_FPAGE 0x03 /* L1 fine page mapping */
|
||||
#define L1_MASK 0x03 /* Mask for L1 entry type */
|
||||
#define L2_LPAGE 0x01 /* L2 large page (64KB) */
|
||||
#define L2_SPAGE 0x02 /* L2 small page (4KB) */
|
||||
#define L2_MASK 0x03 /* Mask for L2 entry type */
|
||||
#define L2_INVAL 0x00 /* L2 invalid type */
|
||||
|
||||
/*
|
||||
* The ARM MMU architecture was introduced with ARM v3 (previous ARM
|
||||
* architecture versions used an optional off-CPU memory controller
|
||||
* to perform address translation).
|
||||
*
|
||||
* The ARM MMU consists of a TLB and translation table walking logic.
|
||||
* There is typically one TLB per memory interface (or, put another
|
||||
* way, one TLB per software-visible cache).
|
||||
*
|
||||
* The ARM MMU is capable of mapping memory in the following chunks:
|
||||
*
|
||||
* 1M Sections (L1 table)
|
||||
*
|
||||
* 64K Large Pages (L2 table)
|
||||
*
|
||||
* 4K Small Pages (L2 table)
|
||||
*
|
||||
* 1K Tiny Pages (L2 table)
|
||||
*
|
||||
* There are two types of L2 tables: Coarse Tables and Fine Tables.
|
||||
* Coarse Tables can map Large and Small Pages. Fine Tables can
|
||||
* map Tiny Pages.
|
||||
*
|
||||
* Coarse Tables can define 4 Subpages within Large and Small pages.
|
||||
* Subpages define different permissions for each Subpage within
|
||||
* a Page.
|
||||
*
|
||||
* Coarse Tables are 1K in length. Fine tables are 4K in length.
|
||||
*
|
||||
* The Translation Table Base register holds the pointer to the
|
||||
* L1 Table. The L1 Table is a 16K contiguous chunk of memory
|
||||
* aligned to a 16K boundary. Each entry in the L1 Table maps
|
||||
* 1M of virtual address space, either via a Section mapping or
|
||||
* via an L2 Table.
|
||||
*
|
||||
* In addition, the Fast Context Switching Extension (FCSE) is available
|
||||
* on some ARM v4 and ARM v5 processors. FCSE is a way of eliminating
|
||||
* TLB/cache flushes on context switch by use of a smaller address space
|
||||
* and a "process ID" that modifies the virtual address before being
|
||||
* presented to the translation logic.
|
||||
*/
|
||||
|
||||
/* ARMv6 super-sections. */
|
||||
#define L1_SUP_SIZE 0x01000000 /* 16M */
|
||||
#define L1_SUP_OFFSET (L1_SUP_SIZE - 1)
|
||||
#define L1_SUP_FRAME (~L1_SUP_OFFSET)
|
||||
#define L1_SUP_SHIFT 24
|
||||
|
||||
#define L1_S_SIZE 0x00100000 /* 1M */
|
||||
#define L1_S_OFFSET (L1_S_SIZE - 1)
|
||||
#define L1_S_FRAME (~L1_S_OFFSET)
|
||||
#define L1_S_SHIFT 20
|
||||
|
||||
#define L2_L_SIZE 0x00010000 /* 64K */
|
||||
#define L2_L_OFFSET (L2_L_SIZE - 1)
|
||||
#define L2_L_FRAME (~L2_L_OFFSET)
|
||||
#define L2_L_SHIFT 16
|
||||
|
||||
#define L2_S_SIZE 0x00001000 /* 4K */
|
||||
#define L2_S_OFFSET (L2_S_SIZE - 1)
|
||||
#define L2_S_FRAME (~L2_S_OFFSET)
|
||||
#define L2_S_SHIFT 12
|
||||
|
||||
#define L2_T_SIZE 0x00000400 /* 1K */
|
||||
#define L2_T_OFFSET (L2_T_SIZE - 1)
|
||||
#define L2_T_FRAME (~L2_T_OFFSET)
|
||||
#define L2_T_SHIFT 10
|
||||
|
||||
/*
|
||||
* The NetBSD VM implementation only works on whole pages (4K),
|
||||
* whereas the ARM MMU's Coarse tables are sized in terms of 1K
|
||||
* (16K L1 table, 1K L2 table).
|
||||
*
|
||||
* So, we allocate L2 tables 4 at a time, thus yielding a 4K L2
|
||||
* table.
|
||||
*/
|
||||
#define L1_TABLE_SIZE 0x4000 /* 16K */
|
||||
#define L2_TABLE_SIZE 0x1000 /* 4K */
|
||||
/*
|
||||
* The new pmap deals with the 1KB coarse L2 tables by
|
||||
* allocating them from a pool. Until every port has been converted,
|
||||
* keep the old L2_TABLE_SIZE define lying around. Converted ports
|
||||
* should use L2_TABLE_SIZE_REAL until then.
|
||||
*/
|
||||
#define L2_TABLE_SIZE_REAL 0x400 /* 1K */
|
||||
|
||||
/* Total number of page table entries in L2 table */
|
||||
#define L2_PTE_NUM_TOTAL (L2_TABLE_SIZE_REAL / sizeof(pt_entry_t))
|
||||
|
||||
/*
|
||||
* ARM L1 Descriptors
|
||||
*/
|
||||
|
||||
#define L1_TYPE_INV 0x00 /* Invalid (fault) */
|
||||
#define L1_TYPE_C 0x01 /* Coarse L2 */
|
||||
#define L1_TYPE_S 0x02 /* Section */
|
||||
#define L1_TYPE_F 0x03 /* Fine L2 */
|
||||
#define L1_TYPE_MASK 0x03 /* mask of type bits */
|
||||
|
||||
/* L1 Section Descriptor */
|
||||
#define L1_S_B 0x00000004 /* bufferable Section */
|
||||
#define L1_S_C 0x00000008 /* cacheable Section */
|
||||
#define L1_S_IMP 0x00000010 /* implementation defined */
|
||||
#define L1_S_XN (1 << 4) /* execute not */
|
||||
#define L1_S_DOM(x) ((x) << 5) /* domain */
|
||||
#define L1_S_DOM_MASK L1_S_DOM(0xf)
|
||||
#define L1_S_AP(x) ((x) << 10) /* access permissions */
|
||||
#define L1_S_ADDR_MASK 0xfff00000 /* phys address of section */
|
||||
#define L1_S_TEX(x) (((x) & 0x7) << 12) /* Type Extension */
|
||||
#define L1_S_TEX_MASK (0x7 << 12) /* Type Extension */
|
||||
#define L1_S_APX (1 << 15)
|
||||
#define L1_SHARED (1 << 16)
|
||||
|
||||
#define L1_S_XSCALE_P 0x00000200 /* ECC enable for this section */
|
||||
#define L1_S_XSCALE_TEX(x) ((x) << 12) /* Type Extension */
|
||||
|
||||
#define L1_S_SUPERSEC ((1) << 18) /* Section is a super-section. */
|
||||
|
||||
/* L1 Coarse Descriptor */
|
||||
#define L1_C_IMP0 0x00000004 /* implementation defined */
|
||||
#define L1_C_IMP1 0x00000008 /* implementation defined */
|
||||
#define L1_C_IMP2 0x00000010 /* implementation defined */
|
||||
#define L1_C_DOM(x) ((x) << 5) /* domain */
|
||||
#define L1_C_DOM_MASK L1_C_DOM(0xf)
|
||||
#define L1_C_ADDR_MASK 0xfffffc00 /* phys address of L2 Table */
|
||||
|
||||
#define L1_C_XSCALE_P 0x00000200 /* ECC enable for this section */
|
||||
|
||||
/* L1 Fine Descriptor */
|
||||
#define L1_F_IMP0 0x00000004 /* implementation defined */
|
||||
#define L1_F_IMP1 0x00000008 /* implementation defined */
|
||||
#define L1_F_IMP2 0x00000010 /* implementation defined */
|
||||
#define L1_F_DOM(x) ((x) << 5) /* domain */
|
||||
#define L1_F_DOM_MASK L1_F_DOM(0xf)
|
||||
#define L1_F_ADDR_MASK 0xfffff000 /* phys address of L2 Table */
|
||||
|
||||
#define L1_F_XSCALE_P 0x00000200 /* ECC enable for this section */
|
||||
|
||||
/*
|
||||
* ARM L2 Descriptors
|
||||
*/
|
||||
|
||||
#define L2_TYPE_INV 0x00 /* Invalid (fault) */
|
||||
#define L2_TYPE_L 0x01 /* Large Page */
|
||||
#define L2_TYPE_S 0x02 /* Small Page */
|
||||
#define L2_TYPE_T 0x03 /* Tiny Page */
|
||||
#define L2_TYPE_MASK 0x03 /* mask of type bits */
|
||||
|
||||
/*
|
||||
* This L2 Descriptor type is available on XScale processors
|
||||
* when using a Coarse L1 Descriptor. The Extended Small
|
||||
* Descriptor has the same format as the XScale Tiny Descriptor,
|
||||
* but describes a 4K page, rather than a 1K page.
|
||||
*/
|
||||
#define L2_TYPE_XSCALE_XS 0x03 /* XScale Extended Small Page */
|
||||
|
||||
#define L2_B 0x00000004 /* Bufferable page */
|
||||
#define L2_C 0x00000008 /* Cacheable page */
|
||||
#define L2_AP0(x) ((x) << 4) /* access permissions (sp 0) */
|
||||
#define L2_AP1(x) ((x) << 6) /* access permissions (sp 1) */
|
||||
#define L2_AP2(x) ((x) << 8) /* access permissions (sp 2) */
|
||||
#define L2_AP3(x) ((x) << 10) /* access permissions (sp 3) */
|
||||
|
||||
#define L2_SHARED (1 << 10)
|
||||
#define L2_APX (1 << 9)
|
||||
#define L2_XN (1 << 0)
|
||||
#define L2_L_TEX_MASK (0x7 << 12) /* Type Extension */
|
||||
#define L2_L_TEX(x) (((x) & 0x7) << 12)
|
||||
#define L2_S_TEX_MASK (0x7 << 6) /* Type Extension */
|
||||
#define L2_S_TEX(x) (((x) & 0x7) << 6)
|
||||
|
||||
#define L2_XSCALE_L_TEX(x) ((x) << 12) /* Type Extension */
|
||||
#define L2_XSCALE_L_S(x) (1 << 15) /* Shared */
|
||||
#define L2_XSCALE_T_TEX(x) ((x) << 6) /* Type Extension */
|
||||
|
||||
/*
|
||||
* Access Permissions for L1 and L2 Descriptors.
|
||||
*/
|
||||
#define AP_W 0x01 /* writable */
|
||||
#define AP_REF 0x01 /* referenced flag */
|
||||
#define AP_U 0x02 /* user */
|
||||
|
||||
/*
|
||||
* Short-hand for common AP_* constants.
|
||||
*
|
||||
* Note: These values assume the S (System) bit is set and
|
||||
* the R (ROM) bit is clear in CP15 register 1.
|
||||
*/
|
||||
#define AP_KR 0x00 /* kernel read */
|
||||
#define AP_KRW 0x01 /* kernel read/write */
|
||||
#define AP_KRWUR 0x02 /* kernel read/write usr read */
|
||||
#define AP_KRWURW 0x03 /* kernel read/write usr read/write */
|
||||
|
||||
/*
|
||||
* Domain Types for the Domain Access Control Register.
|
||||
*/
|
||||
#define DOMAIN_FAULT 0x00 /* no access */
|
||||
#define DOMAIN_CLIENT 0x01 /* client */
|
||||
#define DOMAIN_RESERVED 0x02 /* reserved */
|
||||
#define DOMAIN_MANAGER 0x03 /* manager */
|
||||
|
||||
/*
|
||||
* Type Extension bits for XScale processors.
|
||||
*
|
||||
* Behavior of C and B when X == 0:
|
||||
*
|
||||
* C B Cacheable Bufferable Write Policy Line Allocate Policy
|
||||
* 0 0 N N - -
|
||||
* 0 1 N Y - -
|
||||
* 1 0 Y Y Write-through Read Allocate
|
||||
* 1 1 Y Y Write-back Read Allocate
|
||||
*
|
||||
* Behavior of C and B when X == 1:
|
||||
* C B Cacheable Bufferable Write Policy Line Allocate Policy
|
||||
* 0 0 - - - - DO NOT USE
|
||||
* 0 1 N Y - -
|
||||
* 1 0 Mini-Data - - -
|
||||
* 1 1 Y Y Write-back R/W Allocate
|
||||
*/
|
||||
#define TEX_XSCALE_X 0x01 /* X modifies C and B */
|
||||
#define TEX_XSCALE_E 0x02
|
||||
#define TEX_XSCALE_T 0x04
|
||||
|
||||
/* Xscale core 3 */
|
||||
|
||||
/*
|
||||
*
|
||||
* Cache attributes with L2 present, S = 0
|
||||
* T E X C B L1 i-cache L1 d-cache L1 DC WP L2 cacheable write coalesce
|
||||
* 0 0 0 0 0 N N - N N
|
||||
* 0 0 0 0 1 N N - N Y
|
||||
* 0 0 0 1 0 Y Y WT N Y
|
||||
* 0 0 0 1 1 Y Y WB Y Y
|
||||
* 0 0 1 0 0 N N - Y Y
|
||||
* 0 0 1 0 1 N N - N N
|
||||
* 0 0 1 1 0 Y Y - - N
|
||||
* 0 0 1 1 1 Y Y WT Y Y
|
||||
* 0 1 0 0 0 N N - N N
|
||||
* 0 1 0 0 1 N/A N/A N/A N/A N/A
|
||||
* 0 1 0 1 0 N/A N/A N/A N/A N/A
|
||||
* 0 1 0 1 1 N/A N/A N/A N/A N/A
|
||||
* 0 1 1 X X N/A N/A N/A N/A N/A
|
||||
* 1 X 0 0 0 N N - N Y
|
||||
* 1 X 0 0 1 Y N WB N Y
|
||||
* 1 X 0 1 0 Y N WT N Y
|
||||
* 1 X 0 1 1 Y N WB Y Y
|
||||
* 1 X 1 0 0 N N - Y Y
|
||||
* 1 X 1 0 1 Y Y WB Y Y
|
||||
* 1 X 1 1 0 Y Y WT Y Y
|
||||
* 1 X 1 1 1 Y Y WB Y Y
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Cache attributes with L2 present, S = 1
|
||||
* T E X C B L1 i-cache L1 d-cache L1 DC WP L2 cacheable write coalesce
|
||||
* 0 0 0 0 0 N N - N N
|
||||
* 0 0 0 0 1 N N - N Y
|
||||
* 0 0 0 1 0 Y Y - N Y
|
||||
* 0 0 0 1 1 Y Y WT Y Y
|
||||
* 0 0 1 0 0 N N - Y Y
|
||||
* 0 0 1 0 1 N N - N N
|
||||
* 0 0 1 1 0 Y Y - - N
|
||||
* 0 0 1 1 1 Y Y WT Y Y
|
||||
* 0 1 0 0 0 N N - N N
|
||||
* 0 1 0 0 1 N/A N/A N/A N/A N/A
|
||||
* 0 1 0 1 0 N/A N/A N/A N/A N/A
|
||||
* 0 1 0 1 1 N/A N/A N/A N/A N/A
|
||||
* 0 1 1 X X N/A N/A N/A N/A N/A
|
||||
* 1 X 0 0 0 N N - N Y
|
||||
* 1 X 0 0 1 Y N - N Y
|
||||
* 1 X 0 1 0 Y N - N Y
|
||||
* 1 X 0 1 1 Y N - Y Y
|
||||
* 1 X 1 0 0 N N - Y Y
|
||||
* 1 X 1 0 1 Y Y WT Y Y
|
||||
* 1 X 1 1 0 Y Y WT Y Y
|
||||
* 1 X 1 1 1 Y Y WT Y Y
|
||||
*/
|
||||
#endif /* !_MACHINE_PTE_V4_H_ */
|
||||
|
||||
/* End of pte.h */
|
@ -19,7 +19,7 @@ arm/arm/cpufunc_asm_armv7.S optional cpu_cortexa | cpu_krait | cpu_mv_pj4b
|
||||
arm/arm/cpufunc_asm_pj4b.S optional cpu_mv_pj4b
|
||||
arm/arm/cpufunc_asm_sheeva.S optional cpu_arm9e
|
||||
arm/arm/cpuinfo.c standard
|
||||
arm/arm/cpu_asm-v6.S optional armv7 | armv6
|
||||
arm/arm/cpu_asm-v6.S standard
|
||||
arm/arm/db_disasm.c optional ddb
|
||||
arm/arm/db_interface.c optional ddb
|
||||
arm/arm/db_trace.c optional ddb
|
||||
@ -37,14 +37,12 @@ arm/arm/gdb_machdep.c optional gdb
|
||||
arm/arm/generic_timer.c optional generic_timer
|
||||
arm/arm/gic.c optional gic
|
||||
arm/arm/gic_fdt.c optional gic fdt
|
||||
arm/arm/identcpu-v4.c optional !armv7 !armv6
|
||||
arm/arm/identcpu-v6.c optional armv7 | armv6
|
||||
arm/arm/identcpu-v6.c standard
|
||||
arm/arm/in_cksum.c optional inet | inet6
|
||||
arm/arm/in_cksum_arm.S optional inet | inet6
|
||||
arm/arm/intr.c optional !intrng
|
||||
kern/subr_intr.c optional intrng
|
||||
kern/subr_intr.c standard
|
||||
arm/arm/locore.S standard no-obj
|
||||
arm/arm/hypervisor-stub.S optional armv7 | armv6
|
||||
arm/arm/hypervisor-stub.S standard
|
||||
arm/arm/machdep.c standard
|
||||
arm/arm/machdep_boot.c standard
|
||||
arm/arm/machdep_kdb.c standard
|
||||
@ -61,8 +59,7 @@ arm/arm/pl310.c optional pl310
|
||||
arm/arm/platform.c optional platform
|
||||
arm/arm/platform_if.m optional platform
|
||||
arm/arm/platform_pl310_if.m optional platform pl310
|
||||
arm/arm/pmap-v4.c optional !armv7 !armv6
|
||||
arm/arm/pmap-v6.c optional armv7 | armv6
|
||||
arm/arm/pmap-v6.c standard
|
||||
arm/arm/pmu.c optional pmu | fdt hwpmc
|
||||
arm/arm/ptrace_machdep.c standard
|
||||
arm/arm/sc_machdep.c optional sc
|
||||
@ -73,12 +70,10 @@ arm/arm/stdatomic.c standard \
|
||||
compile-with "${NORMAL_C:N-Wmissing-prototypes}"
|
||||
arm/arm/support.S standard
|
||||
arm/arm/swtch.S standard
|
||||
arm/arm/swtch-v4.S optional !armv7 !armv6
|
||||
arm/arm/swtch-v6.S optional armv7 | armv6
|
||||
arm/arm/swtch-v6.S standard
|
||||
arm/arm/sys_machdep.c standard
|
||||
arm/arm/syscall.c standard
|
||||
arm/arm/trap-v4.c optional !armv7 !armv6
|
||||
arm/arm/trap-v6.c optional armv7 | armv6
|
||||
arm/arm/trap-v6.c standard
|
||||
arm/arm/uio_machdep.c standard
|
||||
arm/arm/undefined.c standard
|
||||
arm/arm/unwind.c optional ddb | kdtrace_hooks | stack
|
||||
|
Loading…
Reference in New Issue
Block a user