m-labs / misoc

The original high performance and small footprint system-on-chip based on Migen™
https://m-labs.hk
Other
306 stars 85 forks source link

Add updated libunwind with RV32 support #114

Closed occheung closed 3 years ago

occheung commented 3 years ago

Summary

This PR adds a newer version of libunwind that supports RISC-V 32-bits target.

Details

occheung commented 3 years ago

Tested libunwind with OR1K by inserting a panic in artiq runtime startup, this is the result of the subsequent backtrace.

0x40031014
0x400139b0
0x4001395c
0x40030148
0x40030754

These PC refers to the following instructions.

40031014:   04 00 2e 3e     l.jal 4003c90c <_Unwind_Backtrace>
...
400139b0:   04 00 75 1e     l.jal 40030e28 <rust_begin_unwind>
...
4001395c:   04 00 00 04     l.jal 4001396c <_ZN4core9panicking9panic_fmt17h7960887f32d6fb90E>
...
40030148:   07 ff 8d ec     l.jal 400138f8 <_ZN4core9panicking5panic17h404b8d21e6fc634fE>
...
40030754:   07 ff ee 3a     l.jal 4002c03c <_ZN7runtime7startup17hbac6b0b62f1dea75E>

Which leads back to the runtime startup.

sbourdeauducq commented 3 years ago

@occheung Nope, that breaks or1k. artiq.test.coredevice.test_portability.HostVsDeviceCase.test_exceptions hangs. https://nixbld.m-labs.hk/build/197745/nixlog/2

occheung commented 3 years ago

Ran the test and got the following trace.

