github.com/f-secure-foundry/tamago@v0.0.0-20220307101044-d73fcdd7f11b/arm/timer.go (about) 1 // ARM processor support 2 // https://github.com/f-secure-foundry/tamago 3 // 4 // Copyright (c) F-Secure Corporation 5 // https://foundry.f-secure.com 6 // 7 // Use of this source code is governed by the license 8 // that can be found in the LICENSE file. 9 10 package arm 11 12 import ( 13 "github.com/f-secure-foundry/tamago/internal/reg" 14 ) 15 16 // ARM timer register constants 17 const ( 18 // p2402, Table D5-1, ARMv7 Architecture Reference Manual 19 CNTCR = 0 20 // base frequency 21 CNTFID0 = 0x20 22 23 // p2410, D5.7.2 CNTCR, Counter Control Register, ARMv7 Architecture 24 // Reference Manual 25 // 26 // frequency = CNTFID0/CNTFID2 27 CNTCR_FCREQ2 = 10 28 // frequency = CNTFID0/CNTFID1 29 CNTCR_FCREQ1 = 9 30 // frequency = CNTFID0 31 CNTCR_FCREQ0 = 8 32 CNTCR_HDBG = 1 33 CNTCR_EN = 0 34 35 CNTKCTL_PL0PCTEN = 0 36 37 // nanoseconds 38 refFreq int64 = 1000000000 39 ) 40 41 // defined in timer_arm.s 42 func read_gtc() int64 43 func read_cntfrq() int32 44 func write_cntfrq(freq int32) 45 func write_cntkctl(val uint32) 46 func read_cntpct() int64 47 48 // Busyloop spins the processor for busy waiting purposes, taking a counter 49 // value for the number of loops. 50 func Busyloop(count int32) 51 52 // InitGlobalTimers initializes ARM Cortex-A9 timers. 53 func (cpu *CPU) InitGlobalTimers() { 54 cpu.TimerFn = read_gtc 55 cpu.TimerMultiplier = 10 56 } 57 58 // InitGenericTimers initializes ARM Cortex-A7 timers. 59 func (cpu *CPU) InitGenericTimers(base uint32, freq int32) { 60 var timerFreq int64 61 62 if freq != 0 && cpu.Secure() { 63 // set base frequency 64 write_cntfrq(freq) 65 reg.Write(base+CNTFID0, uint32(freq)) 66 67 // set system counter to base frequency 68 reg.Set(base+CNTCR, CNTCR_FCREQ0) 69 // stop system counter on debug 70 reg.Set(base+CNTCR, CNTCR_HDBG) 71 // start system counter 72 reg.Set(base+CNTCR, CNTCR_EN) 73 74 // grant PL0 access 75 write_cntkctl(1 << CNTKCTL_PL0PCTEN) 76 } 77 78 timerFreq = int64(read_cntfrq()) 79 80 cpu.TimerMultiplier = int64(refFreq / timerFreq) 81 cpu.TimerFn = read_cntpct 82 } 83 84 // SetTimerOffset sets the timer offset in nanoseconds. 85 func (cpu *CPU) SetTimerOffset(offset int64) { 86 if cpu.TimerFn == nil || cpu.TimerMultiplier == 0 { 87 return 88 } 89 90 cpu.TimerOffset = offset - int64(cpu.TimerFn()*cpu.TimerMultiplier) 91 }