[roll] Roll fuchsia [starnix/usercopy] Avoid reads from multiple pages

...in individual instructions.

The `hermetic_copy` function is written as a simple byte copy looping
over the source/destination buffers. However, the compiler assumes
that the full buffers (with the caller specified size) is valid for
copying and no faults would normally occur (as is the normal user-mode
copying expectations). `hermetic_copy`'s use-case is different - it may
trigger faults and we need to allow read/writes up until the faulting
address.

On x86_64, the compiler attempts to optimize for the regular user-mode
copying case where faults don't occur. By doing this, it ends up using
instructions like `MOVUPS` with `XMM` registers which ends up performing
_unaligned_ moving of 64 byte values.

If the user requested a read at 1 byte before the end of a valid mapping
but provided a large buffer to read into, the `hermetic_copy` method may
attempt to perform the read with instructions that read bytes across
multiple pages. When this happens, the whole read fails and no bytes are
written to the destination buffer. Howevever, the fault handler will
still process the fault and `Usercopy` will return the number of bytes
between the start address and the faulting address even though none of
those bytes were copied.

By adding the `volatile` qualifier to the buffers, we let the compiler
know that each byte access may have visible side-effects and that it
shouldn't attempt to perform any optimizations to effectively batch
the reads/writes of memory since a fault within the batch will fail
the whole operation which prevents the read/write of bytes before
the faulting address.

Below is the disassembly for `hemetic_copy` in release builds without
this change:
```
ghanan@ghanan-glinux:~/Projects/fuchsia/out/workbench_eng.qemu-x64$ objdump -b binary -m i386:x86-64 -D ./user.basic_x64/obj/src/starnix/lib/usercopy/hermetic_copy.bin

./user.basic_x64/obj/src/starnix/lib/usercopy/hermetic_copy.bin:     file format binary

Disassembly of section .data:

0000000000000000 <.data>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 85 d2                test   %rdx,%rdx
   7:   0f 84 ee 00 00 00       je     0xfb
   d:   31 c0                   xor    %eax,%eax
   f:   48 83 fa 08             cmp    $0x8,%rdx
  13:   0f 82 7d 00 00 00       jb     0x96
  19:   48 89 f9                mov    %rdi,%rcx
  1c:   48 29 f1                sub    %rsi,%rcx
  1f:   90                      nop
  20:   48 83 f9 20             cmp    $0x20,%rcx
  24:   72 70                   jb     0x96
  26:   48 83 fa 20             cmp    $0x20,%rdx
  2a:   73 04                   jae    0x30
  2c:   31 c0                   xor    %eax,%eax
  2e:   eb 3e                   jmp    0x6e
  30:   48 89 d0                mov    %rdx,%rax
  33:   48 83 e0 e0             and    $0xffffffffffffffe0,%rax
  37:   31 c9                   xor    %ecx,%ecx
  39:   0f 1f 80 00 00 00 00    nopl   0x0(%rax)
  40:   0f 10 04 0e             movups (%rsi,%rcx,1),%xmm0
  44:   0f 10 4c 0e 10          movups 0x10(%rsi,%rcx,1),%xmm1
  49:   0f 11 04 0f             movups %xmm0,(%rdi,%rcx,1)
  4d:   0f 11 4c 0f 10          movups %xmm1,0x10(%rdi,%rcx,1)
  52:   48 83 c1 20             add    $0x20,%rcx
  56:   48 39 c8                cmp    %rcx,%rax
  59:   75 e5                   jne    0x40
  5b:   0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
  60:   48 39 d0                cmp    %rdx,%rax
  63:   0f 84 92 00 00 00       je     0xfb
  69:   f6 c2 18                test   $0x18,%dl
  6c:   74 28                   je     0x96
  6e:   48 89 c1                mov    %rax,%rcx
  71:   48 89 d0                mov    %rdx,%rax
  74:   48 83 e0 f8             and    $0xfffffffffffffff8,%rax
  78:   0f 1f 84 00 00 00 00    nopl   0x0(%rax,%rax,1)
  7f:   00
  80:   4c 8b 04 0e             mov    (%rsi,%rcx,1),%r8
  84:   4c 89 04 0f             mov    %r8,(%rdi,%rcx,1)
  88:   48 83 c1 08             add    $0x8,%rcx
  8c:   48 39 c8                cmp    %rcx,%rax
  8f:   75 ef                   jne    0x80
  91:   48 39 d0                cmp    %rdx,%rax
  94:   74 65                   je     0xfb
  96:   48 89 c1                mov    %rax,%rcx
  99:   48 f7 d1                not    %rcx
  9c:   48 01 d1                add    %rdx,%rcx
  9f:   49 89 d0                mov    %rdx,%r8
  a2:   49 83 e0 03             and    $0x3,%r8
  a6:   74 1d                   je     0xc5
  a8:   0f 1f 84 00 00 00 00    nopl   0x0(%rax,%rax,1)
  af:   00
  b0:   44 0f b6 0c 06          movzbl (%rsi,%rax,1),%r9d
  b5:   44 88 0c 07             mov    %r9b,(%rdi,%rax,1)
  b9:   48 ff c0                inc    %rax
  bc:   0f 1f 40 00             nopl   0x0(%rax)
  c0:   49 ff c8                dec    %r8
  c3:   75 eb                   jne    0xb0
  c5:   48 83 f9 03             cmp    $0x3,%rcx
  c9:   72 30                   jb     0xfb
  cb:   0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
  d0:   0f b6 0c 06             movzbl (%rsi,%rax,1),%ecx
  d4:   88 0c 07                mov    %cl,(%rdi,%rax,1)
  d7:   0f b6 4c 06 01          movzbl 0x1(%rsi,%rax,1),%ecx
  dc:   88 4c 07 01             mov    %cl,0x1(%rdi,%rax,1)
  e0:   0f b6 4c 06 02          movzbl 0x2(%rsi,%rax,1),%ecx
  e5:   88 4c 07 02             mov    %cl,0x2(%rdi,%rax,1)
  e9:   0f b6 4c 06 03          movzbl 0x3(%rsi,%rax,1),%ecx
  ee:   88 4c 07 03             mov    %cl,0x3(%rdi,%rax,1)
  f2:   48 83 c0 04             add    $0x4,%rax
  f6:   48 39 c2                cmp    %rax,%rdx
  f9:   75 d5                   jne    0xd0
  fb:   31 c0                   xor    %eax,%eax
  fd:   5d                      pop    %rbp
  fe:   c3                      ret
```