Trace ``` [ 15.356606s] INFO(runtime::session): new connection from 192.168.1.125:40536 [ 15.364129s] DEBUG(runtime::session): comm<-host SystemInfo [ 15.368462s] DEBUG(runtime::session): comm->host SystemInfo { ident: "7.7657.f531af51.beta;mirnytest", finished_cleanly: true } [ 15.386821s] DEBUG(runtime::session): comm<-host LoadLibrary(...) [ 15.419778s] DEBUG(runtime::session): comm->kern LoadRequest(...) [ 15.425928s] DEBUG(runtime::session): comm<-kern LoadReply(Ok(())) [ 15.430901s] DEBUG(runtime::session): comm->host LoadCompleted [ 15.438253s] DEBUG(runtime::session): comm<-host RunKernel [ 15.442914s] DEBUG(runtime::session): comm<-kern RpcSend { async: false, service: 3, tag: [79, 105, 58, 110], data: 0x4ffffe98 } [ 15.454035s] DEBUG(runtime::session): comm->host RpcRequest { async: false } [ 15.461123s] DEBUG(proto_artiq::rpc_proto): send<3>(Object, Int32)->None [ 15.469323s] DEBUG(runtime::session): comm<-host RpcReply { tag: [110] } [ 15.475116s] DEBUG(runtime::session): comm<-kern RpcRecvRequest(0x4ffffec8) [ 15.481735s] DEBUG(proto_artiq::rpc_proto): recv ...->None [ 15.487226s] DEBUG(runtime::session): comm->kern RpcRecvReply(Ok(0)) [ 15.493798s] DEBUG(runtime::session): comm<-kern RpcSend { async: false, service: 3, tag: [79, 105, 58, 110], data: 0x4ffffe90 } [ 15.505149s] DEBUG(runtime::session): comm->host RpcRequest { async: false } [ 15.512232s] DEBUG(proto_artiq::rpc_proto): send<3>(Object, Int32)->None [ 15.520426s] DEBUG(runtime::session): comm<-host RpcReply { tag: [110] } [ 15.526212s] DEBUG(runtime::session): comm<-kern RpcRecvRequest(0x4ffffec8) [ 15.532832s] DEBUG(proto_artiq::rpc_proto): recv ...->None [ 15.538320s] DEBUG(runtime::session): comm->kern RpcRecvReply(Ok(0)) [ 15.544897s] DEBUG(runtime::session): comm<-kern RpcSend { async: false, service: 3, tag: [79, 105, 58, 110], data: 0x4ffffe88 } [ 15.556249s] DEBUG(runtime::session): comm->host RpcRequest { async: false } [ 15.563331s] DEBUG(proto_artiq::rpc_proto): send<3>(Object, Int32)->None [ 15.571525s] DEBUG(runtime::session): comm<-host RpcReply { tag: [110] } [ 15.577306s] DEBUG(runtime::session): comm<-kern RpcRecvRequest(0x4ffffec8) [ 15.583931s] DEBUG(proto_artiq::rpc_proto): recv ...->None [ 15.589419s] DEBUG(runtime::session): comm->kern RpcRecvReply(Ok(0)) [ 15.595994s] DEBUG(runtime::session): comm<-kern RpcSend { async: false, service: 3, tag: [79, 105, 58, 110], data: 0x4ffffe80 } [ 15.607348s] DEBUG(runtime::session): comm->host RpcRequest { async: false } [ 15.614430s] DEBUG(proto_artiq::rpc_proto): send<3>(Object, Int32)->None [ 15.622620s] DEBUG(runtime::session): comm<-host RpcReply { tag: [110] } [ 15.628403s] DEBUG(runtime::session): comm<-kern RpcRecvRequest(0x4ffffec8) [ 15.635026s] DEBUG(proto_artiq::rpc_proto): recv ...->None [ 15.640515s] DEBUG(runtime::session): comm->kern RpcRecvReply(Ok(0)) [ 15.647089s] DEBUG(runtime::session): comm<-kern RpcSend { async: false, service: 3, tag: [79, 105, 58, 110], data: 0x4ffffe78 } [ 15.658443s] DEBUG(runtime::session): comm->host RpcRequest { async: false } [ 15.665526s] DEBUG(proto_artiq::rpc_proto): send<3>(Object, Int32)->None [ 15.673721s] DEBUG(runtime::session): comm<-host RpcReply { tag: [110] } [ 15.679502s] DEBUG(runtime::session): comm<-kern RpcRecvRequest(0x4ffffec8) [ 15.686126s] DEBUG(proto_artiq::rpc_proto): recv ...->None [ 15.691615s] DEBUG(runtime::session): comm->kern RpcRecvReply(Ok(0)) [ 15.698194s] DEBUG(runtime::session): comm<-kern RpcSend { async: false, service: 3, tag: [79, 105, 58, 110], data: 0x4ffffe70 } [ 15.709544s] DEBUG(runtime::session): comm->host RpcRequest { async: false } [ 15.716626s] DEBUG(proto_artiq::rpc_proto): send<3>(Object, Int32)->None [ 15.724819s] DEBUG(runtime::session): comm<-host RpcReply { tag: [110] } [ 15.730599s] DEBUG(runtime::session): comm<-kern RpcRecvRequest(0x4ffffec8) [ 15.737224s] DEBUG(proto_artiq::rpc_proto): recv ...->None [ 15.742713s] DEBUG(runtime::session): comm->kern RpcRecvReply(Ok(0)) [ 15.749287s] DEBUG(runtime::session): comm<-kern RpcSend { async: false, service: 3, tag: [79, 105, 58, 110], data: 0x4ffffe68 } [ 15.760644s] DEBUG(runtime::session): comm->host RpcRequest { async: false } [ 15.767724s] DEBUG(proto_artiq::rpc_proto): send<3>(Object, Int32)->None [ 15.775915s] DEBUG(runtime::session): comm<-host RpcReply { tag: [110] } [ 15.781695s] DEBUG(runtime::session): comm<-kern RpcRecvRequest(0x4ffffec8) [ 15.788321s] DEBUG(proto_artiq::rpc_proto): recv ...->None [ 15.793809s] DEBUG(runtime::session): comm->kern RpcRecvReply(Ok(0)) [ 15.800385s] DEBUG(runtime::session): comm<-kern RpcSend { async: false, service: 3, tag: [79, 105, 58, 110], data: 0x4ffffe5c } [ 15.811738s] DEBUG(runtime::session): comm->host RpcRequest { async: false } [ 15.818821s] DEBUG(proto_artiq::rpc_proto): send<3>(Object, Int32)->None [ 15.827011s] DEBUG(runtime::session): comm<-host RpcReply { tag: [110] } [ 15.832793s] DEBUG(runtime::session): comm<-kern RpcRecvRequest(0x4ffffec8) [ 15.839417s] DEBUG(proto_artiq::rpc_proto): recv ...->None [ 15.844905s] DEBUG(runtime::session): comm->kern RpcRecvReply(Ok(0)) [ 15.851480s] DEBUG(runtime::session): comm<-kern RpcSend { async: false, service: 3, tag: [79, 105, 58, 110], data: 0x4ffffe54 } [ 15.862834s] DEBUG(runtime::session): comm->host RpcRequest { async: false } [ 15.869916s] DEBUG(proto_artiq::rpc_proto): send<3>(Object, Int32)->None [ 15.878108s] DEBUG(runtime::session): comm<-host RpcReply { tag: [110] } [ 15.883889s] DEBUG(runtime::session): comm<-kern RpcRecvRequest(0x4ffffec8) [ 15.890514s] DEBUG(proto_artiq::rpc_proto): recv ...->None [ 15.896002s] DEBUG(runtime::session): comm->kern RpcRecvReply(Ok(0)) [ 15.902577s] DEBUG(runtime::session): comm<-kern RpcSend { async: false, service: 3, tag: [79, 105, 58, 110], data: 0x4ffffe4c } [ 15.913931s] DEBUG(runtime::session): comm->host RpcRequest { async: false } [ 15.921013s] DEBUG(proto_artiq::rpc_proto): send<3>(Object, Int32)->None [ 15.929203s] DEBUG(runtime::session): comm<-host RpcReply { tag: [110] } [ 15.934984s] DEBUG(runtime::session): comm<-kern RpcRecvRequest(0x4ffffec8) [ 15.941609s] DEBUG(proto_artiq::rpc_proto): recv ...->None [ 15.947097s] DEBUG(runtime::session): comm->kern RpcRecvReply(Ok(0)) [ 15.953672s] DEBUG(runtime::session): comm<-kern RpcSend { async: false, service: 3, tag: [79, 105, 58, 110], data: 0x4ffffe40 } [ 15.965026s] DEBUG(runtime::session): comm->host RpcRequest { async: false } [ 15.972108s] DEBUG(proto_artiq::rpc_proto): send<3>(Object, Int32)->None [ 15.980298s] DEBUG(runtime::session): comm<-host RpcReply { tag: [110] } [ 15.986078s] DEBUG(runtime::session): comm<-kern RpcRecvRequest(0x4ffffec8) [ 15.992703s] DEBUG(proto_artiq::rpc_proto): recv ...->None [ 15.998192s] DEBUG(runtime::session): comm->kern RpcRecvReply(Ok(0)) ```

