1/** 2 * \file timers.c 3 * \brief Timer support for ARMv8 4 */ 5 6/* 7 * Copyright (c) 2016 ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <kernel.h> 16#include <offsets.h> 17#include <platform.h> 18#include <serial.h> 19#include <sysreg.h> 20#include <arch/arm/gic.h> 21#include <systime.h> 22#include <timers.h> 23#include <dev/armv8_dev.h> 24 25cycles_t ticks_per_ms = 1; 26 27/* 28 * Timers 29 */ 30void timers_init(int timeslice) 31{ 32 printk(LOG_NOTE, "isr_el1=%p\n", sysreg_read_isr_el1()); 33 { 34 //armv8_CNTPS_CTL_EL1_t kctl; 35 armv8_CNTKCTL_EL1_t kctl; 36 kctl = armv8_CNTKCTL_EL1_rd(NULL); 37 38 /* don't trap access to CNTFRQ* and CNTFRQ* registers from EL0 to EL1 */ 39 kctl = armv8_CNTKCTL_EL1_EL0PCTEN_insert(kctl, 0x1); 40 kctl = armv8_CNTKCTL_EL1_EL0VCTEN_insert(kctl, 0x1); 41 42 /* trap access to CNTP_* and CNTV_* registers from EL0 to EL1 */ 43 kctl = armv8_CNTKCTL_EL1_EL0PTEN_insert(kctl, 0x0); 44 kctl = armv8_CNTKCTL_EL1_EL0VTEN_insert(kctl, 0x0); 45 46 armv8_CNTKCTL_EL1_wr(NULL, kctl); 47 } 48 49 /* enable the timer */ 50 armv8_CNTP_CTL_EL0_IMASK_wrf(NULL, 0x0); 51 armv8_CNTP_CTL_EL0_ENABLE_wrf(NULL, 0x1); 52 53 /* set the compare value */ 54 armv8_CNTP_CVAL_EL0_wr(NULL, 0xffffffffffffffff); 55 56 57 /* systime_frequency is ticks per milisecond, while timer_get_frequency is in HZ */ 58 systime_frequency = timer_get_frequency() / 1000; 59 60 /* The timeslice is in ms */ 61 kernel_timeslice = ns_to_systime(timeslice * 1000000); 62 63 printf("System counter frequency is %uHz.\n", timer_get_frequency()); 64 printf("Timeslice interrupt every %u ticks (%dms).\n", 65 kernel_timeslice, timeslice); 66 67 // Wait for n time units, close to cycles 68 armv8_CNTP_TVAL_EL0_wr(NULL, 100); 69 70 while (timer_is_set()) 71 ; 72 73 timer_reset(timeslice); 74 75 armv8_PMCR_EL0_t pmcr = 0; 76 pmcr = armv8_PMCR_EL0_E_insert(pmcr, 1); /* All counters are enabled.*/ 77 pmcr = armv8_PMCR_EL0_P_insert(pmcr, 1); /* reset all event counters */ 78 pmcr = armv8_PMCR_EL0_C_insert(pmcr, 1); /* reset all clock counters */ 79 pmcr = armv8_PMCR_EL0_D_insert(pmcr, 0); /* set counter to tick every clock cycle (1=ever 64th) */ 80 pmcr = armv8_PMCR_EL0_X_insert(pmcr, 1); /* enable event support */ 81 pmcr = armv8_PMCR_EL0_DP_insert(pmcr, 0); /* don't disable cycle counter */ 82 //pmcr = armv8_PMCR_EL0_N_insert(pmcr, 6); /* N is RO ? */ 83 armv8_PMCR_EL0_wr(NULL, pmcr); 84 85// AT: disable for now because it's not supported by QEMU version<2.6.0 86// AT: doesn't seem to break anything 87// armv8_PMUSERENR_EL0_t pmu = 0; 88 /* don't trap access to PM registers to EL 1 */ 89// pmu = armv8_PMUSERENR_EL0_EN_insert(pmu, 1); 90 /* don't trap software increment wrap to EL 1 */ 91// pmu = armv8_PMUSERENR_EL0_SW_insert(pmu, 1); 92 /* don't trap cycle counter to EL 1 */ 93// pmu = armv8_PMUSERENR_EL0_CR_insert(pmu, 1); 94 /* don't trap event counter read to EL 1*/ 95// pmu = armv8_PMUSERENR_EL0_ER_insert(pmu, 1); 96// armv8_PMUSERENR_EL0_wr(NULL, pmu); 97} 98 99/** 100 * 101 * @param ms 102 */ 103void timer_reset(uint64_t ms) 104{ 105 uint32_t val = ms * systime_frequency; 106 armv8_CNTP_TVAL_EL0_wr(NULL, val); 107} 108 109 110systime_t systime_now(void) 111{ 112 return timer_get_timestamp(); 113} 114