Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

target/uefi: clarify documentation #58420

Merged
merged 1 commit into from
Feb 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/librustc_target/spec/uefi_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// UEFI uses COFF/PE32+ format for binaries. All binaries must be statically linked. No dynamic
// linker is supported. As native to COFF, binaries are position-dependent, but will be relocated
// by the loader if the pre-chosen memory location is already in use.
// UEFI forbids running code on anything but the boot-CPU. Not interrupts are allowed other than
// UEFI forbids running code on anything but the boot-CPU. No interrupts are allowed other than
// the timer-interrupt. Device-drivers are required to use polling-based models. Furthermore, all
// code runs in the same environment, no process separation is supported.

Expand All @@ -21,7 +21,10 @@ pub fn opts() -> TargetOptions {
"/NOLOGO".to_string(),

// UEFI is fully compatible to non-executable data pages. Tell the compiler that
// non-code sections can be marked as non-executable, including stack pages.
// non-code sections can be marked as non-executable, including stack pages. In fact,
// firmware might enforce this, so we better let the linker know about this, so it
// will fail if the compiler ever tries placing code on the stack (e.g., trampoline
// constructs and alike).
"/NXCOMPAT".to_string(),

// There is no runtime for UEFI targets, prevent them from being linked. UEFI targets
Expand Down
22 changes: 12 additions & 10 deletions src/librustc_target/spec/x86_64_unknown_uefi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,25 @@ pub fn target() -> TargetResult {
base.cpu = "x86-64".to_string();
base.max_atomic_width = Some(64);

// We disable MMX and SSE for now. UEFI does not prevent these from being used, but there have
// been reports to GRUB that some firmware does not initialize the FP exception handlers
// properly. Therefore, using FP coprocessors will end you up at random memory locations when
// you throw FP exceptions.
// To be safe, we disable them for now and force soft-float. This can be revisited when we
// have more test coverage. Disabling FP served GRUB well so far, so it should be good for us
// as well.
// We disable MMX and SSE for now, even though UEFI allows using them. Problem is, you have to
// enable these CPU features explicitly before their first use, otherwise their instructions
// will trigger an exception. Rust does not inject any code that enables AVX/MMX/SSE
// instruction sets, so this must be done by the firmware. However, existing firmware is known
// to leave these uninitialized, thus triggering exceptions if we make use of them. Which is
// why we avoid them and instead use soft-floats. This is also what GRUB and friends did so
// far.
// If you initialize FP units yourself, you can override these flags with custom linker
// arguments, thus giving you access to full MMX/SSE acceleration.
base.features = "-mmx,-sse,+soft-float".to_string();

// UEFI systems run without a host OS, hence we cannot assume any code locality. We must tell
// LLVM to expect code to reference any address in the address-space. The "large" code-model
// places no locality-restrictions, so it fits well here.
base.code_model = Some("large".to_string());

// UEFI mostly mirrors the calling-conventions used on windows. In case of x86-64 this means
// small structs will be returned as int. This shouldn't matter much, since the restrictions
// placed by the UEFI specifications forbid any ABI to return structures.
// UEFI mirrors the calling-conventions used on windows. In case of x86-64 this means small
// structs will be returned as int. This shouldn't matter much, since the restrictions placed
// by the UEFI specifications forbid any ABI to return structures.
base.abi_return_struct_as_int = true;

Ok(Target {
Expand Down