summaryrefslogtreecommitdiff
path: root/sys/arch/hppa
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2003-11-24 19:27:04 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2003-11-24 19:27:04 +0000
commit23f6b300e126827f7fc68c370d8e4c304b002edc (patch)
treeaa367a26536af76cfec4e979d896afd0e5fc698c /sys/arch/hppa
parent4171f47595321ea0aedd6616b0189c33d0b875bb (diff)
experimental support for HVT as a 2nd level tlb
Diffstat (limited to 'sys/arch/hppa')
-rw-r--r--sys/arch/hppa/hppa/locore.S59
-rw-r--r--sys/arch/hppa/hppa/machdep.c14
-rw-r--r--sys/arch/hppa/hppa/pmap.c95
3 files changed, 115 insertions, 53 deletions
diff --git a/sys/arch/hppa/hppa/locore.S b/sys/arch/hppa/hppa/locore.S
index 82f46aeb661..721c0c31f45 100644
--- a/sys/arch/hppa/hppa/locore.S
+++ b/sys/arch/hppa/hppa/locore.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.S,v 1.119 2003/11/07 18:43:25 mickey Exp $ */
+/* $OpenBSD: locore.S,v 1.120 2003/11/24 19:27:03 mickey Exp $ */
/*
* Copyright (c) 1998-2003 Michael Shalayeff
@@ -1363,6 +1363,14 @@ $tlbd_l
TLB_PULL_L(1)
IDTLBAF(17)
IDTLBPF(25)
+#ifdef USE_HPT
+ /* invalidate instead of update */
+ mfctl cr28, r17
+ ldw 0(r17), r24
+ VTAG
+ sub,<> r16, r24, r0
+ stw r25, 4(r17)
+#endif
TLB_STATS_AFT(tlbd)
rfir
nop
@@ -1384,11 +1392,60 @@ $itlbna_l
rfir
nop
$dtlbna_l
+ TLB_STATS_PRE(dtlb)
+ TLB_PULL_L(0)
+ IDTLBAF(17)
+ IDTLBPF(25)
+ /* figure out later if it's worth caching mappings here as well */
+ TLB_STATS_AFT(dtlb)
+ rfir
+ nop
$dtlb_l
TLB_STATS_PRE(dtlb)
TLB_PULL_L(0)
IDTLBAF(17)
IDTLBPF(25)
+#ifdef USE_HPT
+ /*
+ * cache the next page mapping in the hpt.
+ *
+ * mapping for a page at the end of each 128k is uncachable
+ * in the hvt since it'd be in the tlb itself and thus there
+ * is no reason to cache it!
+ * as a side effect this avoids recomputing hpt entry and
+ * retraversing the whole page table each time.
+ */
+
+ ldo PAGE_SIZE(r9), r9
+ extru,<> r9, 20, 5, r0
+ b,n $dtlb_done_l /* skip if no simple advance */
+ /* do not check the PT overlap since the above
+ * check already guaranties that */
+
+ /* ripped from TLB_PULL_L(0) */
+ extru r9, 19, 10, r16 /* r24 was loaded in the TLB_PULL_L */
+ ldwx,s r16(r24), r17 /* va -> pa:prot */
+ sh2addl r16, r24, r25
+ combt,=,n r0, r17, $dtlb_done_l
+ copy r17, r16
+ depi 0, 21, 1, r17
+ sub,= r16, r17, r0 /* do not store if unchanged */
+ stws r17, 0(r25) /* store back w/ the bits */
+ shd r17, r0, 13, r25
+ dep r8, 30, 15, r25 /* mix0r the pid from the sid */
+ dep r0, 31, 12, r17 /* needed ? */
+ addi 2, r25, r25
+ extru r17, 24, 25, r17
+ sync
+
+ mfctl cr28, r24
+ VTAG
+ ldo 16(r24), r24
+ stw r16, 0(r24)
+ stw r25, 4(r24)
+ stw r17, 8(r24)
+$dtlb_done_l
+#endif
TLB_STATS_AFT(dtlb)
rfir
nop
diff --git a/sys/arch/hppa/hppa/machdep.c b/sys/arch/hppa/hppa/machdep.c
index b182b6399b8..1f97c718a39 100644
--- a/sys/arch/hppa/hppa/machdep.c
+++ b/sys/arch/hppa/hppa/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.116 2003/10/15 18:54:55 mickey Exp $ */
+/* $OpenBSD: machdep.c,v 1.117 2003/11/24 19:27:03 mickey Exp $ */
/*
* Copyright (c) 1999-2002 Michael Shalayeff
@@ -250,12 +250,12 @@ const struct hppa_cpu_typed {
#ifdef HP7100LC_CPU
{ "PCXL", hpcxl, HPPA_CPU_PCXL, HPPA_FTRS_BTLBU|HPPA_FTRS_HVT,
desidhash_l, itlb_l, itlbna_l, dtlb_l, dtlbna_l, tlbd_l,
- ibtlb_g, NULL, pbtlb_g, hpti_l},
+ ibtlb_g, NULL, pbtlb_g, hpti_g},
#endif
#ifdef HP7300LC_CPU
{ "PCXL2", hpcxl2,HPPA_CPU_PCXL2, HPPA_FTRS_BTLBU|HPPA_FTRS_HVT,
desidhash_l, itlb_l, itlbna_l, dtlb_l, dtlbna_l, tlbd_l,
- ibtlb_g, NULL, pbtlb_g, hpti_l},
+ ibtlb_g, NULL, pbtlb_g, hpti_g},
#endif
#ifdef HP8000_CPU
{ "PCXU", hpcxu, HPPA_CPU_PCXU, HPPA_FTRS_W32B|HPPA_FTRS_BTLBU|HPPA_FTRS_HVT,
@@ -511,9 +511,13 @@ cpuid()
}
if (!pdc_call((iodcio_t)pdc, 0, PDC_TLB, PDC_TLB_INFO, &pdc_hwtlb) &&
- pdc_hwtlb.min_size && pdc_hwtlb.max_size)
+ pdc_hwtlb.min_size && pdc_hwtlb.max_size) {
cpu_features |= HPPA_FTRS_HVT;
- else {
+ if (pmap_hptsize > pdc_hwtlb.max_size)
+ pmap_hptsize = pdc_hwtlb.max_size;
+ else if (pmap_hptsize && pmap_hptsize < pdc_hwtlb.min_size)
+ pmap_hptsize = pdc_hwtlb.min_size;
+ } else {
printf("WARNING: no HPT support, fine!\n");
pmap_hptsize = 0;
}
diff --git a/sys/arch/hppa/hppa/pmap.c b/sys/arch/hppa/hppa/pmap.c
index e406f0632d4..14a27cc5308 100644
--- a/sys/arch/hppa/hppa/pmap.c
+++ b/sys/arch/hppa/hppa/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.103 2003/10/31 21:24:19 mickey Exp $ */
+/* $OpenBSD: pmap.c,v 1.104 2003/11/24 19:27:03 mickey Exp $ */
/*
* Copyright (c) 1998-2003 Michael Shalayeff
@@ -91,9 +91,8 @@ int pmapdebug = 0
paddr_t physical_steal, physical_end;
-#if defined(HP7100LC_CPU) || defined(HP7300LC_CPU)
-int pmap_hptsize = 256; /* patchable */
-#endif
+int pmap_hptsize = 16 * PAGE_SIZE; /* patchable */
+vaddr_t pmap_hpt;
struct pmap kernel_pmap_store;
int hppa_sid_max = HPPA_SID_MAX;
@@ -122,24 +121,22 @@ pmap_pagealloc(struct uvm_object *obj, voff_t off)
return (pg);
}
-#if defined(HP7100LC_CPU) || defined(HP7300LC_CPU)
+#ifdef USE_HPT
/*
* This hash function is the one used by the hardware TLB walker on the 7100LC.
*/
-static inline struct hpt_entry *
-pmap_hash(pa_space_t sp, vaddr_t va)
+static __inline struct vp_entry *
+pmap_hash(struct pmap *pmap, vaddr_t va)
+{
+ return (struct vp_entry *)(pmap_hpt +
+ (((va >> 8) ^ (pmap->pm_space << 9)) & (pmap_hptsize - 1)));
+}
+
+static __inline u_int32_t
+pmap_vtag(struct pmap *pmap, vaddr_t va)
{
- struct hpt_entry *hpt;
- __asm __volatile (
- "extru %2, 23, 20, %%r22\n\t" /* r22 = (va >> 8) */
- "zdep %1, 22, 16, %%r23\n\t" /* r23 = (sp << 9) */
- "xor %%r22,%%r23, %%r23\n\t" /* r23 ^= r22 */
- "mfctl %%cr24, %%r22\n\t" /* r22 = sizeof(HPT)-1 */
- "and %%r22,%%r23, %%r23\n\t" /* r23 &= r22 */
- "mfctl %%cr25, %%r22\n\t" /* r22 = addr of HPT table */
- "or %%r23, %%r22, %0" /* %0 = HPT entry */
- : "=r" (hpt) : "r" (sp), "r" (va) : "r22", "r23");
- return hpt;
+ return (0x80000000 | (pmap->pm_space & 0xffff) |
+ ((va >> 1) & 0x7fff0000));
}
#endif
@@ -275,6 +272,14 @@ pmap_pte_flush(struct pmap *pmap, vaddr_t va, pt_entry_t pte)
}
fdcache(pmap->pm_space, va, PAGE_SIZE);
pdtlb(pmap->pm_space, va);
+#ifdef USE_HPT
+ if (pmap_hpt) {
+ struct vp_entry *hpt;
+ hpt = pmap_hash(pmap, va);
+ if (hpt->vp_tag == pmap_vtag(pmap, va))
+ hpt->vp_tag = 0xffff;
+ }
+#endif
}
static __inline pt_entry_t
@@ -434,9 +439,6 @@ pmap_bootstrap(vstart)
extern paddr_t hppa_vtop;
vaddr_t va, addr = hppa_round_page(vstart), t;
vsize_t size;
-#if 0 && (defined(HP7100LC_CPU) || defined(HP7300LC_CPU))
- struct vp_entry *hptp;
-#endif
struct pmap *kpm;
int npdes, nkpdes;
@@ -487,36 +489,35 @@ pmap_bootstrap(vstart)
ie_mem = (u_int *)addr;
addr += 0x8000;
-#if 0 && (defined(HP7100LC_CPU) || defined(HP7300LC_CPU))
- if (pmap_hptsize && (cpu_type == hpcxl || cpu_type == hpcxl2)) {
- int error;
+#ifdef USE_HPT
+ if (pmap_hptsize) {
+ struct vp_entry *hptp;
+ int i, error;
- if (pmap_hptsize > pdc_hwtlb.max_size)
- pmap_hptsize = pdc_hwtlb.max_size;
- else if (pmap_hptsize < pdc_hwtlb.min_size)
- pmap_hptsize = pdc_hwtlb.min_size;
+ /* must be aligned to the size XXX */
+ if (addr & (pmap_hptsize - 1))
+ addr += pmap_hptsize;
+ addr &= ~(pmap_hptsize - 1);
- size = pmap_hptsize * sizeof(*hptp);
- bzero((void *)addr, size);
- /* Allocate the HPT */
- for (hptp = (struct vp_entry *)addr, i = pmap_hptsize; i--;)
+ bzero((void *)addr, pmap_hptsize);
+ for (hptp = (struct vp_entry *)addr, i = pmap_hptsize / 16; i--;)
hptp[i].vp_tag = 0xffff;
-
- DPRINTF(PDB_INIT, ("hpt_table: 0x%x @ %p\n", size, addr));
-
- if ((error = (cpu_hpt_init)(addr, size)) < 0) {
- printf("WARNING: HPT init error %d\n", error);
- } else {
- printf("HPT: %d entries @ 0x%x\n",
- pmap_hptsize / sizeof(struct vp_entry), addr);
- }
-
- /* TODO find a way to avoid using cr*, use cpu regs instead */
- mtctl(addr, CR_VTOP);
- mtctl(size - 1, CR_HPTMASK);
- addr += size; /* should keep the alignment right */
+ pmap_hpt = addr;
+ addr += pmap_hptsize;
+
+ DPRINTF(PDB_INIT, ("hpt_table: 0x%x @ %p\n",
+ pmap_hptsize, addr));
+
+ if ((error = (cpu_hpt_init)(pmap_hpt, pmap_hptsize)) < 0) {
+ printf("WARNING: HPT init error %d -- DISABLED\n",
+ error);
+ pmap_hpt = 0;
+ } else
+ DPRINTF(PDB_INIT,
+ ("HPT: installed for %d entries @ 0x%x\n",
+ pmap_hptsize / sizeof(struct vp_entry), addr));
}
-#endif /* HP7100LC_CPU | HP7300LC_CPU */
+#endif
/* XXX PCXS needs this inserted into an IBTLB */
/* and can block-map the whole phys w/ another */