Then the kernel hangs afterwards. The TCP session is still alive.

occheung commented 3 years ago

These 2 lines are a bit questionable. https://github.com/m-labs/misoc/blob/79a27a82050266ce4d99d35ca0fe6b53a44649ac/misoc/software/unwinder/src/UnwindRegistersRestore.S#L803-L807 During unwind_resume in the second phase of raiseException, the landing pad address (lpad) is wrote to the __pc field of a or1k_thread_state_t struct by invoking the setIP method.

  struct or1k_thread_state_t {
    unsigned int __r[32]; // r0-r31
    unsigned int __pc;    // Program counter
    unsigned int __epcr;  // Program counter at exception
  };

Therefore, the lpad is stored with an offset of 128, as all registers in OR1K contains 32 bits/4 bytes. After the lpad is found, the unwinder proceeds to resume the execution at lpad. This is handled by __unw_resume, which calls jumpto. This is then resolved into the assembly procedure in UnwindRegistersRestore.S.

The quoted code above will NOT load the lpad to r9 (link address register) from the offset explained above, since r3 is restored prematurely. It will fail to resume in the expected catch block.

Swapping these 2 instructions should resolve the issue, like the following.

  # load new pc into ra
  l.lwz     r9,128(r3)

  # at last, restore r3
  l.lwz     r3, 12(r3)