Skip to content
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

MIPS32 support / alignment issues #3761

Open
InBetweenNames opened this issue Aug 31, 2024 · 11 comments
Open

MIPS32 support / alignment issues #3761

InBetweenNames opened this issue Aug 31, 2024 · 11 comments

Comments

@InBetweenNames
Copy link

Hello WAMR team,

Thanks for maintaining such a cool project. I have a MIPS related problem I was hoping you could help me with.
How well is MIPS32 supported in WAMR? I'm having a hard time getting a simple "Hello world" Rust wasip1 application running on mips32 (big endian). I'm noticing that on x86[-64], arm, and aarch64 everything seems to work fine, but on mips32, I'm getting an "undefined element" exception in both the Classic and Fast interpreter modes:

wasm_set_exception(module, "undefined element");

and similarly for the classic interpreter here:

wasm_set_exception(module, "undefined element");

What seems to be happening is the "val" variable in both cases is being dereferenced to the value 0x80000000 which is far outside of the table range in the Rust example. It seems this has to do with the handling of the call_indirect function, where it looks up from the wasm table where the call target will be.

I wonder, is this an endian related issue? I haven't debugged it further to see what val should be on a normal execution.

Now, Zig's "hello world" application seems to work just fine with target triple wasm32-wasi-musl. It seems to only feature one call_indirect.

In addition to this, mips64 seems to SIGBUS on a misaligned access when running the Rust hello world (although not directly relevant to my use case). It seems I can't attach the .wasm here directly, but it is simple enough to reproduce: Just cargo init and then build for Rust using cargo build --target wasm32-wasip1.

Thank you very much!

@InBetweenNames
Copy link
Author

InBetweenNames commented Sep 1, 2024

Okay, I did a lot more digging into this today. It turns out that it's not just MIPS32 that's having problems. There are a number of pointer misalignment issues within WAMR that I believe are causing runtime issues. Two examples to note are that tables are not aligned correctly (easily fixable), and the CSP related stuff (involving frame->sp_boundary) on the WASM stack isn't aligned properly. That one seems a little less obvious to fix. There still may be some endianness issues at play here too but the pointer misalignment is definitely a higher priority to fix. I noticed that the CI for the repo largely uses 32-bit x86 and RISC-V. The problems will be much more apparent on platforms where sizeof(int) != sizeof(void*). On x86_64, when I built in Debug mode on Clang 18, it seems that CMake enabled some sanitizers which was enough to trigger the issue.

@InBetweenNames
Copy link
Author

Ref: #2349

@InBetweenNames
Copy link
Author

Possible ref: #2136

@InBetweenNames InBetweenNames changed the title MIPS32 support MIPS32 support / alignment issues Sep 1, 2024
@wenyongh
Copy link
Contributor

wenyongh commented Sep 4, 2024

Okay, I did a lot more digging into this today. It turns out that it's not just MIPS32 that's having problems. There are a number of pointer misalignment issues within WAMR that I believe are causing runtime issues. Two examples to note are that tables are not aligned correctly (easily fixable), and the CSP related stuff (involving frame->sp_boundary) on the WASM stack isn't aligned properly. That one seems a little less obvious to fix. There still may be some endianness issues at play here too but the pointer misalignment is definitely a higher priority to fix. I noticed that the CI for the repo largely uses 32-bit x86 and RISC-V. The problems will be much more apparent on platforms where sizeof(int) != sizeof(void*). On x86_64, when I built in Debug mode on Clang 18, it seems that CMake enabled some sanitizers which was enough to trigger the issue.

Hi, thanks for reporting the issue, I tried building iwasm under Ubuntu x86-64 with clang and enabled the sanitizer ubsan: cmake .. -DWAMR_BUILD_SANITIZER=ubsan, and then tested some standalone cases, but no sanitizer error was reported. Could you tell us how to reproduce the issue?

BTW, I have no mips environment to test the case, could you submit a PR to fix issues found? Thanks.

@InBetweenNames
Copy link
Author

InBetweenNames commented Sep 4, 2024 via email

@wenyongh
Copy link
Contributor

wenyongh commented Sep 5, 2024

Hi, I tried to fix the issue with below patch, could you test whether it works for you:
fix_unaligned_access.zip

@InBetweenNames
Copy link
Author

InBetweenNames commented Sep 5, 2024 via email

@wenyongh
Copy link
Contributor

wenyongh commented Sep 6, 2024

The WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS is only enabled in x86-64, x86-32 and aarch64 by default, and it helps reduce the footprint in some situations, e.g., for generate less pre-compiled code in fast interpreter mode. Developer can also select whether to enable it or not, I don't think we had better remove it entirely. In the patch for mips32, you can remove it if you want.

@InBetweenNames
Copy link
Author

InBetweenNames commented Sep 6, 2024 via email

@wenyongh
Copy link
Contributor

wenyongh commented Sep 9, 2024

I did a test for the coremark standalone case, disabling the macro while keeping storing the label address in the pre-compiled code (that means the label address will be stored at 8-byte align address and there may be unused paddings before it) will increase the pre-compiled size from 115925 bytes to 134596 bytes, and interpreter has to align to 8-byte aligned address before get the label address, which may impact the performance. Since it increases the code size a lot, currently in 64-bit when the macro is disabled, we store the offset of two labels instead (dest label - base label) and a add operation is added to calculate the label address after reading the offset, which also impacts the performance but gets better footprint.

The wasm runtime itself doesn't uses movaps, we didn't find that the gcc/clang generates movaps instruction after compiling wamr runtime. And in the generated AOT/JIT code, the movapu is emitted instead if the address may be not 16-byte aligned.

The point is that the hardware supports the unaligned access operations and we can control it and it benefits to the developers, is it better to keep the capability? And runtime has provided the option to disable it.

@InBetweenNames
Copy link
Author

InBetweenNames commented Sep 9, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants