trap, main: implement trap handler
This commit implements a trap handler, which handles a number of basic
exception cases and sets the code up for handling interrupts, which will
be really useful for making a serial console properly without relying on
looping.
Changes:
* trap.rs implements a TrapFrame struct and declares one in memory.
This will allow the code to preserve registers and context without
using the stack.
* trap.S implements the low-level parts of the trap handler, copying the
general-purpose and floating-point registers, plus the trap cause and
other context info, into the TrapFrame, and calls the Rust function
m_trap.
* trap.rs implements m_trap, which performs dispatch based on the
exception code and, if the exception is non-fatal, returns the address
of the PC that the trap returns to (typically PC+4).
* main.rs expands the panic handler to log panic information to serial
out so that fatal exceptions are logged. It also adds the trap vector
init code.
This particular method of performing traps is heavily inspired from
Stephen Marz' blog on bare metal Rust for RISC-V:
http://osblog.stephenmarz.com/ch4.html