mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-23 02:05:57 +01:00
aarch64 baremetal svc factored out for C and asm
This commit is contained in:
22
README.adoc
22
README.adoc
@@ -11293,21 +11293,19 @@ output:
|
|||||||
|
|
||||||
==== ARM exception handling
|
==== ARM exception handling
|
||||||
|
|
||||||
Setup a handler for `svc`, do an `svc`, and observe that the handler got called and returned:
|
Setup a handler for `svc`, do an `svc`, and observe that the handler got called and returned from C and assembly:
|
||||||
|
|
||||||
....
|
|
||||||
./run --arch aarch64 --baremetal arch/aarch64/svc_asm
|
|
||||||
....
|
|
||||||
|
|
||||||
Source: link:baremetal/arch/aarch64/svc_asm.S[]
|
|
||||||
|
|
||||||
TODO: factor out the above, and make it also work on C:
|
|
||||||
|
|
||||||
....
|
....
|
||||||
./run --arch aarch64 --baremetal arch/aarch64/svc
|
./run --arch aarch64 --baremetal arch/aarch64/svc
|
||||||
|
./run --arch aarch64 --baremetal arch/aarch64/svc_asm
|
||||||
....
|
....
|
||||||
|
|
||||||
Output:
|
Sources:
|
||||||
|
|
||||||
|
* link:baremetal/arch/aarch64/svc_asm.S[]
|
||||||
|
* link:baremetal/arch/aarch64/svc.c[]
|
||||||
|
|
||||||
|
Output for the C one:
|
||||||
|
|
||||||
....
|
....
|
||||||
daif 0x3c0
|
daif 0x3c0
|
||||||
@@ -11315,8 +11313,6 @@ spsel 0x1
|
|||||||
vbar_el1 0x0
|
vbar_el1 0x0
|
||||||
....
|
....
|
||||||
|
|
||||||
Source: link:baremetal/arch/aarch64/svc.c[]
|
|
||||||
|
|
||||||
The vector table format is described on <<armarm8>> Table D1-7 "Vector offsets from vector table base address".
|
The vector table format is described on <<armarm8>> Table D1-7 "Vector offsets from vector table base address".
|
||||||
|
|
||||||
A good representation of the format of the vector table can also be found at <<programmers-guide-for-armv8-a>> Table 10-2 "Vector table offsets from vector table base address".
|
A good representation of the format of the vector table can also be found at <<programmers-guide-for-armv8-a>> Table 10-2 "Vector table offsets from vector table base address".
|
||||||
@@ -13034,7 +13030,7 @@ to the terminal, then our run scripts detect that and exit with status `1`.
|
|||||||
|
|
||||||
This magic output string is notably used by:
|
This magic output string is notably used by:
|
||||||
|
|
||||||
* the `common_assert_fail()` function, which is used by <<baremetal-tests>>
|
* the `lkmc_assert_fail()` function, which is used by <<baremetal-tests>>
|
||||||
* link:rootfs_overlay/test_fail.sh[], which is used by <<test-userland-in-full-system>>
|
* link:rootfs_overlay/test_fail.sh[], which is used by <<test-userland-in-full-system>>
|
||||||
|
|
||||||
==== Non-automated tests
|
==== Non-automated tests
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include <common.h>
|
#include <lkmc.h>
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
@@ -9,5 +9,5 @@ int main(void) {
|
|||||||
k = i + j;
|
k = i + j;
|
||||||
/* test-gdb-result */
|
/* test-gdb-result */
|
||||||
if (k != 3)
|
if (k != 3)
|
||||||
common_assert_fail();
|
lkmc_assert_fail();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,6 @@ main:
|
|||||||
/* test-gdb-result */
|
/* test-gdb-result */
|
||||||
cmp x1, #3
|
cmp x1, #3
|
||||||
beq 1f
|
beq 1f
|
||||||
bl common_assert_fail
|
bl lkmc_assert_fail
|
||||||
1:
|
1:
|
||||||
ret
|
ret
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
#ifndef COMMON_AARCH64_H
|
|
||||||
#define COMMON_AARCH64_H
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#define SYSREG_READ(type, name) \
|
|
||||||
type sysreg_ ## name ## _read(void) { \
|
|
||||||
type name; \
|
|
||||||
__asm__ __volatile__("mrs %0, " #name : "=r" (name) : : ); \
|
|
||||||
return name; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SYSREG_WRITE(type, name) \
|
|
||||||
void sysreg_ ## name ## _write(type name) { \
|
|
||||||
__asm__ __volatile__("msr " #name ", %0" : : "r" (name) : ); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SYSREG_READ_WRITE(name, type) \
|
|
||||||
SYSREG_READ(name, type) \
|
|
||||||
SYSREG_WRITE(name, type)
|
|
||||||
|
|
||||||
SYSREG_READ_WRITE(uint32_t, daif)
|
|
||||||
SYSREG_READ_WRITE(uint32_t, spsel)
|
|
||||||
SYSREG_READ_WRITE(uint64_t, sp_el1)
|
|
||||||
SYSREG_READ_WRITE(uint64_t, vbar_el1)
|
|
||||||
|
|
||||||
#define SVC(immediate) __asm__ __volatile__("svc " #immediate : : : )
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -12,7 +12,7 @@ main:
|
|||||||
fmov d3, #4.0
|
fmov d3, #4.0
|
||||||
fcmp d2, d3
|
fcmp d2, d3
|
||||||
beq 1f
|
beq 1f
|
||||||
bl common_assert_fail
|
bl lkmc_assert_fail
|
||||||
1:
|
1:
|
||||||
|
|
||||||
/* Now in 32-bit. */
|
/* Now in 32-bit. */
|
||||||
@@ -26,7 +26,7 @@ main:
|
|||||||
fmov s3, #4.0
|
fmov s3, #4.0
|
||||||
fcmp s2, s3
|
fcmp s2, s3
|
||||||
beq 1f
|
beq 1f
|
||||||
bl common_assert_fail
|
bl lkmc_assert_fail
|
||||||
1:
|
1:
|
||||||
|
|
||||||
/* Higher registers. */
|
/* Higher registers. */
|
||||||
@@ -40,6 +40,6 @@ main:
|
|||||||
/* test-gdb-d31 */
|
/* test-gdb-d31 */
|
||||||
fcmp d30, d31
|
fcmp d30, d31
|
||||||
beq 1f
|
beq 1f
|
||||||
bl common_assert_fail
|
bl lkmc_assert_fail
|
||||||
1:
|
1:
|
||||||
ret
|
ret
|
||||||
|
|||||||
@@ -2,33 +2,22 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <common.h>
|
#include <lkmc.h>
|
||||||
#include "common_aarch64.h"
|
|
||||||
|
|
||||||
void handle_svc() {
|
int myvar = 0;
|
||||||
exit(0);
|
|
||||||
|
void lkmc_vector_trap_handler(LkmcVectorExceptionFrame *exception) {
|
||||||
|
puts("trap handler");
|
||||||
|
myvar = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
/* View initial register values. */
|
/* View initial relevant register values. */
|
||||||
printf("daif 0x%" PRIx32 "\n", sysreg_daif_read());
|
printf("daif 0x%" PRIx32 "\n", lkmc_sysreg_daif_read());
|
||||||
printf("spsel 0x%" PRIx32 "\n", sysreg_spsel_read());
|
printf("spsel 0x%" PRIx32 "\n", lkmc_sysreg_spsel_read());
|
||||||
printf("vbar_el1 0x%" PRIx64 "\n", sysreg_vbar_el1_read());
|
printf("vbar_el1 0x%" PRIx64 "\n", lkmc_sysreg_vbar_el1_read());
|
||||||
|
lkmc_assert(myvar == 0);
|
||||||
/* Set registers to the values that we need. */
|
LKMC_SVC(0);
|
||||||
sysreg_daif_write(0);
|
lkmc_assert(myvar == 1);
|
||||||
sysreg_vbar_el1_write(0);
|
|
||||||
printf("daif 0x%" PRIx32 "\n", sysreg_daif_read());
|
|
||||||
printf("spsel 0x%" PRIx32 "\n", sysreg_spsel_read());
|
|
||||||
printf("vbar_el1 0x%" PRIx64 "\n", sysreg_vbar_el1_read());
|
|
||||||
|
|
||||||
/* TODO this breaks execution because reading system registers that end
|
|
||||||
* in ELx "trap", leading into an exception on the upper EL.
|
|
||||||
*/
|
|
||||||
/*printf("sp_el1 0x%" PRIx64 "\n", sysreg_sp_el1_read());*/
|
|
||||||
/*SVC(0);*/
|
|
||||||
|
|
||||||
/* Should never be reached. */
|
|
||||||
/*common_assert_fail();*/
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
/* TODO factor it out to make reusable. */
|
#include <lkmc.h>
|
||||||
|
|
||||||
.global main
|
.global main
|
||||||
main:
|
main:
|
||||||
/* Load the vector table. */
|
|
||||||
ldr x0, =vector_table
|
|
||||||
msr vbar_el1, x0
|
|
||||||
|
|
||||||
/* Do the svc. */
|
/* Do the svc. */
|
||||||
svc 0
|
svc 0
|
||||||
|
|
||||||
@@ -14,13 +10,13 @@ main:
|
|||||||
ldr x1, mynewvar
|
ldr x1, mynewvar
|
||||||
cmp x0, x1
|
cmp x0, x1
|
||||||
beq 1f
|
beq 1f
|
||||||
bl common_assert_fail
|
bl lkmc_assert_fail
|
||||||
1:
|
1:
|
||||||
|
|
||||||
/* Go home. */
|
/* Go home. */
|
||||||
ret
|
ret
|
||||||
|
|
||||||
common_trap_handler:
|
LKMC_GLOBAL(lkmc_vector_trap_handler)
|
||||||
/* Modify myvar as a visible side effect. */
|
/* Modify myvar as a visible side effect. */
|
||||||
ldr x0, mynewvar
|
ldr x0, mynewvar
|
||||||
ldr x1, =myvar
|
ldr x1, =myvar
|
||||||
@@ -31,210 +27,3 @@ myvar:
|
|||||||
.quad 0x0
|
.quad 0x0
|
||||||
mynewvar:
|
mynewvar:
|
||||||
.quad 0x12346789ABCDEF0
|
.quad 0x12346789ABCDEF0
|
||||||
|
|
||||||
/* .h
|
|
||||||
*
|
|
||||||
* Adapted from: https://github.com/takeharukato/sample-tsk-sw/blob/ce7973aa5d46c9eedb58309de43df3b09d4f8d8d/hal/aarch64/vector.S
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define AARCH64_EXC_SYNC_SP0 (0x1)
|
|
||||||
#define AARCH64_EXC_IRQ_SP0 (0x2)
|
|
||||||
#define AARCH64_EXC_FIQ_SP0 (0x3)
|
|
||||||
#define AARCH64_EXC_SERR_SP0 (0x4)
|
|
||||||
|
|
||||||
#define AARCH64_EXC_SYNC_SPX (0x11)
|
|
||||||
#define AARCH64_EXC_IRQ_SPX (0x12)
|
|
||||||
#define AARCH64_EXC_FIQ_SPX (0x13)
|
|
||||||
#define AARCH64_EXC_SERR_SPX (0x14)
|
|
||||||
|
|
||||||
#define AARCH64_EXC_SYNC_AARCH64 (0x21)
|
|
||||||
#define AARCH64_EXC_IRQ_AARCH64 (0x22)
|
|
||||||
#define AARCH64_EXC_FIQ_AARCH64 (0x23)
|
|
||||||
#define AARCH64_EXC_SERR_AARCH64 (0x24)
|
|
||||||
|
|
||||||
#define AARCH64_EXC_SYNC_AARCH32 (0x31)
|
|
||||||
#define AARCH64_EXC_IRQ_AARCH32 (0x32)
|
|
||||||
#define AARCH64_EXC_FIQ_AARCH32 (0x33)
|
|
||||||
#define AARCH64_EXC_SERR_AARCH32 (0x34)
|
|
||||||
|
|
||||||
#if !defined(__ASSEMBLER__)
|
|
||||||
#include <stdint.h>
|
|
||||||
typedef struct _exception_frame{
|
|
||||||
uint64_t exc_type;
|
|
||||||
uint64_t exc_esr;
|
|
||||||
uint64_t exc_sp;
|
|
||||||
uint64_t exc_elr;
|
|
||||||
uint64_t exc_spsr;
|
|
||||||
uint64_t x0;
|
|
||||||
uint64_t x1;
|
|
||||||
uint64_t x2;
|
|
||||||
uint64_t x3;
|
|
||||||
uint64_t x4;
|
|
||||||
uint64_t x5;
|
|
||||||
uint64_t x6;
|
|
||||||
uint64_t x7;
|
|
||||||
uint64_t x8;
|
|
||||||
uint64_t x9;
|
|
||||||
uint64_t x10;
|
|
||||||
uint64_t x11;
|
|
||||||
uint64_t x12;
|
|
||||||
uint64_t x13;
|
|
||||||
uint64_t x14;
|
|
||||||
uint64_t x15;
|
|
||||||
uint64_t x16;
|
|
||||||
uint64_t x17;
|
|
||||||
uint64_t x18;
|
|
||||||
uint64_t x19;
|
|
||||||
uint64_t x20;
|
|
||||||
uint64_t x21;
|
|
||||||
uint64_t x22;
|
|
||||||
uint64_t x23;
|
|
||||||
uint64_t x24;
|
|
||||||
uint64_t x25;
|
|
||||||
uint64_t x26;
|
|
||||||
uint64_t x27;
|
|
||||||
uint64_t x28;
|
|
||||||
uint64_t x29;
|
|
||||||
uint64_t x30;
|
|
||||||
} exception_frame;
|
|
||||||
void common_trap_handler(exception_frame *exception);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* .S */
|
|
||||||
|
|
||||||
#define EXC_FRAME_SIZE (288) /* sizeof(exception_frame) */
|
|
||||||
#define EXC_EXC_TYPE_OFFSET (0) /* offsetof(exception_frame, exc_type) */
|
|
||||||
#define EXC_EXC_ESR_OFFSET (8) /* offsetof(exception_frame, exc_esr) */
|
|
||||||
#define EXC_EXC_SP_OFFSET (16) /* offsetof(exception_frame, exc_sp) */
|
|
||||||
#define EXC_EXC_ELR_OFFSET (24) /* offsetof(exception_frame, exc_elr) */
|
|
||||||
#define EXC_EXC_SPSR_OFFSET (32) /* offsetof(exception_frame, exc_spsr) */
|
|
||||||
|
|
||||||
#define BUILD_TRAPFRAME(exc_type) \
|
|
||||||
stp x29, x30, [sp, -16]!; \
|
|
||||||
stp x27, x28, [sp, -16]!; \
|
|
||||||
stp x25, x26, [sp, -16]!; \
|
|
||||||
stp x23, x24, [sp, -16]!; \
|
|
||||||
stp x21, x22, [sp, -16]!; \
|
|
||||||
stp x19, x20, [sp, -16]!; \
|
|
||||||
stp x17, x18, [sp, -16]!; \
|
|
||||||
stp x15, x16, [sp, -16]!; \
|
|
||||||
stp x13, x14, [sp, -16]!; \
|
|
||||||
stp x11, x12, [sp, -16]!; \
|
|
||||||
stp x9, x10, [sp, -16]!; \
|
|
||||||
stp x7, x8, [sp, -16]!; \
|
|
||||||
stp x5, x6, [sp, -16]!; \
|
|
||||||
stp x3, x4, [sp, -16]!; \
|
|
||||||
stp x1, x2, [sp, -16]!; \
|
|
||||||
mrs x21, spsr_el1; \
|
|
||||||
stp x21, x0, [sp, -16]!; \
|
|
||||||
mrs x21, elr_el1; \
|
|
||||||
stp xzr, x21, [sp, -16]!; \
|
|
||||||
mov x21, (exc_type); \
|
|
||||||
mrs x22, esr_el1; \
|
|
||||||
stp x21, x22, [sp, -16]!
|
|
||||||
|
|
||||||
#define STORE_TRAPED_SP \
|
|
||||||
mrs x21, sp_el0; \
|
|
||||||
str x21, [sp, EXC_EXC_SP_OFFSET]
|
|
||||||
|
|
||||||
#define CALL_COMMON_TRAP_HANDLER \
|
|
||||||
mov x0, sp; \
|
|
||||||
bl common_trap_handler
|
|
||||||
|
|
||||||
#define STORE_NESTED_SP \
|
|
||||||
mov x21, sp; \
|
|
||||||
add x21, x21, EXC_FRAME_SIZE; \
|
|
||||||
str x21, [sp, EXC_EXC_SP_OFFSET]
|
|
||||||
|
|
||||||
#define RESTORE_TRAPED_SP \
|
|
||||||
ldr x21, [sp, EXC_EXC_SP_OFFSET]; \
|
|
||||||
msr sp_el0, x21
|
|
||||||
|
|
||||||
#define RESTORE_TRAPFRAME \
|
|
||||||
add sp, sp, 16; \
|
|
||||||
ldp x21, x22, [sp], 16; \
|
|
||||||
msr elr_el1, x22; \
|
|
||||||
ldp x21, x0, [sp], 16; \
|
|
||||||
msr spsr_el1, x21; \
|
|
||||||
ldp x1, x2, [sp], 16; \
|
|
||||||
ldp x3, x4, [sp], 16; \
|
|
||||||
ldp x5, x6, [sp], 16; \
|
|
||||||
ldp x7, x8, [sp], 16; \
|
|
||||||
ldp x9, x10, [sp], 16; \
|
|
||||||
ldp x11, x12, [sp], 16; \
|
|
||||||
ldp x13, x14, [sp], 16; \
|
|
||||||
ldp x15, x16, [sp], 16; \
|
|
||||||
ldp x17, x18, [sp], 16; \
|
|
||||||
ldp x19, x20, [sp], 16; \
|
|
||||||
ldp x21, x22, [sp], 16; \
|
|
||||||
ldp x23, x24, [sp], 16; \
|
|
||||||
ldp x25, x26, [sp], 16; \
|
|
||||||
ldp x27, x28, [sp], 16; \
|
|
||||||
ldp x29, x30, [sp], 16; \
|
|
||||||
eret
|
|
||||||
|
|
||||||
#define VECTOR_ENTRY(func_name) \
|
|
||||||
.align 7; \
|
|
||||||
b func_name
|
|
||||||
|
|
||||||
#define VECTOR_FUNC_ALIGN .align 2
|
|
||||||
|
|
||||||
#define VECTOR_FUNC(func_name, func_id) \
|
|
||||||
VECTOR_FUNC_ALIGN; \
|
|
||||||
func_name:; \
|
|
||||||
BUILD_TRAPFRAME(func_id); \
|
|
||||||
STORE_TRAPED_SP; \
|
|
||||||
CALL_COMMON_TRAP_HANDLER; \
|
|
||||||
RESTORE_TRAPED_SP; \
|
|
||||||
RESTORE_TRAPFRAME
|
|
||||||
|
|
||||||
#define VECTOR_FUNC_NESTED(func_name, func_id) \
|
|
||||||
VECTOR_FUNC_ALIGN; \
|
|
||||||
func_name:; \
|
|
||||||
BUILD_TRAPFRAME(func_id); \
|
|
||||||
STORE_NESTED_SP; \
|
|
||||||
CALL_COMMON_TRAP_HANDLER; \
|
|
||||||
RESTORE_TRAPFRAME
|
|
||||||
|
|
||||||
.align 11
|
|
||||||
.global vector_table
|
|
||||||
vector_table:
|
|
||||||
VECTOR_ENTRY(_curr_el_sp0_sync)
|
|
||||||
VECTOR_ENTRY(_curr_el_sp0_irq)
|
|
||||||
VECTOR_ENTRY(_curr_el_sp0_fiq)
|
|
||||||
VECTOR_ENTRY(_curr_el_sp0_serror)
|
|
||||||
|
|
||||||
VECTOR_ENTRY(_curr_el_spx_sync)
|
|
||||||
VECTOR_ENTRY(_curr_el_spx_irq)
|
|
||||||
VECTOR_ENTRY(_curr_el_spx_fiq)
|
|
||||||
VECTOR_ENTRY(_curr_el_spx_serror)
|
|
||||||
|
|
||||||
VECTOR_ENTRY(_lower_el_aarch64_sync)
|
|
||||||
VECTOR_ENTRY(_lower_el_aarch64_irq)
|
|
||||||
VECTOR_ENTRY(_lower_el_aarch64_fiq)
|
|
||||||
VECTOR_ENTRY(_lower_el_aarch64_serror)
|
|
||||||
|
|
||||||
VECTOR_ENTRY(_lower_el_aarch32_sync)
|
|
||||||
VECTOR_ENTRY(_lower_el_aarch32_irq)
|
|
||||||
VECTOR_ENTRY(_lower_el_aarch32_fiq)
|
|
||||||
VECTOR_ENTRY(_lower_el_aarch32_serror)
|
|
||||||
|
|
||||||
VECTOR_FUNC(_curr_el_sp0_sync, AARCH64_EXC_SYNC_SP0)
|
|
||||||
VECTOR_FUNC(_curr_el_sp0_irq, AARCH64_EXC_IRQ_SP0)
|
|
||||||
VECTOR_FUNC(_curr_el_sp0_fiq, AARCH64_EXC_FIQ_SP0)
|
|
||||||
VECTOR_FUNC(_curr_el_sp0_serror, AARCH64_EXC_SERR_SP0)
|
|
||||||
|
|
||||||
VECTOR_FUNC_NESTED(_curr_el_spx_sync, AARCH64_EXC_SYNC_SPX)
|
|
||||||
VECTOR_FUNC_NESTED(_curr_el_spx_irq, AARCH64_EXC_IRQ_SPX)
|
|
||||||
VECTOR_FUNC_NESTED(_curr_el_spx_fiq, AARCH64_EXC_FIQ_SPX)
|
|
||||||
VECTOR_FUNC_NESTED(_curr_el_spx_serror, AARCH64_EXC_SERR_SPX)
|
|
||||||
|
|
||||||
VECTOR_FUNC(_lower_el_aarch64_sync, AARCH64_EXC_SYNC_AARCH64)
|
|
||||||
VECTOR_FUNC(_lower_el_aarch64_irq, AARCH64_EXC_IRQ_AARCH64)
|
|
||||||
VECTOR_FUNC(_lower_el_aarch64_fiq, AARCH64_EXC_FIQ_AARCH64)
|
|
||||||
VECTOR_FUNC(_lower_el_aarch64_serror, AARCH64_EXC_SERR_AARCH64)
|
|
||||||
|
|
||||||
VECTOR_FUNC(_lower_el_aarch32_sync, AARCH64_EXC_SYNC_AARCH32)
|
|
||||||
VECTOR_FUNC(_lower_el_aarch32_irq, AARCH64_EXC_IRQ_AARCH32)
|
|
||||||
VECTOR_FUNC(_lower_el_aarch32_fiq, AARCH64_EXC_FIQ_AARCH32)
|
|
||||||
VECTOR_FUNC(_lower_el_aarch32_serror, AARCH64_EXC_SERR_AARCH32)
|
|
||||||
|
|||||||
@@ -1,31 +1,14 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include "common_aarch64.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
#define CNTV_CTL_ENABLE (1 << 0)
|
#define CNTV_CTL_ENABLE (1 << 0)
|
||||||
#define CNTV_CTL_IMASK (1 << 1)
|
#define CNTV_CTL_IMASK (1 << 1)
|
||||||
#define CNTV_CTL_ISTATUS (1 << 2)
|
#define CNTV_CTL_ISTATUS (1 << 2)
|
||||||
|
|
||||||
/* Frequency in Hz. ? */
|
|
||||||
SYSREG_READ_WRITE(uint64_t, cntfrq_el0)
|
|
||||||
|
|
||||||
/* Current virtual counter value. */
|
|
||||||
SYSREG_READ(uint64_t, cntvct_el0)
|
|
||||||
|
|
||||||
/* Compare value. See: cntv_ctl_el0_enable. */
|
|
||||||
SYSREG_READ_WRITE(uint64_t, cntv_cval_el0)
|
|
||||||
|
|
||||||
/* On write, set cntv_cval_el0 = (cntvct_el0 + cntv_tval_el0).
|
|
||||||
* This means that the next interrupt will happen in cntv_tval_el0 cycles.
|
|
||||||
*/
|
|
||||||
SYSREG_READ_WRITE(uint64_t, cntv_tval_el0)
|
|
||||||
|
|
||||||
/* Control register. */
|
|
||||||
SYSREG_READ_WRITE(uint32_t, cntv_ctl_el0)
|
|
||||||
|
|
||||||
void cntv_ctl_el0_disable(void) {
|
void cntv_ctl_el0_disable(void) {
|
||||||
sysreg_cntv_ctl_el0_write(sysreg_cntv_ctl_el0_read() & ~CNTV_CTL_ENABLE);
|
lkmc_sysreg_cntv_ctl_el0_write(lkmc_sysreg_cntv_ctl_el0_read() & ~CNTV_CTL_ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If enabled, when: cntv_ctl > cntv_cval then:
|
/* If enabled, when: cntv_ctl > cntv_cval then:
|
||||||
@@ -34,25 +17,25 @@ void cntv_ctl_el0_disable(void) {
|
|||||||
* * set CNTV_CTL_ISTATUS
|
* * set CNTV_CTL_ISTATUS
|
||||||
*/
|
*/
|
||||||
void cntv_ctl_el0_enable(void) {
|
void cntv_ctl_el0_enable(void) {
|
||||||
sysreg_cntv_ctl_el0_write(sysreg_cntv_ctl_el0_read() | CNTV_CTL_ENABLE);
|
lkmc_sysreg_cntv_ctl_el0_write(lkmc_sysreg_cntv_ctl_el0_read() | CNTV_CTL_ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
/* Initial state. */
|
/* Initial state. */
|
||||||
printf("cntv_ctl_el0 0x%" PRIx32 "\n", sysreg_cntv_ctl_el0_read());
|
printf("cntv_ctl_el0 0x%" PRIx32 "\n", lkmc_sysreg_cntv_ctl_el0_read());
|
||||||
printf("cntfrq_el0 0x%" PRIx64 "\n", sysreg_cntfrq_el0_read());
|
printf("cntfrq_el0 0x%" PRIx64 "\n", lkmc_sysreg_cntfrq_el0_read());
|
||||||
printf("cntv_cval_el0 0x%" PRIx64 "\n", sysreg_cntv_cval_el0_read());
|
printf("cntv_cval_el0 0x%" PRIx64 "\n", lkmc_sysreg_cntv_cval_el0_read());
|
||||||
|
|
||||||
/* Get the counter value many times to watch the time pass. */
|
/* Get the counter value many times to watch the time pass. */
|
||||||
printf("cntvct_el0 0x%" PRIx64 "\n", sysreg_cntvct_el0_read());
|
printf("cntvct_el0 0x%" PRIx64 "\n", lkmc_sysreg_cntvct_el0_read());
|
||||||
printf("cntvct_el0 0x%" PRIx64 "\n", sysreg_cntvct_el0_read());
|
printf("cntvct_el0 0x%" PRIx64 "\n", lkmc_sysreg_cntvct_el0_read());
|
||||||
printf("cntvct_el0 0x%" PRIx64 "\n", sysreg_cntvct_el0_read());
|
printf("cntvct_el0 0x%" PRIx64 "\n", lkmc_sysreg_cntvct_el0_read());
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* TODO crashes gem5. */
|
/* TODO crashes gem5. */
|
||||||
puts("cntfrq_el0 = 1");
|
puts("cntfrq_el0 = 1");
|
||||||
sysreg_cntfrq_el0_write(1);
|
lkmc_sysreg_cntfrq_el0_write(1);
|
||||||
printf("cntfrq_el0 0x%" PRIx64 "\n", sysreg_cntfrq_el0_read());
|
printf("cntfrq_el0 0x%" PRIx64 "\n", lkmc_sysreg_cntfrq_el0_read());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -7,6 +7,6 @@ main:
|
|||||||
/* test-gdb-result */
|
/* test-gdb-result */
|
||||||
cmp r1, #3
|
cmp r1, #3
|
||||||
beq 1f
|
beq 1f
|
||||||
bl common_assert_fail
|
bl lkmc_assert_fail
|
||||||
1:
|
1:
|
||||||
bx lr
|
bx lr
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include <common.h>
|
#include <lkmc.h>
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
common_assert_fail();
|
lkmc_assert_fail();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include <lkmc.h>
|
||||||
|
|
||||||
.global mystart
|
.global mystart
|
||||||
mystart:
|
mystart:
|
||||||
/* = NEON setup */
|
/* = NEON setup */
|
||||||
@@ -5,7 +7,26 @@ mystart:
|
|||||||
msr cpacr_el1, x1
|
msr cpacr_el1, x1
|
||||||
isb
|
isb
|
||||||
|
|
||||||
|
/* Load the vector table. */
|
||||||
|
ldr x0, =vector_table
|
||||||
|
msr vbar_el1, x0
|
||||||
|
|
||||||
|
/* Prepare the stack for main, mandatory for C code. */
|
||||||
ldr x0, =stack_top
|
ldr x0, =stack_top
|
||||||
mov sp, x0
|
mov sp, x0
|
||||||
bl main
|
bl main
|
||||||
|
|
||||||
|
/* If main returns, exit. */
|
||||||
bl exit
|
bl exit
|
||||||
|
|
||||||
|
LKMC_VECTOR_TABLE
|
||||||
|
|
||||||
|
/* Default trap handler that does nothing.
|
||||||
|
*
|
||||||
|
* Weak means that if any other file deinfes it as a non-weak global,
|
||||||
|
* that one will take precedence.
|
||||||
|
*
|
||||||
|
* We need this one to not get undefined references.
|
||||||
|
*/
|
||||||
|
LKMC_WEAK(lkmc_vector_trap_handler)
|
||||||
|
ret
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ Build the baremetal examples with crosstool-NG.
|
|||||||
def build(self):
|
def build(self):
|
||||||
build_dir = self.get_build_dir()
|
build_dir = self.get_build_dir()
|
||||||
bootloader_obj = os.path.join(self.env['baremetal_build_lib_dir'], 'bootloader{}'.format(self.env['obj_ext']))
|
bootloader_obj = os.path.join(self.env['baremetal_build_lib_dir'], 'bootloader{}'.format(self.env['obj_ext']))
|
||||||
common_basename_noext = 'common'
|
common_basename_noext = 'lkmc'
|
||||||
common_src = os.path.join(self.env['root_dir'], common_basename_noext + self.env['c_ext'])
|
common_src = os.path.join(self.env['root_dir'], common_basename_noext + self.env['c_ext'])
|
||||||
common_obj = os.path.join(self.env['baremetal_build_lib_dir'], common_basename_noext + self.env['obj_ext'])
|
common_obj = os.path.join(self.env['baremetal_build_lib_dir'], common_basename_noext + self.env['obj_ext'])
|
||||||
syscalls_basename_noext = 'syscalls'
|
syscalls_basename_noext = 'syscalls'
|
||||||
|
|||||||
7
common.c
7
common.c
@@ -1,7 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
void common_assert_fail() {
|
|
||||||
puts("lkmc_test_fail");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
8
common.h
8
common.h
@@ -1,8 +0,0 @@
|
|||||||
#ifndef COMMON_H
|
|
||||||
#define COMMON_H
|
|
||||||
|
|
||||||
/* Common baremetal and userland functionality. */
|
|
||||||
|
|
||||||
void common_assert_fail();
|
|
||||||
|
|
||||||
#endif
|
|
||||||
28
lkmc.c
Normal file
28
lkmc.c
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <lkmc.h>
|
||||||
|
|
||||||
|
void lkmc_assert(bool condition) {
|
||||||
|
if (!condition)
|
||||||
|
lkmc_assert_fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
void lkmc_assert_fail() {
|
||||||
|
puts("lkmc_test_fail");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__aarch64__)
|
||||||
|
#define LKMC_SYSREG_READ_WRITE(type, name) \
|
||||||
|
type CONCAT(CONCAT(LKMC_SYSREG_SYMBOL_PREFIX, name), _read(void)) { \
|
||||||
|
type name; \
|
||||||
|
__asm__ __volatile__("mrs %0, " #name : "=r" (name) : : ); \
|
||||||
|
return name; \
|
||||||
|
} \
|
||||||
|
void CONCAT(CONCAT(LKMC_SYSREG_SYMBOL_PREFIX, name), _write(type name)) { \
|
||||||
|
__asm__ __volatile__("msr " #name ", %0" : : "r" (name) : ); \
|
||||||
|
}
|
||||||
|
LKMC_SYSREG_OPS
|
||||||
|
#undef LKMC_SYSREG_READ_WRITE
|
||||||
|
#endif
|
||||||
259
lkmc.h
Normal file
259
lkmc.h
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
#ifndef LKMC_H
|
||||||
|
#define LKMC_H
|
||||||
|
|
||||||
|
/* Common C definitions. */
|
||||||
|
#if !defined(__ASSEMBLER__)
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
void lkmc_assert(bool);
|
||||||
|
void lkmc_assert_fail();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* https://stackoverflow.com/questions/1489932/how-to-concatenate-twice-with-the-c-preprocessor-and-expand-a-macro-as-in-arg */
|
||||||
|
#define CONCAT_EVAL(a,b) a ## b
|
||||||
|
#define CONCAT(a,b) CONCAT_EVAL(a, b)
|
||||||
|
|
||||||
|
#define LKMC_GLOBAL(name) \
|
||||||
|
.global name; \
|
||||||
|
name:
|
||||||
|
|
||||||
|
#define LKMC_WEAK(name) \
|
||||||
|
.weak name; \
|
||||||
|
name:
|
||||||
|
|
||||||
|
/* aarch64 specifics. */
|
||||||
|
#if defined(__aarch64__)
|
||||||
|
|
||||||
|
/* LKMC_VECTOR_TABLE
|
||||||
|
*
|
||||||
|
* Adapted from: https://github.com/takeharukato/sample-tsk-sw/blob/ce7973aa5d46c9eedb58309de43df3b09d4f8d8d/hal/aarch64/vector.S
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_SYNC_SP0 (0x1)
|
||||||
|
#define LKMC_VECTOR_IRQ_SP0 (0x2)
|
||||||
|
#define LKMC_VECTOR_FIQ_SP0 (0x3)
|
||||||
|
#define LKMC_VECTOR_SERR_SP0 (0x4)
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_SYNC_SPX (0x11)
|
||||||
|
#define LKMC_VECTOR_IRQ_SPX (0x12)
|
||||||
|
#define LKMC_VECTOR_FIQ_SPX (0x13)
|
||||||
|
#define LKMC_VECTOR_SERR_SPX (0x14)
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_SYNC_AARCH64 (0x21)
|
||||||
|
#define LKMC_VECTOR_IRQ_AARCH64 (0x22)
|
||||||
|
#define LKMC_VECTOR_FIQ_AARCH64 (0x23)
|
||||||
|
#define LKMC_VECTOR_SERR_AARCH64 (0x24)
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_SYNC_AARCH32 (0x31)
|
||||||
|
#define LKMC_VECTOR_IRQ_AARCH32 (0x32)
|
||||||
|
#define LKMC_VECTOR_FIQ_AARCH32 (0x33)
|
||||||
|
#define LKMC_VECTOR_SERR_AARCH32 (0x34)
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_EXC_FRAME_SIZE (288) /* sizeof(lkmc_vector_exception_frame) */
|
||||||
|
#define LKMC_VECTOR_EXC_EXC_TYPE_OFFSET (0) /* offsetof(lkmc_vector_exception_frame, exc_type) */
|
||||||
|
#define LKMC_VECTOR_EXC_EXC_ESR_OFFSE (8) /* offsetof(lkmc_vector_exception_frame, exc_esr) */
|
||||||
|
#define LKMC_VECTOR_EXC_EXC_SP_OFFSET (16) /* offsetof(lkmc_vector_exception_frame, exc_sp) */
|
||||||
|
#define LKMC_VECTOR_EXC_EXC_ELR_OFFSET (24) /* offsetof(lkmc_vector_exception_frame, exc_elr) */
|
||||||
|
#define LKMC_VECTOR_EXC_EXC_SPSR_OFFSET (32) /* offsetof(lkmc_vector_exception_frame, exc_spsr) */
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_FUNC_ALIGN .align 2
|
||||||
|
#define LKMC_VECTOR_SYMBOL_PREFIX lkmc_vector_
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_BUILD_TRAPFRAME(exc_type) \
|
||||||
|
stp x29, x30, [sp, -16]!; \
|
||||||
|
stp x27, x28, [sp, -16]!; \
|
||||||
|
stp x25, x26, [sp, -16]!; \
|
||||||
|
stp x23, x24, [sp, -16]!; \
|
||||||
|
stp x21, x22, [sp, -16]!; \
|
||||||
|
stp x19, x20, [sp, -16]!; \
|
||||||
|
stp x17, x18, [sp, -16]!; \
|
||||||
|
stp x15, x16, [sp, -16]!; \
|
||||||
|
stp x13, x14, [sp, -16]!; \
|
||||||
|
stp x11, x12, [sp, -16]!; \
|
||||||
|
stp x9, x10, [sp, -16]!; \
|
||||||
|
stp x7, x8, [sp, -16]!; \
|
||||||
|
stp x5, x6, [sp, -16]!; \
|
||||||
|
stp x3, x4, [sp, -16]!; \
|
||||||
|
stp x1, x2, [sp, -16]!; \
|
||||||
|
mrs x21, spsr_el1; \
|
||||||
|
stp x21, x0, [sp, -16]!; \
|
||||||
|
mrs x21, elr_el1; \
|
||||||
|
stp xzr, x21, [sp, -16]!; \
|
||||||
|
mov x21, (exc_type); \
|
||||||
|
mrs x22, esr_el1; \
|
||||||
|
stp x21, x22, [sp, -16]!
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_STORE_TRAPED_SP \
|
||||||
|
mrs x21, sp_el0; \
|
||||||
|
str x21, [sp, LKMC_VECTOR_EXC_EXC_SP_OFFSET]
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_CALL_TRAP_HANDLER \
|
||||||
|
mov x0, sp; \
|
||||||
|
bl lkmc_vector_trap_handler
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_STORE_NESTED_SP \
|
||||||
|
mov x21, sp; \
|
||||||
|
add x21, x21, LKMC_VECTOR_EXC_FRAME_SIZE; \
|
||||||
|
str x21, [sp, LKMC_VECTOR_EXC_EXC_SP_OFFSET]
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_RESTORE_TRAPED_SP \
|
||||||
|
ldr x21, [sp, LKMC_VECTOR_EXC_EXC_SP_OFFSET]; \
|
||||||
|
msr sp_el0, x21
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_RESTORE_TRAPFRAME \
|
||||||
|
add sp, sp, 16; \
|
||||||
|
ldp x21, x22, [sp], 16; \
|
||||||
|
msr elr_el1, x22; \
|
||||||
|
ldp x21, x0, [sp], 16; \
|
||||||
|
msr spsr_el1, x21; \
|
||||||
|
ldp x1, x2, [sp], 16; \
|
||||||
|
ldp x3, x4, [sp], 16; \
|
||||||
|
ldp x5, x6, [sp], 16; \
|
||||||
|
ldp x7, x8, [sp], 16; \
|
||||||
|
ldp x9, x10, [sp], 16; \
|
||||||
|
ldp x11, x12, [sp], 16; \
|
||||||
|
ldp x13, x14, [sp], 16; \
|
||||||
|
ldp x15, x16, [sp], 16; \
|
||||||
|
ldp x17, x18, [sp], 16; \
|
||||||
|
ldp x19, x20, [sp], 16; \
|
||||||
|
ldp x21, x22, [sp], 16; \
|
||||||
|
ldp x23, x24, [sp], 16; \
|
||||||
|
ldp x25, x26, [sp], 16; \
|
||||||
|
ldp x27, x28, [sp], 16; \
|
||||||
|
ldp x29, x30, [sp], 16; \
|
||||||
|
eret
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_ENTRY(func_name) \
|
||||||
|
.align 7; \
|
||||||
|
b LKMC_VECTOR_SYMBOL_PREFIX ## func_name
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_FUNC(func_name, func_id) \
|
||||||
|
LKMC_VECTOR_FUNC_ALIGN; \
|
||||||
|
LKMC_VECTOR_SYMBOL_PREFIX ## func_name:; \
|
||||||
|
LKMC_VECTOR_BUILD_TRAPFRAME(func_id); \
|
||||||
|
LKMC_VECTOR_STORE_TRAPED_SP; \
|
||||||
|
LKMC_VECTOR_CALL_TRAP_HANDLER; \
|
||||||
|
LKMC_VECTOR_RESTORE_TRAPED_SP; \
|
||||||
|
LKMC_VECTOR_RESTORE_TRAPFRAME
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_FUNC_NESTED(func_name, func_id) \
|
||||||
|
LKMC_VECTOR_FUNC_ALIGN; \
|
||||||
|
LKMC_VECTOR_SYMBOL_PREFIX ## func_name:; \
|
||||||
|
LKMC_VECTOR_BUILD_TRAPFRAME(func_id); \
|
||||||
|
LKMC_VECTOR_STORE_NESTED_SP; \
|
||||||
|
LKMC_VECTOR_CALL_TRAP_HANDLER; \
|
||||||
|
LKMC_VECTOR_RESTORE_TRAPFRAME
|
||||||
|
|
||||||
|
/* Define the actual vector table. */
|
||||||
|
#define LKMC_VECTOR_TABLE \
|
||||||
|
.align 11; \
|
||||||
|
.global vector_table; \
|
||||||
|
vector_table:; \
|
||||||
|
LKMC_VECTOR_ENTRY(curr_el_sp0_sync); \
|
||||||
|
LKMC_VECTOR_ENTRY(curr_el_sp0_irq); \
|
||||||
|
LKMC_VECTOR_ENTRY(curr_el_sp0_fiq); \
|
||||||
|
LKMC_VECTOR_ENTRY(curr_el_sp0_serror); \
|
||||||
|
; \
|
||||||
|
LKMC_VECTOR_ENTRY(curr_el_spx_sync); \
|
||||||
|
LKMC_VECTOR_ENTRY(curr_el_spx_irq); \
|
||||||
|
LKMC_VECTOR_ENTRY(curr_el_spx_fiq); \
|
||||||
|
LKMC_VECTOR_ENTRY(curr_el_spx_serror); \
|
||||||
|
; \
|
||||||
|
LKMC_VECTOR_ENTRY(lower_el_aarch64_sync); \
|
||||||
|
LKMC_VECTOR_ENTRY(lower_el_aarch64_irq); \
|
||||||
|
LKMC_VECTOR_ENTRY(lower_el_aarch64_fiq); \
|
||||||
|
LKMC_VECTOR_ENTRY(lower_el_aarch64_serror); \
|
||||||
|
; \
|
||||||
|
LKMC_VECTOR_ENTRY(lower_el_aarch32_sync); \
|
||||||
|
LKMC_VECTOR_ENTRY(lower_el_aarch32_irq); \
|
||||||
|
LKMC_VECTOR_ENTRY(lower_el_aarch32_fiq); \
|
||||||
|
LKMC_VECTOR_ENTRY(lower_el_aarch32_serror); \
|
||||||
|
; \
|
||||||
|
LKMC_VECTOR_FUNC(curr_el_sp0_sync, LKMC_VECTOR_SYNC_SP0); \
|
||||||
|
LKMC_VECTOR_FUNC(curr_el_sp0_irq, LKMC_VECTOR_IRQ_SP0); \
|
||||||
|
LKMC_VECTOR_FUNC(curr_el_sp0_fiq, LKMC_VECTOR_FIQ_SP0); \
|
||||||
|
LKMC_VECTOR_FUNC(curr_el_sp0_serror, LKMC_VECTOR_SERR_SP0); \
|
||||||
|
; \
|
||||||
|
LKMC_VECTOR_FUNC_NESTED(curr_el_spx_sync, LKMC_VECTOR_SYNC_SPX); \
|
||||||
|
LKMC_VECTOR_FUNC_NESTED(curr_el_spx_irq, LKMC_VECTOR_IRQ_SPX); \
|
||||||
|
LKMC_VECTOR_FUNC_NESTED(curr_el_spx_fiq, LKMC_VECTOR_FIQ_SPX); \
|
||||||
|
LKMC_VECTOR_FUNC_NESTED(curr_el_spx_serror, LKMC_VECTOR_SERR_SPX); \
|
||||||
|
; \
|
||||||
|
LKMC_VECTOR_FUNC(lower_el_aarch64_sync, LKMC_VECTOR_SYNC_AARCH64); \
|
||||||
|
LKMC_VECTOR_FUNC(lower_el_aarch64_irq, LKMC_VECTOR_IRQ_AARCH64); \
|
||||||
|
LKMC_VECTOR_FUNC(lower_el_aarch64_fiq, LKMC_VECTOR_FIQ_AARCH64); \
|
||||||
|
LKMC_VECTOR_FUNC(lower_el_aarch64_serror, LKMC_VECTOR_SERR_AARCH64); \
|
||||||
|
; \
|
||||||
|
LKMC_VECTOR_FUNC(lower_el_aarch32_sync, LKMC_VECTOR_SYNC_AARCH32); \
|
||||||
|
LKMC_VECTOR_FUNC(lower_el_aarch32_irq, LKMC_VECTOR_IRQ_AARCH32); \
|
||||||
|
LKMC_VECTOR_FUNC(lower_el_aarch32_fiq, LKMC_VECTOR_FIQ_AARCH32); \
|
||||||
|
LKMC_VECTOR_FUNC(lower_el_aarch32_serror, LKMC_VECTOR_SERR_AARCH32)
|
||||||
|
|
||||||
|
/* aarch64 C definitions. */
|
||||||
|
#if !defined(__ASSEMBLER__)
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t exc_type;
|
||||||
|
uint64_t exc_esr;
|
||||||
|
uint64_t exc_sp;
|
||||||
|
uint64_t exc_elr;
|
||||||
|
uint64_t exc_spsr;
|
||||||
|
uint64_t x0;
|
||||||
|
uint64_t x1;
|
||||||
|
uint64_t x2;
|
||||||
|
uint64_t x3;
|
||||||
|
uint64_t x4;
|
||||||
|
uint64_t x5;
|
||||||
|
uint64_t x6;
|
||||||
|
uint64_t x7;
|
||||||
|
uint64_t x8;
|
||||||
|
uint64_t x9;
|
||||||
|
uint64_t x10;
|
||||||
|
uint64_t x11;
|
||||||
|
uint64_t x12;
|
||||||
|
uint64_t x13;
|
||||||
|
uint64_t x14;
|
||||||
|
uint64_t x15;
|
||||||
|
uint64_t x16;
|
||||||
|
uint64_t x17;
|
||||||
|
uint64_t x18;
|
||||||
|
uint64_t x19;
|
||||||
|
uint64_t x20;
|
||||||
|
uint64_t x21;
|
||||||
|
uint64_t x22;
|
||||||
|
uint64_t x23;
|
||||||
|
uint64_t x24;
|
||||||
|
uint64_t x25;
|
||||||
|
uint64_t x26;
|
||||||
|
uint64_t x27;
|
||||||
|
uint64_t x28;
|
||||||
|
uint64_t x29;
|
||||||
|
uint64_t x30;
|
||||||
|
} LkmcVectorExceptionFrame;
|
||||||
|
|
||||||
|
void lkmc_vector_trap_handler(LkmcVectorExceptionFrame *exception);
|
||||||
|
|
||||||
|
#define LKMC_SVC(immediate) __asm__ __volatile__("svc " #immediate : : : )
|
||||||
|
|
||||||
|
#define LKMC_SYSREG_SYMBOL_PREFIX lkmc_sysreg_
|
||||||
|
#define LKMC_SYSREG_READ_WRITE(type, name) \
|
||||||
|
type CONCAT(CONCAT(LKMC_SYSREG_SYMBOL_PREFIX, name), _read)(void); \
|
||||||
|
void CONCAT(CONCAT(LKMC_SYSREG_SYMBOL_PREFIX, name), _write)(type name)
|
||||||
|
#define LKMC_SYSREG_OPS \
|
||||||
|
LKMC_SYSREG_READ_WRITE(uint32_t, cntv_ctl_el0); \
|
||||||
|
LKMC_SYSREG_READ_WRITE(uint32_t, daif); \
|
||||||
|
LKMC_SYSREG_READ_WRITE(uint32_t, spsel); \
|
||||||
|
LKMC_SYSREG_READ_WRITE(uint64_t, cntfrq_el0); \
|
||||||
|
LKMC_SYSREG_READ_WRITE(uint64_t, cntv_cval_el0); \
|
||||||
|
LKMC_SYSREG_READ_WRITE(uint64_t, cntv_tval_el0); \
|
||||||
|
LKMC_SYSREG_READ_WRITE(uint64_t, cntvct_el0); \
|
||||||
|
LKMC_SYSREG_READ_WRITE(uint64_t, sp_el1); \
|
||||||
|
LKMC_SYSREG_READ_WRITE(uint64_t, vbar_el1);
|
||||||
|
LKMC_SYSREG_OPS
|
||||||
|
#undef LKMC_SYSREG_READ_WRITE
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@@ -7,7 +7,7 @@ CXXFLAGS = -std=c++17 $(CCFLAGS) $(CXXFLAGS_EXTRA)
|
|||||||
# -Wno-unused-function for function definitions on headers,
|
# -Wno-unused-function for function definitions on headers,
|
||||||
# because we are lazy to make a shared object. TODO.
|
# because we are lazy to make a shared object. TODO.
|
||||||
COMMON_DIR = $(CURDIR)/..
|
COMMON_DIR = $(CURDIR)/..
|
||||||
COMMON_BASENAME = common
|
COMMON_BASENAME = lkmc
|
||||||
COMMON_OBJ = $(OUT_DIR)/$(COMMON_BASENAME)$(OBJ_EXT)
|
COMMON_OBJ = $(OUT_DIR)/$(COMMON_BASENAME)$(OBJ_EXT)
|
||||||
IN_EXT_ASM = .S
|
IN_EXT_ASM = .S
|
||||||
IN_EXT_C = .c
|
IN_EXT_C = .c
|
||||||
|
|||||||
Reference in New Issue
Block a user