From dc8e2985370f05184d47f956d98fc2404dbb6316 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Wed, 31 Aug 2011 02:39:45 +0200 Subject: Fix copyout retry on lazy allocation on >= i486 * i386/i386/locore.S (copyout): Add a >=i486 variant of copyout which uses no loop, but simply retries rep mov. --- i386/i386/locore.S | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/i386/i386/locore.S b/i386/i386/locore.S index 58d5efd..221201c 100644 --- a/i386/i386/locore.S +++ b/i386/i386/locore.S @@ -1288,14 +1288,36 @@ Entry(copyoutmsg) movl $USER_DS,%eax /* use user data segment for accesses */ mov %ax,%es +#if !defined(MACH_HYP) && !PAE + cmpl $3,machine_slot+SUB_TYPE_CPU_TYPE + jbe copyout_retry /* Use slow version on i386 */ +#endif /* !defined(MACH_HYP) && !PAE */ + + movl %edx,%eax /* use count */ + /*cld*/ /* count up: always this way in GCC code */ + movl %eax,%ecx /* move by longwords first */ + shrl $2,%ecx + RECOVER(copyout_fail) + RETRY(copyout_retry_longs) +copyout_retry_longs: + rep + movsl + movl %eax,%ecx /* now move remaining bytes */ + andl $3,%ecx + RECOVER(copyout_fail) + RETRY(copyout_retry_bytes) +copyout_retry_bytes: + rep + movsb /* move */ + xorl %eax,%eax /* return 0 for success */ + jmp copyout_ret + +#if !defined(MACH_HYP) && !PAE /* * Check whether user address space is writable * before writing to it - i386 hardware is broken. */ copyout_retry: -#if !defined(MACH_HYP) && !PAE - cmpl $3,machine_slot+SUB_TYPE_CPU_TYPE - ja 1f /* Skip on i486 and above */ movl %cr3,%ecx /* point to page directory */ movl %edi,%eax /* get page directory bits */ shrl $(PDESHIFT),%eax /* from user address */ @@ -1330,11 +1352,9 @@ copyout_retry: andl $(-NBPG),%eax /* start of next page */ subl %edi,%eax /* get number of bytes to that point */ cmpl %edx,%eax /* bigger than count? */ - jle 2f /* if so, */ -1: -#endif /* !defined(MACH_HYP) && !PAE */ + jle 1f /* if so, */ movl %edx,%eax /* use count */ -2: +1: /*cld*/ /* count up: always this way in GCC code */ movl %eax,%ecx /* move by longwords first */ @@ -1352,6 +1372,7 @@ copyout_retry: subl %eax,%edx /* decrement count */ jg copyout_retry /* restart on next page if not done */ xorl %eax,%eax /* return 0 for success */ +#endif /* !defined(MACH_HYP) && !PAE */ copyout_ret: mov %ss,%di /* restore ES to kernel segment */ -- cgit v1.2.3