github.com/f-secure-foundry/tamago@v0.0.0-20220307101044-d73fcdd7f11b/arm/gic.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  const (
    17  	// GIC offsets in Cortex-A7
    18  	// (p178, Table 8-1, Cortex-A7 MPCore Technical Reference Manual).
    19  	GICD_OFF = 0x1000
    20  	GICC_OFF = 0x2000
    21  
    22  	// Distributor register map
    23  	// (p75, Table 4-1, ARM Generic Interrupt Controller Architecture Specification).
    24  	GICD_CTLR            = 0
    25  	GICD_CTLR_ENABLEGRP1 = 1
    26  	GICD_CTLR_ENABLEGRP0 = 0
    27  
    28  	GICD_TYPER         = 0x4
    29  	GICD_TYPER_ITLINES = 0
    30  
    31  	GICD_IGROUPR   = 0x080
    32  	GICD_ICENABLER = 0x180
    33  	GICD_ICPENDR   = 0x280
    34  
    35  	// CPU interface register map
    36  	// (p76, Table 4-2, ARM Generic Interrupt Controller Architecture Specification).
    37  	GICC_CTLR            = 0
    38  	GICC_CTLR_FIQEN      = 3
    39  	GICC_CTLR_ENABLEGRP1 = 1
    40  	GICC_CTLR_ENABLEGRP0 = 0
    41  
    42  	GICC_PMR          = 0x4
    43  	GICC_PMR_PRIORITY = 0
    44  )
    45  
    46  // InitGIC initializes the ARM Generic Interrupt Controller (GIC).
    47  func InitGIC(base uint32) {
    48  	gicd := base + GICD_OFF
    49  	gicc := base + GICC_OFF
    50  
    51  	// Get the maximum number of external interrupt lines
    52  	itLinesNum := reg.Get(gicd+GICD_TYPER, GICD_TYPER_ITLINES, 0x1f)
    53  
    54  	// Add a line for the 32 internal interrupts
    55  	itLinesNum += 1
    56  
    57  	for i := uint32(0); i < itLinesNum; i++ {
    58  		// Disable interrupts
    59  		addr := gicd + GICD_ICENABLER + 4*i
    60  		reg.Write(addr, 0xffffffff)
    61  
    62  		// Clear pending interrupts
    63  		addr = gicd + GICD_ICPENDR + 4*i
    64  		reg.Write(addr, 0xffffffff)
    65  
    66  		// Assign all interrupts to Non-Secure
    67  		addr = gicd + GICD_IGROUPR + 4*i
    68  		reg.Write(addr, 0xffffffff)
    69  	}
    70  
    71  	// Set priority mask to allow Non-Secure world to use the lower half
    72  	// of the priority range.
    73  	reg.Write(gicc+GICC_PMR, 0x80)
    74  
    75  	// Enable GIC
    76  	reg.Write(gicc+GICC_CTLR, GICC_CTLR_ENABLEGRP1|GICC_CTLR_ENABLEGRP0|GICC_CTLR_FIQEN)
    77  	reg.Set(gicd+GICD_CTLR, GICD_CTLR_ENABLEGRP1)
    78  	reg.Set(gicd+GICD_CTLR, GICD_CTLR_ENABLEGRP0)
    79  }