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  }