Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm32/arm32 The ARM has the same copy-on-write bug ...



details:   https://anonhg.NetBSD.org/src/rev/0fb1a34cca12
branches:  trunk
changeset: 467351:0fb1a34cca12
user:      mycroft <mycroft%NetBSD.org@localhost>
date:      Tue Mar 23 17:14:34 1999 +0000

description:
The ARM has the same copy-on-write bug as the i386 -- the write enable bit in
PTEs is ignored when in kernel mode.  Hack around this just like we do on the
i386, by adding a prepass to copyout() to check for write permission on the
destination pages.

diffstat:

 sys/arch/arm32/arm32/bcopyinout.S |  64 +++++++++++++++++++++++++++++++++++---
 sys/arch/arm32/arm32/fault.c      |  22 ++++++++++++-
 sys/arch/arm32/arm32/genassym.cf  |   3 +-
 3 files changed, 80 insertions(+), 9 deletions(-)

diffs (162 lines):

diff -r 0d1cb9c43457 -r 0fb1a34cca12 sys/arch/arm32/arm32/bcopyinout.S
--- a/sys/arch/arm32/arm32/bcopyinout.S Tue Mar 23 15:56:56 1999 +0000
+++ b/sys/arch/arm32/arm32/bcopyinout.S Tue Mar 23 17:14:34 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bcopyinout.S,v 1.15 1998/11/26 19:34:38 mycroft Exp $  */
+/*     $NetBSD: bcopyinout.S,v 1.16 1999/03/23 17:14:34 mycroft Exp $  */
 
 /*
  * Copyright (c) 1995-1998 Mark Brinicombe.
@@ -83,6 +83,11 @@
        cmp     r1, r3
        bcs     Lbadaddress
 
+       /* Quick exit if length is zero */      
+       teq     r2, #0
+       moveq   r0, #0
+       moveq   lr, pc
+
        /* Do the actual copy */
        b       do_copyinout
 
@@ -94,6 +99,9 @@
  * Copies bytes from user space to kernel space
  */
 
+Lpgbase:
+       .long   PROCESS_PAGE_TBLS_BASE
+       
 ENTRY(copyout)
        /* Validate user and kernel addresses */
        ldr     r3, Lvm_min_address
@@ -108,14 +116,58 @@
        cmp     r0, r3
        bcs     Lbadaddress
 
