2

So I'm trying to use the RISC-V SBI debug console extension of OpenSBI on Qemu using inline Rust assembly, but it isn't working. I've come to learn that the issue may be because of memory placement, but I'd still like to know if my assembly is correct to narrow my troubleshooting down, even if you don't know the SBI specification, I'd appreciate knowing if my general inline assembly format is correct:

pub fn debug_console_write(text: &str) -> SBIResult {
    let mut sbi_result = SBIResult::new();
    unsafe {
        asm!(
            "li a7, 0x4442434E", // Specifies SBI extension
            "li a6, 0x00", //  Specifies function ID in extension
            "lw a0, ({})", // Provides number of bytes in string
            "lw a1, ({})", // Provides pointer to string
            "li a2, 0", // Provides the high end of the pointers address which should always be 0
            "ecall", // Short for "enviroment call", in this case it's a call to the sbi
            in(reg) &text.len(), // Provides number of bytes in string
            in(reg) &text.as_ptr(), // Provides pointer to string
            lateout("a0") sbi_result.error, // Puts error value from sbi call into result struct
            lateout("a1") sbi_result.value, // Puts value value from sbi call into result struct
            out("a7") _, // Clobbering a7
            out("a6") _, // Clobbering a6
            out("a2") _, // Clobbering a2
            clobber_abi("system") // Clobbering everything else that the system specifcation specifies
        );
    }

    return sbi_result
}

Note that the error and value fields are both isize.

4
  • 1
    Debugging questions asking about code that doesn't work need to include the code directly, in a code block (triple backticks), not just linking to it. When you edit, you should probably also add the [inline-assembly] tag. I think Rust's inline asm works similarly to GNU C inline asm, where you need to declare clobbers for any explicit register names you write, so the compiler doesn't pick them as inputs and it knows they're modified. Your code doesn't do that. It also doesn't have a "memory" clobber or memory input to tell the compiler that pointed-to memory is also an input. Commented Jan 21 at 12:48
  • Does "lw a0, ({})" ... in(reg) &text.len() put the address of the length into a register, and load the length from memory? Seems weird; since the syntax seems to support asking for operands in registers, can't you just ask for in("a0") with the Rust expression whose value you want in that register? Oh also, you write a6 and a7 before reading any of your reg inputs. That also wouldn't be a problem if you asked for your inputs in the regs you want them in, and didn't do your own lw. The li for constants could also be replaced with in operands. Commented Jan 23 at 12:36
  • 2
    @PeterCordes Indeed, in(reg) &text.len() puts the address of the length in a register, which is probably not what OP intended. Memory clobber is the default in Rust though and needs to be opted-out. Commented Jan 25 at 18:22
  • @ChayimFriedman: Well maybe they just don't know a better way (asking for the value they want in the register they want); address in a register is what they need for lw to work. Commented Jan 25 at 21:09

1 Answer 1

1

This works:

pub fn debug_console_write(text: &str) -> SBIResult {
    let mut sbi_result = SBIResult::new();
    unsafe {
        asm!(
            "li a7, 0x4442434E", // Specifies SBI extension
            "li a6, 0x00", //  Specifies function ID in extension
            "li a2, 0", // Provides the high end of the pointers address which should always be 0
            "ecall", // Short for "enviroment call", in this case it's a call to the sbi
            lateout("a0") sbi_result.error, // Puts error value from sbi call into result struct
            lateout("a1") sbi_result.value, // Puts value value from sbi call into result struct
            in("a0") text.len(), // Provides number of bytes in string
            in("a1") text.as_ptr(), // Provides pointer to string
            clobber_abi("system")
        );
    }

    return sbi_result
}

I'm not sure if the previous one worked or not because of other issues, but I know this one does, for now at least.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.