From 84f88e5770270d7958c0787bc25aa954d00bc403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciro=20Santilli=20=E5=85=AD=E5=9B=9B=E4=BA=8B=E4=BB=B6=20?= =?UTF-8?q?=E6=B3=95=E8=BD=AE=E5=8A=9F?= Date: Tue, 6 Aug 2019 00:00:00 +0000 Subject: [PATCH] fix arm timer baremetal! --- baremetal/arch/aarch64/svc.c | 2 +- baremetal/arch/aarch64/timer.c | 54 ++++++++++++++++++++++++++-------- common.py | 2 ++ lkmc/aarch64.h | 6 ++-- lkmc/gicv3.h | 9 +++--- 5 files changed, 53 insertions(+), 20 deletions(-) diff --git a/baremetal/arch/aarch64/svc.c b/baremetal/arch/aarch64/svc.c index 09808d8..4f132b1 100644 --- a/baremetal/arch/aarch64/svc.c +++ b/baremetal/arch/aarch64/svc.c @@ -71,7 +71,7 @@ int main(void) { printf("&after_svc %p\n", &&after_svc); assert(myvar == 0); /* Max 16-bits. */ - LKMC_SVC(0xABCD); + lkmc_svc(0xABCD); after_svc: assert(myvar == 1); return 0; diff --git a/baremetal/arch/aarch64/timer.c b/baremetal/arch/aarch64/timer.c index 367c1ea..b02cd1a 100644 --- a/baremetal/arch/aarch64/timer.c +++ b/baremetal/arch/aarch64/timer.c @@ -4,15 +4,25 @@ #include #include -#define IRQ_FOUND (0) -#define IRQ_NOT_FOUND (1) +#define CLOCK_FREQUENCY 10 +#define INTERRUPT_FREQUENCY 1 void enable_irq(void) { - __asm__ __volatile__("msr DAIFClr, %0\n\t" : : "i" (LKMC_SYSREG_BITS_DAIF_IRQ) : "memory"); + __asm__ __volatile__( + "msr DAIFClr, %0\n\t" + : + : "i" (LKMC_SYSREG_BITS_DAIF_IRQ) + : "memory" + ); } void disable_irq(void) { - __asm__ __volatile__("msr DAIFSet, %0\n\t" : : "i" (LKMC_SYSREG_BITS_DAIF_IRQ) : "memory"); + __asm__ __volatile__( + "msr DAIFSet, %0\n\t" + : + : "i" (LKMC_SYSREG_BITS_DAIF_IRQ) + : "memory" + ); } /* Processor status word. */ @@ -23,6 +33,20 @@ void psw_disable_and_save_interrupt(uint64_t *pswp) { *pswp = psw; } +void disable_cntv(void) { + lkmc_sysreg_write_cntv_ctl_el0( + lkmc_sysreg_read_cntv_ctl_el0() & + LKMC_SYSREG_CNTV_CTL_ENABLE + ); +} + +void enable_cntv(void) { + lkmc_sysreg_write_cntv_ctl_el0( + lkmc_sysreg_read_cntv_ctl_el0() | + LKMC_SYSREG_CNTV_CTL_ENABLE + ); +} + /* Processor status word. */ void psw_restore_interrupt(uint64_t *pswp) { uint64_t psw; @@ -39,7 +63,7 @@ void lkmc_vector_trap_handler( if ((exception->exc_type & 0xff) == LKMC_VECTOR_IRQ_SPX) { psw_disable_and_save_interrupt(&psw); rc = gic_v3_find_pending_irq(exception, &irq); - if (rc != IRQ_FOUND) { + if (rc) { puts("IRQ not found!"); goto restore_irq_out; } else { @@ -47,17 +71,23 @@ void lkmc_vector_trap_handler( } gicd_disable_int(irq); gic_v3_eoi(irq); - printf("CNTVCT_EL0 0x%" PRIX64 "\n", lkmc_sysreg_read_cntvct_el0()); + // Timer specific stuff. + { + disable_cntv(); + gicd_clear_pending(TIMER_IRQ); + lkmc_sysreg_print_cntvct_el0(); + raw_write_cntv_cval_el0( + lkmc_sysreg_read_cntvct_el0() + + CLOCK_FREQUENCY / INTERRUPT_FREQUENCY + ); + enable_cntv(); + } gicd_enable_int(irq); restore_irq_out: psw_restore_interrupt(&psw); } } -void enable_cntv(void) { - lkmc_sysreg_write_cntv_ctl_el0(lkmc_sysreg_read_cntv_ctl_el0() | LKMC_CNTV_CTL_ENABLE); -} - int main(void) { /* Initial state. */ lkmc_sysreg_print_cntv_ctl_el0(); @@ -73,7 +103,7 @@ int main(void) { { /*uint64_t ticks, current_cnt;*/ /*uint32_t cntfrq;*/ - lkmc_sysreg_write_cntfrq_el0(1); + lkmc_sysreg_write_cntfrq_el0(CLOCK_FREQUENCY); /*ticks = cntfrq;*/ /*current_cnt = lkmc_sysreg_read_cntvct_el0();*/ /*lkmc_sysreg_write_cntv_cval_el0(current_cnt + ticks);*/ @@ -81,7 +111,7 @@ int main(void) { enable_irq(); } while (1) { - LKMC_WFI; + lkmc_wfi(); } return 0; } diff --git a/common.py b/common.py index bf94a76..5a56904 100644 --- a/common.py +++ b/common.py @@ -719,6 +719,8 @@ Incompatible archs are skipped. # http://lists.nongnu.org/archive/html/qemu-discuss/2018-08/msg00034.html env['machine2'] = 'highmem=off' elif env['arch'] == 'aarch64': + # TODO allow the Gic version to be controlled from the CLI. + # env['machine2'] = 'gic_version=3' env['machine2'] = None else: env['machine2'] = None diff --git a/lkmc/aarch64.h b/lkmc/aarch64.h index aec3c58..e6c5f74 100644 --- a/lkmc/aarch64.h +++ b/lkmc/aarch64.h @@ -293,9 +293,9 @@ typedef struct { void lkmc_vector_trap_handler(LkmcVectorExceptionFrame *exception); -/* Mistc assembly instructions. */ -#define LKMC_SVC(immediate) __asm__ __volatile__("svc " #immediate : : : ) -#define LKMC_WFI() __asm__ __volatile__ ("wfi" : : : "memory") +/* Misc assembly instructions. */ +#define lkmc_svc(immediate) __asm__ __volatile__("svc " #immediate : : : ) +#define lkmc_wfi() __asm__ __volatile__ ("wfi" : : : "memory") /* Sysreg read and write functions, e.g.: * diff --git a/lkmc/gicv3.h b/lkmc/gicv3.h index 69a135c..ecdaae1 100644 --- a/lkmc/gicv3.h +++ b/lkmc/gicv3.h @@ -286,8 +286,8 @@ void gic_v3_initialize(void) { init_gicd(); init_gicc(); gicd_config(TIMER_IRQ, GIC_GICD_ICFGR_EDGE); - gicd_set_priority(TIMER_IRQ, 0 << GIC_PRI_SHIFT ); /* Set priority */ - gicd_set_target(TIMER_IRQ, 0x1); /* processor 0 */ + gicd_set_priority(TIMER_IRQ, 0 << GIC_PRI_SHIFT); + gicd_set_target(TIMER_IRQ, 0x1); /* processor 0 */ gicd_clear_pending(TIMER_IRQ); gicd_enable_int(TIMER_IRQ); } @@ -296,6 +296,7 @@ void gic_v3_initialize(void) { /* Find pending IRQ * @param[in] exc An exception frame * @param[in,out] irqp An IRQ number to be processed + * @return 0 if found, 1 if not found */ int gic_v3_find_pending_irq( LkmcVectorExceptionFrame *exc __attribute__((unused)), @@ -305,12 +306,12 @@ int gic_v3_find_pending_irq( irq_no i; for (i = 0; GIC_INT_MAX > i; ++i) { if (gicd_probe_pending(i)) { - rc = 1; + rc = 0; *irqp = i; goto found; } } - rc = 0; + rc = 1; found: return rc; }