+       /* Quick exit if length is zero */      
+       teq     r2, #0
+       moveq   r0, #0
+       moveq   pc, lr
+
+       /* Check the page protection for copy-on-write */
+       stmfd   sp!, {r4-r7}
+       ldr     r4, Lcurpcb
+       ldr     r4, [r4]
+
+       ldr     r5, [r4, #PCB_ONFAULT]
+       add     r3, pc, #do_cowfault - . - 8
+       str     r3, [r4, #PCB_ONFAULT]
+
+       ldr     r3, Lpgbase
+       add     r6, r3, r1, lsr #(PGSHIFT-2)
+       bic     r6, r6, #3                      /* beginning PTE */
+
+       mov     r7, r1, lsl #(32-PGSHIFT)
+       add     r7, r2, r7, lsr #(32-PGSHIFT)
+       sub     r7, r7, #1
+       mov     r7, r7, lsr #(PGSHIFT)          /* number of pages -1 */
+
+do_ptecheck:
+       ldr     r3, [r6]                        /* grab PTE */
+       tst     r3, #1                          /* check writable bit */
+       beq     do_cowfault                     /* if clear, do COW fault */
+do_ptecheck_next:
+       add     r6, r6, #4
+       subs    r7, r7, #1
+       bpl     do_ptecheck
+       str     r5, [r4, #PCB_ONFAULT]
+       ldmfd   sp!, {r4-r7}
+
        /* Do the actual copy */
+       b       do_copyinout
+
+do_cowfault:
+       stmfd   sp!, {r0-r2, lr}
+       ldr     r3, Lpgbase
+       sub     r0, r6, r3
+       mov     r0, r0, lsl #(PGSHIFT-2)        /* calculate VA of page */
+       bl      _cowfault
+       mov     r3, r0
+       ldmfd   sp!, {r0-r2, lr}
+       teq     r3, #0                          /* check for error return */
+       beq     do_ptecheck_next
+       mov     r0, r3
+       str     r5, [r4, #PCB_ONFAULT]
+       ldmfd   sp!, {r4-r7}
 
 do_copyinout:
-       /* Quick exit if length is zero */      
-       teq     r2, #0x00000000
-       moveq   r0, #0x00000000
-       moveq   pc, lr
-
        stmfd   sp!, {r4, r5}
        ldr     r4, Lcurpcb
        ldr     r4, [r4]
diff -r 0d1cb9c43457 -r 0fb1a34cca12 sys/arch/arm32/arm32/fault.c
--- a/sys/arch/arm32/arm32/fault.c      Tue Mar 23 15:56:56 1999 +0000
+++ b/sys/arch/arm32/arm32/fault.c      Tue Mar 23 17:14:34 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fault.c,v 1.37 1999/03/18 04:56:04 chs Exp $   */
+/*     $NetBSD: fault.c,v 1.38 1999/03/23 17:14:35 mycroft Exp $       */
 
 /*
  * Copyright (c) 1994-1997 Mark Brinicombe.
@@ -79,6 +79,7 @@
 int pmap_modified_emulation __P((pmap_t, vm_offset_t));
 int pmap_handled_emulation __P((pmap_t, vm_offset_t));
 pt_entry_t *pmap_pte __P((pmap_t pmap, vm_offset_t va));
+int cowfault __P((vaddr_t));
 
 int fetchuserword __P((u_int address, u_int *location));
 extern char fusubailout[];
@@ -577,9 +578,9 @@
                }
 nogo:
                if (user == 0) {
-                       printf("Failed page fault in kernel\n");
                        if (pcb->pcb_onfault)
                                goto copyfault;
+                       printf("Failed page fault in kernel\n");
                        printf("[u]vm_fault(%p, %lx, %x, 0) -> %x\n",
                            map, va, ftype, rv);
                        goto we_re_toast;
@@ -849,4 +850,21 @@
        userret(p, frame->tf_pc, sticks);
 }
 
+int
+cowfault(va)
+       vaddr_t va;
+{
+       struct vmspace *vm;
+
+       if (va >= VM_MAXUSER_ADDRESS)
+               return (EFAULT);
+
+       vm = curproc->p_vmspace;
+       if (uvm_fault(&vm->vm_map, va, 0, VM_PROT_READ | VM_PROT_WRITE)
+           != KERN_SUCCESS)
+               return (EFAULT);
+
+       return (0);
+}
+
 /* End of fault.c */
diff -r 0d1cb9c43457 -r 0fb1a34cca12 sys/arch/arm32/arm32/genassym.cf
--- a/sys/arch/arm32/arm32/genassym.cf  Tue Mar 23 15:56:56 1999 +0000
+++ b/sys/arch/arm32/arm32/genassym.cf  Tue Mar 23 17:14:34 1999 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: genassym.cf,v 1.1 1998/08/31 06:52:18 mrg Exp $
+#      $NetBSD: genassym.cf,v 1.2 1999/03/23 17:14:35 mycroft Exp $
 
 # Copyright (c) 1982, 1990 The Regents of the University of California.
 # All rights reserved.
@@ -58,6 +58,7 @@
 define VM_MIN_ADDRESS          VM_MIN_ADDRESS
 define VM_MAXUSER_ADDRESS      VM_MAXUSER_ADDRESS
 define VM_MAXKERN_ADDRESS      VM_MAXKERN_ADDRESS
+define PROCESS_PAGE_TBLS_BASE  PROCESS_PAGE_TBLS_BASE
 
 define UPAGES                  UPAGES
 define PGSHIFT                 PGSHIFT



Home | Main Index | Thread Index | Old Index