Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rustc/LLVM generates faulty code for aarch64 with opt-level=0

I have two files which are assembled/compiled/linked into minimalistic kernel.

start.s:

    .set CPACR_EL1_FPEN, 0b11 << 20

    .set BOOT_STACK_SIZE, 8 * 1024

    .global __boot_stack
    .global __start
    .global __halt

    .bss
    .align 16
__boot_stack:
    .fill BOOT_STACK_SIZE

    .text
__start:
    /* disable FP and SIMD traps */
    mov x0, #CPACR_EL1_FPEN
    msr cpacr_el1, x0

    /* set stack */
    adr x0, __boot_stack
    add sp, x0, #BOOT_STACK_SIZE

    /* call the Rust entry point */
    bl __boot

__halt:
    /* halt CPU */
    wfi
    b __halt

boot.rs:

#[no_mangle]
pub extern fn __boot() {
    unsafe {
        let ptr = 0x9000000 as *mut u8;
        *ptr = '!' as u8;
   }
}

For opt-level=3 the resulting code outputs single '!' to a serial port (as was intended). For opt-level=0 I have a strange infinite loop (e.g. '!!!!!!!!!....'). Here is the disassembled dump of the problematic code:

0000000000000000 <__kernel_begin>:
   0:   d2a00600    mov x0, #0x300000               // #3145728
   4:   d5181040    msr cpacr_el1, x0
   8:   100007c0    adr x0, 100 <__boot_stack>
   c:   9140081f    add sp, x0, #0x2, lsl #12
  10:   94000003    bl  1c <__boot>

0000000000000014 <__halt>:
  14:   d503207f    wfi
  18:   17ffffff    b   14 <__halt>

000000000000001c <__boot>:
  1c:   a9bf7bfd    stp x29, x30, [sp,#-16]!
  20:   910003fd    mov x29, sp
  24:   94000003    bl  30 <aarch64::boot::__boot::__rust_abi>
  28:   a8c17bfd    ldp x29, x30, [sp],#16
  2c:   d65f03c0    ret

0000000000000030 <aarch64::boot::__boot::__rust_abi>:
  30:   d10043ff    sub sp, sp, #0x10
  34:   52a12008    mov w8, #0x9000000              // #150994944
  38:   2a0803e9    mov w9, w8
  3c:   f90007e9    str x9, [sp,#8]
  40:   52800428    mov w8, #0x21                   // #33
  44:   39000128    strb    w8, [x9]
  48:   910043ff    add sp, sp, #0x10
  4c:   d65f03c0    ret

The code is tested using qemu-system-aarch64. I don't see serious problems with it (except redundancy). Can you suggest a possible cause of such abnormal behaviour?

P.S. This is the optimised version which works properly:

0000000000000000 <__kernel_begin>:
   0:   d2a00600    mov x0, #0x300000               // #3145728
   4:   d5181040    msr cpacr_el1, x0
   8:   1007ffc0    adr x0, 10000 <__boot_stack>
   c:   9140081f    add sp, x0, #0x2, lsl #12
  10:   94000003    bl  1c <__boot>

0000000000000014 <__halt>:
  14:   d503207f    wfi
  18:   17ffffff    b   14 <__halt>

000000000000001c <__boot>:
  1c:   52a12008    mov w8, #0x9000000              // #150994944
  20:   52800429    mov w9, #0x21                   // #33
  24:   39000109    strb    w9, [x8]
  28:   d65f03c0    ret
like image 526
ababo Avatar asked Nov 09 '22 11:11

ababo


1 Answers

I've succeeded to run the non-optimised code without abnormalities. Thanks to Notlikethat for the idea. My stack was just mapped into readonly memory.

So I've just added the offset statement into my linker script (". = 1024M;") in order to make all the symbols to start from 1GiB (where RAM begins). After this modification the code started to work properly.

like image 116
ababo Avatar answered Dec 25 '22 14:12

ababo