2015-06-10 30 views
5

Ho due file che sono assemblati/compilati/collegati in un kernel minimalista.Rustc/LLVM genera codice errato per aarch64 con opt-level = 0

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

Per opt-livello = 3 le uscite codice risultante singoli a una porta seriale (come era previsto). Per opt-level = 0 ho uno strano loop infinito (ad esempio '!!!!!!!!! ....'). Ecco la discarica disassemblato del codice problematico:

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 

Il codice è testato utilizzando qemu-system-aarch64. Non vedo gravi problemi con esso (eccetto ridondanza). Puoi suggerire una possibile causa di questo comportamento anormale?

P.S. Questa è la versione ottimizzata che funziona correttamente:

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 
+0

Sembra una segnalazione di bug, non una domanda. In tal caso, dovrebbe essere [archiviato sul repository Github] (https://github.com/rust-lang/rust/issues). – Shepmaster

+0

Non sono sicuro che questo sia un bug. Forse ho perso alcuni passaggi obbligatori di inizializzazione della CPU in start.s. – ababo

+0

Non vedo nulla di evidentemente sbagliato nel codice prodotto. Potresti pubblicare un disassemblaggio del codice con opt-level = 3? Inoltre, probabilmente dovresti fare una fase di bootstrap in C per impostare alcuni pagetables, poiché nella mia esperienza Rust genera accessi non allineati (che non ho potuto disabilitare) e gli accessi non allineati sono vietati prima di impostare gli impaginati. (nota: non so se qemu emula questo comportamento) – Vaelden

risposta

1

Sono riuscito a eseguire il codice non ottimizzato senza anomalie. Grazie a Notlikethat per l'idea. Il mio stack era appena mappato nella memoria di sola lettura.

Quindi ho appena aggiunto l'istruzione offset nel mio script linker (". = 1024M;") per far partire tutti i simboli da 1GiB (dove inizia la RAM). Dopo questa modifica il codice ha iniziato a funzionare correttamente.

+0

Ho appena aggiunto un'istruzione offset in script linker:.= 1024M; – ababo