Make copyout() and Co. work with PMAP_NEW on real i386 processors.
PMAP_NEW doesn't fault in page table pages automatically on access to PTmap[], so we have to check the PTD explicitely. If a PTP is needed, call uvm_fault(). pmap_enter() will DTRT. Move calculation of the index into PTmap[] inside the loop in copyoutstr() (non-PMAP_NEW case). Page boundary crosses are rare, so this should save some cycles in average.
This commit is contained in:
parent
796e91b2a7
commit
6de27a7083
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: locore.s,v 1.191 1998/05/08 10:05:47 mycroft Exp $ */
|
||||
/* $NetBSD: locore.s,v 1.192 1998/05/20 16:30:54 drochner Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993, 1994, 1995, 1997
|
||||
|
@ -1071,6 +1071,17 @@ ENTRY(copyout)
|
|||
* doesn't do it for us.
|
||||
*/
|
||||
|
||||
#if defined(PMAP_NEW)
|
||||
pushl %eax
|
||||
pushl %eax
|
||||
pushl %edi
|
||||
call _C_LABEL(i386_writecheck)
|
||||
addl $8,%esp # pop arguments
|
||||
testl %eax,%eax # if not ok, return EFAULT
|
||||
popl %eax
|
||||
jz 3f
|
||||
jmp _copy_fault
|
||||
#else
|
||||
/* Compute number of pages. */
|
||||
movl %edi,%ecx
|
||||
andl $PGOFSET,%ecx
|
||||
|
@ -1105,6 +1116,7 @@ ENTRY(copyout)
|
|||
popl %eax
|
||||
jz 4b
|
||||
jmp _copy_fault
|
||||
#endif /* PMAP_NEW */
|
||||
#endif /* I386_CPU */
|
||||
|
||||
3: /* bcopy(%esi, %edi, %eax); */
|
||||
|
@ -1205,10 +1217,6 @@ ENTRY(copyoutstr)
|
|||
movl $NBPG,%ecx
|
||||
subl %eax,%ecx # ecx = NBPG - (src % NBPG)
|
||||
|
||||
/* Compute PTE offset for start address. */
|
||||
movl %edi,%eax
|
||||
shrl $PGSHIFT,%eax # calculate pte address
|
||||
|
||||
1: /*
|
||||
* Once per page, check that we are still within the bounds of user
|
||||
* space, and check for a write fault.
|
||||
|
@ -1216,27 +1224,40 @@ ENTRY(copyoutstr)
|
|||
cmpl $VM_MAXUSER_ADDRESS,%edi
|
||||
jae _copystr_fault
|
||||
|
||||
#if defined(PMAP_NEW)
|
||||
pushl %edx
|
||||
pushl $1
|
||||
pushl %edi
|
||||
call _C_LABEL(i386_writecheck)
|
||||
addl $8,%esp
|
||||
popl %edx
|
||||
testl %eax,%eax
|
||||
jnz _copystr_fault
|
||||
#else
|
||||
/* Compute PTE offset. */
|
||||
movl %edi,%eax
|
||||
shrl $PGSHIFT,%eax # calculate pte address
|
||||
|
||||
testb $PG_RW,_PTmap(,%eax,4)
|
||||
jnz 2f
|
||||
|
||||
/* Simulate a trap. */
|
||||
pushl %eax
|
||||
pushl %edx
|
||||
pushl %edi
|
||||
call _trapwrite # trapwrite(addr)
|
||||
addl $4,%esp # clear argument from stack
|
||||
popl %edx
|
||||
testl %eax,%eax
|
||||
popl %eax
|
||||
jnz _copystr_fault
|
||||
2:
|
||||
#endif
|
||||
|
||||
2: /* Copy up to end of this page. */
|
||||
/* Copy up to end of this page. */
|
||||
subl %ecx,%edx # predecrement total count
|
||||
jnc 6f
|
||||
jnc 3f
|
||||
addl %edx,%ecx # ecx += (edx - ecx) = edx
|
||||
xorl %edx,%edx
|
||||
|
||||
6: pushl %eax # save PT index
|
||||
3: decl %ecx
|
||||
js 4f
|
||||
lodsb
|
||||
|
@ -1245,15 +1266,12 @@ ENTRY(copyoutstr)
|
|||
jnz 3b
|
||||
|
||||
/* Success -- 0 byte reached. */
|
||||
addl $4,%esp # discard PT index
|
||||
addl %ecx,%edx # add back residual for this page
|
||||
xorl %eax,%eax
|
||||
jmp copystr_return
|
||||
|
||||
4: /* Go to next page, if any. */
|
||||
popl %eax # restore PT index
|
||||
movl $NBPG,%ecx
|
||||
incl %eax
|
||||
testl %edx,%edx
|
||||
jnz 1b
|
||||
|
||||
|
@ -1503,6 +1521,17 @@ ENTRY(suword)
|
|||
jne 2f
|
||||
#endif /* I486_CPU || I586_CPU || I686_CPU */
|
||||
|
||||
#if defined(PMAP_NEW)
|
||||
pushl %edx
|
||||
pushl $4
|
||||
pushl %edx
|
||||
call _C_LABEL(i386_writecheck)
|
||||
addl $8,%esp
|
||||
popl %edx
|
||||
movl _curpcb,%ecx
|
||||
testl %eax,%eax
|
||||
jnz _fusufault
|
||||
#else
|
||||
movl %edx,%eax
|
||||
shrl $PGSHIFT,%eax # calculate pte address
|
||||
testb $PG_RW,_PTmap(,%eax,4)
|
||||
|
@ -1519,7 +1548,8 @@ ENTRY(suword)
|
|||
jnz _fusufault
|
||||
|
||||
1: /* XXX also need to check the following 3 bytes for validity! */
|
||||
#endif
|
||||
#endif /* PMAP_NEW */
|
||||
#endif /* I386_CPU */
|
||||
|
||||
2: movl 8(%esp),%eax
|
||||
movl %eax,(%edx)
|
||||
|
@ -1544,6 +1574,17 @@ ENTRY(susword)
|
|||
jne 2f
|
||||
#endif /* I486_CPU || I586_CPU || I686_CPU */
|
||||
|
||||
#if defined(PMAP_NEW)
|
||||
pushl %edx
|
||||
pushl $2
|
||||
pushl %edx
|
||||
call _C_LABEL(i386_writecheck)
|
||||
addl $8,%esp
|
||||
popl %edx
|
||||
movl _curpcb,%ecx
|
||||
testl %eax,%eax
|
||||
jnz _fusufault
|
||||
#else
|
||||
movl %edx,%eax
|
||||
shrl $PGSHIFT,%eax # calculate pte address
|
||||
testb $PG_RW,_PTmap(,%eax,4)
|
||||
|
@ -1560,7 +1601,8 @@ ENTRY(susword)
|
|||
jnz _fusufault
|
||||
|
||||
1: /* XXX also need to check the following byte for validity! */
|
||||
#endif
|
||||
#endif /* PMAP_NEW */
|
||||
#endif /* I386_CPU */
|
||||
|
||||
2: movl 8(%esp),%eax
|
||||
movw %ax,(%edx)
|
||||
|
@ -1586,6 +1628,19 @@ ENTRY(suswintr)
|
|||
jne 2f
|
||||
#endif /* I486_CPU || I586_CPU || I686_CPU */
|
||||
|
||||
#if defined(PMAP_NEW)
|
||||
movl %edx,%eax
|
||||
shrl $PDSHIFT,%eax # calculate pde address
|
||||
testb $PG_V,_PTD(,%eax,4)
|
||||
jz 3f
|
||||
movl %edx,%eax
|
||||
shrl $PGSHIFT,%eax # calculate pte address
|
||||
testb $PG_RW,_PTmap(,%eax,4)
|
||||
jnz 1f
|
||||
|
||||
3: /* Simulate a trap. */
|
||||
jmp _fusubail
|
||||
#else
|
||||
movl %edx,%eax
|
||||
shrl $PGSHIFT,%eax # calculate pte address
|
||||
testb $PG_RW,_PTmap(,%eax,4)
|
||||
|
@ -1593,6 +1648,7 @@ ENTRY(suswintr)
|
|||
|
||||
/* Simulate a trap. */
|
||||
jmp _fusubail
|
||||
#endif /* PMAP_NEW */
|
||||
|
||||
1: /* XXX also need to check the following byte for validity! */
|
||||
#endif
|
||||
|
@ -1620,6 +1676,17 @@ ENTRY(subyte)
|
|||
jne 2f
|
||||
#endif /* I486_CPU || I586_CPU || I686_CPU */
|
||||
|
||||
#if defined(PMAP_NEW)
|
||||
pushl %edx
|
||||
pushl $1
|
||||
pushl %edx
|
||||
call _C_LABEL(i386_writecheck)
|
||||
addl $8,%esp
|
||||
popl %edx
|
||||
movl _curpcb,%ecx
|
||||
testl %eax,%eax
|
||||
jnz _fusufault
|
||||
#else
|
||||
movl %edx,%eax
|
||||
shrl $PGSHIFT,%eax # calculate pte address
|
||||
testb $PG_RW,_PTmap(,%eax,4)
|
||||
|
@ -1636,7 +1703,8 @@ ENTRY(subyte)
|
|||
jnz _fusufault
|
||||
|
||||
1:
|
||||
#endif
|
||||
#endif /* PMAP_NEW */
|
||||
#endif /* I386_CPU */
|
||||
|
||||
2: movb 8(%esp),%al
|
||||
movb %al,(%edx)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: trap.c,v 1.112 1998/03/05 04:20:45 scottb Exp $ */
|
||||
/* $NetBSD: trap.c,v 1.113 1998/05/20 16:30:54 drochner Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995 Charles M. Hannum. All rights reserved.
|
||||
|
@ -47,6 +47,7 @@
|
|||
#include "opt_vm86.h"
|
||||
#include "opt_uvm.h"
|
||||
#include "opt_pmap_new.h"
|
||||
#include "opt_cputype.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -97,7 +98,14 @@ extern struct emul emul_freebsd;
|
|||
|
||||
static __inline void userret __P((struct proc *, int, u_quad_t));
|
||||
void trap __P((struct trapframe));
|
||||
#if defined(I386_CPU)
|
||||
static int i386_faultrw __P((struct proc *, struct vmspace *, vm_offset_t));
|
||||
#if defined(PMAP_NEW)
|
||||
int i386_writecheck __P((unsigned, unsigned));
|
||||
#else
|
||||
int trapwrite __P((unsigned));
|
||||
#endif
|
||||
#endif
|
||||
void syscall __P((struct trapframe));
|
||||
|
||||
/*
|
||||
|
@ -540,25 +548,17 @@ out:
|
|||
userret(p, frame.tf_eip, sticks);
|
||||
}
|
||||
|
||||
#if defined(I386_CPU)
|
||||
/*
|
||||
* Compensate for 386 brain damage (missing URKR)
|
||||
*/
|
||||
int
|
||||
trapwrite(addr)
|
||||
unsigned addr;
|
||||
{
|
||||
vm_offset_t va;
|
||||
unsigned nss;
|
||||
static __inline int
|
||||
i386_faultrw(p, vm, va)
|
||||
struct proc *p;
|
||||
struct vmspace *vm;
|
||||
|
||||
va = trunc_page((vm_offset_t)addr);
|
||||
if (va >= VM_MAXUSER_ADDRESS)
|
||||
return 1;
|
||||
|
||||
nss = 0;
|
||||
p = curproc;
|
||||
vm = p->p_vmspace;
|
||||
vm_offset_t va;
|
||||
{
|
||||
unsigned nss = 0;
|
||||
if ((caddr_t)va >= vm->vm_maxsaddr) {
|
||||
nss = clrnd(btoc(USRSTACK-(unsigned)va));
|
||||
if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur))
|
||||
|
@ -581,6 +581,60 @@ trapwrite(addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(PMAP_NEW)
|
||||
int
|
||||
i386_writecheck(addr, len)
|
||||
unsigned addr, len;
|
||||
{
|
||||
vm_offset_t va, eva;
|
||||
pt_entry_t *pde, *pte;
|
||||
struct proc *p = curproc;
|
||||
struct vmspace *vm = p->p_vmspace;
|
||||
|
||||
va = i386_trunc_page((vm_offset_t)addr);
|
||||
eva = i386_round_page(addr + len);
|
||||
|
||||
pde = vtopte(vtopte(va)); /* hmmm */
|
||||
|
||||
while (va < eva) {
|
||||
vm_offset_t endofpde = i386_round_pdr(va);
|
||||
if (endofpde > eva)
|
||||
endofpde = eva;
|
||||
|
||||
pte = vtopte(va);
|
||||
|
||||
if (!(*pde))
|
||||
goto fault;
|
||||
|
||||
while (va < endofpde) {
|
||||
if (!(*pte & PG_RW)) {
|
||||
fault:
|
||||
if (i386_faultrw(p, vm, va))
|
||||
return (1);
|
||||
}
|
||||
va += NBPG;
|
||||
pte++;
|
||||
}
|
||||
pde++;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#else
|
||||
int
|
||||
trapwrite(addr)
|
||||
unsigned addr;
|
||||
{
|
||||
vm_offset_t va;
|
||||
|
||||
va = trunc_page((vm_offset_t)addr);
|
||||
if (va >= VM_MAXUSER_ADDRESS)
|
||||
return 1;
|
||||
|
||||
return (i386_faultrw(curproc, curproc->p_vmspace, va));
|
||||
}
|
||||
#endif /* PMAP_NEW */
|
||||
#endif /* I386_CPU */
|
||||
|
||||
/*
|
||||
* syscall(frame):
|
||||
* System call request from POSIX system call gate interface to kernel.
|
||||
|
|
Loading…
Reference in New Issue