Synchronous Exception Handler
目前在 sync_exc_router
會透過 ESR_EL1
帶的 EC 與 ISS 決定執行哪個 handler,目前先簡易的實作一個可以動的 System call,之後會再將 System call number 改為透過正常的參數傳遞。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| void sync_exc_router(unsigned long esr, unsigned long elr) {
int ec = (esr >> 26) & 0b111111;
int iss = esr & 0x1FFFFFF;
if (ec == 0b010101) { // system call
switch (iss) {
case 1:
uart_printf("Exception return address 0x%x\n", elr);
uart_printf("Exception class (EC) 0x%x\n", ec);
uart_printf("Instruction specific syndrome (ISS) 0x%x\n", iss);
break;
case 2:
arm_core_timer_enable();
arm_local_timer_enable();
break;
case 3:
arm_core_timer_disable();
arm_local_timer_disable();
break;
case 4:
asm volatile ("mrs %0, cntfrq_el0" : "=r" (cntfrq_el0)); // get current counter frequency
asm volatile ("mrs %0, cntpct_el0" : "=r" (cntpct_el0)); // read current counter
break;
}
}
else {
uart_printf("Exception return address 0x%x\n", elr);
uart_printf("Exception class (EC) 0x%x\n", ec);
uart_printf("Instruction specific syndrome (ISS) 0x%x\n", iss);
}
}
|
按照 spec 要求實作 exc
指令,用於測試 Synchronous Exception
1
2
3
4
5
6
7
| void shell_controller(char* cmd) {
...
else if (!strcmp(cmd, "exc")) {
asm volatile("svc #1");
}
...
}
|
因為 shell 現在執行在 EL0,不能直接碰到 System Registers,所以 timestamp
指令也需要透過 system call 下去拿到頻率與 counter 再進行相除,正常來說應該要把一個指標當作參數傳進 system call 拿到對應的值,但目前還沒有這麼高級。
1
2
3
4
| float get_timestamp() {
asm volatile ("svc #4");
return (float) cntpct_el0 / cntfrq_el0;
}
|
Holds syndrome information for an exception taken to EL1.
[63:32] | [31:26] | [25] | [24:0] |
---|
Reserved | EC | IL | ISS |
- EC: Exception Class. Indicates the reason for the exception that this register holds information about.
- IL: Instruction Length for synchronous exceptions.
- ISS: Instruction Specific Syndrome.
When EC = 0b000000 (exception with an unknown reason), ISS is not valid