summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/hppa/conf/ld.script3
-rw-r--r--sys/arch/hppa/dev/mem.c5
-rw-r--r--sys/arch/hppa/gsc/if_ie_gsc.c10
-rw-r--r--sys/arch/hppa/hppa/genassym.cf21
-rw-r--r--sys/arch/hppa/hppa/locore.S293
-rw-r--r--sys/arch/hppa/hppa/machdep.c117
-rw-r--r--sys/arch/hppa/hppa/pmap.c1855
-rw-r--r--sys/arch/hppa/hppa/trap.c10
-rw-r--r--sys/arch/hppa/hppa/vm_machdep.c7
-rw-r--r--sys/arch/hppa/include/cpu.h4
-rw-r--r--sys/arch/hppa/include/cpufunc.h7
-rw-r--r--sys/arch/hppa/include/db_machdep.h30
-rw-r--r--sys/arch/hppa/include/pmap.h240
-rw-r--r--sys/arch/hppa/include/pte.h50
-rw-r--r--sys/arch/hppa/include/vmparam.h4
15 files changed, 1075 insertions, 1581 deletions
diff --git a/sys/arch/hppa/conf/ld.script b/sys/arch/hppa/conf/ld.script
index a05233c4c5a..7134843aae7 100644
--- a/sys/arch/hppa/conf/ld.script
+++ b/sys/arch/hppa/conf/ld.script
@@ -1,4 +1,4 @@
-/* $OpenBSD: ld.script,v 1.8 2001/11/29 17:28:09 mickey Exp $ */
+/* $OpenBSD: ld.script,v 1.9 2002/03/15 21:44:14 mickey Exp $ */
OUTPUT_FORMAT("elf32-hppa")
OUTPUT_ARCH(hppa)
@@ -22,6 +22,7 @@ SECTIONS
__unwind_end = .;
. = ALIGN(4096);
} = 0 /* 0x08000240 nop filled, does not work */
+ . = 0x400000;
etext = ABSOLUTE(.);
.data :
diff --git a/sys/arch/hppa/dev/mem.c b/sys/arch/hppa/dev/mem.c
index 2032abbb72c..008b4fcc63d 100644
--- a/sys/arch/hppa/dev/mem.c
+++ b/sys/arch/hppa/dev/mem.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mem.c,v 1.9 2002/03/14 01:26:31 millert Exp $ */
+/* $OpenBSD: mem.c,v 1.10 2002/03/15 21:44:18 mickey Exp $ */
/*
* Copyright (c) 1998,1999 Michael Shalayeff
@@ -164,14 +164,15 @@ memattach(parent, self, aux)
printf (" viper rev %x, ctrl %b",
sc->sc_vp->vi_status.hw_rev,
VI_CTRL, VIPER_BITS);
-
s = splhigh();
+#if 0
VI_CTRL |= VI_CTRL_ANYDEN;
((struct vi_ctrl *)&VI_CTRL)->core_den = 0;
((struct vi_ctrl *)&VI_CTRL)->sgc0_den = 0;
((struct vi_ctrl *)&VI_CTRL)->sgc1_den = 0;
((struct vi_ctrl *)&VI_CTRL)->core_prf = 1;
sc->sc_vp->vi_control = VI_CTRL;
+#endif
splx(s);
#ifdef DEBUG
printf (" >> %b", VI_CTRL, VIPER_BITS);
diff --git a/sys/arch/hppa/gsc/if_ie_gsc.c b/sys/arch/hppa/gsc/if_ie_gsc.c
index c37b285d2d7..a630796325f 100644
--- a/sys/arch/hppa/gsc/if_ie_gsc.c
+++ b/sys/arch/hppa/gsc/if_ie_gsc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ie_gsc.c,v 1.10 2002/03/14 01:26:31 millert Exp $ */
+/* $OpenBSD: if_ie_gsc.c,v 1.11 2002/03/15 21:44:18 mickey Exp $ */
/*
* Copyright (c) 1998,1999 Michael Shalayeff
@@ -85,7 +85,7 @@ static int ie_gsc_media[] = {
};
#define IE_NMEDIA (sizeof(ie_gsc_media) / sizeof(ie_gsc_media[0]))
-static char mem[IE_SIZE+16];
+char *ie_mem;
void ie_gsc_reset(struct ie_softc *sc, int what);
void ie_gsc_attend(struct ie_softc *sc);
@@ -154,7 +154,7 @@ ie_gsc_attend(sc)
{
register volatile struct ie_gsc_regs *r = (struct ie_gsc_regs *)sc->ioh;
- fdcache(0, (vaddr_t)&mem, sizeof(mem));
+ fdcache(0, (vaddr_t)ie_mem, IE_SIZE);
r->ie_attn = 0;
}
@@ -328,8 +328,8 @@ ie_gsc_attach(parent, self, aux)
sc->sc_maddr = kvtop((caddr_t)sc->bh);
#else
- bzero(mem, sizeof(mem));
- sc->bh = ((u_int)&mem + 15) & ~0xf;
+ printf("%x ", ie_mem);
+ sc->bh = (u_int)ie_mem;
sc->sc_maddr = sc->bh;
#endif
sc->sysbus = 0x40 | IE_SYSBUS_82586 | IE_SYSBUS_INTLOW | IE_SYSBUS_TRG | IE_SYSBUS_BE;
diff --git a/sys/arch/hppa/hppa/genassym.cf b/sys/arch/hppa/hppa/genassym.cf
index 53f2b449a17..6d3f4cb87e3 100644
--- a/sys/arch/hppa/hppa/genassym.cf
+++ b/sys/arch/hppa/hppa/genassym.cf
@@ -1,4 +1,4 @@
-# $OpenBSD: genassym.cf,v 1.19 2002/01/16 20:50:16 miod Exp $
+# $OpenBSD: genassym.cf,v 1.20 2002/03/15 21:44:18 mickey Exp $
#
# Copyright (c) 1982, 1990, 1993
@@ -69,24 +69,9 @@ export HPPA_BREAK_GET_PSW
export HPPA_BREAK_SET_PSW
# pte things
-export TLB_REF_POS
+#export TLB_REF_POS
export TLB_GATE_PROT
-export TLB_DIRTY_POS
-
-# hpt_table fields
-struct hpt_entry
-member hpt_tlbprot
-member hpt_tlbpage
-member hpt_entry
-define HPT_TAG 0
-
-# pv_entry fields
-struct pv_entry
-member pv_hash
-member pv_space
-member pv_va
-member pv_tlbpage
-member pv_tlbprot
+#export TLB_DIRTY_POS
# saved state fields
struct trapframe
diff --git a/sys/arch/hppa/hppa/locore.S b/sys/arch/hppa/hppa/locore.S
index a6dbee2a517..e4108956232 100644
--- a/sys/arch/hppa/hppa/locore.S
+++ b/sys/arch/hppa/hppa/locore.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.S,v 1.59 2002/03/15 19:53:49 mickey Exp $ */
+/* $OpenBSD: locore.S,v 1.60 2002/03/15 21:44:18 mickey Exp $ */
/*
* Copyright (c) 1998-2002 Michael Shalayeff
@@ -117,6 +117,11 @@ fpu_curpcb
.comm 4
fpu_enable
.comm 4
+$trap_tmp_save /* XXX assumed to be aligned on 2048 */
+ .align 2048
+ .block TF_PHYS /* XXX must be aligned to 64 */
+ .align 64
+
.text
/*
@@ -517,10 +522,6 @@ $bsd_syscall
.export gateway_page_end, entry
gateway_page_end
-$trap_tmp_save /* XXX assumed to be aligned on 2048 */
- .block TF_PHYS /* XXX must be aligned to 64 */
- .align 64
-
.export $syscall,entry
.proc
.callinfo calls
@@ -898,6 +899,7 @@ $syscall_end
#ifdef HP7000_CPU
LDILDO(itlb_x)
+LDILDO(itlbna_x)
LDILDO(dtlb_x)
LDILDO(dtlbna_x)
LDILDO(tlbd_x)
@@ -905,6 +907,7 @@ LDILDO(tlbd_x)
#ifdef HP7100_CPU
LDILDO(itlb_s)
+LDILDO(itlbna_s)
LDILDO(dtlb_s)
LDILDO(dtlbna_s)
LDILDO(tlbd_s)
@@ -912,6 +915,7 @@ LDILDO(tlbd_s)
#ifdef HP7200_CPU
LDILDO(itlb_t)
+LDILDO(itlbna_t)
LDILDO(dtlb_t)
LDILDO(dtlbna_t)
LDILDO(tlbd_t)
@@ -919,6 +923,7 @@ LDILDO(tlbd_t)
#ifdef HP7100LC_CPU
LDILDO(itlb_l)
+LDILDO(itlbna_l)
LDILDO(dtlb_l)
LDILDO(dtlbna_l)
LDILDO(tlbd_l)
@@ -960,8 +965,8 @@ hpmc_v
ATRAP(excpt,T_EXCEPTION)
#endif
STRAP(dtlb,T_DTLBMISS,DTLBPRE) /* 15. data TLB miss fault */
- STRAP(itlb,T_ITLBMISSNA,ITLBPRE)/* 16. ITLB non-access miss fault */
- STRAP(dtlb,T_DTLBMISSNA,DTLBPRE)/* 17. DTLB non-access miss fault */
+ STRAP(itlbna,T_ITLBMISSNA,ITLBPRE)/* 16. ITLB non-access miss fault */
+ STRAP(dtlbna,T_DTLBMISSNA,DTLBPRE)/* 17. DTLB non-access miss fault */
ATRAP(dprot,T_DPROT) /* 18. data protection trap
unalligned data reference trap */
ATRAP(dbrk,T_DBREAK) /* 19. data break trap */
@@ -1303,48 +1308,54 @@ LEAF_ENTRY(desidhash_t)
EXIT(desidhash_t)
#endif
+#if defined(HP7000_CPU) || defined(HP7100_CPU) || defined(HP7200_CPU)
+#define TLB_PULL(bits) ! \
+ /* space:pgaddr -- r8:r9 */ ! \
+ mfctl vtop, r16 ! \
+ ldwax,s r8(r16), r17 /* space -> page directory */ ! \
+ extru r9, 9, 10, r25 ! \
+ combt,=,n r0, r17, TLABEL(all) ! \
+ ldwax,s r25(r17), r24 /* page -> page table */ ! \
+ extru r9, 19, 10, r16 ! \
+ combt,=,n r0, r24, TLABEL(all) ! \
+ ldwax,s r16(r24), r17 /* va -> pa:prot */ ! \
+ sh2addl r16, r24, r25 ! \
+ combt,=,n r0, r17, TLABEL(all) ! \
+ depi (bits), 21+bits, 1+bits, r17 ! \
+ mfctl tr7, r1 ! \
+ stwas 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
+
$tlbd_x
$tlbd_s
$tlbd_t
-#if 1
- HPTENT
- mtctl r24, cr28
-
- /*
- * Chase the list of entries for this hash bucket until we find
- * the correct mapping or NULL.
- */
- ldw HPT_ENTRY(r24), r24
-$hash_loop_tlbd_t
- comb,=,n r0, r24, TLABEL(all)
- ldw PV_VA(r24), r25
- ldw PV_SPACE(r24), r17
- comb,<>,n r9, r25, $hash_loop_tlbd_t
- ldw PV_HASH(r24), r24
- comb,<>,n r8, r17, $hash_loop_tlbd_t
- ldw PV_HASH(r24), r24
-
- VTAG /* (r8,r9) -> r16 */
- /* Set the dirty bit for this physical page. */
- ldw PV_TLBPROT(r24), r25
- b $tlb_inshpt_t
- depi 1, TLB_DIRTY_POS, 1, r25
-#else
-
- mfsp %sr1, %r25
- mtsp %r8, %sr1
- lpa %r0(%sr1, %r9), %r17
- mfctl %cr29, %r16
- mtsp %r25, %sr1
- extru %r17, 20, 21, %r24
- sh3add %r24, %r16, %r16
-
-#endif
+ TLB_PULL(1)
+ mfsp sr1, r16
+ mtsp r8, sr1
+ idtlba r17,(sr1, r9)
+ idtlbp r25,(sr1, r9)
+ mtsp r16, sr1
+ rfir
+ nop
$itlb_x
+$itlbna_x
$itlb_s
+$itlbna_s
$itlb_t
- depi 1, TFF_ITLB_POS, 1, r1 /* mark for ITLB insert */
+$itlbna_t
+ TLB_PULL(0)
+ mfsp sr1, r16
+ mtsp r8, sr1
+ iitlba r17,(sr1, r9)
+ iitlbp r25,(sr1, r9)
+ mtsp r16, sr1
+ rfir
+ nop
$dtlb_x
$dtlbna_x
@@ -1352,77 +1363,15 @@ $dtlb_s
$dtlbna_s
$dtlb_t
$dtlbna_t
- /*
- * r1 is the trap type
- * r8 is the space of the address that had the TLB miss
- * r9 is the offset of the address that had the TLB miss
- * r24 is the correspondent HPT entry pointer
- */
-
- HPTENT
- mtctl r24, cr28
-
- ldw HPT_TAG(r24),r17
- VTAG /* (r8,r9) -> r16 */
-
- /* Compare the tag against the HPT entry.
- If it matches, then do the TLB insertion. */
- comb,<>,n r16, r17, $tlb_gottalook_t
-
- ldw HPT_TLBPAGE(r24), r17
- b $tlb_gothpt_t
- ldw HPT_TLBPROT(r24), r25
-
-$tlb_gottalook_t
- /*
- * Chase the list of entries for this hash bucket until we find
- * the correct mapping or NULL.
- */
- ldw HPT_ENTRY(r24),r24
-$hash_loop_t
- comb,=,n r0, r24, TLABEL(all)
- ldw PV_VA(r24),r25
- ldw PV_SPACE(r24),r17
- comb,<>,n r9,r25,$hash_loop_t
- ldw PV_HASH(r24),r24
- comb,<>,n r8,r17,$hash_loop_t
- ldw PV_HASH(r24),r24
-
- /* Now set things up to enter the real mapping that we want */
- ldw PV_TLBPROT(r24),r25
- depi 1, TLB_REF_POS, 1, r25
-
- /*
- * Load the HPT cache with the miss information for the next time.
- */
-$tlb_inshpt_t
- stw r25, PV_TLBPROT(r24)
- ldw PV_TLBPAGE(r24),r17
- mfctl cr28, r24
-
- stw r16, HPT_TAG(r24)
- stw r25, HPT_TLBPROT(r24)
- stw r17, HPT_TLBPAGE(r24)
-
-$tlb_gothpt_t
+ TLB_PULL(0)
mfsp sr1, r16
- bb,< r1, TFF_ITLB_POS, $tlb_itlb_t
mtsp r8, sr1
-
idtlba r17,(sr1, r9)
idtlbp r25,(sr1, r9)
- nop ! nop
- mtsp r16, sr1
- rfir
- nop
-
-$tlb_itlb_t
- iitlba r17,(sr1, r9)
- iitlbp r25,(sr1, r9)
- nop ! nop
mtsp r16, sr1
rfir
nop
+#endif /* defined(HP7000_CPU) || defined(HP7100_CPU) || defined(HP7200_CPU) */
#ifdef HP7100LC_CPU
/*
@@ -1481,98 +1430,58 @@ EXIT(desidhash_l)
.align 32
-$tlbd_l
- mfctl cr28, r24
+#define IITLBAF(r) .word 0x04000440 | ((r) << 16)
+#define IITLBPF(r) .word 0x04000400 | ((r) << 16)
+#define IDTLBAF(r) .word 0x04001440 | ((r) << 16)
+#define IDTLBPF(r) .word 0x04001400 | ((r) << 16)
- /*
- * Chase the list of entries for this hash bucket until we find
- * the correct mapping or NULL.
- */
- ldw HPT_ENTRY(r24), r16
-$hash_loop_tlbd_l
- comb,=,n r0, r16, TLABEL(all)
- ldw PV_VA(r16), r25
- ldw PV_SPACE(r16), r17
- comb,<>,n r9, r25, $hash_loop_tlbd_l
- ldw PV_HASH(r16), r16
- comb,<>,n r8, r17, $hash_loop_tlbd_l
- ldw PV_HASH(r16), r16
-
- /* Set the dirty bit for this physical page. */
- ldw PV_TLBPAGE(r16), r17
- ldw PV_TLBPROT(r16), r25
- depi 1, TLB_DIRTY_POS, 1, r25
- depi 1, TLB_REF_POS, 1, r25
- stw r25, PV_TLBPROT(r16)
- VTAG /* (r8,r9) -> r16 */
-
- stw r16, HPT_TAG(r24)
- stw r25, HPT_TLBPROT(r24)
- stw r17, HPT_TLBPAGE(r24)
-
- .word 0x04111440 ; idtlbaf r17
- .word 0x04191400 ; idtlbpf r25
- nop ! nop
+/*
+ * possible optimizations:
+ * change pte to reduce number of shifts
+ * reorder to reduce stalls
+ * check if stwas is needed (if we changed the bits)
+ */
+#define TLB_PULL_L(bits) ! \
+ /* space:pgaddr -- r8:r9 */ ! \
+ mfctl vtop, r16 ! \
+ ldwax,s r8(r16), r17 /* space -> page directory */ ! \
+ extru r9, 9, 10, r25 ! \
+ combt,=,n r0, r17, TLABEL(all) ! \
+ ldwax,s r25(r17), r24 /* page -> page table */ ! \
+ extru r9, 19, 10, r16 ! \
+ combt,=,n r0, r24, TLABEL(all) ! \
+ ldwax,s r16(r24), r17 /* va -> pa:prot */ ! \
+ sh2addl r16, r24, r25 ! \
+ combt,=,n r0, r17, TLABEL(all) ! \
+ depi (bits), 21+bits, 1+bits, r17 ! \
+ mfctl tr7, r1 ! \
+ stwas 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
+
+$tlbd_l
+ TLB_PULL_L(1)
+ IDTLBAF(17)
+ IDTLBPF(25)
rfir
nop
-
- .align 8
+$itlbna_l
$itlb_l
- depi 1, TFF_ITLB_POS, 1, r1 /* mark for ITLB insert */
-$dtlbna_l
- HPTENT
- mtctl r24, cr28
-
-$dtlb_l
- mfctl cr28, r24
- /*
- * r1 is the trap type
- * r8 is the space of the address that had the TLB miss
- * r9 is the offset of the address that had the TLB miss
- * r24 is the correspondent HPT entry pointer
- */
-
- /*
- * Chase the list of entries for this hash bucket until we find
- * the correct mapping or NULL.
- */
- ldw HPT_ENTRY(r24), r16
-$hash_loop_l
- comb,=,n r0, r16, TLABEL(all)
- ldw PV_VA(r16), r25
- ldw PV_SPACE(r16), r17
- comb,<>,n r9, r25, $hash_loop_l
- ldw PV_HASH(r16), r16
- comb,<>,n r8, r17, $hash_loop_l
- ldw PV_HASH(r16), r16
-
- /* Now set things up to enter the real mapping that we want */
- ldw PV_TLBPAGE(r16), r17
- ldw PV_TLBPROT(r16), r25
-
- /*
- * Load the HPT cache with the miss information for the next time.
- * The HPT entry address was saved by the HPTENT
- */
- depi 1, TLB_REF_POS, 1, r25
- stw r25, PV_TLBPROT(r16)
- VTAG /* (r8,r9) -> r16 */
-
- stw r16, HPT_TAG(r24)
- stw r25, HPT_TLBPROT(r24)
- bb,< r1, TFF_ITLB_POS, $tlb_itlb_l
- stw r17, HPT_TLBPAGE(r24)
-
- .word 0x04111440 ; idtlbaf r17
- .word 0x04191400 ; idtlbpf r25
- nop ! nop
+#if 0 /* XXX assume combined TLB */
+ TLB_PULL_L(0)
+ IITLBAF(17)
+ IITLBPF(25)
rfir
nop
-
-$tlb_itlb_l
- .word 0x04110440 ; iitlbaf r17
- .word 0x04190400 ; iitlbpf r25
- nop ! nop
+#endif
+$dtlbna_l
+$dtlb_l
+ TLB_PULL_L(0)
+ IDTLBAF(17)
+ IDTLBPF(25)
rfir
nop
#endif /* HP7100LC_CPU */
diff --git a/sys/arch/hppa/hppa/machdep.c b/sys/arch/hppa/hppa/machdep.c
index ebacbf7c8ab..48ace22fc02 100644
--- a/sys/arch/hppa/hppa/machdep.c
+++ b/sys/arch/hppa/hppa/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.61 2002/03/14 01:26:31 millert Exp $ */
+/* $OpenBSD: machdep.c,v 1.62 2002/03/15 21:44:18 mickey Exp $ */
/*
* Copyright (c) 1999-2002 Michael Shalayeff
@@ -184,7 +184,9 @@ void hppa_user2frame(struct trapframe *sf, struct trapframe *tf);
/*
* wide used hardware params
*/
+#if defined(HP7100LC_CPU) || defined(HP7300LC_CPU)
struct pdc_hwtlb pdc_hwtlb PDC_ALIGNMENT;
+#endif
struct pdc_coproc pdc_coproc PDC_ALIGNMENT;
struct pdc_coherence pdc_coherence PDC_ALIGNMENT;
struct pdc_spidb pdc_spidbits PDC_ALIGNMENT;
@@ -198,10 +200,10 @@ pid_t sigpid = 0;
/*
* Whatever CPU types we support
*/
-extern const u_int itlb_x[], dtlb_x[], dtlbna_x[], tlbd_x[];
-extern const u_int itlb_s[], dtlb_s[], dtlbna_s[], tlbd_s[];
-extern const u_int itlb_t[], dtlb_t[], dtlbna_t[], tlbd_t[];
-extern const u_int itlb_l[], dtlb_l[], dtlbna_l[], tlbd_l[];
+extern const u_int itlb_x[], itlbna_x[], dtlb_x[], dtlbna_x[], tlbd_x[];
+extern const u_int itlb_s[], itlbna_s[], dtlb_s[], dtlbna_s[], tlbd_s[];
+extern const u_int itlb_t[], itlbna_t[], dtlb_t[], dtlbna_t[], tlbd_t[];
+extern const u_int itlb_l[], itlbna_l[], dtlb_l[], dtlbna_l[], tlbd_l[];
int iibtlb_s(int i, pa_space_t sp, vaddr_t va, paddr_t pa,
vsize_t sz, u_int prot);
int idbtlb_s(int i, pa_space_t sp, vaddr_t va, paddr_t pa,
@@ -226,7 +228,7 @@ const struct hppa_cpu_typed {
int arch;
int features;
int (*desidhash)(void);
- const u_int *itlbh, *dtlbh, *dtlbnah, *tlbdh;
+ const u_int *itlbh, *itlbnah, *dtlbh, *dtlbnah, *tlbdh;
int (*dbtlbins)(int i, pa_space_t sp, vaddr_t va, paddr_t pa,
vsize_t sz, u_int prot);
int (*ibtlbins)(int i, pa_space_t sp, vaddr_t va, paddr_t pa,
@@ -236,50 +238,50 @@ const struct hppa_cpu_typed {
} cpu_types[] = {
#ifdef HP7000_CPU
{ "PCX", hpcx, 0x10, 0,
- desidhash_x, itlb_x, dtlb_x, dtlbna_x, tlbd_x,
+ desidhash_x, itlb_x, itlbna_l, dtlb_x, dtlbna_x, tlbd_x,
ibtlb_g, NULL, pbtlb_g},
#endif
#ifdef HP7100_CPU
- { "PCXS", hpcxs, 0x11, HPPA_FTRS_BTLBS,
- desidhash_s, itlb_s, dtlb_s, dtlbna_s, tlbd_s,
+ { "PCXS", hpcxs, 0x11, 0,
+ desidhash_s, itlb_s, itlbna_l, dtlb_s, dtlbna_s, tlbd_s,
ibtlb_g, NULL, pbtlb_g},
#endif
#ifdef HP7200_CPU
{ "PCXT", hpcxt, 0x11, HPPA_FTRS_BTLBU,
- desidhash_t, itlb_t, dtlb_t, dtlbna_t, tlbd_t,
+ desidhash_t, itlb_t, itlbna_l, dtlb_t, dtlbna_t, tlbd_t,
ibtlb_g, NULL, pbtlb_g},
/* HOW? { "PCXT'", hpcxta,0x11, HPPA_FTRS_BTLBU,
- desidhash_t, itlb_t, dtlb_t, dtlbna_t, tlbd_t,
+ desidhash_t, itlb_t, itlbna_l, dtlb_t, dtlbna_t, tlbd_t,
ibtlb_g, NULL, pbtlb_g}, */
#endif
#ifdef HP7100LC_CPU
{ "PCXL", hpcxl, 0x11, HPPA_FTRS_BTLBU|HPPA_FTRS_HVT,
- desidhash_l, itlb_l, dtlb_l, dtlbna_l, tlbd_l,
+ desidhash_l, itlb_l, itlbna_l, dtlb_l, dtlbna_l, tlbd_l,
ibtlb_g, NULL, pbtlb_g, hpti_g},
#endif
#ifdef HP7300LC_CPU
/* HOW? { "PCXL2", hpcxl2,0x11, HPPA_FTRS_BTLBU|HPPA_FTRS_HVT,
- desidhash_l, itlb_l, dtlb_l, dtlbna_l, tlbd_l,
+ desidhash_l, itlb_l, itlbna_l, dtlb_l, dtlbna_l, tlbd_l,
ibtlb_g, NULL, pbtlb_g, hpti_g}, */
#endif
#ifdef HP8000_CPU
{ "PCXU", hpcxu, 0x20, HPPA_FTRS_W32B|HPPA_FTRS_BTLBU|HPPA_FTRS_HVT,
- desidhash_g, itlb_l, dtlb_l, dtlbna_l, tlbd_l,
+ desidhash_g, itlb_l, itlbna_l, dtlb_l, dtlbna_l, tlbd_l,
ibtlb_g, NULL, pbtlb_g, hpti_g},
#endif
#ifdef HP8200_CPU
/* HOW? { "PCXU2", hpcxu2,0x20, HPPA_FTRS_W32B|HPPA_FTRS_BTLBU|HPPA_FTRS_HVT,
- desidhash_g, itlb_l, dtlb_l, dtlbna_l, tlbd_l,
+ desidhash_g, itlb_l, itlbna_l, dtlb_l, dtlbna_l, tlbd_l,
ibtlb_g, NULL, pbtlb_g, hpti_g}, */
#endif
#ifdef HP8500_CPU
/* HOW? { "PCXW", hpcxw, 0x20, HPPA_FTRS_W32B|HPPA_FTRS_BTLBU|HPPA_FTRS_HVT,
- desidhash_g, itlb_l, dtlb_l, dtlbna_l, tlbd_l,
+ desidhash_g, itlb_l, itlbna_l, dtlb_l, dtlbna_l, tlbd_l,
ibtlb_g, NULL, pbtlb_g, hpti_g}, */
#endif
#ifdef HP8600_CPU
/* HOW? { "PCXW+", hpcxw, 0x20, HPPA_FTRS_W32B|HPPA_FTRS_BTLBU|HPPA_FTRS_HVT,
- desidhash_g, itlb_l, dtlb_l, dtlbna_l, tlbd_l,
+ desidhash_g, itlb_l, itlbna_l, dtlb_l, dtlbna_l, tlbd_l,
ibtlb_g, NULL, pbtlb_g, hpti_g}, */
#endif
{ "", 0 }
@@ -290,10 +292,8 @@ hppa_init(start)
paddr_t start;
{
extern int kernel_text;
- vaddr_t v, vstart, vend;
- register int error;
- int hptsize; /* size of HPT table if supported */
- int cpu_features = 0;
+ vaddr_t v, v1;
+ int error, cpu_features = 0;
boothowto |= RB_SINGLE; /* XXX always go into single-user while debug */
@@ -364,6 +364,9 @@ hppa_init(start)
PAGE0->ivec_mempflen = (hppa_pfr_end - hppa_pfr + 1) * 4;
}
+ /* may the scientific guessing begin */
+ cpu_features = 0;
+
/* BTLB params */
if ((error = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB,
PDC_BTLB_DEFAULT, &pdc_btlb)) < 0) {
@@ -388,8 +391,8 @@ hppa_init(start)
PDC_BTLB_PURGE_ALL) < 0)
printf("WARNING: BTLB purge failed\n");
- cpu_features = pdc_btlb.finfo.num_c?
- HPPA_FTRS_BTLBU : HPPA_FTRS_BTLBS;
+ if (pdc_btlb.finfo.num_c)
+ cpu_features |= HPPA_FTRS_BTLBU;
}
ptlball();
@@ -398,24 +401,14 @@ hppa_init(start)
totalphysmem = PAGE0->imm_max_mem / NBPG;
resvmem = ((vaddr_t)&kernel_text) / NBPG;
- /* calculate HPT size */
- for (hptsize = 256; hptsize < totalphysmem; hptsize *= 2);
- hptsize *= 16; /* sizeof(hpt_entry) */
-
+#if defined(HP7100LC_CPU) || defined(HP7300LC_CPU)
if (pdc_call((iodcio_t)pdc, 0, PDC_TLB, PDC_TLB_INFO, &pdc_hwtlb) &&
!pdc_hwtlb.min_size && !pdc_hwtlb.max_size) {
printf("WARNING: no HPT support, fine!\n");
- mtctl(hptsize - 1, CR_HPTMASK);
- hptsize = 0;
- } else {
+ pmap_hptsize = 0;
+ } else
cpu_features |= HPPA_FTRS_HVT;
-
- if (hptsize > pdc_hwtlb.max_size)
- hptsize = pdc_hwtlb.max_size;
- else if (hptsize < pdc_hwtlb.min_size)
- hptsize = pdc_hwtlb.min_size;
- mtctl(hptsize - 1, CR_HPTMASK);
- }
+#endif
/*
* Deal w/ CPU now
@@ -452,8 +445,13 @@ hppa_init(start)
LDILDO(trap_ep_T_TLB_DIRTY , p->tlbdh);
LDILDO(trap_ep_T_DTLBMISS , p->dtlbh);
LDILDO(trap_ep_T_DTLBMISSNA, p->dtlbnah);
- LDILDO(trap_ep_T_ITLBMISS , p->itlbh);
- LDILDO(trap_ep_T_ITLBMISSNA, p->itlbh);
+ if (pdc_cache.dt_conf.tc_sh) {
+ LDILDO(trap_ep_T_DTLBMISS , p->dtlbh);
+ LDILDO(trap_ep_T_DTLBMISSNA, p->dtlbnah);
+ } else {
+ LDILDO(trap_ep_T_ITLBMISS , p->itlbh);
+ LDILDO(trap_ep_T_ITLBMISSNA, p->itlbnah);
+ }
#undef LDILDO
}
}
@@ -466,9 +464,6 @@ hppa_init(start)
EX_NOWAIT))
panic("cannot reserve main memory");
- vstart = hppa_round_page(start);
- vend = VM_MAX_KERNEL_ADDRESS;
-
/*
* Now allocate kernel dynamic variables
*/
@@ -491,7 +486,7 @@ hppa_init(start)
if (bufpages > nbuf * MAXBSIZE / PAGE_SIZE)
bufpages = nbuf * MAXBSIZE / PAGE_SIZE;
- v = vstart;
+ v1 = v = hppa_round_page(start);
#define valloc(name, type, num) (name) = (type *)v; v = (vaddr_t)((name)+(num))
valloc(buf, struct buf, nbuf);
@@ -514,34 +509,16 @@ hppa_init(start)
#undef valloc
v = hppa_round_page(v);
- bzero ((void *)vstart, (v - vstart));
- vstart = v;
+ bzero ((void *)v1, (v - v1));
/* sets physmem */
- pmap_bootstrap(&vstart, &vend);
+ pmap_bootstrap(v);
/* alloc msgbuf */
if (!(msgbufp = (void *)pmap_steal_memory(MSGBUFSIZE, NULL, NULL)))
panic("cannot allocate msgbuf");
msgbufmapped = 1;
- /* Turn on the HW TLB assist */
- if (hptsize) {
- u_int hpt;
-
- mfctl(CR_VTOP, hpt);
- if ((error = (cpu_hpt_init)(hpt, hptsize)) < 0) {
-#ifdef DEBUG
- printf("WARNING: HPT init error %d\n", error);
-#endif
- } else {
-#ifdef PMAPDEBUG
- printf("HPT: %d entries @ 0x%x\n",
- hptsize / sizeof(struct hpt_entry), hpt);
-#endif
- }
- }
-
/* locate coprocessors and SFUs */
if ((error = pdc_call((iodcio_t)pdc, 0, PDC_COPROC, PDC_COPROC_DFLT,
&pdc_coproc)) < 0)
@@ -630,10 +607,6 @@ cpu_startup()
printf("real mem = %d (%d reserved for PROM, %d used by OpenBSD)\n",
ctob(totalphysmem), ctob(resvmem), ctob(physmem));
- /*
- * Now allocate buffers proper. They are different than the above
- * in that they usually occupy more virtual memory than physical.
- */
size = MAXBSIZE * nbuf;
if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size),
NULL, UVM_UNKNOWN_OFFSET, 0, UVM_MAPFLAG(UVM_PROT_NONE,
@@ -661,9 +634,8 @@ cpu_startup()
if ((pg = uvm_pagealloc(NULL, 0, NULL, 0)) == NULL)
panic("cpu_startup: not enough memory for "
"buffer cache");
- pmap_enter(kernel_map->pmap, curbuf,
- VM_PAGE_TO_PHYS(pg), VM_PROT_READ|VM_PROT_WRITE,
- VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED);
+ pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg),
+ VM_PROT_READ|VM_PROT_WRITE);
curbuf += PAGE_SIZE;
curbufsize -= PAGE_SIZE;
}
@@ -890,11 +862,12 @@ btlb_insert(space, va, pa, lenp, prot)
va >>= PGSHIFT;
/* check address alignment */
if (pa & (len - 1))
- printf("WARNING: BTLB address misaligned\n");
+ printf("WARNING: BTLB address misaligned pa=0x%x, len=0x%x\n",
+ pa, len);
/* ensure IO space is uncached */
if ((pa & 0xF0000) == 0xF0000)
- prot |= TLB_UNCACHEABLE;
+ prot |= TLB_UNCACHABLE;
#ifdef BTLBDEBUG
printf("btlb_insert(%d): %x:%x=%x[%x,%x]\n", i, space, va, pa, len, prot);
diff --git a/sys/arch/hppa/hppa/pmap.c b/sys/arch/hppa/hppa/pmap.c
index aeb1b1ff72e..30bb0d71213 100644
--- a/sys/arch/hppa/hppa/pmap.c
+++ b/sys/arch/hppa/hppa/pmap.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: pmap.c,v 1.61 2002/03/14 01:26:31 millert Exp $ */
+/* $OpenBSD: pmap.c,v 1.62 2002/03/15 21:44:18 mickey Exp $ */
/*
- * Copyright (c) 1998-2001 Michael Shalayeff
+ * Copyright (c) 1998-2002 Michael Shalayeff
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,104 +24,12 @@
* IN NO EVENT SHALL THE AUTHOR 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
+ * MOND, 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 1996 1995 by Open Software Foundation, Inc.
- * All Rights Reserved
- *
- * Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appears in all copies and
- * that both the copyright notice and this permission notice appear in
- * supporting documentation.
- *
- * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
- * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-/*
- * Mach Operating System
- * Copyright (c) 1990,1991,1992,1993,1994 The University of Utah and
- * the Computer Systems Laboratory (CSL).
- * Copyright (c) 1991,1987 Carnegie Mellon University.
- * All rights reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation,
- * and that all advertising materials mentioning features or use of
- * this software display the following acknowledgement: ``This product
- * includes software developed by the Computer Systems Laboratory at
- * the University of Utah.''
- *
- * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
- * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
- * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
- * THIS SOFTWARE.
- *
- * CSL requests users of this software to return to csl-dist@cs.utah.edu any
- * improvements that they make and grant CSL redistribution rights.
- *
- * Carnegie Mellon requests users of this software to return to
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- *
- * Utah $Hdr: pmap.c 1.49 94/12/15$
- * Author: Mike Hibler, Bob Wheeler, University of Utah CSL, 10/90
- */
-/*
- * Manages physical address maps for hppa.
- *
- * In addition to hardware address maps, this
- * module is called upon to provide software-use-only
- * maps which may or may not be stored in the same
- * form as hardware maps. These pseudo-maps are
- * used to store intermediate results from copy
- * operations to and from address spaces.
- *
- * Since the information managed by this module is
- * also stored by the logical address mapping module,
- * this module may throw away valid virtual-to-physical
- * mappings at almost any time. However, invalidations
- * of virtual-to-physical mappings must be done as
- * requested.
- *
- * In order to cope with hardware architectures which
- * make virtual-to-physical map invalidates expensive,
- * this module may delay invalidate or reduced protection
- * operations until such time as they are actually
- * necessary. This module is given full information to
- * when physical maps must be made correct.
- *
- */
-/*
- * CAVEATS:
- *
- * PAGE_SIZE must equal NBPG
- * Needs more work for MP support
- * page maps are stored as linear linked lists, some
- * improvement may be achieved should we use smth else
- * protection id (pid) allocation should be done in a pid_t fashion
- * (maybe just use the pid itself)
- * some ppl say, block tlb entries should be maintained somewhere in uvm
- * and be ready for reloads in the fault handler.
- *
* References:
* 1. PA7100LC ERS, Hewlett-Packard, March 30 1999, Public version 1.0
* 2. PA7300LC ERS, Hewlett-Packard, March 18 1996, Version 1.0
@@ -133,6 +41,7 @@
#include <sys/lock.h>
#include <sys/user.h>
#include <sys/proc.h>
+#include <sys/pool.h>
#include <sys/malloc.h>
#include <uvm/uvm.h>
@@ -161,17 +70,18 @@
#define PDB_BITS 0x00000080
#define PDB_COLLECT 0x00000100
#define PDB_PROTECT 0x00000200
-#define PDB_PDRTAB 0x00000400
-#define PDB_VA 0x00000800
+#define PDB_EXTRACT 0x00000400
+#define PDB_VP 0x00000800
#define PDB_PV 0x00001000
#define PDB_PARANOIA 0x00002000
#define PDB_WIRING 0x00004000
-#define PDB_PVDUMP 0x00008000
+#define PDB_PMAP 0x00008000
#define PDB_STEAL 0x00010000
#define PDB_PHYS 0x00020000
+#define PDB_POOL 0x00040000
int pmapdebug = 0
/* | PDB_FOLLOW */
-/* | PDB_VA */
+/* | PDB_VP */
/* | PDB_PV */
/* | PDB_INIT */
/* | PDB_ENTER */
@@ -184,35 +94,35 @@ int pmapdebug = 0
#define DPRINTF(l,s) /* */
#endif
-vaddr_t virtual_steal, virtual_avail, virtual_end;
+vaddr_t virtual_steal, virtual_avail;
+
+#if defined(HP7100LC_CPU) || defined(HP7300LC_CPU)
+int pmap_hptsize = 256; /* patchable */
+#endif
struct pmap kernel_pmap_store;
-pmap_t kernel_pmap;
+int pmap_sid_counter, hppa_sid_max = HPPA_SID_MAX;
boolean_t pmap_initialized = FALSE;
+struct pool pmap_pmap_pool;
+struct pool pmap_pv_pool;
+struct simplelock pvalloc_lock;
-TAILQ_HEAD(, pmap) pmap_freelist; /* list of free pmaps */
-u_int pmap_nfree;
-struct simplelock pmap_freelock; /* and lock */
-
-struct simplelock pmap_lock; /* XXX this is all broken */
-struct simplelock sid_pid_lock; /* pids */
-
-u_int pages_per_vm_page;
-u_int sid_counter;
+void *pmap_pv_page_alloc(struct pool *, int);
+void pmap_pv_page_free(struct pool *, void *);
-TAILQ_HEAD(, pv_page) pv_page_freelist;
-u_int pv_nfree;
-
-#ifdef PMAPDEBUG
-void pmap_hptdump(int sp);
-#endif
+struct pool_allocator pmap_allocator_pv = {
+ pmap_pv_page_alloc, pmap_pv_page_free, 0
+};
-u_int kern_prot[8], user_prot[8];
+u_int hppa_prot[8];
-void pmap_pinit(pmap_t);
#define pmap_sid(pmap, va) \
(((va & 0xc0000000) != 0xc0000000)? pmap->pmap_space : HPPA_SID_KERNEL)
+#define pmap_pvh_attrs(a) \
+ (((a) & PTE_PROT(TLB_DIRTY)) | ((a) ^ PTE_PROT(TLB_REFTRAP)))
+
+#if defined(HP7100LC_CPU) || defined(HP7300LC_CPU)
/*
* This hash function is the one used by the hardware TLB walker on the 7100LC.
*/
@@ -231,497 +141,368 @@ pmap_hash(pa_space_t sp, vaddr_t va)
: "=r" (hpt) : "r" (sp), "r" (va) : "r22", "r23");
return hpt;
}
+#endif
-/*
- * pmap_enter_va(space, va, pv)
- * insert mapping entry into va->pa translation hash table.
- */
static __inline void
-pmap_enter_va(struct pv_entry *pv)
+pmap_sdir_set(pa_space_t space, paddr_t pa)
{
- struct hpt_entry *hpt = pmap_hash(pv->pv_space, pv->pv_va);
-#if defined(PMAPDEBUG) || defined(DIAGNOSTIC)
- struct pv_entry *pvp = hpt->hpt_entry;
-#endif
- DPRINTF(PDB_FOLLOW | PDB_VA,
- ("pmap_enter_va(%x,%x,%p): hpt=%p, pvp=%p\n",
- pv->pv_space, pv->pv_va, pv, hpt, pvp));
-#ifdef DIAGNOSTIC
- while(pvp && (pvp->pv_va != pv->pv_va || pvp->pv_space != pv->pv_space))
- pvp = pvp->pv_hash;
- if (pvp)
- panic("pmap_enter_va: pv_entry is already in hpt_table");
+ paddr_t vtop;
+
+ mfctl(CR_VTOP, vtop);
+#ifdef PMAPDEBUG
+ if (!vtop)
+ panic("pmap_sdir_set: zero vtop");
#endif
- /* we assume that normally there are no duplicate entries
- would be inserted (use DIAGNOSTIC should you want a proof) */
- pv->pv_hash = hpt->hpt_entry;
- hpt->hpt_entry = pv;
+ asm("stwas %0, 0(%1)":: "r" (pa), "r" (vtop + (space << 2)));
}
-/*
- * pmap_find_va(space, va)
- * returns address of the pv_entry correspondent to sp:va
- */
-static __inline struct pv_entry *
-pmap_find_va(pa_space_t space, vaddr_t va)
+static __inline paddr_t
+pmap_sdir_get(pa_space_t space)
{
- struct pv_entry *pvp = pmap_hash(space, va)->hpt_entry;
+ paddr_t vtop, pa;
- DPRINTF(PDB_FOLLOW | PDB_VA, ("pmap_find_va(%x,%x)\n", space, va));
+ mfctl(CR_VTOP, vtop);
+ asm("ldwax,s %2(%1), %0": "=&r" (pa) : "r" (vtop), "r" (space));
- while(pvp && (pvp->pv_va != va || pvp->pv_space != space))
- pvp = pvp->pv_hash;
-
- return pvp;
+ return (pa);
}
-/*
- * Clear the HPT table entry for the corresponding space/offset to reflect
- * the fact that we have possibly changed the mapping, and need to pick
- * up new values from the mapping structure on the next access.
- */
-static __inline void
-pmap_clear_va(pa_space_t space, vaddr_t va)
+static __inline pt_entry_t *
+pmap_pde_get(paddr_t pa, vaddr_t va)
{
- struct hpt_entry *hpt = pmap_hash(space, va);
+ pt_entry_t *pde;
+
+ asm("ldwax,s %2(%1), %0": "=&r" (pde) : "r" (pa), "r" (va >> 22));
- hpt->hpt_valid = 0;
- hpt->hpt_space = -1;
+ return (pde);
}
-/*
- * pmap_remove_va(pv)
- * removes pv_entry from the va->pa translation hash table
- */
static __inline void
-pmap_remove_va(struct pv_entry *pv)
+pmap_pde_set(struct pmap *pm, vaddr_t va, paddr_t ptp)
{
- struct hpt_entry *hpt = pmap_hash(pv->pv_space, pv->pv_va);
- struct pv_entry **pvp = (struct pv_entry **)&hpt->hpt_entry;
-
- DPRINTF(PDB_FOLLOW | PDB_VA,
- ("pmap_remove_va(%p), hpt=%p, pvp=%p\n", pv, hpt, pvp));
-
- while(*pvp && *pvp != pv)
- pvp = &(*pvp)->pv_hash;
- if (*pvp) {
- *pvp = (*pvp)->pv_hash;
- pv->pv_hash = NULL;
- if (hptbtop(pv->pv_va) == hpt->hpt_vpn &&
- pv->pv_space == hpt->hpt_space) {
- hpt->hpt_space = -1;
- hpt->hpt_valid = 0;
- }
- } else {
-#ifdef DIAGNOSTIC
- printf("pmap_remove_va: entry not found\n");
-#endif
- }
+ asm("stwas %0, 0(%1)"
+ :: "r" (ptp), "r" ((paddr_t)pm->pm_pdir + ((va >> 20) & 0xffc)));
}
-/*
- * pmap_insert_pvp(pvp, flag)
- * loads the passed page into pv_entries free list.
- * flag specifies how the page was allocated where possible
- * choices are (0)static, (1)malloc; (probably bogus, but see free_pv)
- */
-static __inline void
-pmap_insert_pvp(struct pv_page *pvp, u_int flag)
+static __inline pt_entry_t *
+pmap_pde_alloc(struct pmap *pm, vaddr_t va, struct vm_page **pdep)
{
- struct pv_entry *pv;
+ struct vm_page *pg;
+ paddr_t pa;
+
+ DPRINTF(PDB_FOLLOW|PDB_VP,
+ ("pmap_pde_alloc(%p, 0x%x, %p)\n", pm, va, pdep));
+
+ va &= PDE_MASK;
+ pg = uvm_pagealloc(&pm->pm_obj, va, NULL,
+ UVM_PGA_USERESERVE|UVM_PGA_ZERO);
+ if (pg == NULL) {
+ /* try to steal somewhere */
+ return (NULL);
+ }
+
+ pa = VM_PAGE_TO_PHYS(pg);
+
+ DPRINTF(PDB_FOLLOW|PDB_VP, ("pmap_pde_alloc: pde %x\n", pa));
- bzero(pvp, sizeof(*pvp));
- for (pv = &pvp->pvp_pv[0]; pv < &pvp->pvp_pv[NPVPPG - 1]; pv++)
- pv->pv_next = pv + 1;
- pvp->pvp_flag = flag;
- pvp->pvp_freelist = &pvp->pvp_pv[0];
- pv_nfree += pvp->pvp_nfree = NPVPPG;
- TAILQ_INSERT_HEAD(&pv_page_freelist, pvp, pvp_list);
+ pg->flags &= ~PG_BUSY; /* never busy */
+ pg->wire_count = 1; /* no mappings yet */
+ pmap_pde_set(pm, va, pa);
+ pm->pm_stats.resident_count++; /* count PTP as resident */
+ pm->pm_ptphint = pg;
+ if (pdep)
+ *pdep = pg;
+ return ((pt_entry_t *)pa);
}
-/*
- * pmap_alloc_pv()
- * allocates the pv_entry from the pv_entries free list.
- * once we've ran out of preallocated pv_entries, nothing
- * can be done, since tlb fault handlers work in phys mode.
- */
-static __inline struct pv_entry *
-pmap_alloc_pv(void)
+static __inline struct vm_page *
+pmap_pde_ptp(struct pmap *pm, pt_entry_t *pde)
{
- struct pv_page *pvp;
- struct pv_entry *pv;
+ paddr_t pa = (paddr_t)pde;
- DPRINTF(PDB_FOLLOW | PDB_PV, ("pmap_alloc_pv()\n"));
+ DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pde_ptp(%p, %p)\n", pm, pde));
- if (pv_nfree == 0) {
-#if notyet
- MALLOC(pvp, struct pv_page *, NBPG, M_VMPVENT, M_WAITOK);
-
- if (!pvp)
- panic("pmap_alloc_pv: alloc failed");
- pmap_insert_pvp(pvp, 0);
-#else
- panic("out of pv_entries");
-#endif
- }
+ if (pm->pm_ptphint && VM_PAGE_TO_PHYS(pm->pm_ptphint) == pa)
+ return (pm->pm_ptphint);
- --pv_nfree;
- pvp = TAILQ_FIRST(&pv_page_freelist);
- if (--pvp->pvp_nfree == 0)
- TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_list);
- pv = pvp->pvp_freelist;
-#ifdef DIAGNOSTIC
- if (pv == 0)
- panic("pmap_alloc_pv: pgi_nfree inconsistent");
-#endif
- pvp->pvp_freelist = pv->pv_next;
- pv->pv_next = NULL;
- pv->pv_hash = NULL;
- pv->pv_pmap = NULL;
+ DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pde_ptp: lookup 0x%x\n", pa));
- return pv;
+ return (PHYS_TO_VM_PAGE(pa));
}
-/*
- * pmap_free_pv(pv)
- * return pv_entry back into free list.
- * once full page of entries has been freed and that page
- * was allocated dynamically, free the page.
- */
static __inline void
-pmap_free_pv(struct pv_entry *pv)
+pmap_pde_release(struct pmap *pmap, vaddr_t va, struct vm_page *ptp)
{
- struct pv_page *pvp;
-
- DPRINTF(PDB_FOLLOW | PDB_PV, ("pmap_free_pv(%p)\n", pv));
-
- pvp = (struct pv_page *) trunc_page((vaddr_t)pv);
- switch (++pvp->pvp_nfree) {
- case 1:
- TAILQ_INSERT_HEAD(&pv_page_freelist, pvp, pvp_list);
- default:
- pv->pv_next = pvp->pvp_freelist;
- pvp->pvp_freelist = pv;
- ++pv_nfree;
- break;
- case NPVPPG:
- if (!pvp->pvp_flag) {
-#ifdef notyet
- pv_nfree -= NPVPPG - 1;
- TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_list);
- FREE((vaddr_t) pvp, M_VMPVENT);
-#else
- panic("pmap_free_pv: mallocated pv page");
-#endif
- }
- break;
+ ptp->wire_count--;
+ if (ptp->wire_count <= 1) {
+ pmap_pde_set(pmap, va, 0);
+ pmap->pm_stats.resident_count--;
+ if (pmap->pm_ptphint == ptp)
+ pmap->pm_ptphint = TAILQ_FIRST(&pmap->pm_obj.memq);
+ ptp->wire_count = 0;
+ uvm_pagefree(ptp);
}
}
-/*
- * pmap_enter_pv(pmap, va, tlbprot, tlbpage, pv)
- * insert specified mapping into pa->va translation list,
- * where pv specifies the list head (for particular pa)
- */
-static __inline struct pv_entry *
-pmap_enter_pv(pmap_t pmap, vaddr_t va, u_int tlbprot, u_int tlbpage,
- struct pv_entry *pv)
+static __inline pt_entry_t
+pmap_pte_get(pt_entry_t *pde, vaddr_t va)
{
- struct pv_entry *npv, *hpv;
+ pt_entry_t pte;
- if (!pmap_initialized)
- return NULL;
+ asm("ldwax,s %2(%1),%0" : "=&r" (pte)
+ : "r" (pde), "r" ((va >> 12) & 0x3ff));
-#ifdef DEBUG
- if (pv == NULL)
- printf("pmap_enter_pv: zero pv\n");
-#endif
+ return (pte);
+}
- DPRINTF(PDB_FOLLOW | PDB_PV, ("pmap_enter_pv: pv %p: %lx/%p/%p\n",
- pv, pv->pv_va, pv->pv_pmap, pv->pv_next));
+static __inline void
+pmap_pte_set(pt_entry_t *pde, vaddr_t va, pt_entry_t pte)
+{
+ DPRINTF(PDB_FOLLOW|PDB_VP, ("pmap_pte_set(%p, 0x%x, 0x%x)\n",
+ pde, va, pte));
- if (pv->pv_pmap == NULL) {
- /*
- * No entries yet, use header as the first entry
- */
- DPRINTF(PDB_ENTER, ("pmap_enter_pv: no entries yet\n"));
- hpv = npv = NULL;
- } else {
- /*
- * There is at least one other VA mapping this page.
- * Place this entry after the header.
- */
- DPRINTF(PDB_ENTER, ("pmap_enter_pv: adding to the list\n"));
#ifdef PMAPDEBUG
- for (npv = pv; npv; npv = npv->pv_next)
- if (pmap == npv->pv_pmap && va == npv->pv_va) {
- printf("pmap_enter_pv: %p already in pv_tab",
- npv);
- pmap_enter_va(npv); /* HACK UGLY HACK HACK */
- return (npv);
- }
+ if (!pde)
+ panic("pmap_pte_set: zero pde");
+ if (pte && pte < virtual_steal &&
+ hppa_trunc_page(pte) != (paddr_t)&gateway_page)
+ panic("pmap_pte_set: invalid pte");
#endif
- hpv = pv;
- npv = pv->pv_next;
- pv = pmap_alloc_pv();
- }
- pv->pv_va = va;
- pv->pv_pmap = pmap;
- pv->pv_space = pmap->pmap_space;
- pv->pv_tlbprot = tlbprot;
- pv->pv_tlbpage = tlbpage;
- pv->pv_next = npv;
- if (hpv)
- hpv->pv_next = pv;
- pmap_enter_va(pv);
-
- return pv;
+ asm("stwas %0, 0(%1)"
+ :: "r" (pte), "r" ((paddr_t)pde + ((va >> 10) & 0xffc)));
}
-/*
- * pmap_remove_pv(ppv, pv)
- * remove mapping for specified va and pmap, from
- * pa->va translation list, having pv as a list head.
- */
-static __inline void
-pmap_remove_pv(struct pv_entry *ppv, struct pv_entry *pv)
+static __inline pt_entry_t
+pmap_vp_find(struct pmap *pm, vaddr_t va)
{
+ pt_entry_t *pde;
- DPRINTF(PDB_FOLLOW | PDB_PV, ("pmap_remove_pv(%p,%p)\n", ppv, pv));
+ if (!(pde = pmap_pde_get(pm->pm_pdir, va)))
+ return (NULL);
- /*
- * Clear it from cache and TLB
- */
- ficache(ppv->pv_space, ppv->pv_va, PAGE_SIZE);
- pitlb(ppv->pv_space, ppv->pv_va);
+ return (pmap_pte_get(pde, va));
+}
- fdcache(ppv->pv_space, ppv->pv_va, PAGE_SIZE);
- pdtlb(ppv->pv_space, ppv->pv_va);
+void
+pmap_dump_table(pa_space_t space)
+{
+ pa_space_t sp;
- /*
- * If it is the first entry on the list, it is actually
- * in the header and we must copy the following entry up
- * to the header. Otherwise we must search the list for
- * the entry. In either case we free the now unused entry.
- */
- if (ppv == pv) {
- ppv = pv->pv_next;
- pmap_remove_va(pv);
- if (ppv) {
- ppv->pv_tlbprot |= pv->pv_tlbprot &
- (TLB_DIRTY | TLB_REF);
- *pv = *ppv;
- pmap_free_pv(ppv);
- } else
- pv->pv_pmap = NULL;
- } else {
- for (; pv && pv->pv_next != ppv; pv = pv->pv_next)
- ;
-
- if (pv) {
- pv->pv_tlbprot |= ppv->pv_tlbprot &
- (TLB_DIRTY | TLB_REF);
- pv->pv_next = ppv->pv_next;
- pmap_remove_va(ppv);
- pmap_free_pv(ppv);
- } else {
-#ifdef DEBUG
- panic("pmap_remove_pv: npv == NULL\n");
-#endif
+ for (sp = 0; sp <= hppa_sid_max; sp++) {
+ paddr_t pa;
+ pt_entry_t *pde, pte;
+ vaddr_t va, pdemask = virtual_avail + 1;
+
+ if (((int)space >= 0 && sp != space) ||
+ !(pa = pmap_sdir_get(sp)))
+ continue;
+
+ for (va = virtual_avail; va < VM_MAX_KERNEL_ADDRESS;
+ va += PAGE_SIZE) {
+ if (pdemask != (va & PDE_MASK)) {
+ pdemask = va & PDE_MASK;
+ if (!(pde = pmap_pde_get(pa, va))) {
+ va += ~PDE_MASK + 1 - PAGE_SIZE;
+ continue;
+ }
+ printf("%x:0x%08x:\n", sp, pde);
+ }
+
+ if (!(pte = pmap_pte_get(pde, va)))
+ continue;
+
+ printf("0x%08x-0x%08x\n", va, pte);
}
}
}
-/*
- * pmap_find_pv(pa)
- * returns head of the pa->va translation list for specified pa.
- */
static __inline struct pv_entry *
-pmap_find_pv(paddr_t pa)
+pmap_pv_alloc(void)
{
- int bank, off;
+ struct pv_entry *pv;
- if ((bank = vm_physseg_find(atop(pa), &off)) != -1) {
- DPRINTF(PDB_PV, ("pmap_find_pv(%x): %d:%d\n", pa, bank, off));
- return &vm_physmem[bank].pmseg.pvent[off];
- } else
- return NULL;
+ DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pv_alloc()\n"));
+
+ simple_lock(&pvalloc_lock);
+
+ pv = pool_get(&pmap_pv_pool, 0);
+
+ simple_unlock(&pvalloc_lock);
+
+ DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pv_alloc: %p\n", pv));
+
+ return (pv);
}
-/*
- * Flush caches and TLB entries refering to physical page pa. If cmp is
- * non-zero, we do not affect the cache or TLB entires for that mapping.
- */
static __inline void
-pmap_clear_pv(paddr_t pa, struct pv_entry *cpv)
+pmap_pv_free(struct pv_entry *pv)
{
- struct pv_entry *pv;
+ simple_lock(&pvalloc_lock);
- DPRINTF(PDB_FOLLOW | PDB_PV, ("pmap_clear_pv(%x,%p)\n", pa, cpv));
+ if (pv->pv_ptp)
+ pmap_pde_release(pv->pv_pmap, pv->pv_va, pv->pv_ptp);
- if (!(pv = pmap_find_pv(pa)) || !pv->pv_pmap)
- return;
+ pool_put(&pmap_pv_pool, pv);
- for (; pv; pv = pv->pv_next) {
- if (pv == cpv)
- continue;
- DPRINTF(PDB_PV,
- ("pmap_clear_pv: %x:%x\n", pv->pv_space, pv->pv_va));
- /*
- * have to clear the icache first since fic uses the dtlb.
- */
- ficache(pv->pv_space, pv->pv_va, NBPG);
- pitlb(pv->pv_space, pv->pv_va);
-
- fdcache(pv->pv_space, pv->pv_va, NBPG);
- pdtlb(pv->pv_space, pv->pv_va);
-
- pmap_clear_va(pv->pv_space, pv->pv_va);
- }
+ simple_unlock(&pvalloc_lock);
+}
+
+static __inline void
+pmap_pv_enter(struct pv_head *pvh, struct pv_entry *pve, struct pmap *pm,
+ vaddr_t va, struct vm_page *pdep)
+{
+ DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pv_enter(%p, %p, %p, 0x%x, %p)\n",
+ pvh, pve, pm, va, pdep));
+
+ pve->pv_pmap = pm;
+ pve->pv_va = va;
+ pve->pv_ptp = pdep;
+ simple_lock(&pvh->pvh_lock); /* lock pv_head */
+ pve->pv_next = pvh->pvh_list;
+ pvh->pvh_list = pve;
+ simple_unlock(&pvh->pvh_lock); /* unlock, done! */
+}
+
+static __inline struct pv_entry *
+pmap_pv_remove(struct pv_head *pvh, struct pmap *pmap, vaddr_t va)
+{
+ struct pv_entry **pve, *pv;
+
+ for(pv = *(pve = &pvh->pvh_list); pv; pv = *(pve = &(*pve)->pv_next))
+ if (pv->pv_pmap == pmap && pv->pv_va == va) {
+ *pve = pv->pv_next;
+ break;
+ }
+ return (pv);
}
-/*
- * Bootstrap the system enough to run with virtual memory.
- * Map the kernel's code and data, and allocate the system page table.
- * Called with mapping OFF.
- *
- * Parameters:
- * vstart PA of first available physical page
- * vend PA of last available physical page
- */
void
-pmap_bootstrap(vstart, vend)
- vaddr_t *vstart;
- vaddr_t *vend;
+pmap_bootstrap(vstart)
+ vaddr_t vstart;
{
- extern int maxproc; /* used to estimate pv_entries pool size */
- extern u_int totalphysmem;
- vaddr_t addr;
+ extern char etext;
+ extern u_int totalphysmem, *ie_mem;
+ vaddr_t addr = hppa_round_page(vstart), t;
vsize_t size;
- struct pv_page *pvp;
- struct hpt_entry *hptp;
+#if 0 && (defined(HP7100LC_CPU) || defined(HP7300LC_CPU))
+ struct vp_entry *hptp;
+#endif
+ struct pmap *kpm;
int i;
- DPRINTF(PDB_FOLLOW, ("pmap_bootstrap(%p, %p)\n", vstart, vend));
+ DPRINTF(PDB_FOLLOW|PDB_INIT, ("pmap_bootstrap(0x%x)\n", vstart));
uvm_setpagesize();
- pages_per_vm_page = PAGE_SIZE / NBPG;
- /* XXX for now */
- if (pages_per_vm_page != 1)
- panic("HPPA page != VM page");
-
- kern_prot[VM_PROT_NONE | VM_PROT_NONE | VM_PROT_NONE] =TLB_AR_NA;
- kern_prot[VM_PROT_READ | VM_PROT_NONE | VM_PROT_NONE] =TLB_AR_KR;
- kern_prot[VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_NONE] =TLB_AR_KRW;
- kern_prot[VM_PROT_READ | VM_PROT_WRITE | VM_PROT_NONE] =TLB_AR_KRW;
- kern_prot[VM_PROT_NONE | VM_PROT_NONE | VM_PROT_EXECUTE] =TLB_AR_KRX;
- kern_prot[VM_PROT_READ | VM_PROT_NONE | VM_PROT_EXECUTE] =TLB_AR_KRX;
- kern_prot[VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_EXECUTE] =TLB_AR_KRWX;
- kern_prot[VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE] =TLB_AR_KRWX;
-
- user_prot[VM_PROT_NONE | VM_PROT_NONE | VM_PROT_NONE] =TLB_AR_NA;
- user_prot[VM_PROT_READ | VM_PROT_NONE | VM_PROT_NONE] =TLB_AR_UR;
- user_prot[VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_NONE] =TLB_AR_URW;
- user_prot[VM_PROT_READ | VM_PROT_WRITE | VM_PROT_NONE] =TLB_AR_URW;
- user_prot[VM_PROT_NONE | VM_PROT_NONE | VM_PROT_EXECUTE] =TLB_AR_URX;
- user_prot[VM_PROT_READ | VM_PROT_NONE | VM_PROT_EXECUTE] =TLB_AR_URX;
- user_prot[VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_EXECUTE] =TLB_AR_URWX;
- user_prot[VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE] =TLB_AR_URWX;
+ hppa_prot[VM_PROT_NONE | VM_PROT_NONE | VM_PROT_NONE] =TLB_AR_NA;
+ hppa_prot[VM_PROT_READ | VM_PROT_NONE | VM_PROT_NONE] =TLB_AR_R;
+ hppa_prot[VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_NONE] =TLB_AR_RW;
+ hppa_prot[VM_PROT_READ | VM_PROT_WRITE | VM_PROT_NONE] =TLB_AR_RW;
+ hppa_prot[VM_PROT_NONE | VM_PROT_NONE | VM_PROT_EXECUTE] =TLB_AR_RX;
+ hppa_prot[VM_PROT_READ | VM_PROT_NONE | VM_PROT_EXECUTE] =TLB_AR_RX;
+ hppa_prot[VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_EXECUTE] =TLB_AR_RWX;
+ hppa_prot[VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE] =TLB_AR_RWX;
/*
* Initialize kernel pmap
*/
- kernel_pmap = &kernel_pmap_store;
-#if NCPUS > 1
- lock_init(&pmap_lock, FALSE, ETAP_VM_PMAP_SYS, ETAP_VM_PMAP_SYS_I);
-#endif /* NCPUS > 1 */
- simple_lock_init(&kernel_pmap->pmap_lock);
- simple_lock_init(&pmap_freelock);
- simple_lock_init(&sid_pid_lock);
-
- kernel_pmap->pmap_refcnt = 1;
- kernel_pmap->pmap_space = HPPA_SID_KERNEL;
+ kpm = &kernel_pmap_store;
+ bzero(kpm, sizeof(*kpm));
+ simple_lock_init(&kpm->pm_obj.vmobjlock);
+ kpm->pm_obj.pgops = NULL;
+ TAILQ_INIT(&kpm->pm_obj.memq);
+ kpm->pm_obj.uo_npages = 0;
+ kpm->pm_obj.uo_refs = 1;
+ kpm->pm_space = HPPA_SID_KERNEL;
+ kpm->pm_pid = HPPA_PID_KERNEL;
+ kpm->pm_pdir_pg = NULL;
+ kpm->pm_pdir = addr;
+ addr += PAGE_SIZE;
+ bzero((void *)addr, PAGE_SIZE);
+ fdcache(HPPA_SID_KERNEL, addr, PAGE_SIZE);
/*
* Allocate various tables and structures.
*/
- addr = hppa_round_page(*vstart);
- virtual_end = *vend;
- pvp = (struct pv_page *)addr;
-
- mfctl(CR_HPTMASK, size);
- addr = (addr + size) & ~(size);
-
- DPRINTF(PDB_INIT, ("pmap_bootstrap: allocating %d pv_pages\n",
- (struct pv_page *)addr - pvp));
-
- TAILQ_INIT(&pv_page_freelist);
- for (; pvp + 1 <= (struct pv_page *)addr; pvp++)
- pmap_insert_pvp(pvp, 1);
-
- /* Allocate the HPT */
- for (hptp = (struct hpt_entry *)addr;
- ((u_int)hptp - addr) <= size; hptp++) {
- hptp->hpt_valid = 0;
- hptp->hpt_vpn = 0;
- hptp->hpt_space = -1;
- hptp->hpt_tlbpage = 0;
- hptp->hpt_tlbprot = 0;
- hptp->hpt_entry = NULL;
- }
-
- DPRINTF(PDB_INIT, ("hpt_table: 0x%x @ %p\n", size + 1, addr));
- /* load cr25 with the address of the HPT table
- NB: It sez CR_VTOP, but we (and the TLB handlers) know better ... */
mtctl(addr, CR_VTOP);
- addr += size + 1;
+ bzero((void *)addr, (hppa_sid_max + 1) * 4);
+ fdcache(HPPA_SID_KERNEL, addr, (hppa_sid_max + 1) * 4);
+ printf("vtop: 0x%x @ 0x%x\n", (hppa_sid_max + 1) * 4, addr);
+ addr += (hppa_sid_max + 1) * 4;
+ pmap_sdir_set(HPPA_SID_KERNEL, kpm->pm_pdir);
+
+ 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;
+
+ 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;
+
+ size = pmap_hptsize * sizeof(*hptp);
+ bzero((void *)addr, size);
+ /* Allocate the HPT */
+ for (hptp = (struct vp_entry *)addr, i = pmap_hptsize; 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);
+ }
- /*
- * we know that btlb_insert() will round it up to the next
- * power of two at least anyway
- */
- for (physmem = 1; physmem < btoc(addr); physmem *= 2);
+ /* TODO find a way to avoid using cr*, use cpu regs instead */
+ mtctl(addr, CR_VTOP);
+ mtctl(size - 1, CR_HPTMASK);
+ addr += size;
+ }
+#endif /* HP7100LC_CPU | HP7300LC_CPU */
/* map the kernel space, which will give us virtual_avail */
- *vstart = hppa_round_page(addr + (totalphysmem - physmem) *
- (sizeof(struct pv_entry) * maxproc / 8 +
- sizeof(struct vm_page)));
+ vstart = hppa_round_page(addr + (totalphysmem - (atop(addr))) *
+ (16 + sizeof(struct pv_head) + sizeof(struct vm_page)));
/* XXX PCXS needs two separate inserts in separate btlbs */
- if (btlb_insert(HPPA_SID_KERNEL, 0, 0, vstart,
+ t = (vaddr_t)&etext;
+ if (btlb_insert(HPPA_SID_KERNEL, 0, 0, &t,
pmap_sid2pid(HPPA_SID_KERNEL) |
- pmap_prot(kernel_pmap, VM_PROT_ALL)) < 0)
+ pmap_prot(pmap_kernel(), VM_PROT_READ|VM_PROT_EXECUTE)) < 0)
+ panic("pmap_bootstrap: cannot block map kernel text");
+ t = vstart - (vaddr_t)&etext;
+ if (btlb_insert(HPPA_SID_KERNEL, (vaddr_t)&etext, (vaddr_t)&etext, &t,
+ pmap_sid2pid(HPPA_SID_KERNEL) | TLB_UNCACHABLE |
+ pmap_prot(pmap_kernel(), VM_PROT_ALL)) < 0)
panic("pmap_bootstrap: cannot block map kernel");
- virtual_avail = *vstart;
+ vstart = (vaddr_t)&etext + t;
+ virtual_avail = vstart;
+ kpm->pm_stats.wired_count = kpm->pm_stats.resident_count =
+ physmem = atop(vstart);
/*
* NOTE: we no longer trash the BTLB w/ unused entries,
* lazy map only needed pieces (see bus_mem_add_mapping() for refs).
*/
- size = hppa_round_page(sizeof(struct pv_entry) * totalphysmem);
+ addr = hppa_round_page(addr);
+ size = hppa_round_page(sizeof(struct pv_head) * totalphysmem);
bzero ((caddr_t)addr, size);
- DPRINTF(PDB_INIT, ("pv_array: 0x%x @ 0x%x\n", size, addr));
+ DPRINTF(PDB_INIT, ("pmseg.pvent: 0x%x @ 0x%x\n", size, addr));
+ /* XXX we might need to split this for isa */
virtual_steal = addr + size;
i = atop(virtual_avail - virtual_steal);
uvm_page_physload(0, totalphysmem + i,
atop(virtual_avail), totalphysmem + i, VM_FREELIST_DEFAULT);
/* we have only one initial phys memory segment */
- vm_physmem[0].pmseg.pvent = (struct pv_entry *)addr;
- /* mtctl(addr, CR_PSEG); */
-
- /* here will be a hole due to the kernel memory alignment
- and we use it for pmap_steal_memory */
-}
-
-void
-pmap_virtual_space(vaddr_t *vstartp, vaddr_t *vendp)
-{
- *vstartp = virtual_avail;
- *vendp = virtual_end;
+ vm_physmem[0].pmseg.pvhead = (struct pv_head *)addr;
}
/*
@@ -738,13 +519,13 @@ pmap_steal_memory(size, startp, endp)
{
vaddr_t va;
- DPRINTF(PDB_FOLLOW,
+ DPRINTF(PDB_FOLLOW|PDB_STEAL,
("pmap_steal_memory(%x, %x, %x)\n", size, startp, endp));
if (startp)
*startp = virtual_avail;
if (endp)
- *endp = virtual_end;
+ *endp = VM_MAX_KERNEL_ADDRESS;
size = hppa_round_page(size);
if (size <= virtual_avail - virtual_steal) {
@@ -765,38 +546,20 @@ pmap_steal_memory(size, startp, endp)
return va;
}
-/*
- * Finishes the initialization of the pmap module.
- * This procedure is called from vm_mem_init() in vm/vm_init.c
- * to initialize any remaining data structures that the pmap module
- * needs to map virtual memory (VM is already ON).
- */
void
pmap_init()
{
- struct pv_page *pvp;
+ DPRINTF(PDB_FOLLOW|PDB_INIT, ("pmap_init()\n"));
-#ifdef PMAPDEBUG
- int opmapdebug = pmapdebug;
- DPRINTF(PDB_FOLLOW, ("pmap_init()\n"));
- pmapdebug = 0;
-#endif
+ pool_init(&pmap_pmap_pool, sizeof(struct pmap), 0, 0, 0, "pmappl",
+ &pool_allocator_nointr);
+ pool_init(&pmap_pv_pool, sizeof(struct pv_entry), 0, 0, 0, "pmappv",
+ &pmap_allocator_pv);
+ /* depleet the steal area */
+ pool_prime(&pmap_pv_pool, (virtual_avail - virtual_steal) / PAGE_SIZE *
+ pmap_pv_pool.pr_itemsperpage);
- /* allocate the rest of the steal area for pv_pages */
-#ifdef PMAPDEBUG
- printf("pmap_init: %d pv_pages @ %x allocated\n",
- (virtual_avail - virtual_steal) / sizeof(struct pv_page),
- virtual_steal);
-#endif
- while ((pvp = (struct pv_page *)
- pmap_steal_memory(sizeof(*pvp), NULL, NULL)))
- pmap_insert_pvp(pvp, 1);
-
-#ifdef PMAPDEBUG
- pmapdebug = opmapdebug /* | PDB_VA | PDB_PV */;
-#endif
- TAILQ_INIT(&pmap_freelist);
- sid_counter = HPPA_SID_KERNEL + 1;
+ simple_lock_init(&pvalloc_lock);
pmap_initialized = TRUE;
@@ -807,465 +570,497 @@ pmap_init()
*
* no spls since no interrupts.
*/
- pmap_enter_pv(pmap_kernel(), SYSCALLGATE, TLB_GATE_PROT,
- tlbbtop((paddr_t)&gateway_page),
- pmap_find_pv((paddr_t)&gateway_page));
-}
+ {
+ pt_entry_t *pde;
-/*
- * Initialize a preallocated and zeroed pmap structure,
- * such as one in a vmspace structure.
- */
-void
-pmap_pinit(pmap)
- pmap_t pmap;
-{
- pa_space_t sid;
- int s;
-
- DPRINTF(PDB_FOLLOW, ("pmap_pinit(%p)\n", pmap));
-
- if (!(sid = pmap->pmap_space)) {
+ if (!(pde = pmap_pde_get(pmap_kernel()->pm_pdir, SYSCALLGATE)) &&
+ !(pde = pmap_pde_alloc(pmap_kernel(), SYSCALLGATE, NULL)))
+ panic("pmap_init: cannot allocate pde");
- /*
- * Allocate space and protection IDs for the pmap.
- * If all are allocated, there is nothing we can do.
- */
- s = splimp();
- if (sid_counter < HPPA_SID_MAX) {
- sid = sid_counter;
- sid_counter++;
- } else
- sid = 0;
- splx(s);
-
- if (sid == 0)
- panic("no more space ids\n");
-
- simple_lock_init(&pmap->pmap_lock);
+ pmap_pte_set(pde, SYSCALLGATE, (paddr_t)&gateway_page |
+ PTE_PROT(TLB_GATE_PROT));
}
-
- s = splimp();
- pmap->pmap_space = sid;
- pmap->pmap_refcnt = 1;
- pmap->pmap_stats.resident_count = 0;
- pmap->pmap_stats.wired_count = 0;
- splx(s);
}
-/*
- * pmap_create()
- *
- * Create and return a physical map.
- * the map is an actual physical map, and may be referenced by the hardware.
- */
-pmap_t
+struct pmap *
pmap_create()
{
- register pmap_t pmap;
- int s;
+ struct pmap *pmap;
+ pa_space_t space;
- DPRINTF(PDB_FOLLOW, ("pmap_create()\n"));
+ DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_create()\n"));
+ pmap = pool_get(&pmap_pmap_pool, PR_WAITOK);
- /*
- * If there is a pmap in the pmap free list, reuse it.
- */
- s = splimp();
- if (pmap_nfree) {
- pmap = pmap_freelist.tqh_first;
- TAILQ_REMOVE(&pmap_freelist, pmap, pmap_list);
- pmap_nfree--;
- splx(s);
- } else {
- splx(s);
- MALLOC(pmap, struct pmap *, sizeof(*pmap), M_VMMAP, M_NOWAIT);
- if (pmap == NULL)
- return NULL;
- bzero(pmap, sizeof(*pmap));
- }
+ simple_lock_init(&pmap->pm_obj.vmobjlock);
+ pmap->pm_obj.pgops = NULL; /* currently not a mappable object */
+ TAILQ_INIT(&pmap->pm_obj.memq);
+ pmap->pm_obj.uo_npages = 0;
+ pmap->pm_obj.uo_refs = 1;
+ pmap->pm_stats.wired_count = 0;
+ pmap->pm_stats.resident_count = 1;
- pmap_pinit(pmap);
+ if (pmap_sid_counter >= hppa_sid_max) {
+ /* collect some */
+ panic("pmap_create: outer space");
+ } else
+ space = ++pmap_sid_counter;
+
+ pmap->pm_space = space;
+ pmap->pm_pid = (space + 1) << 1;
+ pmap->pm_pdir_pg = uvm_pagealloc(NULL, 0, NULL,
+ UVM_PGA_USERESERVE|UVM_PGA_ZERO);
+ if (!pmap->pm_pdir_pg)
+ panic("pmap_create: no pages");
+ pmap->pm_pdir = VM_PAGE_TO_PHYS(pmap->pm_pdir_pg);
+
+ pmap_sdir_set(space, pmap->pm_pdir);
return(pmap);
}
-/*
- * pmap_destroy(pmap)
- * Gives up a reference to the specified pmap. When the reference count
- * reaches zero the pmap structure is added to the pmap free list.
- * Should only be called if the map contains no valid mappings.
- */
void
pmap_destroy(pmap)
- pmap_t pmap;
+ struct pmap *pmap;
{
- int ref_count;
- int s;
-
- DPRINTF(PDB_FOLLOW, ("pmap_destroy(%p)\n", pmap));
-
- if (!pmap)
- return;
+ struct vm_page *pg;
+ pa_space_t space;
+ int refs;
- s = splimp();
+ DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_destroy(%p)\n", pmap));
- ref_count = --pmap->pmap_refcnt;
+ simple_lock(&pmap->pm_obj.vmobjlock);
+ refs = --pmap->pm_obj.uo_refs;
+ simple_unlock(&pmap->pm_obj.vmobjlock);
- if (ref_count < 0)
- panic("pmap_destroy(): ref_count < 0");
- if (!ref_count) {
- assert(pmap->pmap_stats.resident_count == 0);
+ if (refs > 0)
+ return;
- /*
- * Add the pmap to the pmap free list
- * We cannot free() disposed pmaps because of
- * PID shortage of 2^16
- * (do some random pid allocation later)
- */
- TAILQ_INSERT_HEAD(&pmap_freelist, pmap, pmap_list);
- pmap_nfree++;
+ TAILQ_FOREACH(pg, &pmap->pm_obj.memq, listq) {
+#ifdef DIAGNOSTIC
+ if (pg->flags & PG_BUSY)
+ panic("pmap_release: busy page table page");
+#endif
+ pg->wire_count = 0;
+ uvm_pagefree(pg);
}
- splx(s);
+
+ uvm_pagefree(pmap->pm_pdir_pg);
+ pmap->pm_pdir_pg = NULL; /* XXX cache it? */
+ pmap_sdir_set(space, 0);
+ pool_put(&pmap_pmap_pool, pmap);
}
+
/*
- * pmap_enter(pmap, va, pa, prot, flags)
- * Create a translation for the virtual address (va) to the physical
- * address (pa) in the pmap with the protection requested. If the
- * translation is wired then we can not allow a page fault to occur
- * for this mapping.
+ * Add a reference to the specified pmap.
*/
+void
+pmap_reference(pmap)
+ struct pmap *pmap;
+{
+ DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_reference(%p)\n", pmap));
+
+ simple_lock(&pmap->pm_obj.vmobjlock);
+ pmap->pm_obj.uo_refs++;
+ simple_unlock(&pmap->pm_obj.vmobjlock);
+}
+
+void
+pmap_collect(struct pmap *pmap)
+{
+ DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_collect(%p)\n", pmap));
+ /* nothing yet */
+}
+
int
pmap_enter(pmap, va, pa, prot, flags)
- pmap_t pmap;
+ struct pmap *pmap;
vaddr_t va;
paddr_t pa;
vm_prot_t prot;
int flags;
{
- register struct pv_entry *pv, *ppv;
- u_int tlbpage, tlbprot;
- pa_space_t space;
- boolean_t waswired;
+ pt_entry_t *pde, pte;
+ struct vm_page *ptp = NULL;
+ struct pv_head *pvh;
+ struct pv_entry *pve;
+ int bank, off;
boolean_t wired = (flags & PMAP_WIRED) != 0;
- int s;
- pa = hppa_trunc_page(pa);
- va = hppa_trunc_page(va);
- space = pmap_sid(pmap, va);
-#ifdef PMAPDEBUG
- if (pmapdebug & PDB_FOLLOW &&
- (!pmap_initialized || pmapdebug & PDB_ENTER))
- printf("pmap_enter(%p, %x, %x, %x, %swired)\n", pmap, va, pa,
- prot, wired? "" : "un");
-#endif
+ DPRINTF(PDB_FOLLOW|PDB_ENTER,
+ ("pmap_enter(%p, 0x%x, 0x%x, 0x%x, 0x%x)\n",
+ pmap, va, pa, prot, flags));
- s = splimp(); /* are we already high enough? XXX */
+ simple_lock(&pmap->pm_obj.vmobjlock);
- if (!(pv = pmap_find_pv(pa)))
- panic("pmap_enter: pmap_find_pv failed");
+ if (!(pde = pmap_pde_get(pmap->pm_pdir, va)) &&
+ !(pde = pmap_pde_alloc(pmap, va, &ptp))) {
+ if (flags & PMAP_CANFAIL)
+ return (KERN_RESOURCE_SHORTAGE);
- tlbpage = tlbbtop(pa);
- tlbprot = TLB_UNCACHEABLE | pmap_prot(pmap, prot) | pmap_sid2pid(space);
+ panic("pmap_kenter: cannot allocate pde");
+ }
- if (!(ppv = pmap_find_va(space, va))) {
- /*
- * Mapping for this virtual address doesn't exist.
- * Enter a new mapping.
- */
- DPRINTF(PDB_ENTER, ("pmap_enter: new mapping\n"));
- pv = pmap_enter_pv(pmap, va, tlbprot, tlbpage, pv);
- pmap->pmap_stats.resident_count++;
+ if (!ptp)
+ ptp = pmap_pde_ptp(pmap, pde);
- } else {
+ if ((pte = pmap_pte_get(pde, va))) {
- /* see if we are remapping the page to another PA */
- if (ppv->pv_tlbpage != tlbpage) {
- DPRINTF(PDB_ENTER, ("pmap_enter: moving pa %x -> %x\n",
- ppv->pv_tlbpage, tlbpage));
- /* update tlbprot to avoid extra subsequent fault */
- pmap_remove_pv(ppv, pmap_find_pv(tlbptob(ppv->pv_tlbpage)));
- pv = pmap_enter_pv(pmap, va, tlbprot, tlbpage, pv);
- } else {
- /* We are just changing the protection. */
- DPRINTF(PDB_ENTER, ("pmap_enter: changing %b->%b\n",
- ppv->pv_tlbprot, TLB_BITS, tlbprot, TLB_BITS));
- pv = ppv;
- ppv->pv_tlbprot = (tlbprot & ~TLB_PID_MASK) |
- (ppv->pv_tlbprot & ~(TLB_AR_MASK|TLB_PID_MASK));
- pmap_clear_pv(pa, NULL);
+ DPRINTF(PDB_ENTER,
+ ("pmap_enter: remapping 0x%x -> 0x%x\n", pte, pa));
+
+ if (pte & PTE_PROT(TLB_EXECUTE))
+ ficache(pmap->pm_space, va, NBPG);
+ pitlb(pmap->pm_space, va);
+ fdcache(pmap->pm_space, va, NBPG);
+ pdtlb(pmap->pm_space, va);
+
+ if (wired && !(pte & PTE_PROT(TLB_WIRED)) == 0)
+ pmap->pm_stats.wired_count++;
+ else if (!wired && (pte & PTE_PROT(TLB_WIRED)) != 0)
+ pmap->pm_stats.wired_count--;
+
+ if (PTE_PAGE(pte) == pa) {
+ DPRINTF(PDB_FOLLOW|PDB_ENTER,
+ ("pmap_enter: same page\n"));
+ goto enter;
}
+
+ bank = vm_physseg_find(atop(PTE_PAGE(pte)), &off);
+ if (bank != -1) {
+ pvh = &vm_physmem[bank].pmseg.pvhead[off];
+ simple_lock(&pvh->pvh_lock);
+ pve = pmap_pv_remove(pvh, pmap, va);
+ pvh->pvh_attrs |= pmap_pvh_attrs(pte);
+ simple_unlock(&pvh->pvh_lock);
+ } else
+ pve = NULL;
+ } else {
+ DPRINTF(PDB_ENTER,
+ ("pmap_enter: new mapping 0x%x -> 0x%x\n", va, pa));
+ pte = PTE_PROT(TLB_REFTRAP);
+ pve = NULL;
+ pmap->pm_stats.resident_count++;
+ if (wired)
+ pmap->pm_stats.wired_count++;
+ if (ptp)
+ ptp->wire_count++;
}
- /*
- * Add in software bits and adjust statistics
- */
- waswired = pv->pv_tlbprot & TLB_WIRED;
- if (wired && !waswired) {
- pv->pv_tlbprot |= TLB_WIRED;
- pmap->pmap_stats.wired_count++;
- } else if (!wired && waswired) {
- pv->pv_tlbprot &= ~TLB_WIRED;
- pmap->pmap_stats.wired_count--;
+ bank = vm_physseg_find(atop(pa), &off);
+ if (pmap_initialized && bank != -1) {
+ if (!pve && !(pve = pmap_pv_alloc())) {
+ if (flags & PMAP_CANFAIL) {
+ simple_unlock(&pmap->pm_obj.vmobjlock);
+ return (KERN_RESOURCE_SHORTAGE);
+ }
+ panic("pmap_enter: no pv entries available");
+ }
+ pvh = &vm_physmem[bank].pmseg.pvhead[off];
+ pmap_pv_enter(pvh, pve, pmap, va, ptp);
+ } else {
+ pvh = NULL;
+ if (pve)
+ pmap_pv_free(pve);
}
- splx(s);
- simple_unlock(&pmap->pmap_lock);
- DPRINTF(PDB_ENTER, ("pmap_enter: leaving\n"));
+enter:
+ /* preserve old ref & mod */
+ pte = pa | PTE_PROT(pmap_prot(pmap, prot)) |
+ (pte & PTE_PROT(TLB_UNCACHABLE|TLB_DIRTY|TLB_REFTRAP));
+ if (wired)
+ pte |= PTE_PROT(TLB_WIRED);
+ pmap_pte_set(pde, va, pte);
+
+ simple_unlock(&pmap->pm_obj.vmobjlock);
+
+ DPRINTF(PDB_FOLLOW, ("pmap_enter: leaving\n"));
return (0);
}
-/*
- * pmap_remove(pmap, sva, eva)
- * unmaps all virtual addresses v in the virtual address
- * range determined by [sva, eva) and pmap.
- * sva and eva must be on machine independent page boundaries and
- * sva must be less than or equal to eva.
- */
void
pmap_remove(pmap, sva, eva)
- register pmap_t pmap;
- register vaddr_t sva;
- register vaddr_t eva;
+ struct pmap *pmap;
+ vaddr_t sva;
+ vaddr_t eva;
{
- register struct pv_entry *pv;
- register pa_space_t space;
- int s;
+ struct pv_head *pvh;
+ struct pv_entry *pve;
+ pt_entry_t *pde, pte;
+ int bank, off;
+ u_int pdemask;
- DPRINTF(PDB_FOLLOW, ("pmap_remove(%p, %x, %x)\n", pmap, sva, eva));
+ DPRINTF(PDB_FOLLOW|PDB_REMOVE,
+ ("pmap_remove(%p, 0x%x, 0x%x\n", pmap, sva, eva));
- if(!pmap)
- return;
+ simple_lock(&pmap->pm_obj.vmobjlock);
- s = splimp();
+ for (pdemask = sva + 1; sva < eva; sva += PAGE_SIZE) {
+ if (pdemask != (sva & PDE_MASK)) {
+ pdemask = sva & PDE_MASK;
+ if (!(pde = pmap_pde_get(pmap->pm_pdir, sva))) {
+ sva += ~PDE_MASK + 1 - PAGE_SIZE;
+ continue;
+ }
+ }
- sva = hppa_trunc_page(sva);
- space = pmap_sid(pmap, sva);
-
- while (pmap->pmap_stats.resident_count && ((sva < eva))) {
- pv = pmap_find_va(space, sva);
-
- DPRINTF(PDB_REMOVE, ("pmap_remove: removing %p for 0x%x:0x%x\n",
- pv, space, sva));
- if (pv) {
- pmap->pmap_stats.resident_count--;
- if (pv->pv_tlbprot & TLB_WIRED)
- pmap->pmap_stats.wired_count--;
- pmap_remove_pv(pv,
- pmap_find_pv(tlbptob(pv->pv_tlbpage)));
+ if ((pte = pmap_pte_get(pde, sva))) {
+
+ if (pte & PTE_PROT(TLB_WIRED))
+ pmap->pm_stats.wired_count--;
+ pmap->pm_stats.resident_count--;
+
+ if (pte & PTE_PROT(pte))
+ ficache(pmap->pm_space, sva, PAGE_SIZE);
+ pitlb(pmap->pm_space, sva);
+ fdcache(pmap->pm_space, sva, PAGE_SIZE);
+ pdtlb(pmap->pm_space, sva);
+
+ pmap_pte_set(pde, sva, 0);
+
+ bank = vm_physseg_find(atop(pte), &off);
+ if (pmap_initialized && bank != -1) {
+ pvh = &vm_physmem[bank].pmseg.pvhead[off];
+ pve = pmap_pv_remove(pvh, pmap, sva);
+ if (pve) {
+ pvh->pvh_attrs |= pmap_pvh_attrs(pte);
+ pmap_pv_free(pve);
+ }
+ }
}
- sva += PAGE_SIZE;
}
- splx(s);
+ simple_unlock(&pmap->pm_obj.vmobjlock);
+
+ DPRINTF(PDB_FOLLOW|PDB_REMOVE, ("pmap_remove: leaving\n"));
}
-/*
- * pmap_page_protect(pa, prot)
- *
- * Lower the permission for all mappings to a given page.
- */
void
-pmap_page_protect(pg, prot)
- struct vm_page *pg;
+pmap_write_protect(pmap, sva, eva, prot)
+ struct pmap *pmap;
+ vaddr_t sva;
+ vaddr_t eva;
vm_prot_t prot;
{
- register struct pv_entry *pv;
- register pmap_t pmap;
- register u_int tlbprot;
- paddr_t pa = VM_PAGE_TO_PHYS(pg);
- int s;
+ pt_entry_t *pde, pte;
+ u_int tlbprot, pdemask;
- DPRINTF(PDB_FOLLOW|PDB_PROTECT,
- ("pmap_page_protect(%x, %x)\n", pa, prot));
+ DPRINTF(PDB_FOLLOW|PDB_PMAP,
+ ("pmap_write_protect(%p, %x, %x, %x)\n", pmap, sva, eva, prot));
- switch (prot) {
- case VM_PROT_ALL:
- return;
- case VM_PROT_READ:
- case VM_PROT_READ|VM_PROT_EXECUTE:
- s = splimp();
- if (!(pv = pmap_find_pv(pa)) || !pv->pv_pmap) {
- splx(s);
- break;
+ sva = hppa_trunc_page(sva);
+ tlbprot = PTE_PROT(pmap_prot(pmap, prot));
+
+ simple_lock(&pmap->pm_obj.vmobjlock);
+
+ for(pdemask = sva + 1; sva < eva; sva += PAGE_SIZE) {
+ if (pdemask != (sva & PDE_MASK)) {
+ pdemask = sva & PDE_MASK;
+ if (!(pde = pmap_pde_get(pmap->pm_pdir, sva))) {
+ sva += ~PDE_MASK + 1 - PAGE_SIZE;
+ continue;
+ }
}
+ if ((pte = pmap_pte_get(pde, sva))) {
- for ( ; pv; pv = pv->pv_next) {
/*
- * Compare new protection with old to see if
- * anything needs to be changed.
+ * Determine if mapping is changing.
+ * If not, nothing to do.
*/
- tlbprot = pmap_prot(pv->pv_pmap, prot);
-
- if ((pv->pv_tlbprot & TLB_AR_MASK) != tlbprot) {
- pv->pv_tlbprot &= ~TLB_AR_MASK;
- pv->pv_tlbprot |= tlbprot;
-
- /*
- * Purge the current TLB entry (if any)
- * to force a fault and reload with the
- * new protection.
- */
- ficache(pv->pv_space, pv->pv_va, NBPG);
- pitlb(pv->pv_space, pv->pv_va);
- fdcache(pv->pv_space, pv->pv_va, NBPG);
- pdtlb(pv->pv_space, pv->pv_va);
- pmap_clear_va(pv->pv_space, pv->pv_va);
- }
- }
- splx(s);
- break;
- default:
- s = splimp();
- while ((pv = pmap_find_pv(pa)) && pv->pv_pmap) {
-
- DPRINTF(PDB_PROTECT, ("pv={%p,%x:%x,%b,%x}->%p\n",
- pv->pv_pmap, pv->pv_space, pv->pv_va,
- pv->pv_tlbprot, TLB_BITS,
- tlbptob(pv->pv_tlbpage), pv->pv_hash));
- pmap = pv->pv_pmap;
- pmap_remove_pv(pv, pv);
- pmap->pmap_stats.resident_count--;
+ if ((pte & PTE_PROT(TLB_AR_MASK)) == tlbprot)
+ continue;
+
+ if (pte & PTE_PROT(TLB_EXECUTE))
+ ficache(pmap->pm_space, sva, PAGE_SIZE);
+ pitlb(pmap->pm_space, sva);
+ fdcache(pmap->pm_space, sva, PAGE_SIZE);
+ pdtlb(pmap->pm_space, sva);
+
+ pte &= ~PTE_PROT(TLB_AR_MASK);
+ pte |= tlbprot;
+ pmap_pte_set(pde, sva, pte);
}
- splx(s);
- break;
}
+
+ simple_unlock(&pmap->pm_obj.vmobjlock);
}
-/*
- * pmap_protect(pmap, s, e, prot)
- * changes the protection on all virtual addresses v in the
- * virtual address range determined by [s, e) and pmap to prot.
- * s and e must be on machine independent page boundaries and
- * s must be less than or equal to e.
- */
void
-pmap_protect(pmap, sva, eva, prot)
- pmap_t pmap;
- vaddr_t sva;
- vaddr_t eva;
- vm_prot_t prot;
+pmap_page_remove(pg)
+ struct vm_page *pg;
{
- register struct pv_entry *pv;
- u_int tlbprot;
- pa_space_t space;
-
- DPRINTF(PDB_FOLLOW,
- ("pmap_protect(%p, %x, %x, %x)\n", pmap, sva, eva, prot));
+ struct pv_head *pvh;
+ struct pv_entry *pve, *ppve;
+ pt_entry_t *pde, pte;
+ int bank, off;
- if (!pmap)
- return;
+ DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_page_remove(%p)\n", pg));
- if (prot == VM_PROT_NONE) {
- pmap_remove(pmap, sva, eva);
+ bank = vm_physseg_find(atop(VM_PAGE_TO_PHYS(pg)), &off);
+ if (bank == -1) {
+ printf("pmap_page_remove: unmanaged page?\n");
return;
}
- if (prot & VM_PROT_WRITE)
+
+ pvh = &vm_physmem[bank].pmseg.pvhead[off];
+ if (pvh->pvh_list == NULL)
return;
- sva = hppa_trunc_page(sva);
- space = pmap_sid(pmap, sva);
- tlbprot = pmap_prot(pmap, prot);
+ simple_lock(&pvh->pvh_lock);
- for(; sva < eva; sva += PAGE_SIZE) {
- if((pv = pmap_find_va(space, sva))) {
- /*
- * Determine if mapping is changing.
- * If not, nothing to do.
- */
- if ((pv->pv_tlbprot & TLB_AR_MASK) == tlbprot)
- continue;
+ for (pve = pvh->pvh_list; pve; ) {
+ simple_lock(&pve->pv_pmap->pm_obj.vmobjlock);
- pv->pv_tlbprot &= ~TLB_AR_MASK;
- pv->pv_tlbprot |= tlbprot;
+ pde = pmap_pde_get(pve->pv_pmap->pm_pdir, pve->pv_va);
+ pte = pmap_pte_get(pde, pve->pv_va);
+ pmap_pte_set(pde, pve->pv_va, 0);
- /*
- * Purge the current TLB entry (if any) to force
- * a fault and reload with the new protection.
- */
- ficache(space, sva, NBPG);
- pitlb(space, sva);
- fdcache(space, sva, NBPG);
- pdtlb(space, sva);
- pmap_clear_va(space, sva);
- }
+ if (pte & PTE_PROT(TLB_WIRED))
+ pve->pv_pmap->pm_stats.wired_count--;
+ pve->pv_pmap->pm_stats.resident_count--;
+
+ simple_unlock(&pve->pmap->pm_obj.vmobjlock);
+
+ pvh->pvh_attrs |= pmap_pvh_attrs(pte);
+ ppve = pve;
+ pve = pve->pv_next;
+ pmap_pv_free(ppve);
}
+ simple_unlock(&pvh->pvh_lock);
+
+ DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_page_remove: leaving\n"));
+
}
-/*
- * Routine: pmap_unwire
- * Function: Change the wiring attribute for a map/virtual-address
- * pair.
- * In/out conditions:
- * The mapping must already exist in the pmap.
- *
- * Change the wiring for a given virtual page. This routine currently is
- * only used to unwire pages and hence the mapping entry will exist.
- */
void
pmap_unwire(pmap, va)
- pmap_t pmap;
+ struct pmap *pmap;
vaddr_t va;
{
- struct pv_entry *pv;
- int s;
+ pt_entry_t *pde, pte = 0;
- va = hppa_trunc_page(va);
- DPRINTF(PDB_FOLLOW, ("pmap_unwire(%p, %x)\n", pmap, va));
+ DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_unwire(%p, 0x%x)\n", pmap, va));
- if (!pmap)
- return;
+ simple_lock(&pmap->pm_obj.vmobjlock);
+ if ((pde = pmap_pde_get(pmap->pm_pdir, va))) {
+ pte = pmap_pte_get(pde, va);
+
+ if (pte & PTE_PROT(TLB_WIRED)) {
+ pte &= ~PTE_PROT(TLB_WIRED);
+ pmap->pm_stats.wired_count--;
+ pmap_pte_set(pde, va, pte);
+ }
+ }
+ simple_unlock(&pmap->pm_obj.vmobjlock);
+
+ DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_unwire: leaving\n"));
- simple_lock(&pmap->pmap_lock);
+#ifdef DIAGNOSTIC
+ if (!pte)
+ panic("pmap_unwire: invalid va 0x%x", va);
+#endif
+}
+
+boolean_t
+pmap_changebit(struct vm_page *pg, u_int set, u_int clear)
+{
+ struct pv_head *pvh;
+ struct pv_entry *pve;
+ pt_entry_t *pde, pte, res;
+ int bank, off;
- s = splimp();
- if ((pv = pmap_find_va(pmap_sid(pmap, va), va)) == NULL)
- panic("pmap_unwire: can't find mapping entry");
+ DPRINTF(PDB_FOLLOW|PDB_BITS,
+ ("pmap_changebit(%p, %x, %x)\n", pg, set, clear));
- if (pv->pv_tlbprot & TLB_WIRED) {
- pv->pv_tlbprot &= ~TLB_WIRED;
- pmap->pmap_stats.wired_count--;
+ bank = vm_physseg_find(atop(VM_PAGE_TO_PHYS(pg)), &off);
+ if (bank == -1) {
+ printf("pmap_testbits: unmanaged page?\n");
+ return(FALSE);
}
- splx(s);
- simple_unlock(&pmap->pmap_lock);
+
+ pvh = &vm_physmem[bank].pmseg.pvhead[off];
+ res = pvh->pvh_attrs = 0;
+
+ simple_lock(&pvh->pvh_lock);
+ for(pve = pvh->pvh_list; pve; pve = pve->pv_next) {
+ simple_lock(&pve->pv_pmap->pm_obj.vmobjlock);
+ if ((pde = pmap_pde_get(pve->pv_pmap->pm_pdir, pve->pv_va))) {
+ pte = pmap_pte_get(pde, pve->pv_va);
+ res |= pmap_pvh_attrs(pte);
+ pte &= ~clear;
+ pte |= set;
+
+ pitlb(pve->pv_pmap->pm_space, pve->pv_va);
+ /* XXX flush only if there was mod ? */
+ fdcache(pve->pv_pmap->pm_space, pve->pv_va, PAGE_SIZE);
+ pdtlb(pve->pv_pmap->pm_space, pve->pv_va);
+
+ pmap_pte_set(pde, pve->pv_va, pte);
+ }
+ simple_unlock(&pve->pv_pmap->pm_obj.vmobjlock);
+ }
+ pvh->pvh_attrs = res;
+ simple_unlock(&pvh->pvh_lock);
+
+ return ((res & clear) != 0);
+}
+
+boolean_t
+pmap_testbit(struct vm_page *pg, u_int bits)
+{
+ struct pv_head *pvh;
+ struct pv_entry *pve;
+ pt_entry_t pte;
+ int bank, off;
+
+ DPRINTF(PDB_FOLLOW|PDB_BITS, ("pmap_testbit(%p, %x)\n", pg, bits));
+
+ bank = vm_physseg_find(atop(VM_PAGE_TO_PHYS(pg)), &off);
+ if (bank == -1) {
+ printf("pmap_testbits: unmanaged page?\n");
+ return(FALSE);
+ }
+
+ simple_lock(&pvh->pvh_lock);
+ pvh = &vm_physmem[bank].pmseg.pvhead[off];
+ for(pve = pvh->pvh_list; !(pvh->pvh_attrs & bits) && pve;
+ pve = pve->pv_next) {
+ simple_lock(&pve->pv_pmap->pm_obj.vmobjlock);
+ pte = pmap_vp_find(pve->pv_pmap, pve->pv_va);
+ simple_unlock(&pve->pv_pmap->pm_obj.vmobjlock);
+ pvh->pvh_attrs |= pmap_pvh_attrs(pte);
+ }
+ simple_unlock(&pvh->pvh_lock);
+
+ return ((pvh->pvh_attrs & bits) != 0);
}
-/*
- * pmap_extract(pmap, va, pap)
- * fills in the physical address corrsponding to the
- * virtual address specified by pmap and va into the
- * storage pointed to by pap and returns TRUE if the
- * virtual address is mapped. returns FALSE in not mapped.
- */
boolean_t
pmap_extract(pmap, va, pap)
- pmap_t pmap;
+ struct pmap *pmap;
vaddr_t va;
paddr_t *pap;
{
- struct pv_entry *pv;
- int s;
+ pt_entry_t pte;
+
+ DPRINTF(PDB_FOLLOW|PDB_EXTRACT, ("pmap_extract(%p, %x)\n", pmap, va));
- DPRINTF(PDB_FOLLOW, ("pmap_extract(%p, %x)\n", pmap, va));
+ simple_lock(&pmap->pm_obj.vmobjlock);
+ pte = pmap_vp_find(pmap, va);
+ simple_unlock(&pmap->pm_obj.vmobjlock);
- s = splimp();
- if (!(pv = pmap_find_va(pmap_sid(pmap, va), hppa_trunc_page(va))))
- return (FALSE);
- else {
- *pap = tlbptob(pv->pv_tlbpage) + (va & PGOFSET);
+ if (pte) {
+ if (pap)
+ *pap = (pte & ~PGOFSET) | (va & PGOFSET);
return (TRUE);
}
- splx(s);
+
+ return (FALSE);
}
-/*
- * pmap_zero_page(pa)
- *
- * Zeros the specified page.
- */
void
pmap_zero_page(pa)
- register paddr_t pa;
+ paddr_t pa;
{
extern int dcache_line_mask;
register paddr_t pe = pa + PAGE_SIZE;
@@ -1281,10 +1076,9 @@ pmap_zero_page(pa)
* instead, keep 'em pending (or verify by the book).
*/
s = splhigh();
- pmap_clear_pv(pa, NULL);
while (pa < pe) {
- __asm volatile(
+ __asm volatile( /* can use ,bc */
"stwas,ma %%r0,4(%0)\n\t"
"stwas,ma %%r0,4(%0)\n\t"
"stwas,ma %%r0,4(%0)\n\t"
@@ -1302,14 +1096,6 @@ pmap_zero_page(pa)
splx(s);
}
-/*
- * pmap_copy_page(src, dst)
- *
- * pmap_copy_page copies the src page to the destination page. If a mapping
- * can be found for the source, we use that virtual address. Otherwise, a
- * slower physical page copy must be done. The destination is always a
- * physical address sivnce there is usually no mapping for it.
- */
void
pmap_copy_page(spa, dpa)
paddr_t spa;
@@ -1322,11 +1108,10 @@ pmap_copy_page(spa, dpa)
DPRINTF(PDB_FOLLOW|PDB_PHYS, ("pmap_copy_page(%x, %x)\n", spa, dpa));
s = splhigh();
- pmap_clear_pv(spa, NULL);
- pmap_clear_pv(dpa, NULL);
+ /* XXX flush cache for the spa ??? */
while (spa < spe) {
- __asm volatile(
+ __asm volatile( /* can use ,bc */
"ldwas,ma 4(%0),%%r22\n\t"
"ldwas,ma 4(%0),%%r21\n\t"
"stwas,ma %%r22,4(%1)\n\t"
@@ -1351,239 +1136,105 @@ pmap_copy_page(spa, dpa)
splx(s);
}
-/*
- * pmap_clear_modify(pa)
- * clears the hardware modified ("dirty") bit for one
- * machine independant page starting at the given
- * physical address. phys must be aligned on a machine
- * independant page boundary.
- */
-boolean_t
-pmap_clear_modify(pg)
- struct vm_page *pg;
-{
- register struct pv_entry *pv;
- register paddr_t pa = VM_PAGE_TO_PHYS(pg);
- int s, ret;
-
- DPRINTF(PDB_FOLLOW, ("pmap_clear_modify(%x)\n", pa));
-
- s = splimp();
- for (pv = pmap_find_pv(pa); pv; pv = pv->pv_next)
- if (pv->pv_tlbprot & TLB_DIRTY) {
- pitlb(pv->pv_space, pv->pv_va);
- pdtlb(pv->pv_space, pv->pv_va);
- pv->pv_tlbprot &= ~(TLB_DIRTY);
- pmap_clear_va(pv->pv_space, pv->pv_va);
- ret = TRUE;
- }
- splx(s);
-
- return (ret);
-}
-
-/*
- * pmap_is_modified(pa)
- * returns TRUE if the given physical page has been modified
- * since the last call to pmap_clear_modify().
- */
-boolean_t
-pmap_is_modified(pg)
- struct vm_page *pg;
-{
- register struct pv_entry *pv;
- register paddr_t pa = VM_PAGE_TO_PHYS(pg);
- int s, f = 0;
-
- DPRINTF(PDB_FOLLOW, ("pmap_is_modified(%x)\n", pa));
-
- s = splhigh();
- for (pv = pmap_find_pv(pa); pv && pv->pv_pmap && !f; pv = pv->pv_next)
- f |= pv->pv_tlbprot & TLB_DIRTY;
- splx(s);
-
- return f? TRUE : FALSE;
-}
-
-/*
- * pmap_clear_reference(pa)
- * clears the hardware referenced bit in the given machine
- * independant physical page.
- *
- * Currently, we treat a TLB miss as a reference; i.e. to clear
- * the reference bit we flush all mappings for pa from the TLBs.
- */
-boolean_t
-pmap_clear_reference(pg)
- struct vm_page *pg;
+void
+pmap_kenter_pa(va, pa, prot)
+ vaddr_t va;
+ paddr_t pa;
+ vm_prot_t prot;
{
- register struct pv_entry *pv;
- register paddr_t pa = VM_PAGE_TO_PHYS(pg);
- int s, ret;
-
- DPRINTF(PDB_FOLLOW, ("pmap_clear_reference(%x)\n", pa));
-
- s = splimp();
- for (pv = pmap_find_pv(pa); pv; pv = pv->pv_next)
- if (pv->pv_tlbprot & TLB_REF) {
- pitlb(pv->pv_space, pv->pv_va);
- pdtlb(pv->pv_space, pv->pv_va);
- pv->pv_tlbprot &= ~(TLB_REF);
- pmap_clear_va(pv->pv_space, pv->pv_va);
- ret = TRUE;
- }
- splx(s);
+ pt_entry_t *pde, pte;
- return (ret);
-}
-
-/*
- * pmap_is_referenced(pa)
- * returns TRUE if the given physical page has been referenced
- * since the last call to pmap_clear_reference().
- */
-boolean_t
-pmap_is_referenced(pg)
- struct vm_page *pg;
-{
- register struct pv_entry *pv;
- register paddr_t pa = VM_PAGE_TO_PHYS(pg);
- int s, f;
+ DPRINTF(PDB_FOLLOW|PDB_ENTER,
+ ("pmap_kenter_pa(%x, %x, %x)\n", va, pa, prot));
- DPRINTF(PDB_FOLLOW, ("pmap_is_referenced(%x)\n", pa));
+ if (!(pde = pmap_pde_get(pmap_kernel()->pm_pdir, va)) &&
+ !(pde = pmap_pde_alloc(pmap_kernel(), va, NULL)))
+ panic("pmap_kenter_pa: cannot allocate pde");
+#ifdef DIAGNOSTIC
+ if ((pte = pmap_pte_get(pde, va)))
+ panic("pmap_kenter_pa: 0x%x is already mapped %p:0x%x",
+ va, pde, pte);
+#endif
- s = splhigh();
- for (pv = pmap_find_pv(pa); pv && pv->pv_pmap && !f; pv = pv->pv_next)
- f |= pv->pv_tlbprot & TLB_REF;
- splx(s);
+ pte = pa | PTE_PROT(TLB_UNCACHABLE|TLB_WIRED|TLB_DIRTY|pmap_prot(pmap_kernel(), prot));
+ pmap_pte_set(pde, va, pte);
- return f? TRUE : FALSE;
+ DPRINTF(PDB_FOLLOW|PDB_ENTER, ("pmap_kenter_pa: leaving\n"));
}
-#ifdef notused
void
-pmap_changebit(va, set, reset)
+pmap_kremove(va, size)
vaddr_t va;
- u_int set, reset;
+ vsize_t size;
{
- register struct pv_entry *pv;
- int s;
-
- DPRINTF(PDB_FOLLOW, ("pmap_changebit(%x, %x, %x)\n", va, set, reset));
+ pt_entry_t *pde, pte;
+ vaddr_t eva = va + size, pdemask;
- s = splimp();
- if (!(pv = pmap_find_va(HPPA_SID_KERNEL, va))) {
- splx(s);
- return;
- }
+ DPRINTF(PDB_FOLLOW|PDB_REMOVE,
+ ("pmap_kremove(%x, %x)\n", va, size));
- pv->pv_tlbprot |= set;
- pv->pv_tlbprot &= ~reset;
- splx(s);
+ for (pdemask = va + 1; va < eva; va += PAGE_SIZE) {
+ if (pdemask != (va & PDE_MASK)) {
+ pdemask = va & PDE_MASK;
+ if (!(pde = pmap_pde_get(pmap_kernel()->pm_pdir, va))) {
+ va += ~PDE_MASK + 1 - PAGE_SIZE;
+ continue;
+ }
+ }
+ if (!(pte = pmap_pte_get(pde, va))) {
+#ifdef DEBUG
+ printf("pmap_kremove: unmapping unmapped 0x%x\n", va);
+#endif
+ continue;
+ }
- ficache(HPPA_SID_KERNEL, va, NBPG);
- pitlb(HPPA_SID_KERNEL, va);
+ if (pte & PTE_PROT(TLB_EXECUTE))
+ ficache(HPPA_SID_KERNEL, va, NBPG);
+ pitlb(HPPA_SID_KERNEL, va);
+ fdcache(HPPA_SID_KERNEL, va, NBPG);
+ pdtlb(HPPA_SID_KERNEL, va);
- fdcache(HPPA_SID_KERNEL, va, NBPG);
- pdtlb(HPPA_SID_KERNEL, va);
+ pmap_pte_set(pde, va, 0);
+ }
- pmap_clear_va(HPPA_SID_KERNEL, va);
+ DPRINTF(PDB_FOLLOW|PDB_REMOVE, ("pmap_kremove: leaving\n"));
}
-#endif
-void
-pmap_kenter_pa(va, pa, prot)
- vaddr_t va;
- paddr_t pa;
- vm_prot_t prot;
+void *
+pmap_pv_page_alloc(struct pool *pp, int flags)
{
- register struct pv_entry *pv;
+ vaddr_t va;
- DPRINTF(PDB_FOLLOW|PDB_ENTER,
- ("pmap_kenter_pa(%x, %x, %x)\n", va, pa, prot));
+ DPRINTF(PDB_FOLLOW|PDB_POOL,
+ ("pmap_pv_page_alloc(%p, %x)\n", pp, flags));
- va = hppa_trunc_page(va);
- pv = pmap_find_va(HPPA_SID_KERNEL, va);
- if (pv && (pa & HPPA_IOSPACE) == HPPA_IOSPACE)
- /* if already mapped i/o space, nothing to do */
- ;
- else {
- if (pv)
- panic("pmap_kenter_pa: mapped already %x", va);
- else
- pmap_kernel()->pmap_stats.resident_count++;
-
- pv = pmap_alloc_pv();
- pv->pv_va = va;
- pv->pv_pmap = pmap_kernel();
- pv->pv_space = HPPA_SID_KERNEL;
- pv->pv_tlbpage = tlbbtop(pa);
- pv->pv_tlbprot = TLB_WIRED | TLB_DIRTY | TLB_REF |
- HPPA_PID_KERNEL | pmap_prot(pmap_kernel(), prot) |
- ((pa & HPPA_IOSPACE) == HPPA_IOSPACE? TLB_UNCACHEABLE : 0);
- pmap_enter_va(pv);
+ if ((va = pmap_steal_memory(PAGE_SIZE, NULL, NULL)))
+ return (void *)va;
+
+ /*
+ TODO
+ if (list not empty) {
+ get from the list;
+ return (va);
}
+ */
- DPRINTF(PDB_ENTER, ("pmap_kenter_pa: leaving\n"));
-}
+ DPRINTF(PDB_FOLLOW|PDB_POOL,
+ ("pmap_pv_page_alloc: uvm_km_alloc_poolpage1\n"));
-void
-pmap_kremove(va, size)
- vaddr_t va;
- vsize_t size;
-{
- register struct pv_entry *pv;
-
- for (va = hppa_trunc_page(va); size > 0;
- size -= PAGE_SIZE, va += PAGE_SIZE) {
- pv = pmap_find_va(HPPA_SID_KERNEL, va);
- if (pv) {
- ficache(pv->pv_space, pv->pv_va, NBPG);
- pitlb(pv->pv_space, pv->pv_va);
- fdcache(pv->pv_space, pv->pv_va, NBPG);
- pdtlb(pv->pv_space, pv->pv_va);
- pmap_remove_va(pv);
- } else
- DPRINTF(PDB_REMOVE,
- ("pmap_kremove: no pv for 0x%x\n", va));
- }
+ return ((void *)uvm_km_alloc_poolpage1(kernel_map, uvm.kernel_object,
+ (flags & PR_WAITOK) ? TRUE : FALSE));
}
-#if defined(PMAPDEBUG) && defined(DDB)
-#include <ddb/db_output.h>
-/*
- * prints whole va->pa (aka HPT or HVT)
- */
void
-pmap_hptdump(sp)
- int sp;
+pmap_pv_page_free(struct pool *pp, void *v)
{
- register struct hpt_entry *hpt, *ehpt;
- register struct pv_entry *pv;
- register int hpthf;
-
- mfctl(CR_HPTMASK, ehpt);
- mfctl(CR_VTOP, hpt);
- ehpt = (struct hpt_entry *)((int)hpt + (int)ehpt + 1);
- db_printf("HPT dump %p-%p:\n", hpt, ehpt);
- for (hpthf = 0; hpt < ehpt; hpt++, hpthf = 0)
- for (pv = hpt->hpt_entry; pv; pv = pv->pv_hash)
- if (sp < 0 || sp == pv->pv_space) {
- if (!hpthf) {
- db_printf(
- "hpt@%p: %x{%sv=%x:%x},%b,%x\n",
- hpt, *(u_int *)hpt,
- (hpt->hpt_valid?"ok,":""),
- hpt->hpt_space, hpt->hpt_vpn << 9,
- hpt->hpt_tlbprot, TLB_BITS,
- tlbptob(hpt->hpt_tlbpage));
-
- hpthf++;
- }
- db_printf(" pv={%p,%x:%x,%b,%x}->%p\n",
- pv->pv_pmap, pv->pv_space, pv->pv_va,
- pv->pv_tlbprot, TLB_BITS,
- tlbptob(pv->pv_tlbpage), pv->pv_hash);
- }
+ vaddr_t va = (vaddr_t)v;
+
+ DPRINTF(PDB_FOLLOW|PDB_POOL, ("pmap_pv_page_free(%p, %p)\n", pp, v));
+
+ if (va < virtual_avail) {
+ /* TODO save on list somehow */
+ } else
+ uvm_km_free_poolpage1(kernel_map, va);
}
-#endif
diff --git a/sys/arch/hppa/hppa/trap.c b/sys/arch/hppa/hppa/trap.c
index e74257bedb6..a4d4322fd66 100644
--- a/sys/arch/hppa/hppa/trap.c
+++ b/sys/arch/hppa/hppa/trap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.39 2002/03/14 01:26:32 millert Exp $ */
+/* $OpenBSD: trap.c,v 1.40 2002/03/15 21:44:18 mickey Exp $ */
/*
* Copyright (c) 1998-2001 Michael Shalayeff
@@ -311,10 +311,10 @@ trap(type, frame)
else
map = &vm->vm_map;
- if (map->pmap->pmap_space != space) {
+ if (map->pmap->pm_space != space) {
#ifdef TRAPDEBUG
printf("trap: space missmatch %d != %d\n",
- space, map->pmap->pmap_space);
+ space, map->pmap->pm_space);
#endif
/* actually dump the user, crap the kernel */
goto dead_end;
@@ -371,7 +371,7 @@ trap(type, frame)
pcbp->pcb_onfault = 0;
break;
}
-#if 1
+#if 0
if (kdb_trap (type, va, frame))
return;
#else
@@ -434,7 +434,7 @@ return;
}
/* FALLTHROUGH to unimplemented */
default:
-#if 1
+#if 0
if (kdb_trap (type, va, frame))
return;
#endif
diff --git a/sys/arch/hppa/hppa/vm_machdep.c b/sys/arch/hppa/hppa/vm_machdep.c
index 90293feb08e..d0eb3c2be74 100644
--- a/sys/arch/hppa/hppa/vm_machdep.c
+++ b/sys/arch/hppa/hppa/vm_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm_machdep.c,v 1.33 2002/02/21 06:12:30 mickey Exp $ */
+/* $OpenBSD: vm_machdep.c,v 1.34 2002/03/15 21:44:18 mickey Exp $ */
/*
* Copyright (c) 1999-2002 Michael Shalayeff
@@ -198,7 +198,7 @@ cpu_fork(p1, p2, stack, stacksize, func, arg)
pcbp = &p2->p_addr->u_pcb;
bcopy(&p1->p_addr->u_pcb, pcbp, sizeof(*pcbp));
/* space is cached for the copy{in,out}'s pleasure */
- pcbp->pcb_space = p2->p_vmspace->vm_map.pmap->pmap_space;
+ pcbp->pcb_space = p2->p_vmspace->vm_map.pmap->pm_space;
pcbp->pcb_uva = (vaddr_t)p2->p_addr;
sp = (register_t)p2->p_addr + NBPG;
@@ -214,9 +214,8 @@ cpu_fork(p1, p2, stack, stacksize, func, arg)
tf->tf_sr0 = tf->tf_sr1 = tf->tf_sr2 = tf->tf_sr3 =
tf->tf_sr4 = tf->tf_sr5 = tf->tf_sr6 =
- p2->p_vmspace->vm_map.pmap->pmap_space;
tf->tf_iisq_head = tf->tf_iisq_tail =
- p2->p_vmspace->vm_map.pmap->pmap_space;
+ p2->p_vmspace->vm_map.pmap->pm_space;
tf->tf_pidr1 = tf->tf_pidr2 = pmap_sid2pid(tf->tf_sr0);
/*
diff --git a/sys/arch/hppa/include/cpu.h b/sys/arch/hppa/include/cpu.h
index 3dae3c6d2aa..46b0f66abd5 100644
--- a/sys/arch/hppa/include/cpu.h
+++ b/sys/arch/hppa/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.28 2002/03/14 01:26:32 millert Exp $ */
+/* $OpenBSD: cpu.h,v 1.29 2002/03/15 21:44:18 mickey Exp $ */
/*
* Copyright (c) 2000-2001 Michael Shalayeff
@@ -62,7 +62,7 @@
/*
* CPU types and features
*/
-#define HPPA_FTRS_BTLBS 0x00000001
+#define HPPA_FTRS_TLBU 0x00000001
#define HPPA_FTRS_BTLBU 0x00000002
#define HPPA_FTRS_HVT 0x00000004
#define HPPA_FTRS_W32B 0x00000008
diff --git a/sys/arch/hppa/include/cpufunc.h b/sys/arch/hppa/include/cpufunc.h
index b967a53614d..6b85c9e3aef 100644
--- a/sys/arch/hppa/include/cpufunc.h
+++ b/sys/arch/hppa/include/cpufunc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpufunc.h,v 1.18 2002/03/14 01:26:32 millert Exp $ */
+/* $OpenBSD: cpufunc.h,v 1.19 2002/03/15 21:44:18 mickey Exp $ */
/*
* Copyright (c) 1998,2000 Michael Shalayeff
@@ -218,13 +218,14 @@ ledctl(int on, int off, int toggle)
#endif
#ifdef _KERNEL
+extern int (*cpu_hpt_init)(vaddr_t hpt, vsize_t hptsize);
+
void ficache(pa_space_t sp, vaddr_t va, vsize_t size);
void fdcache(pa_space_t sp, vaddr_t va, vsize_t size);
void pdcache(pa_space_t sp, vaddr_t va, vsize_t size);
void fcacheall(void);
void ptlball(void);
-int btlb_insert(pa_space_t space, vaddr_t va, paddr_t pa,
- vsize_t *lenp, u_int prot);
+int btlb_insert(pa_space_t space, vaddr_t va, paddr_t pa, vsize_t *lenp, u_int prot);
hppa_hpa_t cpu_gethpa(int n);
#endif
diff --git a/sys/arch/hppa/include/db_machdep.h b/sys/arch/hppa/include/db_machdep.h
index d4003aa932a..4951a23fb47 100644
--- a/sys/arch/hppa/include/db_machdep.h
+++ b/sys/arch/hppa/include/db_machdep.h
@@ -1,7 +1,7 @@
-/* $OpenBSD: db_machdep.h,v 1.7 2002/03/14 01:26:32 millert Exp $ */
+/* $OpenBSD: db_machdep.h,v 1.8 2002/03/15 21:44:18 mickey Exp $ */
/*
- * Copyright (c) 1998 Michael Shalayeff
+ * Copyright (c) 1998-2002 Michael Shalayeff
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,7 @@
#include <uvm/uvm_extern.h>
+#define DB_AOUT_SYMBOLS
#define DB_ELF_SYMBOLS
#define DB_ELFSIZE 32
@@ -53,8 +54,8 @@ extern db_regs_t ddb_regs;
#define BKPT_SIZE sizeof(int)
#define BKPT_SET(inst) BKPT_INST
-#define IS_BREAKPOINT_TRAP(type, code) 1
-#define IS_WATCHPOINT_TRAP(type, code) 0
+#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_IBREAK)
+#define IS_WATCHPOINT_TRAP(type, code) ((type) == T_DBREAK)
#define FIXUP_PC_AFTER_BREAK(regs) ((regs)->tf_iioq_head -= sizeof(int))
@@ -90,8 +91,25 @@ static __inline int inst_trap_return(u_int ins) {
return (ins & 0xfc001fc0) == 0x00000ca0;
}
-#define db_clear_single_step(r) ((r)->tf_flags |= 0)
-#define db_set_single_step(r) ((r)->tf_flags |= 0)
+#if 0
+#define db_clear_single_step(r) ((r)->tf_flags &= ~(PSW_Z))
+#define db_set_single_step(r) ((r)->tf_flags |= (PSW_Z))
+#else
+#define SOFTWARE_SSTEP 1
+#define SOFTWARE_SSTEP_EMUL 1
+
+static __inline db_addr_t
+next_instr_address(db_addr_t addr, int b) {
+ return (addr + 4);
+}
+
+#define branch_taken(ins,pc,f,regs) branch_taken1(ins, pc, regs)
+static __inline db_addr_t
+branch_taken1(int ins, db_addr_t pc, db_regs_t *regs) {
+ return (pc);
+}
+
+#endif
int db_valid_breakpoint(db_addr_t);
int kdb_trap(int, int, db_regs_t *);
diff --git a/sys/arch/hppa/include/pmap.h b/sys/arch/hppa/include/pmap.h
index 872c71e20d0..43c16c4a067 100644
--- a/sys/arch/hppa/include/pmap.h
+++ b/sys/arch/hppa/include/pmap.h
@@ -1,7 +1,7 @@
-/* $OpenBSD: pmap.h,v 1.18 2002/03/14 01:26:32 millert Exp $ */
+/* $OpenBSD: pmap.h,v 1.19 2002/03/15 21:44:18 mickey Exp $ */
/*
- * Copyright (c) 1998,1999 Michael Shalayeff
+ * Copyright (c) 2002 Michael Shalayeff
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -14,142 +14,84 @@
* 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 Michael Shalayeff.
+ * This product includes software developed by Michael Shalayeff.
* 4. The name of the author may not 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 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 1996 1995 by Open Software Foundation, Inc.
- * All Rights Reserved
- *
- * Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appears in all copies and
- * that both the copyright notice and this permission notice appear in
- * supporting documentation.
- *
- * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
- * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-/*
- * Copyright (c) 1990,1993,1994 The University of Utah and
- * the Computer Systems Laboratory at the University of Utah (CSL).
- * All rights reserved.
- *
- * Permission to use, copy, modify and distribute this software is hereby
- * granted provided that (1) source code retains these copyright, permission,
- * and disclaimer notices, and (2) redistributions including binaries
- * reproduce the notices in supporting documentation, and (3) all advertising
- * materials mentioning features or use of this software display the following
- * acknowledgement: ``This product includes software developed by the
- * Computer Systems Laboratory at the University of Utah.''
- *
- * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
- * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
- * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * CSL requests users of this software to return to csl-dist@cs.utah.edu any
- * improvements that they make and grant CSL redistribution rights.
- *
- * Utah $Hdr: pmap.h 1.24 94/12/14$
- * Author: Mike Hibler, Bob Wheeler, University of Utah CSL, 9/90
- */
-
-/*
- * Pmap header for hppa.
+ * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES 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 MIND, 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.
*/
-#ifndef _MACHINE_PMAP_H_
-#define _MACHINE_PMAP_H_
+#ifndef _MACHINE_PMAP_H_
+#define _MACHINE_PMAP_H_
#include <machine/pte.h>
+#include <uvm/uvm_pglist.h>
+#include <uvm/uvm_object.h>
-typedef
struct pmap {
- TAILQ_ENTRY(pmap) pmap_list; /* pmap free list */
- struct simplelock pmap_lock; /* lock on map */
- int pmap_refcnt; /* reference count */
- pa_space_t pmap_space; /* space for this pmap */
- struct pmap_statistics pmap_stats; /* statistics */
-} *pmap_t;
-extern pmap_t kernel_pmap; /* The kernel's map */
-
-/*
- * If HPT is defined, we cache the last miss for each bucket using a
- * structure defined for the 7100 hardware TLB walker. On non-7100s, this
- * acts as a software cache that cuts down on the number of times we have
- * to search the hash chain. (thereby reducing the number of instructions
- * and cache misses incurred during the TLB miss).
- *
- * The pv_entry pointer is the address of the associated hash bucket
- * list for fast tlbmiss search.
- */
-struct hpt_entry {
- u_int hpt_valid:1, /* Valid bit */
- hpt_vpn:15, /* Virtual Page Number */
- hpt_space:16; /* Space ID */
- u_int hpt_tlbprot; /* prot/access rights (for TLB load) */
- u_int hpt_tlbpage; /* physical page (<<5 for TLB load) */
- void *hpt_entry; /* Pointer to associated hash list */
+ struct uvm_object pm_obj; /* object (lck by object lock) */
+#define pm_lock pm_obj.vmobjlock
+ struct vm_page *pm_ptphint;
+ struct vm_page *pm_pdir_pg; /* vm_page for pdir */
+ paddr_t pm_pdir; /* PA of PD (read-only after create) */
+ pa_space_t pm_space; /* space id (read-only after create) */
+ u_int pm_pid; /* prot id (read-only after create) */
+
+ struct pmap_statistics pm_stats;
};
-#ifdef _KERNEL
-extern struct hpt_entry *hpt_table;
-#endif /* _KERNEL */
+typedef struct pmap *pmap_t;
-/*
- * keep it at 32 bytes for the cache overall satisfaction
- * also, align commonly used pairs on double-word boundary
- */
-struct pv_entry {
- struct pv_entry *pv_next; /* list of mappings of a given PA */
- pmap_t pv_pmap; /* back link to pmap */
- u_int pv_va; /* virtual page number */
- u_int pv_space; /* copy of space id from pmap */
- u_int pv_tlbpage; /* physical page (for TLB load) */
- u_int pv_tlbprot; /* TLB format protection */
- struct pv_entry *pv_hash; /* VTOP hash bucket list */
- u_int pv_pad; /* pad to 32 bytes */
-};
+#define HPPA_MAX_PID 0xfffa
+#define HPPA_SID_MAX 0x7fff
+#define HPPA_SID_KERNEL 0
+#define HPPA_PID_KERNEL 2
-#define NPVPPG (NBPG/32-1)
-struct pv_page {
- TAILQ_ENTRY(pv_page) pvp_list; /* Chain of pages */
- u_int pvp_nfree;
- struct pv_entry *pvp_freelist;
- u_int pvp_flag; /* is it direct mapped (unused) */
- u_int pvp_pad[3]; /* align to 32 */
- struct pv_entry pvp_pv[NPVPPG];
+#define KERNEL_ACCESS_ID 1
+#define KERNEL_TEXT_PROT (TLB_AR_KRX | (KERNEL_ACCESS_ID << 1))
+#define KERNEL_DATA_PROT (TLB_AR_KRW | (KERNEL_ACCESS_ID << 1))
+
+struct pv_entry;
+
+struct pv_head {
+ struct simplelock pvh_lock; /* locks every pv on this list */
+ struct pv_entry *pvh_list; /* head of list (locked by pvh_lock) */
+ pt_entry_t pvh_attrs; /* to preserve ref/mod */
};
-#define HPPA_SID_MAX 0x7fff
-#define HPPA_SID_KERNEL 0
-#define HPPA_PID_KERNEL 2
+struct pv_entry { /* locked by its list's pvh_lock */
+ struct pv_entry *pv_next;
+ struct pmap *pv_pmap; /* the pmap */
+ vaddr_t pv_va; /* the virtual address */
+ struct vm_page *pv_ptp; /* the vm_page of the PTP */
+};
-#define KERNEL_ACCESS_ID 1
+/* also match the hardware tlb walker definition */
+struct vp_entry {
+ u_int vp_tag;
+ u_int vp_tlbprot;
+ u_int vp_tlbpage;
+ u_int vp_ptr;
+};
-#define KERNEL_TEXT_PROT (TLB_AR_KRX | (KERNEL_ACCESS_ID << 1))
-#define KERNEL_DATA_PROT (TLB_AR_KRW | (KERNEL_ACCESS_ID << 1))
+#ifdef _KERNEL
-#ifdef _KERNEL
extern void gateway_page(void);
+extern struct pmap kernel_pmap_store;
+
+#if defined(HP7100LC_CPU) || defined(HP7300LC_CPU)
+extern int pmap_hptsize;
+extern struct pdc_hwtlb pdc_hwtlb;
+#endif
#define PMAP_STEAL_MEMORY /* we have some memory to steal */
@@ -165,36 +107,56 @@ extern void gateway_page(void);
*(h) = pmap_prefer_hint; \
} while(0)
-#define pmap_kernel_va(VA) \
- (((VA) >= VM_MIN_KERNEL_ADDRESS) && ((VA) <= VM_MAX_KERNEL_ADDRESS))
-
#define pmap_sid2pid(s) (((s) + 1) << 1)
-#define pmap_kernel() (kernel_pmap)
-#define pmap_resident_count(pmap) ((pmap)->pmap_stats.resident_count)
-#define pmap_reference(pmap) \
-do { if (pmap) { \
- simple_lock(&pmap->pmap_lock); \
- pmap->pmap_refcnt++; \
- simple_unlock(&pmap->pmap_lock); \
-} } while (0)
-#define pmap_collect(pmap)
-#define pmap_release(pmap)
+#define pmap_kernel() (&kernel_pmap_store)
+#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count)
+#define pmap_update(pm) (void)(pm)
+#define pmap_activate(pm) (void)(pm)
+#define pmap_deactivate(pm) (void)(pm)
#define pmap_copy(dpmap,spmap,da,len,sa)
-#define pmap_update(pm)
-#define pmap_activate(p)
-#define pmap_deactivate(p)
-#define pmap_phys_address(x) ((x) << PGSHIFT)
-#define pmap_phys_to_frame(x) ((x) >> PGSHIFT)
+#define pmap_clear_modify(pg) pmap_changebit(pg, 0, PTE_PROT(TLB_DIRTY))
+#define pmap_clear_reference(pg) pmap_changebit(pg, PTE_PROT(TLB_REFTRAP), 0)
+#define pmap_is_modified(pg) pmap_testbit(pg, PTE_PROT(TLB_DIRTY))
+#define pmap_is_referenced(pg) pmap_testbit(pg, PTE_PROT(TLB_REFTRAP))
+#define pmap_phys_address(ppn) ((ppn) << PAGE_SHIFT)
+
+void pmap_bootstrap(vaddr_t);
+boolean_t pmap_changebit(struct vm_page *, u_int, u_int);
+boolean_t pmap_testbit(struct vm_page *, u_int);
+void pmap_write_protect(struct pmap *, vaddr_t, vaddr_t, vm_prot_t);
+void pmap_remove(struct pmap *pmap, vaddr_t sva, vaddr_t eva);
+void pmap_page_remove(struct vm_page *pg);
static __inline int
pmap_prot(struct pmap *pmap, int prot)
{
- extern u_int kern_prot[], user_prot[];
- return (pmap == kernel_pmap? kern_prot: user_prot)[prot];
+ extern u_int hppa_prot[];
+ return (hppa_prot[prot] | (pmap == pmap_kernel()? 0 : TLB_USER));
}
-void pmap_bootstrap(vaddr_t *, vaddr_t *);
-#endif /* _KERNEL */
+static __inline void
+pmap_page_protect(struct vm_page *pg, vm_prot_t prot)
+{
+ if ((prot & VM_PROT_WRITE) == 0) {
+ if (prot & (VM_PROT_READ|VM_PROT_EXECUTE))
+ (void) pmap_changebit(pg, PTE_PROT(TLB_READ),
+ PTE_PROT(TLB_WRITE));
+ else
+ pmap_page_remove(pg);
+ }
+}
+static __inline void
+pmap_protect(struct pmap *pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot)
+{
+ if ((prot & VM_PROT_WRITE) == 0) {
+ if (prot & (VM_PROT_READ|VM_PROT_EXECUTE))
+ pmap_write_protect(pmap, sva, eva, prot);
+ else
+ pmap_remove(pmap, sva, eva);
+ }
+}
+
+#endif /* _KERNEL */
#endif /* _MACHINE_PMAP_H_ */
diff --git a/sys/arch/hppa/include/pte.h b/sys/arch/hppa/include/pte.h
index 9e550cf5f02..d6f5f7650e9 100644
--- a/sys/arch/hppa/include/pte.h
+++ b/sys/arch/hppa/include/pte.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pte.h,v 1.8 2001/01/12 23:37:49 mickey Exp $ */
+/* $OpenBSD: pte.h,v 1.9 2002/03/15 21:44:18 mickey Exp $ */
/*
* Copyright (c) 1990,1993,1994 The University of Utah and
@@ -27,42 +27,36 @@
#ifndef _MACHINE_PTE_H_
#define _MACHINE_PTE_H_
+typedef u_int32_t pt_entry_t;
+
+#define PTE_PROT_SHIFT 19
+#define PTE_PROT(tlb) ((tlb) >> PTE_PROT_SHIFT)
+#define TLB_PROT(pte) ((pte) << PTE_PROT_SHIFT)
+#define PDE_MASK (0xffc00000)
+#define PTE_MASK (0x003ff000)
+#define PTE_PAGE(pte) ((pte) & ~PGOFSET)
+
/* TLB access/protection values */
-#define TLB_REF 0x80000000 /* software only */
-#define TLB_ALIGNED 0x40000000 /* software only */
-#define TLB_TRAP 0x20000000
+#define TLB_WIRED 0x40000000 /* software only */
+#define TLB_REFTRAP 0x20000000
#define TLB_DIRTY 0x10000000
#define TLB_BREAK 0x08000000
#define TLB_AR_MASK 0x07f00000
+#define TLB_READ 0x00000000
+#define TLB_WRITE 0x01000000
+#define TLB_EXECUTE 0x02000000
+#define TLB_GATEWAY 0x04000000
+#define TLB_USER 0x00f00000
#define TLB_AR_NA 0x07300000
-#define TLB_AR_KR 0x00000000
-#define TLB_AR_KRW 0x01000000
-#define TLB_AR_KRX 0x02000000
-#define TLB_AR_KRWX 0x03000000
-#define TLB_AR_UR 0x00f00000
-#define TLB_AR_URW 0x01f00000
-#define TLB_AR_URX 0x02f00000
-#define TLB_AR_URWX 0x03f00000
-#define TLB_UNCACHEABLE 0x00080000
-#define TLB_ICACHE 0x00040000 /* software only */
-#define TLB_NOTUSED 0x00020000 /* software only */
-#define TLB_DCACHE 0x00010000 /* software only */
+#define TLB_AR_R TLB_READ
+#define TLB_AR_RW TLB_READ|TLB_WRITE
+#define TLB_AR_RX TLB_READ|TLB_EXECUTE
+#define TLB_AR_RWX TLB_READ|TLB_WRITE|TLB_EXECUTE
+#define TLB_UNCACHABLE 0x00080000
#define TLB_PID_MASK 0x0000fffe
-#define TLB_WIRED 0x00000001 /* software only */
#define TLB_BITS "\020\024U\031W\032X\033N\034B\035D\036T\037A\040R"
-#define TLB_REF_POS 0
-#define TLB_ALIGNED_POS 1
-#define TLB_TRAP_POS 2
-#define TLB_DIRTY_POS 3
-#define TLB_BREAK_POS 4
-#define TLB_ITLB_POS 12
-#define TLB_ICACHE_POS 13
-#define TLB_DTLB_POS 14
-#define TLB_DCACHE_POS 15
-#define TLB_WIRED_POS 31
-
/* protection for a gateway page */
#define TLB_GATE_PROT 0x04c00000
diff --git a/sys/arch/hppa/include/vmparam.h b/sys/arch/hppa/include/vmparam.h
index 22992486c53..3b6be168ea2 100644
--- a/sys/arch/hppa/include/vmparam.h
+++ b/sys/arch/hppa/include/vmparam.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmparam.h,v 1.21 2002/02/17 22:59:52 maja Exp $ */
+/* $OpenBSD: vmparam.h,v 1.22 2002/03/15 21:44:18 mickey Exp $ */
/*
* Copyright (c) 1988-1994, The University of Utah and
@@ -106,7 +106,7 @@
#ifndef _LOCORE
#define __HAVE_PMAP_PHYSSEG
struct pmap_physseg {
- struct pv_entry *pvent;
+ struct pv_head *pvhead;
};
#endif