summaryrefslogtreecommitdiff
path: root/usr/src/uts/sun4/io/trapstat.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/sun4/io/trapstat.c')
-rw-r--r--usr/src/uts/sun4/io/trapstat.c45
1 files changed, 40 insertions, 5 deletions
diff --git a/usr/src/uts/sun4/io/trapstat.c b/usr/src/uts/sun4/io/trapstat.c
index 65a97fbb91..bdaac735fe 100644
--- a/usr/src/uts/sun4/io/trapstat.c
+++ b/usr/src/uts/sun4/io/trapstat.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -46,6 +45,9 @@
#ifdef sun4v
#include <sys/hypervisor_api.h>
#endif
+#ifndef sun4v
+#include <sys/chip.h>
+#endif
/* BEGIN CSTYLED */
/*
@@ -1399,6 +1401,14 @@ trapstat_make_traptab(tstat_percpu_t *tcpu)
#undef TSTAT_ENABLED_BA
#undef TSTAT_DISABLED_BA
+#ifndef sun4v
+/*
+ * See Section A.6 in SPARC v9 Manual.
+ * max branch = 4*((2^21)-1) = 8388604
+ */
+#define MAX_BICC_BRANCH_DISPLACEMENT (4 * ((1 << 21) - 1))
+#endif
+
static void
trapstat_setup(processorid_t cpu)
{
@@ -1407,6 +1417,9 @@ trapstat_setup(processorid_t cpu)
int i;
caddr_t va;
pfn_t *pfn;
+ cpu_t *cp;
+ uint_t strand_idx;
+ size_t tstat_offset;
#endif
ASSERT(tcpu->tcpu_pfn == NULL);
@@ -1422,7 +1435,29 @@ trapstat_setup(processorid_t cpu)
* align our instruction base address appropriately.
*/
#ifndef sun4v
- tcpu->tcpu_ibase = (caddr_t)((KERNELBASE - tstat_total_size)
+ tstat_offset = tstat_total_size;
+
+ cp = cpu_get(cpu);
+ ASSERT(cp != NULL);
+ if ((strand_idx = cpu ^ chip_plat_get_coreid(cp)) != 0) {
+ /*
+ * On sun4u platforms with multiple CPUs sharing the MMU
+ * (Olympus-C has 2 strands per core), each CPU uses a
+ * disjoint trap table. The indexing is based on the
+ * strand id, which is obtained by XOR'ing the cpuid with
+ * the coreid.
+ */
+ tstat_offset += tstat_total_size * strand_idx;
+
+ /*
+ * Offset must be less than the maximum PC-relative branch
+ * displacement for Bicc variants. See the Implementation
+ * Details comment.
+ */
+ ASSERT(tstat_offset <= MAX_BICC_BRANCH_DISPLACEMENT);
+ }
+
+ tcpu->tcpu_ibase = (caddr_t)((KERNELBASE - tstat_offset)
& TSTAT_TBA_MASK);
tcpu->tcpu_dbase = tcpu->tcpu_ibase + TSTAT_INSTR_SIZE;
tcpu->tcpu_vabase = tcpu->tcpu_ibase;