diff options
| author | Alastair Reid | 2018-06-26 17:02:33 +0100 |
|---|---|---|
| committer | Alastair Reid | 2018-06-26 17:03:27 +0100 |
| commit | 16c63bce08d1b7f99320cc669f69e195638e6a65 (patch) | |
| tree | d81e1f69965d393d6dacaee895668ced4c8992bc /aarch64/elfmain.sail | |
| parent | 91c0437a14f67953b6672d0633e2c68de174aa11 (diff) | |
Main: attempt to capture AArch64 execution cycle
Diffstat (limited to 'aarch64/elfmain.sail')
| -rw-r--r-- | aarch64/elfmain.sail | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/aarch64/elfmain.sail b/aarch64/elfmain.sail new file mode 100644 index 00000000..7be920c3 --- /dev/null +++ b/aarch64/elfmain.sail @@ -0,0 +1,180 @@ +$include <elf.sail> + +val read_register = "reg_deref" : forall ('a : Type). register('a) -> 'a effect {rreg} + +// EL1 physical EL2 physical EL3 physical EL1 virtual, EL2 virtual +let CNT_CVAL = [ref CNTP_CVAL_EL0, ref CNTHP_CVAL_EL2, ref CNTPS_CVAL_EL1, ref CNTV_CVAL_EL0, ref CNTHV_CVAL_EL2] +let CNT_TVAL = [ref CNTP_TVAL_EL0, ref CNTHP_TVAL_EL2, ref CNTPS_TVAL_EL1, ref CNTV_TVAL_EL0, ref CNTHV_TVAL_EL2] +let CNT_CTL = [ref CNTP_CTL_EL0, ref CNTHP_CTL_EL2, ref CNTPS_CTL_EL1, ref CNTV_CTL_EL0, ref CNTHV_CTL_EL2 ] +let CNT_CTL = [ref CNTP_CTL_EL0, ref CNTHP_CTL_EL2, ref CNTPS_CTL_EL1, ref CNTV_CTL_EL0, ref CNTHV_CTL_EL2 ] +let CNT_IRQ = [0x0000_000d, 0x0000_000a, 0x0000_03ff, 0x0000_000b, 0x0000_03ff ] +// No IRQ No IRQ? + +// SGI Interrupts are 0-15, PPI interrupts are 16-31, so SPI interrupts have an offset of 32. +let SPI_OFFSET = 32 + +// Simple top level fetch and execute loop. +val fetch_and_execute : unit -> unit effect {escape, undef, wreg, rreg, rmem, wmem} + +function fetch_and_execute () = { + var cycle_counter : int = 0; + while true do { + cycle_counter = cycle_counter + 1; + try { + // Increment the counter + CNTPCT_EL0 = CNTPCT_EL0 + 1; + CNTVCT_EL0 = CNTPCT_EL0 - CNTVOFF_EL2; + + // Timer value view for each timer + foreach (timer from 0 to 4) { + let TVAL = CNT_TVAL[timer]; + let nextTVAL = read_register(TVAL) - 1; + (*TVAL) = nextTVAL; + + if nextTVAL == 0x0000_0000 then { + _IRQPending = true; + AArch64_TakePhysicalIRQException() + } + }; + + // Handle the Kernel event stream, if enabled by CNTKCTL_EL1[2]. + if CNTKCTL_EL1[2] == bitone then { + let mask = LSL(ZeroExtend(0x1, 64), UInt(CNTKCTL_EL1[7 .. 4])); + + // Trigger event stream on either rising bit (0-1, bitzero) or falling (1-0, bitone) + let trigger : bool = if CNTKCTL_EL1[3] == bitzero then { + ((CNTVCT_EL0 - 1) & mask) == Zeros() & (CNTVCT_EL0 & mask) != Zeros() + } else { + ((CNTVCT_EL0 - 1) & mask) != Zeros() & (CNTVCT_EL0 & mask) == Zeros() + }; + + if trigger & PSTATE.I == bitzero then { + _IRQPending = true; + AArch64_TakePhysicalIRQException() + } + }; + + // Handle the Hypervisor event stream, if enabled by CNTHCTL_EL2[2]. + if CNTHCTL_EL2[2] == bitone then { + let mask = LSL(ZeroExtend(0x1, 64), UInt(CNTHCTL_EL2[7 .. 4])); + + // Trigger event stream on either rising bit (0-1, bitzero) or falling (1-0, bitone) + let trigger : bool = if CNTHCTL_EL2[3] == bitzero then { + ((CNTPCT_EL0 - 1) & mask) == Zeros() & (CNTPCT_EL0 & mask) != Zeros() + } else { + ((CNTPCT_EL0 - 1) & mask) != Zeros() & (CNTPCT_EL0 & mask) == Zeros() + }; + + if trigger & PSTATE.I == bitzero then { + prerr("[Clock] Tick\n"); + _IRQPending = true; + AArch64_TakePhysicalIRQException() + } + }; + + var prevEL = PSTATE.EL; + var prevI = PSTATE.I; + + // Store the old values of the Counter-timer Kernel/Hypervisor Control + // registers, as we want to figure out when they changes. + var prevCNTKCTL_EL1 = CNTKCTL_EL1; + var prevCNTHCTL_EL2 = CNTHCTL_EL2; + + if ~(__Sleeping()) then { + var ok = false; + + // Check for pending interrupts + var interrupt_req : InterruptReq = undefined; + interrupt_req.take_SE = true; interrupt_req.take_vSE = true; + interrupt_req.take_IRQ = true; interrupt_req.take_vIRQ = true; + interrupt_req.take_FIQ = true; interrupt_req.take_vFIQ = true; + ok = ~(TakePendingInterrupts(interrupt_req)); + + try { + __currentInstr = __fetchA64(); + ok = true; + } catch { + Error_ExceptionTaken() => { + print("Exception taken during IFetch\n") + }, + _ => { + print("Exiting due to unhandled exception during fetch\n"); + exit() + } + }; + if ok then { + try { + ok = false; + __PC_changed = false; + ShouldAdvanceIT = (PSTATE.nRW == [bitone]) & (PSTATE.T == [bitone]); + decode(__currentInstr); + if ~(__PC_changed) then _PC = _PC + 4 else (); + if ShouldAdvanceIT then AArch32_ITAdvance() else (); + SSAdvance(); + __UpdateSystemCounter(); // should this happen even if sleeping? + ok = true; + } catch { + Error_See(_) => UndefinedFault(), + Error_ReservedEncoding(_) => UndefinedFault(), + Error_Undefined() => UndefinedFault(), + Error_ExceptionTaken() => { + print("Exception taken during IFetch\n") + }, + _ => { + print("Exiting due to unhandled exception during decode/execute\n"); + exit() + } + } + }; + if ~(ok) then { + print(concat_str("Yoiks: something went wrong at ", concat_str(DecStr(cycle_counter), "\n"))); + } + }; + + // We want to keep track of what exception level we are in for debugging purposes. + if UInt(prevEL) > UInt(PSTATE.EL) then { + prerr_bits("[Sail] Exception level dropped to: ", PSTATE.EL) + }; + if prevI != PSTATE.I then { + prerr_bits("[Sail] PSTATE.I changed to: ", PSTATE.I); + }; + if prevCNTKCTL_EL1 != CNTKCTL_EL1 then { + prerr_bits("[Clock] CNTKCTL_EL1 changed to ", CNTKCTL_EL1); + }; + if prevCNTHCTL_EL2 != CNTHCTL_EL2 then { + prerr_bits("[Clock] CNTHCTL_EL2 changed to ", CNTHCTL_EL2); + } + + } catch { + Error_See(str) if str == "HINT" => (), + Error_ExceptionTaken(_) => { + // enable_tracing() + () + }, + _ => { + prerr("Exiting due to unhandled exception\n"); + exit() + } + }; + __EndCycle() + } +} + +let COLD_RESET : bool = true + +val "load_raw" : (bits(64), string) -> unit + +val init : unit -> unit effect {escape, undef, rreg, wreg} + +function init() = { + __currentInstrLength = 4; + TakeReset(COLD_RESET); + _PC = CFG_RVBAR; +} + +val main : unit -> unit effect {escape, undef, wreg, rreg, rmem, wmem} + +function main() = { + init(); + fetch_and_execute() +} |
