Rustc/LLVM 使用 opt-level=0 为 aarch64 生成错误代码 [英] Rustc/LLVM generates faulty code for aarch64 with opt-level=0

查看:24
本文介绍了Rustc/LLVM 使用 opt-level=0 为 aarch64 生成错误代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个文件被组装/编译/链接到简约内核中.

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;
   }
}

对于 opt-level=3,结果代码输出单个 '!'到串行端口(如预期的那样).对于 opt-level=0,我有一个奇怪的无限循环(例如'!!!!!!!!!....').这是有问题的代码的反汇编转储:

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

代码使用 qemu-system-aarch64 测试.我没有看到它有严重的问题(冗余除外).你能提出这种异常行为的可能原因吗?

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

推荐答案

我已经成功运行了未优化的代码,没有出现异常.感谢 Notlikethat 的想法.我的堆栈刚刚映射到只读内存中.

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.

所以我刚刚将偏移量语句添加到我的链接器脚本 (". = 1024M;") 中,以使所有符号从 1GiB(RAM 开始处)开始.在此修改后,代码开始正常工作.

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.

这篇关于Rustc/LLVM 使用 opt-level=0 为 aarch64 生成错误代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