Unaligned memory access with JDK

Palmer Dabbelt palmer at dabbelt.com
Thu Jul 28 21:30:03 UTC 2022


On Thu, 28 Jul 2022 14:22:33 PDT (-0700), vladimir.kempik at gmail.com wrote:
> Right, the system I was playing with doesn’t have misaligned access emulation enabled in M-mode, but that can be enabled.

I suppose it's also undefined whether these accesses need to be handled 
in M-mode or if Linux should also do so, but there's currently no code 
in Linux to do that and no way for userspace to control that handling.

In the long run we probably want to stop predenting misaligned accesses 
are supported when they're actually emulated, via something like 
PR_SET_UNALIGN (and some M-mode interface).  That'd require some code, 
though, and either way we'd need to leave the default as is.

> THanks for clarifying, I was wondering is it a bug or a feature.

I guess it's both ;)

>
>> 29 июля 2022 г., в 00:19, Palmer Dabbelt <palmer at dabbelt.com> написал(а):
>> 
>> On Thu, 28 Jul 2022 13:50:00 PDT (-0700), vladimir.kempik at gmail.com wrote:
>>> Hello
>>> I was recently playing with a simple risc-v core running on an fpga and found the idk crashes on it.
>>> It crashes with SIG_ILL : ILL_TRP, on a simple load from memory instruction.
>>> So I figured the main issue is unaligned memory access MacroAssembler::stop() and that risc-v core was pretty simple and didn’t support unaligned memory access.
>>> Here is what I found:
>>> 
>>> void MacroAssembler::stop(const char* msg) {
>>>  const char * msg1 = ((uint64_t)msg) & ~0x07 + 0x08;
>>>  BLOCK_COMMENT(msg1);
>>>  illegal_instruction(Assembler::csr::time);
>>>  emit_int64((uintptr_t)msg1);
>>> }
>>> 
>>> and emit_64 is :
>>>  void emit_int64( int64_t x)  { *((int64_t*) end()) = x; set_end(end() + sizeof(int64_t)); }
>>> 
>>> the problem is that the end() pointer is shared between emit_int64, emit_int32, emit_int8, etc, and non of them do care about natural memory alignment for processed types:
>>> 
>>>  void emit_int32(int32_t x) {
>>>    address curr = end();
>>>    *((int32_t*) curr) = x;
>>>    set_end(curr + sizeof(int32_t));
>>>  }
>>> 
>>>  void emit_int8(int8_t x1) {
>>>    address curr = end();
>>>    *((int8_t*)  curr++) = x1;
>>>    set_end(curr);
>>>  }
>>> 
>>> So my question is - risc-v cores without unaligned memory access support - are they supported by risc-v openjdk port ?
>> 
>> Support for misaligned accesses lives in a weird grey area in RISC-V: misaligned accesses used to be mandated by the ISA, but that requirement was removed in 2018 via 61cadb9 ("Provide new description of misaligned load/store behavior compatible with privileged architecture.").  I just sent a patch to document this, looks like we never bothered to write it down (probably because nobody was watching for the ISA change).
>> 
>> That said, some implementations support misaligned accesses via a M-mode trap handler, as implementations can do essentially anything they want in RISC-V.  IIUC most of the RISC-V OpenJDK port was done on systems that have hardware support for misaligned accesses, but even on systems that trap to M-mode the port should function correctly -- sure it'll be slow, but the support should otherwise be transparent to userspace (and even to Linux).  It might be worth fixing that performance issue, but if you're seeing a SIGILL from a misaligned access then there's likely also a functional bug in the emulation routines or Linux.


More information about the riscv-port-dev mailing list