From 89084d23327209dece80d9685bd2a3bef6d20050 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: Sun, 16 Jun 2019 00:00:02 +0000 Subject: [PATCH] baremetal aarch64: timer.c get closer to working --- README.adoc | 11 +++++- baremetal/arch/aarch64/timer.c | 70 ++++++++++++++++++++-------------- common.py | 2 +- lkmc/gicv3.h | 12 +++--- path_properties.py | 1 + 5 files changed, 60 insertions(+), 36 deletions(-) diff --git a/README.adoc b/README.adoc index 4d34218..f3c12b5 100644 --- a/README.adoc +++ b/README.adoc @@ -14156,6 +14156,15 @@ TODO: create and study a minimal examples in gem5 where the DMB instruction lead TODO get working. Attempt at: link:baremetal/arch/aarch64/timer.c[] +The timer is documented at: <> Chapter D10 "The Generic Timer in AArch64 state" + +The key registers to keep in mind are: + +* `CNTVCT_EL0`: "Counter-timer Virtual Count register". The increasing current counter value. +* `CNTFRQ_EL0`: "Counter-timer Frequency register". "Indicates the system counter clock frequency, in Hz." +* `CNTV_CTL_EL0`: "Counter-timer Virtual Timer Control register" +* `CNTV_CVAL_EL0`: "Counter-timer Virtual Timer CompareValue register". The interrupt happens when `CNTVCT_EL0` reaches the value in this register. + ==== ARM baremetal bibliography First, also consider the userland bibliography: <>. @@ -14208,7 +14217,7 @@ which further confirms that the exception is correct: v2 has a register range at The original source does not mention GICv3 anywhere, only link:https://github.com/takeharukato/sample-tsk-sw/blob/c7bbc9dce6b14660bcce8d20735f8c6ebb09396b/hal/aarch64/gic-pl390.c[pl390], which is a specific GIC model that predates the GICv2 spec I believe. -TODO I hacked `#define GIC_GICC_BASE (GIC_BASE + 0xa0000)` and now continuing attempt. +TODO if I hack `#define GIC_GICC_BASE (GIC_BASE + 0xa0000)`, then it goes a bit further, but the next loop never ends. ===== tukl-msd/gem5.bare-metal diff --git a/baremetal/arch/aarch64/timer.c b/baremetal/arch/aarch64/timer.c index d39daae..78cff53 100644 --- a/baremetal/arch/aarch64/timer.c +++ b/baremetal/arch/aarch64/timer.c @@ -4,48 +4,62 @@ #include #include -#define CNTV_CTL_ENABLE (1 << 0) -#define CNTV_CTL_IMASK (1 << 1) -#define CNTV_CTL_ISTATUS (1 << 2) - -void cntv_ctl_el0_disable(void) { - lkmc_sysreg_cntv_ctl_el0_write(lkmc_sysreg_cntv_ctl_el0_read() & ~CNTV_CTL_ENABLE); +void lkmc_vector_trap_handler(LkmcVectorExceptionFrame *exception __attribute__((unused))) { + printf("CNTVCT_EL0 0x%" PRIx64 "\n", lkmc_sysreg_cntvct_el0_read()); } -/* If enabled, when: cntv_ctl > cntv_cval then: - * - * * if CNTV_CTL_IMASK is clear, raise an interrupt - * * set CNTV_CTL_ISTATUS - */ -void cntv_ctl_el0_enable(void) { +#define CNTV_CTL_ENABLE (1 << 0) /* Enables the timer */ +#define CNTV_CTL_IMASK (1 << 1) /* Timer interrupt mask bit */ +#define CNTV_CTL_ISTATUS (1 << 2) /* The status of the timer interrupt. This bit is read-only */ + +/* DAIF, Interrupt Mask Bits */ +#define DAIF_DBG_BIT (1<<3) /* Debug mask bit */ +#define DAIF_ABT_BIT (1<<2) /* Asynchronous abort mask bit */ +#define DAIF_IRQ_BIT (1<<1) /* IRQ mask bit */ +#define DAIF_FIQ_BIT (1<<0) /* FIQ mask bit */ + +#define wfi() __asm__ __volatile__ ("wfi" : : : "memory") + +void enable_cntv(void) { lkmc_sysreg_cntv_ctl_el0_write(lkmc_sysreg_cntv_ctl_el0_read() | CNTV_CTL_ENABLE); } - -void lkmc_vector_trap_handler(LkmcVectorExceptionFrame *exception __attribute__((unused))) { +void enable_irq(void) { + __asm__ __volatile__ ("msr DAIFClr, %0" : : "i" (DAIF_IRQ_BIT) : "memory"); } int main(void) { /* Initial state. */ - printf("cntv_ctl_el0 0x%" PRIx32 "\n", lkmc_sysreg_cntv_ctl_el0_read()); - printf("cntfrq_el0 0x%" PRIx64 "\n", lkmc_sysreg_cntfrq_el0_read()); - printf("cntv_cval_el0 0x%" PRIx64 "\n", lkmc_sysreg_cntv_cval_el0_read()); + printf("CNTV_CTL_EL0 0x%" PRIx32 "\n", lkmc_sysreg_cntv_ctl_el0_read()); + printf("CNTFRQ_EL0 0x%" PRIx64 "\n", lkmc_sysreg_cntfrq_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. */ - printf("cntvct_el0 0x%" PRIx64 "\n", lkmc_sysreg_cntvct_el0_read()); - printf("cntvct_el0 0x%" PRIx64 "\n", lkmc_sysreg_cntvct_el0_read()); - printf("cntvct_el0 0x%" PRIx64 "\n", lkmc_sysreg_cntvct_el0_read()); + printf("CNTVCT_EL0 0x%" PRIx64 "\n", lkmc_sysreg_cntvct_el0_read()); + printf("CNTVCT_EL0 0x%" PRIx64 "\n", lkmc_sysreg_cntvct_el0_read()); + printf("CNTVCT_EL0 0x%" PRIx64 "\n", lkmc_sysreg_cntvct_el0_read()); - /*gic_v3_initialize();*/ + /**/ + gic_v3_initialize(); { - /*uint64_t ticks, current_cnt;*/ - /*uint32_t cntfrq;*/ - /*cntfrq = raw_read_cntfrq_el0();*/ - /*ticks = cntfrq;*/ + uint64_t ticks, current_cnt; + uint32_t cntfrq; + cntfrq = lkmc_sysreg_cntfrq_el0_read(); + ticks = cntfrq; + current_cnt = lkmc_sysreg_cntvct_el0_read(); + lkmc_sysreg_cntv_cval_el0_write(current_cnt + ticks); + enable_cntv(); + enable_irq(); + } + while (1) { + /*puts("qwer");*/ /*current_cnt = raw_read_cntvct_el0();*/ - /*raw_write_cntv_cval_el0(current_cnt + ticks);*/ - /*enable_cntv();*/ - /*enable_irq();*/ + /*val = raw_read_cntv_ctl();*/ + /*printf("CNTVCT_EL0 = ");*/ + /*uart_puthex(current_cnt);*/ + /*uart_puts(", CNTV_CTL_EL0 = ");*/ + /*uart_puthex(val);*/ + /*wfi();*/ } #if 0 diff --git a/common.py b/common.py index 86b1f28..20b754c 100644 --- a/common.py +++ b/common.py @@ -699,7 +699,7 @@ Incompatible archs are skipped. # http://lists.nongnu.org/archive/html/qemu-discuss/2018-08/msg00034.html env['machine2'] = 'highmem=off' elif env['arch'] == 'aarch64': - env['machine2'] = 'gic_version=3' + env['machine2'] = None else: env['machine2'] = None diff --git a/lkmc/gicv3.h b/lkmc/gicv3.h index ea2f680..832b3b2 100644 --- a/lkmc/gicv3.h +++ b/lkmc/gicv3.h @@ -7,7 +7,7 @@ typedef int32_t irq_no; #define GIC_GICD_BASE (GIC_BASE) -#define GIC_GICC_BASE (GIC_BASE + 0xa0000) +#define GIC_GICC_BASE (GIC_BASE + 0x10000) #define GIC_GICD_INT_PER_REG (32) #define GIC_GICD_IPRIORITY_PER_REG (4) @@ -135,9 +135,11 @@ static void init_gicc(void) { *REG_GIC_GICC_BPR = GICC_BPR_NO_GROUP; /* Clear all of the active interrupts */ - for(pending_irq = ( *REG_GIC_GICC_IAR & GICC_IAR_INTR_IDMASK ); - ( pending_irq != GICC_IAR_SPURIOUS_INTR ); - pending_irq = ( *REG_GIC_GICC_IAR & GICC_IAR_INTR_IDMASK ) ) + for ( + pending_irq = (*REG_GIC_GICC_IAR & GICC_IAR_INTR_IDMASK); + pending_irq != GICC_IAR_SPURIOUS_INTR; + pending_irq = (*REG_GIC_GICC_IAR & GICC_IAR_INTR_IDMASK) + ) *REG_GIC_GICC_EOIR = *REG_GIC_GICC_IAR; /* Enable CPU interface */ @@ -215,7 +217,6 @@ static int gicd_probe_pending(irq_no irq) { is_pending = ( *REG_GIC_GICD_ISPENDR( (irq / GIC_GICD_ISPENDR_PER_REG) ) & ( 1U << ( irq % GIC_GICD_ISPENDR_PER_REG ) ) ); - return ( is_pending != 0 ); } @@ -232,7 +233,6 @@ static void gicd_set_target(irq_no irq, uint32_t p){ uint32_t reg; shift = (irq % GIC_GICD_ITARGETSR_PER_REG) * GIC_GICD_ITARGETSR_SIZE_PER_REG; - reg = *REG_GIC_GICD_ITARGETSR(irq / GIC_GICD_ITARGETSR_PER_REG); reg &= ~( ((uint32_t)(0xff)) << shift); reg |= (p << shift); diff --git a/path_properties.py b/path_properties.py index 2302590..db38e20 100644 --- a/path_properties.py +++ b/path_properties.py @@ -303,6 +303,7 @@ path_properties_tuples = ( ), 'return1.S': {'exit_status': 1}, 'semihost_exit.S': {'requires_semihosting': True}, + 'timer.c': {'skip_run_unclassified': True}, }, ) }