Issue 173014
Summary LLVM compiles `write_volatile` to instructions which do not affect `ESR_EL{1,2,3}`
Labels new issue
Assignees
Reporter workingjubilee
    To quote @qwandor (with light trimming of extraneous details) from rust-lang/rust#131894.

> Unfortunately, rustc sometimes compiles `core::ptr::write_volatile` on aarch64 to something like `str w9, [x0], #4`... this post-addressing mode is performing register writeback (in this case, incrementing `x0` by 4), and so [doesn't set the exception syndrome register](https://developer.arm.com/documentation/ddi0595/2020-12/AArch64-Registers/ESR-EL1--Exception-Syndrome-Register--EL1-?lang=en#fieldset_0-24_0_15-24_24). This prevents the hypervisor from emulating the MMIO access, as it has no way of decoding the instruction syndrome or finding the faulting address.

> In an unprotected VM (e.g. regular KVM), it is possible for the VMM to work around this by reading the guest VM's memory to find the relevant instruction, decoding the instruction manually, and finding the MMIO address that way. This has a performance overhead and adds extra complexity. In the case of a protected VM where the host doesn't have access to the guest VM's memory (e.g. protected KVM), this is not possible as the VMM is not able to read the guest VM's memory...

> The net result of this is that instructions which perform register writeback (e.g. post-increment addressing modes) are not suitable for MMIO in aarch64 VMs. This is arguably a flaw in the aarch64 architecture, but as that's not feasible to fix at this point it must be fixed in the compiler instead. rustc should therefore avoid generating such instructions for `volatile_read` and `volatile_write` calls.

We cannot avoid generating these instructions except via using inline assembly which would result in an absurd optimization barrier, beyond `volatile`'s requirements, due to inline assembly's optimization opacity. However, as `volatile` is widely understood as being used for MMIO, and developers wish to compose arbitrary architectural features with MMIO, this can only be fixed by code generation backends. Thus I beseech LLVM to fix this on behalf of those who have declined to file an issue upstream.

For reference, this problem does afflict clang as well.

```llvm
define dso_local void @foo_rust(ptr noalias noundef nonnull align 4 %xs.0, i64 noundef range(i64 0, 2305843009213693952) %xs.1) unnamed_addr #0 {
start:
 %_8.idx = shl nuw nsw i64 %xs.1, 2
  %_8 = getelementptr inbounds nuw i8, ptr %xs.0, i64 %_8.idx
  %_141 = icmp eq i64 %xs.1, 0
  br i1 %_141, label %bb2, label %bb3

bb3:
  %iter.sroa.0.02 = phi ptr [ %_20, %bb3 ], [ %xs.0, %start ]
  %_20 = getelementptr inbounds nuw i8, ptr %iter.sroa.0.02, i64 4
  store volatile i32 42, ptr %iter.sroa.0.02, align 4
  %_14 = icmp eq ptr %_20, %_8
  br i1 %_14, label %bb2, label %bb3

bb2:
  ret void
}

attributes #0 = { nofree norecurse noredzone nounwind memory(argmem: readwrite, inaccessiblemem: readwrite) uwtable "probe-stack"="inline-asm" "target-cpu"="generic" "target-features"="+v8a,+strict-align,+neon,+fp-armv8" }
```
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to