Subject: Re: Removing I386_CPU from GENERIC and INSTALL
To: Frank van der Linden <fvdl@netbsd.org>
From: Jason Thorpe <thorpej@shagadelic.org>
List: port-i386
Date: 11/01/2006 21:49:02
--Apple-Mail-1--544250858
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
format=flowed;
delsp=yes
On Oct 31, 2006, at 10:21 AM, Frank van der Linden wrote:
> The fix is just to to do kcopy what i386_copyout already has. It
> isn't much work at all.
Something like this? (Compile-tested only...)
-- thorpej
--Apple-Mail-1--544250858
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
x-unix-mode=0644;
name=i386-kcopy-patch.txt
Content-Disposition: attachment;
filename=i386-kcopy-patch.txt
Index: i386/copy.S
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/copy.S,v
retrieving revision 1.2
diff -u -p -r1.2 copy.S
--- i386/copy.S 11 Dec 2005 12:17:41 -0000 1.2
+++ i386/copy.S 2 Nov 2006 05:47:40 -0000
@@ -120,8 +120,135 @@ ENTRY(fillw)
* int kcopy(const void *from, void *to, size_t len);
* Copy len bytes, abort on fault.
*/
+
+#if defined(I386_CPU)
+#define DEFAULT_KCOPY _C_LABEL(i386_kcopy)
+#elif defined(I486_CPU)
+#define DEFAULT_KCOPY _C_LABEL(i486_kcopy)
+#elif defined(I586_CPU)
+#define DEFAULT_KCOPY _C_LABEL(i486_kcopy)
+#elif defined(I686_CPU)
+#define DEFAULT_KCOPY _C_LABEL(i486_kcopy)
+#endif
+
+ .data
+
+ .globl _C_LABEL(kcopy_func)
+_C_LABEL(kcopy_func):
+ .long DEFAULT_KCOPY
+
+ .text
+
/* LINTSTUB: Func: int kcopy(const void *from, void *to, size_t len) */
ENTRY(kcopy)
+ jmp *_C_LABEL(kcopy_func)
+
+#if defined(I386_CPU)
+/* LINTSTUB: Func: int i386_kcopy(const void *from, void *to, size_t len) */
+ENTRY(i386_kcopy)
+ pushl %esi
+ pushl %edi
+ GET_CURPCB(%eax) # load curpcb into eax and set on-fault
+ pushl PCB_ONFAULT(%eax)
+ movl $_C_LABEL(i386_kcopy_writefault), PCB_ONFAULT(%eax)
+
+ movl 16(%esp),%esi
+ movl 20(%esp),%edi
+ movl 24(%esp),%eax
+
+ /*
+ * We have to compute each PTE for (write) permission, since
+ * the CPU doesn't do it for us.
+ */
+
+ /* Compute number of pages. */
+ movl %edi,%ecx
+ andl $PGOFSET,%ecx
+ addl %eax,%ecx
+ decl %ecx
+ shrl $PGSHIFT,%ecx
+
+ /* Compute PTE offset for start address. */
+ shrl $PGSHIFT,%edi
+
+1: /* Check PTE for each page. */
+ testb $PG_RW,PTE_BASE(,%edi,4)
+ jz _C_LABEL(i386_kcopy_writefault)
+
+ /* Note: this label referenced below in i386_kcopy_writefault: */
+4: incl %edi
+ decl %ecx
+ jns 1b
+
+ movl 20(%esp),%edi
+ movl 24(%esp),%ecx
+ jmp 3f
+
+3: GET_CURPCB(%edx)
+ movl $_C_LABEL(kcopy_fault),PCB_ONFAULT(%edx)
+
+ movl %edi,%eax
+ subl %esi,%eax
+ cmpl %ecx,%eax # overlapping?
+ jb 1f
+
+ cld # nope, copy forward
+ shrl $2,%ecx # copy by 32-bit words
+ rep
+ movsl
+ movl 24(%esp),%ecx
+ andl $3,%ecx # any bytes left?
+ rep
+ movsb
+
+ GET_CURPCB(%edx) # XXX save curpcb?
+ popl PCB_ONFAULT(%edx)
+ popl %edi
+ popl %esi
+ xorl %eax,%eax
+ ret
+
+ ALIGN_TEXT
+1: addl %ecx,%edi # copy backward
+ addl %ecx,%esi
+ std
+ andl $3,%ecx # any fractional bytes?
+ decl %edi
+ decl %esi
+ rep
+ movsb
+ movl 24(%esp),%ecx # copy remainder by 32-bit words
+ shrl $2,%ecx
+ subl $3,%esi
+ subl $3,%edi
+ rep
+ movsl
+ cld
+
+ GET_CURPCB(%edx)
+ popl PCB_ONFAULT(%edx)
+ popl %edi
+ popl %esi
+ xorl %eax,%eax
+ ret
+
+NENTRY(i386_kcopy_writefault)
+ /* Simulate a trap. */
+ pushl %ecx
+ movl %edi,%eax
+ shll $PGSHIFT,%eax
+ pushl %eax
+ call _C_LABEL(trapwrite_kcopy) # trapwrite_kcopy(addr)
+ addl $4,%esp # pop argument
+ popl %ecx
+ testl %eax,%eax # if not ok, return EFAULT
+ jz 4b
+ jmp _C_LABEL(copy_efault)
+#endif /* I386_CPU */
+
+#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
+/* LINTSTUB: Func: int i486_kcopy(const void *from, void *to, size_t len) */
+ENTRY(i486_kcopy)
pushl %esi
pushl %edi
GET_CURPCB(%eax) # load curpcb into eax and set on-fault
@@ -135,6 +262,7 @@ ENTRY(kcopy)
subl %esi,%eax
cmpl %ecx,%eax # overlapping?
jb 1f
+
cld # nope, copy forward
shrl $2,%ecx # copy by 32-bit words
rep
@@ -174,6 +302,7 @@ ENTRY(kcopy)
popl %esi
xorl %eax,%eax
ret
+#endif /* I486_CPU || I586_CPU || I686_CPU */
/*****************************************************************************/
@@ -193,11 +322,11 @@ ENTRY(kcopy)
#define DEFAULT_COPYOUT _C_LABEL(i486_copyout)
#define DEFAULT_COPYIN _C_LABEL(i386_copyin)
#elif defined(I586_CPU)
-#define DEFAULT_COPYOUT _C_LABEL(i486_copyout) /* XXX */
-#define DEFAULT_COPYIN _C_LABEL(i386_copyin) /* XXX */
+#define DEFAULT_COPYOUT _C_LABEL(i486_copyout)
+#define DEFAULT_COPYIN _C_LABEL(i386_copyin)
#elif defined(I686_CPU)
-#define DEFAULT_COPYOUT _C_LABEL(i486_copyout) /* XXX */
-#define DEFAULT_COPYIN _C_LABEL(i386_copyin) /* XXX */
+#define DEFAULT_COPYOUT _C_LABEL(i486_copyout)
+#define DEFAULT_COPYIN _C_LABEL(i386_copyin)
#endif
.data
Index: i386/identcpu.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/identcpu.c,v
retrieving revision 1.47
diff -u -p -r1.47 identcpu.c
--- i386/identcpu.c 12 Oct 2006 01:30:42 -0000 1.47
+++ i386/identcpu.c 2 Nov 2006 05:47:40 -0000
@@ -1543,16 +1543,19 @@ identifycpu(struct cpu_info *ci)
#if defined(I686_CPU)
case CPUCLASS_686:
copyout_func = i486_copyout;
+ kcopy_func = i486_kcopy;
break;
#endif
#if defined(I586_CPU)
case CPUCLASS_586:
copyout_func = i486_copyout;
+ kcopy_func = i486_kcopy;
break;
#endif
#if defined(I486_CPU)
case CPUCLASS_486:
copyout_func = i486_copyout;
+ kcopy_func = i486_kcopy;
break;
#endif
default:
Index: i386/trap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/trap.c,v
retrieving revision 1.214
diff -u -p -r1.214 trap.c
--- i386/trap.c 29 Sep 2006 14:48:15 -0000 1.214
+++ i386/trap.c 2 Nov 2006 05:47:41 -0000
@@ -132,6 +132,7 @@ void trap(struct trapframe *);
void trap_tss(struct i386tss *, int, int);
#if defined(I386_CPU)
int trapwrite(unsigned);
+int trapwrite_kcopy(unsigned);
#endif
#ifdef KVM86
@@ -261,6 +262,9 @@ trap(frame)
resume_iret[], resume_pop_ds[], resume_pop_es[],
resume_pop_fs[], resume_pop_gs[],
IDTVEC(osyscall)[];
+#if defined(I386_CPU)
+ extern char i386_kcopy_writefault[];
+#endif /* I386_CPU */
struct trapframe *vframe;
ksiginfo_t ksi;
int resume;
@@ -648,6 +652,9 @@ copyfault:
*/
if (onfault != kcopy_fault &&
+#if defined(I386_CPU)
+ onfault != i386_kcopy_writefault &&
+#endif /* I386_CPU */
curcpu()->ci_want_pmapload)
pmap_load();
return;
@@ -782,8 +789,7 @@ trapsignal:
* Compensate for 386 brain damage (missing URKR)
*/
int
-trapwrite(addr)
- unsigned addr;
+trapwrite(unsigned addr)
{
vaddr_t va;
struct proc *p;
@@ -804,6 +810,19 @@ trapwrite(addr)
return 0;
}
+
+int
+trapwrite_kcopy(unsigned addr)
+{
+ vaddr_t va;
+
+ va = trunc_page((vaddr_t)addr);
+
+ if (uvm_fault(kernel_map, va, VM_PROT_WRITE) != 0)
+ return 1;
+
+ return 0;
+}
#endif /* I386_CPU */
/*
Index: include/cpufunc.h
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/include/cpufunc.h,v
retrieving revision 1.33
diff -u -p -r1.33 cpufunc.h
--- include/cpufunc.h 26 Aug 2006 20:08:07 -0000 1.33
+++ include/cpufunc.h 2 Nov 2006 05:47:41 -0000
@@ -308,12 +308,16 @@ breakpoint(void)
extern int (*copyout_func)(const void *, void *, size_t);
extern int (*copyin_func)(const void *, void *, size_t);
+extern int (*kcopy_func)(const void *, void *, size_t);
int i386_copyout(const void *, void *, size_t);
int i486_copyout(const void *, void *, size_t);
int i386_copyin(const void *, void *, size_t);
+int i386_kcopy(const void *, void *, size_t);
+int i486_kcopy(const void *, void *, size_t);
+
#endif /* _KERNEL */
#endif /* !_I386_CPUFUNC_H_ */
--Apple-Mail-1--544250858--