Below is the disassembly for `hemetic_copy` in release builds with this
change:
```
ghanan@ghanan-glinux:~/Projects/fuchsia/out/workbench_eng.qemu-x64$ objdump -b binary -m i386:x86-64 -D ./user.basic_x64/obj/src/starnix/lib/usercopy/hermetic_copy.bin

./user.basic_x64/obj/src/starnix/lib/usercopy/hermetic_copy.bin:     file format binary

Disassembly of section .data:

0000000000000000 <.data>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 85 d2                test   %rdx,%rdx
   7:   74 66                   je     0x6f
   9:   89 d0                   mov    %edx,%eax
   b:   83 e0 03                and    $0x3,%eax
   e:   48 83 fa 04             cmp    $0x4,%rdx
  12:   73 04                   jae    0x18
  14:   31 c9                   xor    %ecx,%ecx
  16:   eb 3b                   jmp    0x53
  18:   48 83 e2 fc             and    $0xfffffffffffffffc,%rdx
  1c:   31 c9                   xor    %ecx,%ecx
  1e:   66 90                   xchg   %ax,%ax
  20:   44 0f b6 04 0e          movzbl (%rsi,%rcx,1),%r8d
  25:   44 88 04 0f             mov    %r8b,(%rdi,%rcx,1)
  29:   44 0f b6 44 0e 01       movzbl 0x1(%rsi,%rcx,1),%r8d
  2f:   44 88 44 0f 01          mov    %r8b,0x1(%rdi,%rcx,1)
  34:   44 0f b6 44 0e 02       movzbl 0x2(%rsi,%rcx,1),%r8d
  3a:   44 88 44 0f 02          mov    %r8b,0x2(%rdi,%rcx,1)
  3f:   44 0f b6 44 0e 03       movzbl 0x3(%rsi,%rcx,1),%r8d
  45:   44 88 44 0f 03          mov    %r8b,0x3(%rdi,%rcx,1)
  4a:   48 83 c1 04             add    $0x4,%rcx
  4e:   48 39 ca                cmp    %rcx,%rdx
  51:   75 cd                   jne    0x20
  53:   48 85 c0                test   %rax,%rax
  56:   74 17                   je     0x6f
  58:   48 01 cf                add    %rcx,%rdi
  5b:   48 01 ce                add    %rcx,%rsi
  5e:   31 c9                   xor    %ecx,%ecx
  60:   0f b6 14 0e             movzbl (%rsi,%rcx,1),%edx
  64:   88 14 0f                mov    %dl,(%rdi,%rcx,1)
  67:   48 ff c1                inc    %rcx
  6a:   48 39 c8                cmp    %rcx,%rax
  6d:   75 f1                   jne    0x60
  6f:   31 c0                   xor    %eax,%eax
  71:   5d                      pop    %rbp
  72:   c3                      ret
```

Original-Bug: b/276973344, b/309108366
Original-Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/941432
Original-Revision: 202074b0c3a0b67ad0f19631ceede2edbb370f52
GitOrigin-RevId: cf6203b1eba66d79f49d1e8c002229c00909cb65
Change-Id: I9fa2dd42dbb8091e3318c2f187530f2bd16cf22a
1 file changed
tree: f040b8efa446cdd7440d91b70df9c32d537f4360
  1. git-hooks/
  2. infra/
  3. third_party/
  4. cts
  5. firmware
  6. flower
  7. jiri.lock
  8. MILESTONE
  9. minimal
  10. prebuilts
  11. README.md
  12. stem
  13. test_durations
  14. toolchain
README.md

Integration

This repository contains Fuchsia's Global Integration manifest files.

Making changes

All changes should be made to the internal version of this repository. Our infrastructure automatically updates this version when the internal one changes.

Currently all changes must be made by a Google employee. Non-Google employees wishing to make a change can ask for assistance via the IRC channel #fuchsia on Freenode.

Obtaining the source

First install Jiri.

Next run:

$ jiri init
$ jiri import minimal https://fuchsia.googlesource.com/integration
$ jiri update

Third party

Third party projects should have their own subdirectory in ./third_party.