Skip to content

Runtime assertion error in asm translation tests on arm-unknown-linux-gnueabihf #431

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

Open
kkysen opened this issue Jun 1, 2022 · 3 comments
Labels
bug Something isn't working

Comments

@kkysen
Copy link
Contributor

kkysen commented Jun 1, 2022

tests/asm.arm/ fails its tests (at runtime).

When running ./scripts/test_translator.py tests/ --only-directories asm.arm on #429 (which cross-compiles using cargo zigbuild and zig cc and runs under qemu), there is an assertion error:

     Running `target/arm-unknown-linux-gnueabihf/debug/asm-tests 'test_asm::test_buffer' --release`
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `[0]`,
 right: `[5]`', src/test_asm.rs:26:5

where this is the code in tests/asm.arm/src/test_asm.rs:

pub fn test_buffer() {
    let mut buffer = [0; BUFFER_SIZE];
    let mut rust_buffer = [0; BUFFER_SIZE];
    let expected_buffer = [5];

    unsafe {
        entry(BUFFER_SIZE as u32, buffer.as_mut_ptr());
        rust_entry(BUFFER_SIZE as u32, rust_buffer.as_mut_ptr());
    }
    assert_eq!(buffer, rust_buffer);
    assert_eq!(buffer, expected_buffer);
}

and where this is line 26:

    assert_eq!(buffer, expected_buffer);

That is, entry and rust_entry, and also __STREXB and rust___STREXB give equal results, implying the translation is correct, but then they are both different from the expected results, which is 5 instead of 0. I'm not sure where the 5 here comes from, and I don't know enough about strexb or inline asm to know if it's correct. Maybe the emulation is not correct? Or maybe the 5 is just wrong?

For reference, here are the inline asm functions:

uint32_t __STREXB(uint8_t value, volatile uint8_t *addr)
{
   uint32_t result;

   asm volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
   return(result);
}
#[no_mangle]
pub unsafe extern "C" fn rust___STREXB(
    mut value: uint8_t,
    mut addr: *mut uint8_t,
) -> uint32_t {
    let mut result: uint32_t = 0;
    asm!(
        "strexb {0}, {2}, [{1}]", out(reg) result, in (reg) & mut * addr, inlateout(reg)
        value as uint32_t => _, options(preserves_flags)
    );
    return result;
}

This could be an error caused by cross-compilation and emulation as opposed to the transpiler, but I don't know enough about inline asm and strexb to tell. I did see, however, that rust___STREXB gives the same results as the expected buffer, [5] in tests/asm.arm/src/test_asm.rs:18, while it is the C __STREXB that gives different results, [0].

@fw-immunant
Copy link
Contributor

I think I misunderstood the strexb instruction when writing this test case. It appears that this instruction is intended to be used as part of synchronization primitives, and can either produce (in its first register argument, which is an output) 0 (if the store to the memory address given in the third argument was performed) or 1 (if it was not). The write is performed if "the executing processor has an outstanding tagged physical address" or "the physical address is tagged as exclusive access for the executing processor"; these conditions are apparently achieved by previously executing the ldrex instruction with the same address.

We should fix the test, but ideally using this instruction in a way that does write to memory, since this test case was intended to verify memory accesses to inline asm operands.

@kkysen
Copy link
Contributor Author

kkysen commented Jun 6, 2022

Is there a reason we need to test strexb specifically? Are we testing memory accesses to inline asm operands in general, or just testing memory access to inline asm operands specifically for strexb? If it's the former, it seems like an overly complicated instruction to test, since it needs to previous execute the ldrex instruction on the same address.

@fw-immunant
Copy link
Contributor

We were testing the translation of assembly operands with the =Q constraint; strexb itself isn't critical.

@kkysen kkysen changed the title Runtime Assertion Error in Asm Translation Tests on arm-unknown-linux-gnueabihf Runtime Assertion Error in Asm Translation Tests on arm-unknown-linux-gnueabihf Jun 7, 2022
@kkysen kkysen changed the title Runtime Assertion Error in Asm Translation Tests on arm-unknown-linux-gnueabihf Runtime assertion error in asm translation tests on arm-unknown-linux-gnueabihf Jun 16, 2022
@kkysen kkysen added the bug Something isn't working label Jun 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants