[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
This repository contains Fuchsia's Global Integration manifest files.
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.
First install Jiri.
Next run:
$ jiri init $ jiri import minimal https://fuchsia.googlesource.com/integration $ jiri update
Third party projects should have their own subdirectory in ./third_party.