summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/hppa/hppa/machdep.c41
1 files changed, 37 insertions, 4 deletions
diff --git a/sys/arch/hppa/hppa/machdep.c b/sys/arch/hppa/hppa/machdep.c
index 2b0f98e6d54..51c1d3c09ac 100644
--- a/sys/arch/hppa/hppa/machdep.c
+++ b/sys/arch/hppa/hppa/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.169 2009/02/04 17:19:17 miod Exp $ */
+/* $OpenBSD: machdep.c,v 1.170 2009/02/04 17:22:23 miod Exp $ */
/*
* Copyright (c) 1999-2003 Michael Shalayeff
@@ -845,16 +845,48 @@ btlb_insert(space, va, pa, lenp, prot)
{
static u_int32_t mask;
register vsize_t len;
- register int error, i;
+ register int error, i, btlb_max;
if (!pdc_btlb.min_size && !pdc_btlb.max_size)
return -(ENXIO);
+ /*
+ * On PCXS processors with split BTLB, we should theoretically
+ * insert in the IBTLB (if executable mapping requested), and
+ * into the DBTLB. The PDC documentation is very clear that
+ * slot numbers are, in order, IBTLB, then DBTLB, then combined
+ * BTLB.
+ *
+ * However it also states that ``successful completion may not mean
+ * that the entire address range specified in the call has been
+ * mapped in the block TLB. For both fixed range slots and variable
+ * range slots, complete coverage of the address range specified
+ * is not guaranteed. Only a portion of the address range specified
+ * may get mapped as a result''.
+ *
+ * On an HP 9000/720 with PDC ROM v1.2, it turns out that IBTLB
+ * entries are inserted as expected, but no DBTLB gets inserted
+ * at all, despite PDC returning success.
+ *
+ * So play it dumb, and do not attempt to insert DBTLB entries at
+ * all on split BTLB systems. Callers are supposed to be able to
+ * cope with this.
+ */
+
+ if (pdc_btlb.finfo.num_c == 0) {
+ if ((prot & TLB_EXECUTE) == 0)
+ return -(EINVAL);
+
+ btlb_max = pdc_btlb.finfo.num_i;
+ } else {
+ btlb_max = pdc_btlb.finfo.num_c;
+ }
+
/* align size */
for (len = pdc_btlb.min_size << PGSHIFT; len < *lenp; len <<= 1);
len >>= PGSHIFT;
i = ffs(~mask) - 1;
- if (len > pdc_btlb.max_size || i < 0) {
+ if (len > pdc_btlb.max_size || i < 0 || i >= btlb_max) {
#ifdef BTLBDEBUG
printf("btln_insert: too big (%u < %u < %u)\n",
pdc_btlb.min_size, len, pdc_btlb.max_size);
@@ -879,7 +911,8 @@ btlb_insert(space, va, pa, lenp, prot)
prot |= TLB_UNCACHABLE;
#ifdef BTLBDEBUG
- printf("btlb_insert(%d): %x:%x=%x[%x,%x]\n", i, space, va, pa, len, prot);
+ printf("btlb_insert(%d): %x:%x=%x[%x,%x]\n",
+ i, space, va, pa, len, prot);
#endif
if ((error = (*cpu_dbtlb_ins)(i, space, va, pa, len, prot)) < 0)
return -(EINVAL);