[parisc-linux] CONFIG_DMB_TRAP diff
Grant Grundler
grundler@cup.hp.com
Wed, 22 Nov 2000 18:47:06 -0800 (PST)
Hello again (last one until Monday - I promise),
With Lamont's wisdom, I implemented support for Date Memory Break trap.
This enables the kernel programmer to capture the evil code which
stomps on other people's "private" data. Only works for stores
through virtual addresses. gsc_writeX() and DMA will still
bypass this mechanism.
pb, dhd, (or some equivalent deity), could you review/commit this code?
Or tell me it's ok to commit?
I've touched:
arch/parisc/config.in
arch/parisc/kernel/entry.S
arch/parisc/mm/kmap.c
include/asm-parisc/pgtable.h
thanks,
grant
Index: arch/parisc/config.in
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/config.in,v
retrieving revision 1.25
diff -u -p -r1.25 config.in
--- config.in 2000/10/20 18:28:26 1.25
+++ config.in 2000/11/23 02:18:23
@@ -16,8 +16,12 @@ endmenu
mainmenu_option next_comment
comment 'General options'
-# bool 'Symmetric multi-processing support' CONFIG_SMP
-define_bool CONFIG_SMP n
+bool 'Symmetric multi-processing support' CONFIG_SMP
+# define_bool CONFIG_SMP n
+
+# One needs to tweak dmb_trap_11 code in entry.S to match.
+# Not tested for 64-bit kernel.
+bool 'Debug support for Data Memory Break Trap' CONFIG_DMB_TRAP
bool 'Kernel Debugger support' CONFIG_KWDB
# define_bool CONFIG_KWDB n
Index: arch/parisc/kernel/entry.S
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/entry.S,v
retrieving revision 1.53
diff -u -p -r1.53 entry.S
--- entry.S 2000/11/22 16:51:33 1.53
+++ entry.S 2000/11/23 02:18:23
@@ -23,6 +23,7 @@
*/
#include <asm/offset.h>
+#include <linux/autoconf.h>
/* the following is the setup i think we should follow:
* whenever the CPU is interruptible, the following has to be true:
@@ -349,7 +350,39 @@
.endm
#endif
+#ifdef CONFIG_DMB_TRAP
/*
+ ** Data Memory Bit trap interruption handler (parisc 1.1)
+ **
+ ** This is a debugging aid. Use it when you think someone else
+ ** is stepping on your memory. It only catches *virtual*
+ ** accesses. gsc_writeX() functions disable virtual translation
+ ** (D-bit) and will happily scribble whatever physical address
+ ** is passed in.
+ **
+ ** Here's how to use it:
+ ** 1) Call iterate_pages() from your init routine like this:
+ ** iterate_pages( my_private_mem, private_mem_size,
+ ** set_data_memory_break, 0);
+ ** 2) substitute your functions for your_function1 (or 2) in
+ ** dmb_trap_11 code below.
+ **
+ ** Thanks to Lamont Jones for telling me how to do this.
+ ** - ggg 1/22/2000
+ */
+ .macro dmb_11 code
+
+ mfctl %isr,spc
+ b dmb_trap_11
+ mfctl %ior,va
+
+ .align 32
+ .endm
+#else
+#define dmb_11 def
+#endif
+
+ /*
* dirty bit trap interruption handler (parisc 2.0)
*/
@@ -448,7 +481,7 @@ fault_vector_11:
naitlb_11 16
nadtlb_11 17
def 18
- def 19
+ dmb_11 19
dbit_11 20
def 21
def 22
@@ -467,7 +500,6 @@ fault_vector_11:
.import handle_interruption,code
.import handle_real_interruption,code
.import do_irq_mask,code
- .import parisc_stopkernel,code
.import cpu_irq_region,data
/*
@@ -903,11 +935,15 @@ dtlb_miss_11:
dep pte,8,7,prot
extru,= pte,_PAGE_NO_CACHE_BIT,1,r0
- depi 1,12,1,prot
+ depi 1,12,1,prot /* U-bit */
extru,= pte,_PAGE_USER_BIT,1,r0
depi 7,11,3,prot /* Set for user space (1 rsvd for read) */
extru,= pte,_PAGE_GATEWAY_BIT,1,r0
depi 0,11,2,prot /* If Gateway, Set PL2 to 0 */
+#ifdef CONFIG_DMB_TRAP
+ extru,= pte,_PAGE_DMB_BIT,1,r0
+ depi 1,4,1,prot /* B-bit */
+#endif
/* Get rid of prot bits and convert to page addr for idtlba */
@@ -1300,6 +1336,30 @@ dbit_trap_11:
rfir
nop
+
+#ifdef CONFIG_DMB_TRAP
+ .import your_function1,code
+ .import your_function2,code
+
+dmb_trap_11:
+ mfctl pcsq,t0 /* get space */
+ comb,<>,n t0,%r0,dmb_rfi /* not kernel - bail */
+
+ mfctl pcoq,t0 /* get offset */
+ ldil L%dmb_ok_function1, t1
+ dep %r0, 31, 12, t0
+ comb,=,n t0,t1,dmb_rfi /* it's ours - bail */
+
+ ldil L%dmb_ok_function2, t1
+ comb,<>,n t0,t1,intr_save /* not ours - panic */
+
+dmb_rfi:
+ mfctl ipsw,t0 /* Set PSW X-bit - just continue */
+ depi 1,11,1,t0 /* Set X-bit */
+ mtctl t0, ipsw
+ rfir
+ nop
+#endif
dbit_trap_20:
mfctl %cr25,ptp /* Assume user space trap */
Index: arch/parisc/mm/kmap.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/mm/kmap.c,v
retrieving revision 1.3
diff -u -p -r1.3 kmap.c
--- kmap.c 2000/05/05 18:05:47 1.3
+++ kmap.c 2000/11/23 02:18:23
@@ -43,7 +43,16 @@ static void unmap_cached_pte(pte_t * pte
}
#endif
+#ifdef CONFIG_DMB_TRAP
/* These two routines should probably check a few things... */
+void set_data_memory_break(pte_t * pte, unsigned long arg)
+{
+ pte_val(*pte) |= _PAGE_DMB;
+}
+
+#endif
+
+/* These two routines should probably check a few things... */
static void set_uncached(pte_t * pte, unsigned long arg)
{
pte_val(*pte) |= _PAGE_NO_CACHE;
@@ -106,7 +115,10 @@ static inline void iterate_pmd(pgd_t * d
} while (address < end);
}
-static void iterate_pages(unsigned long address, unsigned long size,
+#ifndef CONFIG_DMB_TRAP
+static
+#endif
+void iterate_pages(unsigned long address, unsigned long size,
pte_iterator_t op, unsigned long arg)
{
pgd_t *dir;
Index: include/asm-parisc/pgtable.h
===================================================================
RCS file: /home/cvs/parisc/linux/include/asm-parisc/pgtable.h,v
retrieving revision 1.29
diff -u -p -r1.29 pgtable.h
--- pgtable.h 2000/11/10 21:44:44 1.29
+++ pgtable.h 2000/11/23 02:18:23
@@ -109,6 +109,10 @@ extern void *vmalloc_start;
#define _PAGE_USER 0x400 /* Software: User accessable page */
#define _PAGE_USER_BIT 21 /* Needs to agree with _PAGE_USER above */
/* 0x800 still available */
+#ifdef CONFIG_DMB_TRAP
+#define _PAGE_DMB 0x800 /* Data Memory Break Trap */
+#define _PAGE_DMB_BIT 20 /* Data Memory Break Trap */
+#endif
#ifdef __ASSEMBLY__
#define _PGB_(x) (1 << (63 - (x)))