Author: kp
Date: Mon Jul 29 14:59:14 2019
New Revision: 350416
URL: https://svnweb.freebsd.org/changeset/base/350416

Log:
  riscv: Fix copyin/copyout
  
  r343275 introduced a performance optimisation to the copyin/copyout
  routines by attempting to copy word-per-word rather than byte-per-byte
  where possible.
  
  This optimisation failed to account for cases where the buffer is longer
  than XLEN_BYTES, but due to misalignment does not not allow for any
  word-sized copies. E.g. a 9 byte buffer (with XLEN_BYTES == 8) which is
  misaligned by 2 bytes. The code nevertheless did a single full-word
  copy, which meant we copied too much data. This potentially clobbered
  other data.
  
  This is most easily demonstrated by a simple `sysctl -a`.
  
  Fix it by not assuming that we'll always have at least one full-word
  copy to do, but instead checking the remaining length first.
  
  Reviewed by:  markj@, mhorne@, br@ (previous version)
  MFC after:    1 week
  Sponsored by: Axiado
  Differential Revision:        https://reviews.freebsd.org/D21100

Modified:
  head/sys/riscv/riscv/copyinout.S

Modified: head/sys/riscv/riscv/copyinout.S
==============================================================================
--- head/sys/riscv/riscv/copyinout.S    Mon Jul 29 14:58:29 2019        
(r350415)
+++ head/sys/riscv/riscv/copyinout.S    Mon Jul 29 14:59:14 2019        
(r350416)
@@ -65,7 +65,7 @@ END(copyio_fault)
        ENTER_USER_ACCESS(a7)
 
        li      t2, XLEN_BYTES
-       blt     a2, t2, 3f              /* Byte-copy if len < XLEN_BYTES */
+       blt     a2, t2, 4f              /* Byte-copy if len < XLEN_BYTES */
 
        /*
         * Compare lower bits of src and dest.
@@ -73,7 +73,7 @@ END(copyio_fault)
         */
        andi    t0, a0, (XLEN_BYTES-1)  /* Low bits of src */
        andi    t1, a1, (XLEN_BYTES-1)  /* Low bits of dest */
-       bne     t0, t1, 3f              /* Misaligned. Go to byte copy */
+       bne     t0, t1, 4f              /* Misaligned. Go to byte copy */
        beqz    t0, 2f                  /* Already word-aligned, skip ahead */
 
        /* Byte copy until the first word-aligned address */
@@ -84,6 +84,7 @@ END(copyio_fault)
        addi    a2, a2, -1              /* len-- */
        andi    t0, a0, (XLEN_BYTES-1)
        bnez    t0, 1b
+       j       3f
 
        /* Copy words */
 2:     ld      a4, 0(a0)               /* Load word from src */
@@ -91,20 +92,20 @@ END(copyio_fault)
        sd      a4, 0(a1)               /* Store word in dest */
        addi    a1, a1, XLEN_BYTES
        addi    a2, a2, -XLEN_BYTES     /* len -= XLEN_BYTES */
-       bgeu    a2, t2, 2b              /* Again if len >= XLEN_BYTES */
+3:     bgeu    a2, t2, 2b              /* Again if len >= XLEN_BYTES */
 
        /* Check if we're finished */
-       beqz    a2, 4f
+       beqz    a2, 5f
 
        /* Copy any remaining bytes */
-3:     lb      a4, 0(a0)               /* Load byte from src */
+4:     lb      a4, 0(a0)               /* Load byte from src */
        addi    a0, a0, 1
        sb      a4, 0(a1)               /* Store byte in dest */
        addi    a1, a1, 1
        addi    a2, a2, -1              /* len-- */
-       bnez    a2, 3b
+       bnez    a2, 4b
 
-4:     EXIT_USER_ACCESS(a7)
+5:     EXIT_USER_ACCESS(a7)
        SET_FAULT_HANDLER(x0, a7)       /* Clear the handler */
        .endm
 
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to