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