├── Makefile ├── ReadMe.txt ├── headers ├── generic_timer.h ├── gicv3_basic.h ├── gicv3_lpis.h ├── gicv3_registers.h ├── gicv4_virt.h ├── sp804_timer.h └── system_counter.h ├── pre-build ├── image_basic.axf ├── image_gicv31.axf ├── image_lpi.axf ├── image_vlpi.axf └── image_vsgi.axf ├── scatter.txt ├── scatter_virt.txt ├── scripts ├── cluster0cpu1.asm ├── run_gicv3.sh ├── run_gicv4.sh └── run_gicv4_tarmac.sh └── src ├── el3_vectors.s ├── generic_timer.s ├── gicv3_basic.c ├── gicv3_cpuif.S ├── gicv3_lpis.c ├── gicv4_virt.c ├── main_basic.c ├── main_gicv31.c ├── main_lpi.c ├── main_vlpi.c ├── main_vsgi.c ├── secondary_virt.s ├── sp804_timer.c ├── startup.s ├── startup_virt.s └── system_counter.c /Makefile: -------------------------------------------------------------------------------- 1 | # ARMv8 Startup Example Makefile 2 | # 3 | # Copyright (C) ARM Limited, 2013. All rights reserved. 4 | # 5 | # This makefile is intended for use with GNU make 6 | # This example is intended to be built with ARM Compiler 6 7 | 8 | ASFLAGS= -gdwarf-3 -c --target=aarch64-arm-none-eabi 9 | CFLAGS= -gdwarf-3 -c --target=aarch64-arm-none-eabi -I"./headers" -O1 10 | 11 | CC=armclang 12 | AS=armclang 13 | LD=armlink 14 | 15 | GIC?= GICV3 16 | 17 | ifeq "$(GIC)" "GICV4" 18 | CFLAGS += -DGICV4=TRUE 19 | endif 20 | 21 | ifeq "$(DEBUG)" "TRUE" 22 | CFLAGS += -DDEBUG 23 | endif 24 | 25 | # Select build rules based on Windows or Unix 26 | ifdef WINDIR 27 | DONE=@if exist $(1) if exist $(2) echo Build completed. 28 | RM=if exist $(1) del /q $(1) 29 | SHELL=$(WINDIR)\system32\cmd.exe 30 | else 31 | ifdef windir 32 | DONE=@if exist $(1) if exist $(2) echo Build completed. 33 | RM=if exist $(1) del /q $(1) 34 | SHELL=$(windir)\system32\cmd.exe 35 | else 36 | DONE=@if [ -f $(1) ]; then if [ -f $(2) ]; then echo Build completed.; fi; fi 37 | RM=rm -f $(1) 38 | endif 39 | endif 40 | 41 | all: image_basic.axf image_lpi.axf image_gicv31.axf 42 | $(call DONE,$(EXECUTABLE)) 43 | 44 | CSCOPE = cscope 45 | TAGS = ctags 46 | 47 | gicv4: image_vlpi.axf image_vsgi.axf 48 | 49 | rebuild: clean all 50 | 51 | clean: 52 | $(call RM,*.o) 53 | $(call RM,cscope*) 54 | $(call RM,tags) 55 | $(call RM,image_basic.axf) 56 | $(call RM,image_lpi.axf) 57 | $(call RM,image_gicv31.axf) 58 | $(call RM,image_vlpi.axf) 59 | $(call RM,image_vsgi.axf) 60 | 61 | cscope: 62 | @find . -name '*.[hcsS]' -print > cscope.files 63 | @cscope -bkqu 64 | .PHONY:cscope 65 | 66 | tags: 67 | @find . -name '*.[hcsS]' -print | xargs $(TAGS) -a 68 | .PHONY:tags 69 | 70 | main_basic.o: ./src/main_basic.c 71 | $(CC) ${CFLAGS} ./src/main_basic.c 72 | 73 | main_gicv31.o: ./src/main_gicv31.c 74 | $(CC) ${CFLAGS} ./src/main_gicv31.c 75 | 76 | main_lpi.o: ./src/main_lpi.c 77 | $(CC) ${CFLAGS} ./src/main_lpi.c 78 | 79 | main_vlpi.o: ./src/main_vlpi.c 80 | $(CC) ${CFLAGS} ./src/main_vlpi.c 81 | 82 | main_vsgi.o: ./src/main_vsgi.c 83 | $(CC) ${CFLAGS} ./src/main_vsgi.c 84 | 85 | gicv3_basic.o: ./src/gicv3_basic.c 86 | $(CC) ${CFLAGS} ./src/gicv3_basic.c 87 | 88 | gicv3_lpis.o: ./src/gicv3_lpis.c 89 | $(CC) ${CFLAGS} ./src/gicv3_lpis.c 90 | 91 | gicv4_virt.o: ./src/gicv4_virt.c 92 | $(CC) ${CFLAGS} ./src/gicv4_virt.c 93 | 94 | system_counter.o: ./src/system_counter.c 95 | $(CC) ${CFLAGS} ./src/system_counter.c 96 | 97 | sp804_timer.o: ./src/sp804_timer.c 98 | $(CC) ${CFLAGS} ./src/sp804_timer.c 99 | 100 | startup.o: ./src/startup.s 101 | $(AS) ${ASFLAGS} ./src/startup.s 102 | 103 | startup_virt.o: ./src/startup_virt.s 104 | $(AS) ${ASFLAGS} ./src/startup_virt.s 105 | 106 | secondary_virt.o: ./src/secondary_virt.s 107 | $(AS) ${ASFLAGS} ./src/secondary_virt.s 108 | 109 | el3_vectors.o: ./src/el3_vectors.s 110 | $(AS) ${ASFLAGS} ./src/el3_vectors.s 111 | 112 | generic_timer.o: ./src/generic_timer.s 113 | $(AS) ${ASFLAGS} ./src/generic_timer.s 114 | 115 | gicv3_cpuif.o: ./src/gicv3_cpuif.S 116 | $(AS) ${ASFLAGS} ./src/gicv3_cpuif.S 117 | 118 | image_basic.axf: main_basic.o generic_timer.o system_counter.o sp804_timer.o startup.o gicv3_basic.o gicv3_cpuif.o el3_vectors.o scatter.txt 119 | $(LD) --scatter=scatter.txt main_basic.o generic_timer.o system_counter.o sp804_timer.o startup.o gicv3_basic.o gicv3_cpuif.o el3_vectors.o -o image_basic.axf --entry=start64 120 | 121 | image_gicv31.axf: main_gicv31.o startup.o gicv3_basic.o gicv3_cpuif.o el3_vectors.o scatter.txt 122 | $(LD) --scatter=scatter.txt main_gicv31.o startup.o gicv3_basic.o gicv3_cpuif.o el3_vectors.o -o image_gicv31.axf --entry=start64 123 | 124 | image_lpi.axf: main_lpi.o generic_timer.o system_counter.o startup.o gicv3_basic.o gicv3_lpis.o gicv3_cpuif.o el3_vectors.o scatter.txt 125 | $(LD) --scatter=scatter.txt main_lpi.o generic_timer.o system_counter.o startup.o gicv3_basic.o gicv3_lpis.o gicv3_cpuif.o el3_vectors.o -o image_lpi.axf --entry=start64 126 | 127 | image_vlpi.axf: main_vlpi.o generic_timer.o system_counter.o startup_virt.o secondary_virt.o gicv3_basic.o gicv4_virt.o gicv3_lpis.o gicv3_cpuif.o el3_vectors.o scatter.txt 128 | $(LD) --scatter=scatter_virt.txt main_vlpi.o generic_timer.o system_counter.o startup_virt.o secondary_virt.o gicv3_basic.o gicv3_lpis.o gicv4_virt.o gicv3_cpuif.o el3_vectors.o -o image_vlpi.axf --entry=start64 129 | 130 | image_vsgi.axf: main_vsgi.o generic_timer.o system_counter.o startup_virt.o secondary_virt.o gicv3_basic.o gicv4_virt.o gicv3_lpis.o gicv3_cpuif.o el3_vectors.o scatter.txt 131 | $(LD) --scatter=scatter_virt.txt main_vsgi.o generic_timer.o system_counter.o startup_virt.o secondary_virt.o gicv3_basic.o gicv3_lpis.o gicv4_virt.o gicv3_cpuif.o el3_vectors.o -o image_vsgi.axf --entry=start64 132 | -------------------------------------------------------------------------------- /ReadMe.txt: -------------------------------------------------------------------------------- 1 | AArch64 Generic Interrupt Controller (v3/v4) Example 2 | ==================================================== 3 | 4 | Introduction 5 | ============ 6 | This example demonstrates the use of the Generic Interrupt Controller (GIC) in a baremetal environment. 7 | 8 | 9 | Notice 10 | ======= 11 | Copyright (C) Arm Limited, 2019-2021 All rights reserved. 12 | 13 | The example code is provided to you as an aid to learning when working 14 | with Arm-based technology, including but not limited to programming tutorials. 15 | Arm hereby grants to you, subject to the terms and conditions of this Licence, 16 | a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 17 | to use and copy the Software solely for the purpose of demonstration and 18 | evaluation. 19 | 20 | You accept that the Software has not been tested by Arm therefore the Software 21 | is provided 'as is', without warranty of any kind, express or implied. In no 22 | event shall the authors or copyright holders be liable for any claim, damages 23 | or other liability, whether in action or contract, tort or otherwise, arising 24 | from, out of or in connection with the Software or the use of Software. 25 | 26 | 27 | Requirements 28 | ============ 29 | * Arm Development Studio Gold edition (GICv3.0) 30 | * Arm Development Studio Platinum edition (GICv3.1 and GICv4.1) 31 | 32 | 33 | File list 34 | ========= 35 | 36 | |-> headers 37 | | |-> generic_timer.h 38 | | |-> gicv3_basic.h 39 | | |-> gicv3_lpi.h 40 | | |-> gicv3_registers.h 41 | | |-> gicv4_virt.h 42 | | |-> system_counter.h 43 | | 44 | |-> src 45 | | |-> el3_vectors.s Minimal vector table 46 | | |-> generic_timer.s Helper functions for Generic Timer 47 | | |-> gicv3_basic.c Helper functions for GICv3.1 48 | | |-> gicv3_lpis.c Helper functions for GICv3.1 physical LPIs 49 | | |-> gicv4_virt.c Helper functions for GICv4.1 virtualization 50 | | |-> main_basic.c Example showing usage of SPIs and PPIs. 51 | | |-> main_gicv31.c Example showing usage of GICv3.1 Extended PPI and SPI rangess. 52 | | |-> main_lpi.c Example showing usage of physical LPIs. 53 | | |-> main_vlpi.c Example showing usage of GICv4.1 virtual LPIs. 54 | | |-> main_vsgi.c Example showing usage of GICv4.1 virtual SGIs. 55 | | |-> secondary_virt.s Boot code for secondary core, used by the GICv4.1 example. 56 | | |-> startup.s Minimal reset handler. 57 | | |-> startup_virt.s Minimal reset handler, used by the GICv4.1 example. 58 | | |-> system_counter.s Helper functions for System Counter 59 | | 60 | |-> scripts 61 | | |-> run_gicv3.sh Helper scripts for runing FVP 62 | | |-> run_gicv4.sh Helper scripts for runing FVP 63 | | 64 | |-> pre-build 65 | | |-> image_basic.axf Pre-build executable image for GICv3.0 SPI & PPI. 66 | | |-> image_gicv31.axf Pre-build executable image for GICv3.1 Extended PPI and SPI. 67 | | |-> image_lpi.axf Pre-build executbale image for GICv3.x physical LPI. 68 | | |-> image_vlpi.axf Pre-build executbale image for GICv4.1 virtual LPI. 69 | | |-> image_vsgi.axf Pre-build executbale image for GICv4.1 virtual SGI. 70 | | 71 | |-> Makefile 72 | |-> ReadMe.txt This file 73 | |-> scatter.txt Memory layout for linker 74 | 75 | 76 | Description 77 | =========== 78 | The package includes a number of small example programs, each demonstrating a different aspect of using the GIC. 79 | 80 | These examples work with GICv3.x and GICv4.x: 81 | 82 | image_basic 83 | This example shows the basic set up of a GICv3/4 interrupt controller, including the PPI and SPI interrupt types. 84 | 85 | image_lpi 86 | This example shows the setup and use of physical LPIs and the ITS. 87 | 88 | 89 | These examples require GICv3.1: 90 | 91 | image_gicv31 92 | This example shows the use of the GICv3.1 extended PPI and SPI ranges. 93 | 94 | 95 | These examples require GICv4.1: 96 | 97 | image_vlpi 98 | This example shows the setup and use of GICv4.1 virtual LPIs. 99 | 100 | image_vsgi 101 | This example shows the setup and use of GICv4.1 virtual SGIs. 102 | 103 | 104 | 105 | Building the example from the command line 106 | ========================================== 107 | To build the example: 108 | - Open a DS-5 or Arm Developer Studio command prompt, then navigate to the location of the example 109 | 110 | The make command depends on the version of the GIC architecture implemented. 111 | 112 | For GICv3.x: 113 | - Run "make DEBUG=TRUE" 114 | 115 | For GICv4.1: 116 | - Run "make GIC=GICV4" to build PPI, SPI, and physical LPI examples. 117 | - Run "make GIC=GICV4 gicv4" to build vLPI and vSGI examples. 118 | 119 | 120 | Optionally, adding "DEBUG=TRUE" results in additional logging messages being printed. 121 | 122 | Note: 123 | When a GIC implements GICv3.x, the Redistributors occupy 128K of address space. 124 | When GICv4.x is implemented, they occupy 256K. 125 | The example requires the Redistributor size at build time, which is why the GIC version is passed as an argument to make. 126 | 127 | 128 | Explanation of model parameters 129 | =============================== 130 | These examples are intended to run on the FVP Base Platform model (FVP_Base_AEMv8A-AEMv8A). 131 | This model takes a number of parameters to configure how the GIC appears to software. 132 | Some of the examples require non-default values, this section describes the parameters used for the different examples. 133 | 134 | -C cluster0.gicv3.extended-interrupt-range-support=1 135 | Controls whether the PE supports the GICv3.1 extended range, default 0. the image_gicv31 examples requires this to be set to 1. 136 | 137 | 138 | -C gic_distributor.extended-ppi-count= 139 | Controls how many (if any) GICv3.1 extended PPIs are available, default 0. The image_gicv31 example requires this to be set to 32. 140 | 141 | 142 | -C gic_distributor.extended-spi-count= 143 | Controls how many (if any) GICv3.1 extended SPIs are available, default 0. The image_gicv31 example requires this to be set to 32. 144 | 145 | 146 | -C gic_distributor.ITS-count= 147 | Controls how many (if any) ITSs are present, default 0. Most of the examples require it to be set to 1. 148 | 149 | 150 | -C gic_distributor.ITS-use-physical-target-addresses= 151 | Controls the value of GITS_TYPER.PTA, default 1. Most of the examples requires it to be set to 0. 152 | 153 | 154 | -C gic_distributor.virtual-lpi-support= 155 | Whether the GIC supports GICv4.x, default FALSE. The GICv4.1 examples require it to be set to TRUE. 156 | 157 | 158 | -C has-gicv4.1= 159 | Whether the GIC supports GICv4.1, default FALSE. The GICv4.1 examples require this to be set to TRUE. 160 | 161 | 162 | -C gic_distributor.GITS_BASER-type= 163 | The type of table for each GITS_BASER register. Most of the examples require to be set to: 164 | GITS_BASER0 = 1 165 | GITS_BASER1 = 4 166 | GITS_BASER2 = 2 (GICv4.1 examples only) 167 | 168 | 169 | -C gic_distributor.ITS-vmovp-bit= 170 | Controls the value of GITS_TYPER.VMOVP, default 0. GICv4.1 examples require 1. 171 | 172 | 173 | -C gic_distributor.common-lpi-configuration=2 174 | -C gic_distributor.ITS-shared-vPE-table=2 175 | 176 | Collectively control the ITS's CommonLPIAff behaviour. 177 | GICv4.1 examples require them both to be set to 2. 178 | -------------------------------------------------------------------------------- /headers/generic_timer.h: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // ARMv8-A AArch64 Generic Timer 3 | // Header Filer 4 | // 5 | // Copyright (C) Arm Limited, 2019 All rights reserved. 6 | // 7 | // The example code is provided to you as an aid to learning when working 8 | // with Arm-based technology, including but not limited to programming tutorials. 9 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 10 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 11 | // to use and copy the Software solely for the purpose of demonstration and 12 | // evaluation. 13 | // ------------------------------------------------------------ 14 | 15 | #ifndef _ARMV8A_GENERIC_TIMER_H 16 | #define _ARMV8A_GENERIC_TIMER_H 17 | 18 | #include 19 | 20 | // ------------------------------------------------------------ 21 | // CNTFRQ holds the frequency of the system counter 22 | // Readable in all ELs 23 | // Writable only by EL3 24 | 25 | // Returns the value of CNTFRQ_EL0 26 | uint32_t getCNTFRQ(void); 27 | 28 | // Sets the value of CNTFRQ_EL0 (EL3 only!) 29 | // freq - The value to be written into CNTFRQ_EL3 30 | void setCNTFRQ(uint32_t freq); 31 | 32 | // ------------------------------------------------------------ 33 | // CNTPCT_EL0 and CNTVCT_EL0 hold the physical and virtual counts 34 | // Always accessable in Hpy and Secure EL1 35 | // Access from EL2 and Non-secure EL1 is configurable 36 | 37 | // Returns the current value of physical count (CNTPCT_EL0) 38 | uint64_t getPhysicalCount(void); 39 | 40 | // Returns the current value of the virtual count register (CNTVCT_EL0) 41 | uint64_t getVirtualCount(void); 42 | 43 | // ------------------------------------------------------------ 44 | // The CNTKCTL register controls whether CNTPCT can be accessed from EL0 45 | // Only acceable from EL1 and EL2 46 | 47 | #define CNTKCTL_PCTEN (1 << 0) // Controls whether the physical counter, CNTPCT, and the frequency register CNTFRQ, are accessible from EL0 48 | #define CNTKCTL_VCTEN (1 << 1) // Controls whether the virtual counter, CNTVCT, and the frequency register CNTFRQ, are accessible from 49 | #define CNTKCTL_EVNTEN (1 << 2) // Enables the generation of an event stream from the virtual counter 50 | #define CNTKCTL_EVNTDIR (1 << 3) // Controls which transition of the CNTVCT trigger bit, defined by EVNTI, generates an event 51 | 52 | // Returns the value of EL1 Timer Control Register (CNTKCTL_EL1) 53 | uint32_t getEL1Ctrl(void); 54 | 55 | // Sets the value of EL1 Timer Control Register (CNTKCTL_EL1) 56 | // value - The value to be written into CNTKCTL_EL1 57 | void setEL1Ctrl(uint32_t value); 58 | 59 | // ------------------------------------------------------------ 60 | // The CNTHCTL_EL2 register controls whether CNTPCT_EL0 can be accessed from EL1 61 | // Only accessable from EL2 and EL3 62 | 63 | #define CNTHCTL_CNTPCT (1 << 0) 64 | #define CNTHCTL_EVNTEN (1 << 2) 65 | #define CNTHCTL_EVNTDIR (1 << 3) 66 | 67 | // Returns the value of the EL2 Timer Control Register (CNTHCTL_EL2) 68 | uint32_t getEL2Ctrl(void); 69 | 70 | // Sets the value of EL2 Timer Control Register (CNTHCTL_EL2) 71 | // value - The value to be written into CNTHCTL_EL2 72 | void setEL2Ctrl(uint32_t value); 73 | 74 | // ------------------------------------------------------------ 75 | // Non-secure Physical Timer 76 | // ------------------------------------------------------------ 77 | // Accessible from EL3, EL2 and EL1 78 | 79 | // Returns the value of Non-secure EL1 Physical Compare Value Register (CNTP_CVAL_EL0) 80 | uint64_t getNSEL1PhysicalCompValue(void); 81 | 82 | // Sets the value of the Non-secure EL1 Physical Compare Value Register (CNTP_CVAL_EL0) 83 | // value - The value to be written into CNTP_CVAL_EL0 84 | void setNSEL1PhysicalCompValue(uint64_t value); 85 | 86 | // Returns the value of Non-secure EL1 Physical Timer Value Register (CNTP_TVAL_EL0) 87 | uint32_t getNSEL1PhysicalTimerValue(void); 88 | 89 | // Sets the value of the Non-secure EL1 Physical Timer Value Register (CNTP_TVAL_EL0) 90 | // value - The value to be written into CNTP_TVAL_EL0 91 | void setNSEL1PhysicalTimerValue(uint32_t value); 92 | 93 | #define CNTP_CTL_ENABLE (1 << 0) 94 | #define CNTP_CTL_MASK (1 << 1) 95 | #define CNTP_CTL_STATUS (1 << 2) 96 | 97 | // Returns the value of Non-secure EL1 Physical Timer Control Register (CNTP_CTL_EL0) 98 | uint32_t getNSEL1PhysicalTimerCtrl(void); 99 | 100 | // Sets the value of the Non-secure EL1 Physical Timer Control Register (CNTP_CTL_EL0) 101 | // value - The value to be written into CNTP_CTL_EL0 102 | void setNSEL1PhysicalTimerCtrl(uint32_t value); 103 | 104 | // ------------------------------------------------------------ 105 | // Secure Physical Timer 106 | // ------------------------------------------------------------ 107 | // Accessible from EL3, and configurably from secure EL1 108 | 109 | // Returns the value of Secure EL1 Physical Compare Value Register (CNTPS_CVAL_EL1) 110 | uint64_t getSEL1PhysicalCompValue(void); 111 | 112 | // Sets the value of the Secure EL1 Physical Compare Value Register (CNTPS_CVAL_EL1) 113 | // value - The value to be written into CNTPS_CVAL_EL1 114 | void setSEL1PhysicalCompValue(uint64_t value); 115 | 116 | // Returns the value of Secure EL1 Physical Timer Value Register (CNTPS_TVAL_EL1) 117 | uint32_t getSEL1PhysicalTimerValue(void); 118 | 119 | // Sets the value of the Secure EL1 Physical Timer Value Register (CNTPS_TVAL_EL1) 120 | // value - The value to be written into CNTPS_TVAL_EL1 121 | void setSEL1PhysicalTimerValue(uint32_t value); 122 | 123 | #define CNTPS_CTL_ENABLE (1 << 0) 124 | #define CNTPS_CTL_MASK (1 << 1) 125 | #define CNTPS_CTL_STATUS (1 << 2) 126 | 127 | // Returns the value of Secure EL1 Physical Timer Control Register (CNTPS_CTL_EL1) 128 | uint32_t getSEL1PhysicalTimerCtrl(void); 129 | 130 | // Sets the value of the Secure EL1 Physical Timer Control Register (CNTPS_CTL_EL1) 131 | // value - The value to be written into CNTPS_CTL_EL1 132 | void setSEL1PhysicalTimerCtrl(uint32_t value); 133 | 134 | // The SCR_EL3 register controls whether CNTPS_TVAL_EL1, 135 | // CNTPS_CTL_EL1, and CNTPS_CVAL_EL1 can be accessed by secure 136 | // EL1. 137 | // Only accessible from EL3 138 | 139 | #define SCR_ENABLE_SECURE_EL1_ACCESS (1) 140 | #define SCR_DISABLE_SECURE_EL1_ACCESS (0) 141 | 142 | // Sets the values of the SCR_EL3.ST bit (bit 11) based on the value passed in 'config' 143 | void configSecureEL1TimerAccess(uint32_t config); 144 | 145 | // ------------------------------------------------------------ 146 | // Virtual Timer 147 | // ------------------------------------------------------------ 148 | // Accessible from Non-secure EL1 and EL2 149 | 150 | // Returns the value of EL1 Virtual Compare Value Register (CNTV_CVAL) 151 | uint64_t getEL1VirtualCompValue(void); 152 | 153 | // Sets the value of the EL1 Virtual Compare Value Register (CNTV_CVAL) 154 | // value - The value to be written into CNTV_CVAL 155 | void setEL1VirtualCompValue(uint64_t value); 156 | 157 | // Returns the value of EL1 Virtual Timer Value Register (CNTV_TVAL) 158 | uint32_t getEL1VirtualTimerValue(void); 159 | 160 | // Sets the value of the EL1 Virtual Timer Value Register (CNTV_TVAL) 161 | // value - The value to be written into CNTV_TVAL 162 | void setEL1VirtualTimerValue(uint32_t value); 163 | 164 | #define CNTV_CTL_ENABLE (1 << 0) 165 | #define CNTV_CTL_MASK (1 << 1) 166 | #define CNTV_CTL_STATUS (1 << 2) 167 | 168 | // Returns the value of EL1 Virtual Timer Control Register (CNTV_CTL) 169 | uint32_t getEL1VirtualTimerCtrl(void); 170 | 171 | // Sets the value of the EL1 Virtual Timer Control Register (CNTV_CTL) 172 | // value - The value to be written into CNTV_CTL 173 | void setEL1VirtualTimerCtrl(uint32_t value); 174 | 175 | // 176 | // Virtual timer functions to be called by EL2 177 | // 178 | 179 | // CNTVCT_EL2 holds the offset the virtual count is from the physical count 180 | // Only accessable from EL2 and EL3 181 | 182 | // Returns the value of the Counter Virtual Offset Register (CNTVOFF_EL2) 183 | uint64_t getVirtualCounterOffset(void); 184 | 185 | // Sets the value of the Counter Virtual Offset Register (CNTVOFF_EL2) 186 | // offset - The value to be written into CNTVOFF_EL2 187 | void setVirtualCounterOffset(uint64_t offset); 188 | 189 | // ------------------------------------------------------------ 190 | // Hypervisor (EL2) Timer 191 | // ------------------------------------------------------------ 192 | 193 | // Returns the value of EL2 Physical Compare Value Register (CNTHP_CVAL_EL2) 194 | uint64_t getEL2PhysicalCompValue(void); 195 | 196 | // Sets the value of the EL2 Physical Compare Value Register (CNTHP_CVAL_EL2) 197 | // value - The value to be written into CNTHP_CVAL_EL2 198 | void setEL2PhysicalCompValue(uint64_t value); 199 | 200 | // Returns the value of EL2 Physical Timer Value Register (CNTHP_TVAL_EL2) 201 | uint32_t getEL2PhysicalTimerValue(void); 202 | 203 | #define CNTHP_CTL_ENABLE (1 << 0) 204 | #define CNTHP_CTL_MASK (1 << 1) 205 | #define CNTHP_CTL_STATUS (1 << 2) 206 | 207 | // Sets the value of the EL2 Physical Timer Value Register (CNTHP_TVAL_EL2) 208 | // value - The value to be written into CNTHP_TVAL_EL2 209 | void setEL2PhysicalTimerValue(uint32_t value); 210 | 211 | #endif 212 | 213 | // ------------------------------------------------------------ 214 | // End of generic_timer.h 215 | // ------------------------------------------------------------ 216 | -------------------------------------------------------------------------------- /headers/gicv3_basic.h: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------- 2 | // GICv3 Helper Functions for AArch64 3 | // Header 4 | // 5 | // Copyright (C) Arm Limited, 2019 All rights reserved. 6 | // 7 | // The example code is provided to you as an aid to learning when working 8 | // with Arm-based technology, including but not limited to programming tutorials. 9 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 10 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 11 | // to use and copy the Software solely for the purpose of demonstration and 12 | // evaluation. 13 | // ------------------------------------------------------------ 14 | 15 | 16 | #ifndef __gicv3_h 17 | #define __gicv3_h 18 | 19 | #include 20 | 21 | /* GICD_TYPER field descriptions */ 22 | #define ESPI_range_SHIFT 27 23 | #define ESPI_range_MASK (0x1f << ESPI_range_SHIFT) 24 | #define RSS_SHIFT 26 25 | #define RSS_MASK (0x1 << RSS_SHIFT) 26 | #define No1N_SHIFT 25 27 | #define No1N_MASK (0x1 << No1N_SHIFT) 28 | #define A3V_SHIFT 24 29 | #define A3V_MASK (0x1 << A3V_SHIFT) 30 | #define IDbits_SHIFT 19 31 | #define IDbits_MASK (0x1f << IDbits_SHIFT) 32 | #define DVIS_SHIFT 19 33 | #define DVIS_MASK (0x1 << DVIS_SHIFT) 34 | #define MBIS_SHIFT 16 35 | #define MBIS_MASK (0x1 << MBIS_SHIFT) 36 | #define num_LPIs_SHIFT 11 37 | #define num_LPIs_MASK (0x1f << num_LPIs_SHIFT) 38 | #define SecurityExtn_SHIFT 10 39 | #define SecurityExtn_MASK (0x1 << SecurityExtn_SHIFT) 40 | #define ESPI_SHIFT 8 41 | #define ESPI_MASK (0x1 << ESPI_SHIFT) 42 | #define CPUNumber_SHIFT 5 43 | #define CPUNumber_MASK (0x7 << CPUNumber_SHIFT) 44 | #define ITLinesNumber_SHIFT 0 45 | #define ITLinesNumber_MASK (0x1f << ITLinesNumber_SHIFT) 46 | 47 | /* GICR_TYPER field descriptions */ 48 | #define PPInum_SHIFT 27 49 | #define PPInum_MASK (0x1f << PPInum_SHIFT) 50 | #define VSGI_SHIFT 26 51 | #define VSGI_MASK (0x1 << VSGI_SHIFT) 52 | #define CommonLPIAff_SHIFT 24 53 | #define CommonLPIAff_MASK (0x3 << CommonLPIAff_SHIFT) 54 | #define Processor_Number_SHIFT 8 55 | #define Processor_Number_MASK (0xffff << Processor_Number_SHIFT) 56 | #define RVPEID_SHIFT 7 57 | #define RVPEID_MASK (0x1 << RVPEID_SHIFT) 58 | #define MPAM_SHIFT 6 59 | #define MPAM_MASK (0x1 << MPAM_SHIFT) 60 | #define DPGS_SHIFT 5 61 | #define DPGS_MASK (0x1 << DPGS_SHIFT) 62 | #define Last_SHIFT 4 63 | #define Last_MASK (0x1 << Last_SHIFT) 64 | #define DirectLPI_SHIFT 3 65 | #define DirectLPI_MASK (0x1 << DirectLPI_SHIFT) 66 | #define Dirty_SHIFT 2 67 | #define Dirty_MASK (0x1 << Dirty_SHIFT) 68 | #define VLPIS_SHIFT 1 69 | #define VLPIS_MASK (0x1 << VLPIS_SHIFT) 70 | #define PLPIS_SHIFT 0 71 | #define PLPIS_MASK (0x1 << PLPIS_SHIFT) 72 | 73 | #define GET_FIELD(reg,mask,shift) ((reg & mask ) >> shift) 74 | 75 | // ------------------------------------------------------------ 76 | // Address Functions 77 | // ------------------------------------------------------------ 78 | 79 | // 80 | // THESE FUNCTIONS MUST BE CALLED TO SET THE REGISTER FILE 81 | // LOCATIONS BEFORE USING THE OTHER FUNCTIONS! 82 | // 83 | 84 | // Sets the address of the Distributor and Redistributors 85 | // dist = virtual address of the Distributor 86 | // rdist = virtual address of the first RD_base register page 87 | void setGICAddr(void* dist, void* rdist); 88 | 89 | 90 | // ------------------------------------------------------------ 91 | // Discovery function for Distributor and Redistributors 92 | // ------------------------------------------------------------ 93 | 94 | // Returns the number of PPIs in the GICv3.1 extended range 95 | uint32_t getExtPPI(uint32_t rd); 96 | 97 | // Returns the number of SPIs in the GICv3.0 range 98 | uint32_t getSPI(void); 99 | 100 | // Returns the number of SPIs in the GICv3.1 extended SPI range 101 | uint32_t getExtSPI(void); 102 | 103 | // ------------------------------------------------------------ 104 | // Distributor Functions 105 | // ------------------------------------------------------------ 106 | 107 | // Sets the group enable bits in the Distributor, with GICv3 mode selected 108 | uint32_t enableGIC(void); 109 | 110 | 111 | // ------------------------------------------------------------ 112 | // Redistributor Functions 113 | // 114 | // These functions make a number of assumptions about the 115 | // memory used for the command queue: 116 | // * The memory is flat mapped (VA==PA) 117 | // * The memory is either coherent or non-cacheble. 118 | // 119 | // ------------------------------------------------------------ 120 | 121 | // Get Redistributer number for a given affinity 122 | // affinity 123 | uint32_t getRedistID(uint32_t affinity); 124 | 125 | 126 | // Wakes the currently select redistributor 127 | // rd = Redistributor number 128 | uint32_t wakeUpRedist(uint32_t rd); 129 | 130 | // ---------------------------------------------------------- 131 | // SGI, PPIs and SPI configuration functions 132 | // ---------------------------------------------------------- 133 | 134 | // Enables the INTID 135 | // INTID = INTID of interrupt 136 | // rd = Redistributor number (ignored if INTID is a SPI) 137 | uint32_t enableInt(uint32_t INTID, uint32_t rd); 138 | 139 | 140 | // Disables the INTID 141 | // INTID = INTID of interrupt 142 | // rd = Redistributor number (ignored if INTID is a SPI) 143 | uint32_t disableInt(uint32_t INTID, uint32_t rd); 144 | 145 | 146 | // Sets the priority of the specified INITD 147 | // INTID = INTID of interrupt 148 | // rd = Redistributor number (ignored if INTID is a SPI) 149 | // priority = priority (8-bit unsigned value) 150 | uint32_t setIntPriority(uint32_t INTID, uint32_t rd, uint8_t priority); 151 | 152 | 153 | // Sets the target CPUs of the specified INTID 154 | // INTID = INTID of interrupt (must be in the range 32 to 1019) 155 | // mode = Routing mode 156 | // aff = Affinity co-ordinate of target 157 | #define GICV3_ROUTE_MODE_ANY (0x80000000) 158 | #define GICV3_ROUTE_MODE_COORDINATE (0) 159 | uint32_t setIntRoute(uint32_t INTID, uint32_t mode, uint32_t affinity); 160 | 161 | 162 | // Configures the INTID as edge or level sensitive 163 | // INTID = INTID of interrupt 164 | // rd = Redistributor number (ignored if INTID is a SPI) 165 | // conf = Whether the INTID should edge or level (use define above) 166 | #define GICV3_CONFIG_LEVEL (0) 167 | #define GICV3_CONFIG_EDGE (2) 168 | uint32_t setIntType(uint32_t INTID, uint32_t rd, uint32_t conf); 169 | 170 | 171 | // Set security/group of the specified INTID 172 | // INTID = INTID of interrupt (ID must be less than 32) 173 | // rd = Redistributor number (ignored if INTID is a SPI) 174 | // group = Security/group setting 175 | #define GICV3_GROUP0 (0) 176 | #define GICV3_GROUP1_SECURE (1) 177 | #define GICV3_GROUP1_NON_SECURE (2) 178 | 179 | uint32_t setIntGroup(uint32_t INTID, uint32_t rd, uint32_t group); 180 | 181 | 182 | // Sets the pending bit of the specified INIT 183 | // INTID = INTID of interrupt (ID must be less than 1020) 184 | uint32_t setIntPending(uint32_t INTID, uint32_t rd); 185 | 186 | 187 | // Clears the pending bit of the specified INTID 188 | // INTID = INTID of interrupt (ID must be less than 1020) 189 | uint32_t clearIntPending(uint32_t INTID, uint32_t rd); 190 | 191 | // ------------------------------------------------------------ 192 | // CPU Interface functions 193 | // ------------------------------------------------------------ 194 | 195 | // Enables group 0 interrupts 196 | // The lowest EL that access the ICC_IGRPEN0_EL1 is determined 197 | // by the routine of the FIQ exception. 198 | void enableGroup0Ints(void); 199 | 200 | 201 | // Disables group 0 interrupts 202 | // The lowest EL that access the ICC_IGRPEN0_EL1 is determined 203 | // by the routine of the FIQ exception. 204 | void disableGroup0Ints(void); 205 | 206 | 207 | // Enables group 1 interrupts for current security state 208 | // The lowest EL that access the ICC_IGRPEN1_EL1 is determined 209 | // by the routine of the IRQ exception. 210 | void enableGroup1Ints(void); 211 | 212 | 213 | // Disables group 1 interrupts for current security state 214 | // The lowest EL that access the ICC_IGRPEN1_EL1 is determined 215 | // by the routine of the IRQ exception. 216 | void disableGroup1Ints(void); 217 | 218 | 219 | // Enables group 1 interrupts for non-secure state 220 | // 221 | // Used by EL3 to enable non-secure group 1 interrupts 222 | void enableNSGroup1Ints(void); 223 | 224 | 225 | // Disables group 1 interrupts for non-secure state 226 | // 227 | // Used by EL3 to disable non-secure group 1 interrupts 228 | void disableNSGroup1Ints(void); 229 | 230 | 231 | // Returns the value of the ICC_IAR0_EL1 (Group 0 Interrupt Acknowledge) 232 | uint32_t readIARGrp0(void); 233 | 234 | 235 | // Writes INTID to the End Of Interrupt register 236 | void writeEOIGrp0(uint32_t INTID); 237 | 238 | 239 | // Writes INTID to the De-active Interrupt register 240 | void writeDIR(uint32_t INTID); 241 | 242 | 243 | // Returns the value of the ICC_IAR1_EL1 (Group 1 Interrupt Acknowledge) 244 | uint32_t readIARGrp1(void); 245 | 246 | 247 | // Writes INTID to the Aliased End Of Interrupt register 248 | void writeEOIGrp1(uint32_t INTID); 249 | 250 | 251 | // Sets the Priority mask register for the core run on 252 | // priority - mask value (8-bit unsigned value). 253 | // 254 | // NOTE: An interrupt must be high priority (lower numeric value) than the mask to be sent 255 | void setPriorityMask(uint32_t priority); 256 | 257 | 258 | // Sets ICC_BPR0_EL1 for the core run on 259 | // priority - Binary piont value 260 | void setBPR0(uint32_t priority); 261 | 262 | 263 | // Sets ICC_BPR1_EL1 for the core run on 264 | // priority - Binary piont value 265 | void setBPR1(uint32_t priority); 266 | 267 | 268 | // Returns the priority of the current active interrupt 269 | uint32_t getRunningPriority(void); 270 | 271 | // ------------------------------------------------------------ 272 | // SGIs 273 | // ------------------------------------------------------------ 274 | 275 | #define GICV3_SGI_AFF3_SHIFT (48) 276 | #define GICV3_SGI_AFF2_SHIFT (32) 277 | #define GICV3_SGI_AFF1_SHIFT (16) 278 | 279 | #define GICV3_SGI_ROUTING_ALL ((uint64_t)1 << 40) 280 | #define GICV3_SGI_ROUTING_LIST (0) 281 | 282 | #define GICV3_SGI_TARGET_CPU0 (0x0001) 283 | #define GICV3_SGI_TARGET_CPU1 (0x0002) 284 | #define GICV3_SGI_TARGET_CPU2 (0x0004) 285 | #define GICV3_SGI_TARGET_CPU3 (0x0008) 286 | #define GICV3_SGI_TARGET_CPU4 (0x0010) 287 | #define GICV3_SGI_TARGET_CPU5 (0x0020) 288 | #define GICV3_SGI_TARGET_CPU6 (0x0040) 289 | #define GICV3_SGI_TARGET_CPU7 (0x0080) 290 | #define GICV3_SGI_TARGET_CPU8 (0x0100) 291 | #define GICV3_SGI_TARGET_CPU9 (0x0200) 292 | #define GICV3_SGI_TARGET_CPU10 (0x0400) 293 | #define GICV3_SGI_TARGET_CPU11 (0x0800) 294 | #define GICV3_SGI_TARGET_CPU12 (0x1000) 295 | #define GICV3_SGI_TARGET_CPU13 (0x2000) 296 | #define GICV3_SGI_TARGET_CPU14 (0x4000) 297 | #define GICV3_SGI_TARGET_CPU15 (0x8000) 298 | 299 | #define GICV3_SGI_ID0 (0x0 << 24) 300 | #define GICV3_SGI_ID1 (0x1 << 24) 301 | #define GICV3_SGI_ID2 (0x2 << 24) 302 | #define GICV3_SGI_ID3 (0x3 << 24) 303 | #define GICV3_SGI_ID4 (0x4 << 24) 304 | #define GICV3_SGI_ID5 (0x5 << 24) 305 | #define GICV3_SGI_ID6 (0x6 << 24) 306 | #define GICV3_SGI_ID7 (0x7 << 24) 307 | #define GICV3_SGI_ID8 (0x8 << 24) 308 | #define GICV3_SGI_ID9 (0x9 << 24) 309 | #define GICV3_SGI_ID10 (0xA << 24) 310 | #define GICV3_SGI_ID11 (0xB << 24) 311 | #define GICV3_SGI_ID12 (0xC << 24) 312 | #define GICV3_SGI_ID13 (0xD << 24) 313 | #define GICV3_SGI_ID14 (0xE << 24) 314 | #define GICV3_SGI_ID15 (0xF << 24) 315 | 316 | // Send a Group 0 SGI 317 | void sendGroup0SGI(uint32_t INTID, uint64_t mode, uint32_t target_list); 318 | 319 | 320 | // Send a Group 1 SGI, current security state 321 | void sendGroup1SGI(uint32_t INTID, uint64_t mode, uint32_t target_list); 322 | 323 | 324 | // Send a Group 1 SGI, other security state 325 | void sendOtherGroup1SGI(uint32_t INTID, uint64_t mode, uint32_t target_list); 326 | 327 | 328 | // Sets non-secure state ability to generate secure group 0/1 SGIs 329 | // INTID = INTID of interrupt (must be 0 to 15) 330 | #define GICV3_SGI_NO_NS_ACCESS (0) 331 | #define GICV3_SGI_NS_ACCESS_GROUP0 (0x1) 332 | #define GICV3_SGI_NS_ACCESS_GROUP1 (0x2) 333 | 334 | void configNSAccessSGI(uint32_t INTID, unsigned access); 335 | 336 | uint32_t getGICDTyper(void); 337 | uint64_t getGICRTyper(void); 338 | 339 | #endif 340 | 341 | // ---------------------------------------------------------- 342 | // End of gicv3_basic.h 343 | // ---------------------------------------------------------- 344 | -------------------------------------------------------------------------------- /headers/gicv3_lpis.h: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------- 2 | // GICv3 Functions for managing physical LPIs 3 | // Header 4 | // 5 | // Copyright (C) Arm Limited, 2019 All rights reserved. 6 | // 7 | // The example code is provided to you as an aid to learning when working 8 | // with Arm-based technology, including but not limited to programming tutorials. 9 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 10 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 11 | // to use and copy the Software solely for the purpose of demonstration and 12 | // evaluation. 13 | // ------------------------------------------------------------ 14 | 15 | #ifndef __gicv3_lpis_h 16 | #define __gicv3_lpis_h 17 | 18 | #include 19 | 20 | // ------------------------------------------------------------ 21 | // Address Functions 22 | // ------------------------------------------------------------ 23 | 24 | // Selects an ITS 25 | // ITS_base = virtual address of ITS_base register page 26 | void setITSBaseAddress(void* ITS_base); 27 | 28 | // ------------------------------------------------------------ 29 | // Redistributor setup functions 30 | // ------------------------------------------------------------ 31 | 32 | // Used for setLPIConfigTableAddr() and setLPIPendingTableAddr() 33 | #define GICV3_LPI_INNER_SHARED (0x1 << 10) 34 | #define GICV3_LPI_OUTER_SHARED (0x2 << 10) 35 | #define GICV3_LPI_NON_SHARED (0) 36 | 37 | #define GICV3_LPI_NORMAL_WBWA (((uint64_t)0x5 << 56) | (uint64_t)(0x5 << 7)) 38 | #define GICV3_LPI_DEVICE_nGnRnE (0) 39 | 40 | 41 | // Set address of LPI config table for the selected Redistributor 42 | // rd = Redistributor 43 | // addr = physical address of allocated memory 44 | // attributes = cacheability/shareabilty settings 45 | // IDbits = number of ID bits 46 | // 47 | // NOTE: If IDbits > GICD_TYPER.IDbits, GICD_CTLR.IDbits will be used 48 | // NOTE: The amount of memory allocated must be enough for the number of IDbits! 49 | // NOTE: This function will use memset() to zero the allocated memory. 50 | uint32_t setLPIConfigTableAddr(uint32_t rd, uint64_t addr, uint64_t attributes, uint32_t INTIDbits); 51 | 52 | 53 | // Set address of the LPI pending table for the selected Redistributor 54 | // rd = Redistributor 55 | // addr = physical address of allocated memory 56 | // attributes = cacheability/shareabilty settings 57 | // IDbits = number of ID bits (needed in order to work how much memory to zero) 58 | // 59 | // NOTE: The amount of memory allocated must be enough for the number of IDbits! 60 | // NOTE: This function will use memset() to zero the allocated memory. 61 | uint32_t setLPIPendingTableAddr(uint32_t rd, uint64_t addr, uint64_t attributes, uint32_t INTIDbits); 62 | 63 | 64 | // Enables LPIs for the currently selected Redistributor 65 | // NOTE: DO NOT CALL THIS BEFORE ALLOCATING TABLES! 66 | void enableLPIs(uint32_t rd); 67 | 68 | 69 | // Returns the RD's Processor_Number, used in ITS commands when GITS_TYPER.PTA==0 70 | uint32_t getRdProcNumber(uint32_t rd); 71 | 72 | 73 | // Returns the maximum LPI INTID supported by the GIC 74 | uint32_t getMaxLPI(uint32_t rd); 75 | 76 | // ------------------------------------------------------------ 77 | // Configuring LPI functions 78 | // ------------------------------------------------------------ 79 | 80 | #define GICV3_LPI_ENABLE (1) 81 | #define GICV3_LPI_DISABLE (0) 82 | 83 | // Configures specified LPI 84 | // rd = Redistributor 85 | // INTID = INTID of LPI to be configured (must be 8192 or greater, no upper limit check) 86 | // enable = whether ID is enabled (1=enabled, 0=disabled) 87 | // priority = priority for ID 88 | uint32_t configureLPI(uint32_t rd, uint32_t INTID, uint32_t enable, uint32_t priority); 89 | 90 | 91 | // ------------------------------------------------------------ 92 | // ITS setup functions 93 | // ------------------------------------------------------------ 94 | 95 | #define GICV3_ITS_CQUEUE_VALID ((uint64_t)1 << 63) 96 | #define GICV3_ITS_CQUEUE_INVALID (0) 97 | 98 | // Initializes the currently selected ITS's command queue 99 | // addr = base address of allocated memory, must be 64K aligned 100 | // attributes = cacheabilit, shareabilty and valid bit 101 | // num_pages = number of 4K pages (must be 1 or greater) 102 | // 103 | // NOTE: The GITS_CBASER encodes the number of pages as (number - 1). 104 | // This functions expects an unmodified value (i.e. pass 1, if 1 page allocated). 105 | // NOTE: This function will use memset() to zero the allocated memory. 106 | uint32_t initITSCommandQueue(uint64_t addr, uint64_t attributes, uint32_t num_pages); 107 | 108 | // Returns the type and entry size of GITS_BASER[index] of the currently selected ITS 109 | // index = which GITS_BASERn register to access, must be in the range 0 to 7 110 | // type = pointer to a uint32_t, function write the vale of the GITS_BASERn.Type to this pointer 111 | // entry_size = pointer to a uint32_t, function write the vale of the GITS_BASERn.Entry_Size to this pointer 112 | 113 | #define GICV3_ITS_TABLE_TYPE_UNIMPLEMENTED (0x0) 114 | #define GICV3_ITS_TABLE_TYPE_DEVICE (0x1) 115 | #define GICV3_ITS_TABLE_TYPE_VIRTUAL (0x2) 116 | #define GICV3_ITS_TABLE_TYPE_COLLECTION (0x4) 117 | 118 | #define GICV3_ITS_TABLE_PAGE_SIZE_4K (0x0) 119 | #define GICV3_ITS_TABLE_PAGE_SIZE_16K (0x1) 120 | #define GICV3_ITS_TABLE_PAGE_SIZE_64K (0x2) 121 | 122 | uint64_t getITSTableType(uint32_t index, uint32_t* type, uint32_t* entry_size); 123 | 124 | 125 | // Sets GITS_BASER[entry] 126 | // index = which GITS_BASERn register to access, must be in the range 0 to 7 127 | // addr = phsyical address of allocated memory. Must be at least 4K aligned. 128 | // attributes = Cacheability, shareabilty, validity and indirect settings 129 | // page_size = Size of allocated pages (4K=0x0, 16K=0x100, 64K=0x200) 130 | // num_pages = The number of allocated pages. Must be greater than 0. 131 | // 132 | // NOTE: The registers encodes as (number - 1), this function expecst then 133 | // actual number 134 | 135 | #define GICV3_ITS_TABLE_PAGE_VALID ((uint64_t)1 << 63) 136 | #define GICV3_ITS_TABLE_PAGE_INVALID (0) 137 | 138 | #define GICV3_ITS_TABLE_PAGE_DIRECT (0) 139 | #define GICV3_ITS_TABLE_PAGE_INDIRECT (1 << 62) 140 | 141 | #define GICV3_ITS_TABLE_PAGE_DEVICE_nGnRnE (0) 142 | #define GICV3_ITS_TABLE_PAGE_NORM_WBWA (((uint64_t)0x5 << 59) | ((uint64_t)0x5 << 53)) 143 | 144 | #define GICV3_ITS_TABLE_INNER_SHAREABLE (0x1 << 10) 145 | #define GICV3_ITS_TABLE_OUTER_SHAREABLE (0x2 << 10) 146 | #define GICV3_ITS_TABLE_NON_SHAREABLE (0) 147 | 148 | uint32_t setITSTableAddr(uint32_t index, uint64_t addr, uint64_t attributes, uint32_t page_size, uint32_t num_pages); 149 | 150 | 151 | // Returns the value of GITS_TYPER.PTA bit (shifted down to LSB) 152 | 153 | #define GICV3_ITS_PTA_ADDRESS (1) 154 | #define GICV3_ITS_PTA_ID (0) 155 | 156 | uint32_t getITSPTA(void); 157 | 158 | uint32_t getITSNID(void); 159 | 160 | 161 | // Sets the GITS_CTLR.Enabled bit 162 | void enableITS(void); 163 | 164 | 165 | // Clears the GITS_CTLR.Enabled bit 166 | void disableITS(void); 167 | 168 | 169 | // ------------------------------------------------------------ 170 | // ITS commands 171 | // ------------------------------------------------------------ 172 | 173 | // Issues a MAPD command to the currently selected ITS 174 | // device = The device id 175 | // table = Physical address of the ITT table to be used 176 | // size = The number of bits of ID used by the device 177 | // 178 | // NOTE: The underlying command records the size as (number - 1). 179 | // This functions expects an unmodified value (i.e. pass 2, if 2 bits). 180 | void itsMAPD(uint32_t device_id, uint64_t table, uint32_t size); 181 | 182 | 183 | // Issues a MAPC command to the currently selected ITS 184 | // target = the target Redistributor. Either the PA or the ID, depending on GITS_TYPER 185 | // collection = the collection id 186 | void itsMAPC(uint32_t target, uint32_t collection); 187 | 188 | 189 | // Issues a MAPTI command to the currently selected ITS 190 | // device_id= the DeviceID 191 | // event_id = the EventID (the "ID" the peripheral will write) 192 | // intid = the GIC INTID (the "ID" that will be reported when readin IAR) 193 | // cid = the collection id 194 | void itsMAPTI(uint32_t device_id, uint32_t event_id, uint32_t intid, uint32_t cid); 195 | 196 | 197 | // Issues an INVALL command to the currently selected ITS 198 | // cid = the collection id 199 | void itsINVALL(uint32_t cid); 200 | 201 | 202 | // Issues an INV command to the currently selected ITS 203 | // device_id = the DeviceID 204 | // event_id = the EventID 205 | void itsINV(uint32_t device_id, uint32_t event_id); 206 | 207 | 208 | // Issues a SYNC command to the currently selected ITS 209 | // target = The target Redistributor. Either the PA or the ID, depending on GITS_TYPER 210 | void itsSYNC(uint64_t target); 211 | 212 | 213 | // Issues a INT command to the currently selected ITS 214 | // device = device id 215 | // id = EventID (the value the peripheral would have written) 216 | void itsINT(uint32_t device, uint32_t event_id); 217 | 218 | #endif 219 | 220 | // ---------------------------------------------------------- 221 | // End of armv8_aarch64_gicv3.h 222 | // ---------------------------------------------------------- 223 | -------------------------------------------------------------------------------- /headers/gicv3_registers.h: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------- 2 | // GICv3 Memory mapped registers 3 | // Header 4 | // 5 | // Copyright (C) Arm Limited, 2019 All rights reserved. 6 | // 7 | // The example code is provided to you as an aid to learning when working 8 | // with Arm-based technology, including but not limited to programming tutorials. 9 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 10 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 11 | // to use and copy the Software solely for the purpose of demonstration and 12 | // evaluation. 13 | // ------------------------------------------------------------ 14 | 15 | 16 | #ifndef __gicv3_regs_h 17 | #define __gicv3_regs_h 18 | 19 | #include 20 | 21 | // refs: Table 12-25 Distributor register map 22 | struct GICv3_dist_if 23 | { 24 | volatile uint32_t GICD_CTLR; // +0x0000 - RW - Distributor Control Register 25 | const volatile uint32_t GICD_TYPER; // +0x0004 - RO - Interrupt Controller Type Register 26 | const volatile uint32_t GICD_IIDR; // +0x0008 - RO - Distributor Implementer Identification Register 27 | 28 | const volatile uint32_t padding0; // +0x000C - RESERVED 29 | 30 | volatile uint32_t GICD_STATUSR; // +0x0010 - RW - Status register 31 | 32 | const volatile uint32_t padding1[3]; // +0x0014 - RESERVED 33 | 34 | volatile uint32_t IMP_DEF[8]; // +0x0020 - RW - Implementation defined registers 35 | 36 | volatile uint32_t GICD_SETSPI_NSR; // +0x0040 - WO - Non-secure Set SPI Pending (Used when SPI is signalled using MSI) 37 | const volatile uint32_t padding2; // +0x0044 - RESERVED 38 | volatile uint32_t GICD_CLRSPI_NSR; // +0x0048 - WO - Non-secure Clear SPI Pending (Used when SPI is signalled using MSI) 39 | const volatile uint32_t padding3; // +0x004C - RESERVED 40 | volatile uint32_t GICD_SETSPI_SR; // +0x0050 - WO - Secure Set SPI Pending (Used when SPI is signalled using MSI) 41 | const volatile uint32_t padding4; // +0x0054 - RESERVED 42 | volatile uint32_t GICD_CLRSPI_SR; // +0x0058 - WO - Secure Clear SPI Pending (Used when SPI is signalled using MSI) 43 | 44 | const volatile uint32_t padding5[3]; // +0x005C - RESERVED 45 | 46 | volatile uint32_t GICD_SEIR; // +0x0068 - WO - System Error Interrupt Register (Note: This was recently removed from the spec) 47 | 48 | const volatile uint32_t padding6[5]; // +0x006C - RESERVED 49 | 50 | volatile uint32_t GICD_IGROUPR[32]; // +0x0080 - RW - Interrupt Group Registers (Note: In GICv3, need to look at IGROUPR and IGRPMODR) 51 | 52 | volatile uint32_t GICD_ISENABLER[32]; // +0x0100 - RW - Interrupt Set-Enable Registers 53 | volatile uint32_t GICD_ICENABLER[32]; // +0x0180 - RW - Interrupt Clear-Enable Registers 54 | volatile uint32_t GICD_ISPENDR[32]; // +0x0200 - RW - Interrupt Set-Pending Registers 55 | volatile uint32_t GICD_ICPENDR[32]; // +0x0280 - RW - Interrupt Clear-Pending Registers 56 | volatile uint32_t GICD_ISACTIVER[32]; // +0x0300 - RW - Interrupt Set-Active Register 57 | volatile uint32_t GICD_ICACTIVER[32]; // +0x0380 - RW - Interrupt Clear-Active Register 58 | 59 | volatile uint8_t GICD_IPRIORITYR[1024]; // +0x0400 - RW - Interrupt Priority Registers 60 | volatile uint32_t GICD_ITARGETSR[256]; // +0x0800 - RW - Interrupt Processor Targets Registers 61 | volatile uint32_t GICD_ICFGR[64]; // +0x0C00 - RW - Interrupt Configuration Registers 62 | volatile uint32_t GICD_GRPMODR[32]; // +0x0D00 - RW - Interrupt Group Modifier (Note: In GICv3, need to look at IGROUPR and IGRPMODR) 63 | const volatile uint32_t padding7[32]; // +0x0D80 - RESERVED 64 | volatile uint32_t GICD_NSACR[64]; // +0x0E00 - RW - Non-secure Access Control Register 65 | 66 | volatile uint32_t GICD_SGIR; // +0x0F00 - WO - Software Generated Interrupt Register 67 | 68 | const volatile uint32_t padding8[3]; // +0x0F04 - RESERVED 69 | 70 | volatile uint32_t GICD_CPENDSGIR[4]; // +0x0F10 - RW - Clear pending for SGIs 71 | volatile uint32_t GICD_SPENDSGIR[4]; // +0x0F20 - RW - Set pending for SGIs 72 | 73 | const volatile uint32_t padding9[52]; // +0x0F30 - RESERVED 74 | 75 | // GICv3.1 extended SPI range 76 | volatile uint32_t GICD_IGROUPRE[128]; // +0x1000 - RW - Interrupt Group Registers (GICv3.1) 77 | volatile uint32_t GICD_ISENABLERE[128]; // +0x1200 - RW - Interrupt Set-Enable Registers (GICv3.1) 78 | volatile uint32_t GICD_ICENABLERE[128]; // +0x1400 - RW - Interrupt Clear-Enable Registers (GICv3.1) 79 | volatile uint32_t GICD_ISPENDRE[128]; // +0x1600 - RW - Interrupt Set-Pending Registers (GICv3.1) 80 | volatile uint32_t GICD_ICPENDRE[128]; // +0x1800 - RW - Interrupt Clear-Pending Registers (GICv3.1) 81 | volatile uint32_t GICD_ISACTIVERE[128]; // +0x1A00 - RW - Interrupt Set-Active Register (GICv3.1) 82 | volatile uint32_t GICD_ICACTIVERE[128]; // +0x1C00 - RW - Interrupt Clear-Active Register (GICv3.1) 83 | 84 | const volatile uint32_t padding10[128]; // +0x1E00 - RESERVED 85 | 86 | volatile uint8_t GICD_IPRIORITYRE[4096]; // +0x2000 - RW - Interrupt Priority Registers (GICv3.1) 87 | 88 | volatile uint32_t GICD_ICFGRE[256]; // +0x3000 - RW - Interrupt Configuration Registers (GICv3.1) 89 | volatile uint32_t GICD_IGRPMODRE[128]; // +0x3400 - RW - Interrupt Group Modifier (GICv3.1) 90 | volatile uint32_t GICD_NSACRE[256]; // +0x3600 - RW - Non-secure Access Control Register (GICv3.1) 91 | 92 | const volatile uint32_t padding11[2432]; // +0x3A00 - RESERVED 93 | 94 | // GICv3.0 95 | volatile uint64_t GICD_ROUTER[1024]; // +0x6000 - RW - Controls SPI routing when ARE=1 96 | 97 | // GICv3.1 98 | volatile uint64_t GICD_ROUTERE[1024]; // +0x8000 - RW - Controls SPI routing when ARE=1 (GICv3.1) 99 | }; 100 | 101 | 102 | // refs: Table 12-27 GIC physical LPI Redistributor register map 103 | struct GICv3_rdist_lpis_if 104 | { 105 | volatile uint32_t GICR_CTLR; // +0x0000 - RW - Redistributor Control Register 106 | const volatile uint32_t GICR_IIDR; // +0x0004 - RO - Redistributor Implementer Identification Register 107 | const volatile uint32_t GICR_TYPER[2]; // +0x0008 - RO - Redistributor Type Register 108 | volatile uint32_t GICR_STATUSR; // +0x0010 - RW - Redistributor Status register 109 | volatile uint32_t GICR_WAKER; // +0x0014 - RW - Wake Request Registers 110 | const volatile uint32_t GICR_MPAMIDR; // +0x0018 - RO - Reports maximum PARTID and PMG (GICv3.1) 111 | volatile uint32_t GICR_PARTID; // +0x001C - RW - Set PARTID and PMG used for Redistributor memory accesses (GICv3.1) 112 | const volatile uint32_t padding1[8]; // +0x0020 - RESERVED 113 | volatile uint64_t GICR_SETLPIR; // +0x0040 - WO - Set LPI pending (Note: IMP DEF if ITS present) 114 | volatile uint64_t GICR_CLRLPIR; // +0x0048 - WO - Set LPI pending (Note: IMP DEF if ITS present) 115 | const volatile uint32_t padding2[6]; // +0x0058 - RESERVED 116 | volatile uint32_t GICR_SEIR; // +0x0068 - WO - (Note: This was removed from the spec) 117 | const volatile uint32_t padding3; // +0x006C - RESERVED 118 | volatile uint64_t GICR_PROPBASER; // +0x0070 - RW - Sets location of the LPI configuration table 119 | volatile uint64_t GICR_PENDBASER; // +0x0078 - RW - Sets location of the LPI pending table 120 | const volatile uint32_t padding4[8]; // +0x0080 - RESERVED 121 | volatile uint64_t GICR_INVLPIR; // +0x00A0 - WO - Invalidates cached LPI config (Note: In GICv3.x: IMP DEF if ITS present) 122 | const volatile uint32_t padding5[2]; // +0x00A8 - RESERVED 123 | volatile uint64_t GICR_INVALLR; // +0x00B0 - WO - Invalidates cached LPI config (Note: In GICv3.x: IMP DEF if ITS present) 124 | const volatile uint32_t padding6[2]; // +0x00B8 - RESERVED 125 | volatile uint64_t GICR_SYNCR; // +0x00C0 - WO - Redistributor Sync 126 | const volatile uint32_t padding7[2]; // +0x00C8 - RESERVED 127 | const volatile uint32_t padding8[12]; // +0x00D0 - RESERVED 128 | volatile uint64_t GICR_MOVLPIR; // +0x0100 - WO - IMP DEF 129 | const volatile uint32_t padding9[2]; // +0x0108 - RESERVED 130 | volatile uint64_t GICR_MOVALLR; // +0x0110 - WO - IMP DEF 131 | const volatile uint32_t padding10[2]; // +0x0118 - RESERVED 132 | }; 133 | 134 | // refs: Table 12-29 GIC SGI and PPI Redistributor register map 135 | struct GICv3_rdist_sgis_if 136 | { 137 | const volatile uint32_t padding1[32]; // +0x0000 - RESERVED 138 | volatile uint32_t GICR_IGROUPR[3]; // +0x0080 - RW - Interrupt Group Registers (Security Registers in GICv1) 139 | const volatile uint32_t padding2[29]; // +0x008C - RESERVED 140 | volatile uint32_t GICR_ISENABLER[3]; // +0x0100 - RW - Interrupt Set-Enable Registers 141 | const volatile uint32_t padding3[29]; // +0x010C - RESERVED 142 | volatile uint32_t GICR_ICENABLER[3]; // +0x0180 - RW - Interrupt Clear-Enable Registers 143 | const volatile uint32_t padding4[29]; // +0x018C - RESERVED 144 | volatile uint32_t GICR_ISPENDR[3]; // +0x0200 - RW - Interrupt Set-Pending Registers 145 | const volatile uint32_t padding5[29]; // +0x020C - RESERVED 146 | volatile uint32_t GICR_ICPENDR[3]; // +0x0280 - RW - Interrupt Clear-Pending Registers 147 | const volatile uint32_t padding6[29]; // +0x028C - RESERVED 148 | volatile uint32_t GICR_ISACTIVER[3]; // +0x0300 - RW - Interrupt Set-Active Register 149 | const volatile uint32_t padding7[29]; // +0x030C - RESERVED 150 | volatile uint32_t GICR_ICACTIVER[3]; // +0x0380 - RW - Interrupt Clear-Active Register 151 | const volatile uint32_t padding8[29]; // +0x018C - RESERVED 152 | volatile uint8_t GICR_IPRIORITYR[96]; // +0x0400 - RW - Interrupt Priority Registers 153 | const volatile uint32_t padding9[488]; // +0x0460 - RESERVED 154 | volatile uint32_t GICR_ICFGR[6]; // +0x0C00 - RW - Interrupt Configuration Registers 155 | const volatile uint32_t padding10[58]; // +0x0C18 - RESERVED 156 | volatile uint32_t GICR_IGRPMODR[3]; // +0x0D00 - RW - Interrupt Group Modifier Register 157 | const volatile uint32_t padding11[61]; // +0x0D0C - RESERVED 158 | volatile uint32_t GICR_NSACR; // +0x0E00 - RW - Non-secure Access Control Register 159 | 160 | }; 161 | 162 | struct GICv3_rdist_vlpis_if 163 | { 164 | const volatile uint32_t padding1[28]; // +0x0000 - RESERVED 165 | volatile uint64_t GICR_VPROPBASER; // +0x0070 - RW - Sets location of the LPI vPE Configuration table 166 | volatile uint64_t GICR_VPENDBASER; // +0x0078 - RW - Sets location of the LPI Pending table 167 | }; 168 | 169 | struct GICv3_rdist_res_if 170 | { 171 | const volatile uint32_t padding1[32]; // +0x0000 - RESERVED 172 | }; 173 | 174 | // refs: 12.10 The GIC Redistributor register map 175 | // The frames for each Redistributor must be contiguous and must be 176 | // ordered as follows: 177 | // 1. RD_base 178 | // 2. SGI_base 179 | // 3. VLPI_base 180 | // 4. Reserved 181 | struct GICv3_rdist_if 182 | { 183 | struct GICv3_rdist_lpis_if lpis __attribute__((aligned (0x10000))); 184 | struct GICv3_rdist_sgis_if sgis __attribute__((aligned (0x10000))); 185 | 186 | #ifdef GICV4 187 | struct GICv3_rdist_vlpis_if vlpis __attribute__((aligned (0x10000))); 188 | struct GICv3_rdist_res_if res __attribute__((aligned (0x10000))); 189 | #endif 190 | }; 191 | 192 | 193 | // refs: Table 12-33 ITS control register map 194 | struct GICv3_its_ctlr_if 195 | { 196 | volatile uint32_t GITS_CTLR; // +0x0000 - RW - ITS Control Register 197 | const volatile uint32_t GITS_IIDR; // +0x0004 - RO - Implementer Identification Register 198 | const volatile uint64_t GITS_TYPER; // +0x0008 - RO - ITS Type register 199 | const volatile uint32_t GITS_MPAMIDR; // +0x0010 - RO - Reports maxmimum PARTID and PMG (GICv3.1) 200 | volatile uint32_t GITS_PARTIDR; // +0x0004 - RW - Sets the PARTID and PMG used for ITS memory accesses (GICv3.1) 201 | const volatile uint32_t GITS_MPIDR; // +0x0018 - RO - ITS affinity, used for shared vPE table 202 | const volatile uint32_t padding5; // +0x001C - RESERVED 203 | volatile uint32_t GITS_IMPDEF[8]; // +0x0020 - RW - IMP DEF registers 204 | const volatile uint32_t padding2[16]; // +0x0040 - RESERVED 205 | volatile uint64_t GITS_CBASER; // +0x0080 - RW - Sets base address of ITS command queue 206 | volatile uint64_t GITS_CWRITER; // +0x0088 - RW - Points to next enrty to add command 207 | volatile uint64_t GITS_CREADR; // +0x0090 - RW - Points to command being processed 208 | const volatile uint32_t padding3[2]; // +0x0098 - RESERVED 209 | const volatile uint32_t padding4[24]; // +0x00A0 - RESERVED 210 | volatile uint64_t GITS_BASER[8]; // +0x0100 - RW - Sets base address of Device and Collection tables 211 | }; 212 | 213 | // refs: Table 12-34 ITS translation register map 214 | struct GICv3_its_int_if 215 | { 216 | const volatile uint32_t padding1[16]; // +0x0000 - RESERVED 217 | volatile uint32_t GITS_TRANSLATER; // +0x0040 - RW - Written by peripherals to generate LPI 218 | }; 219 | 220 | // refs: Table 12-35 Virtual SGI register map 221 | struct GICv3_its_sgi_if 222 | { 223 | const volatile uint32_t padding1[8]; // +0x0000 - RESERVED 224 | volatile uint64_t GITS_SGIR; // +0x0020 - RW - Written by peripherals to generate vSGI (GICv4.1) 225 | }; 226 | 227 | #endif 228 | 229 | // ---------------------------------------------------------- 230 | // End of gicv3_regs.h 231 | // ---------------------------------------------------------- 232 | -------------------------------------------------------------------------------- /headers/gicv4_virt.h: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------- 2 | // GICv3 Functions for managing physical LPIs 3 | // Header 4 | // 5 | // Copyright (C) Arm Limited, 2019 All rights reserved. 6 | // 7 | // The example code is provided to you as an aid to learning when working 8 | // with Arm-based technology, including but not limited to programming tutorials. 9 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 10 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 11 | // to use and copy the Software solely for the purpose of demonstration and 12 | // evaluation. 13 | // ------------------------------------------------------------ 14 | 15 | #ifndef __gicv4_virt_h 16 | #define __gicv4_virt_h 17 | 18 | #include 19 | 20 | // ------------------------------------------------------------ 21 | // Address space set up 22 | // ------------------------------------------------------------ 23 | 24 | void setSGIBaseAddr(void); 25 | 26 | // ------------------------------------------------------------ 27 | // Discovery 28 | // ------------------------------------------------------------ 29 | 30 | #define GICV3_v3X (30) 31 | #define GICV3_v40 (40) 32 | #define GICV3_v41 (41) 33 | uint32_t isGICv4x(uint32_t rd); 34 | 35 | // Returns 1 if vSGIs supported, 0 if vSGIs not supported 36 | uint32_t hasVSGI(uint32_t rd); 37 | 38 | // ------------------------------------------------------------ 39 | // Redistributor setup functions 40 | // ------------------------------------------------------------ 41 | 42 | uint32_t setVPEConfTableAddr(uint32_t rd, uint64_t addr, uint64_t attributes, uint32_t num_pages); 43 | 44 | uint32_t makeResident(uint32_t rd, uint32_t vpeid, uint32_t g0, uint32_t g1); 45 | 46 | uint32_t makeNotResident(uint32_t rd, uint32_t db); 47 | 48 | // ------------------------------------------------------------ 49 | // Configuring LPI functions 50 | // ------------------------------------------------------------ 51 | 52 | // Configures specified vLPI 53 | uint32_t configureVLPI(uint8_t* table, uint32_t ID, uint32_t enable, uint32_t priority); 54 | 55 | // ------------------------------------------------------------ 56 | // ITS setup functions 57 | // ------------------------------------------------------------ 58 | 59 | uint32_t itsSharedTableSupport(void); 60 | 61 | uint32_t itsGetAffinity(void); 62 | 63 | // ------------------------------------------------------------ 64 | // vSGI 65 | // ------------------------------------------------------------ 66 | 67 | void itsSendSGI(uint32_t vintid, uint32_t vpeid); 68 | 69 | // ------------------------------------------------------------ 70 | // ITS commands 71 | // ------------------------------------------------------------ 72 | 73 | void itsVMAPP(uint32_t vpeid, uint32_t target, uint64_t conf_addr, uint64_t pend_addr, uint32_t alloc, uint32_t v, uint32_t doorbell, uint32_t size); 74 | 75 | void itsVSYNC(uint32_t vpeid); 76 | 77 | void itsVMAPTI(uint32_t DeviceID, uint32_t EventID, uint32_t doorbell, uint32_t vpeid, uint32_t vINTID); 78 | 79 | void itsINVDB(uint32_t vpeid); 80 | 81 | void itsVSGI(uint32_t vpeid, uint32_t vintid, uint32_t enable, uint32_t priority, uint32_t group, uint32_t clear); 82 | 83 | #endif 84 | 85 | // ---------------------------------------------------------- 86 | // End of gicv4_vlpis.h 87 | // ---------------------------------------------------------- 88 | -------------------------------------------------------------------------------- /headers/sp804_timer.h: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------- 2 | // SP804 Dual Timer 3 | // Header 4 | // 5 | // Copyright (C) Arm Limited, 2019 All rights reserved. 6 | // 7 | // The example code is provided to you as an aid to learning when working 8 | // with Arm-based technology, including but not limited to programming tutorials. 9 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 10 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 11 | // to use and copy the Software solely for the purpose of demonstration and 12 | // evaluation. 13 | // ------------------------------------------------------------ 14 | 15 | #ifndef _SP804_TIMER_ 16 | #define _SP804_TIMER_ 17 | 18 | #include 19 | 20 | // Set base address of timer 21 | // address - virtual address of SP804 timer 22 | void setTimerBaseAddress(uint64_t address); 23 | 24 | 25 | // Sets up the private timer 26 | // load_value - Initial value of timer 27 | // auto_reload - Peroidic (SP804_SINGLESHOT) or one shot (SP804_SINGLESHOT) 28 | // interrupt - Whether to generate an interrupt 29 | 30 | #define SP804_AUTORELOAD (0) 31 | #define SP804_SINGLESHOT (1) 32 | #define SP804_GENERATE_IRQ (1 << 5) 33 | #define SP804_NO_IRQ (0) 34 | 35 | void initTimer(uint32_t load_value, uint32_t auto_reload, uint32_t interrupt); 36 | 37 | 38 | // Starts the timer 39 | void startTimer(void); 40 | 41 | 42 | // Stops the timer 43 | void stopTimer(void); 44 | 45 | 46 | // Returns the current timer count 47 | uint32_t getTimerCount(void); 48 | 49 | 50 | // Clears the timer interrupt 51 | void clearTimerIrq(void); 52 | 53 | #endif 54 | 55 | // ------------------------------------------------------------ 56 | // End of sp804_timer.h 57 | // ------------------------------------------------------------ 58 | -------------------------------------------------------------------------------- /headers/system_counter.h: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------- 2 | // System counter 3 | // Header 4 | // 5 | // Copyright (C) Arm Limited, 2019 All rights reserved. 6 | // 7 | // The example code is provided to you as an aid to learning when working 8 | // with Arm-based technology, including but not limited to programming tutorials. 9 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 10 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 11 | // to use and copy the Software solely for the purpose of demonstration and 12 | // evaluation. 13 | // ------------------------------------------------------------ 14 | 15 | 16 | #ifndef __memory_mapped_timer_h 17 | #define __memory_mapped_timer_h 18 | 19 | #include 20 | 21 | // Sets the address of memory mapped counter module 22 | // addr - virtual address of counter module 23 | void setSystemCounterBaseAddr(uint64_t addr); 24 | 25 | #define SYSTEM_COUNTER_CNTCR_HDBG (1) 26 | #define SYSTEM_COUNTER_CNTCR_nHDBG (0) 27 | 28 | #define SYSTEM_COUNTER_CNTCR_SCALE (1) 29 | #define SYSTEM_COUNTER_CNTCR_nSCALE (0) 30 | 31 | #define SYSTEM_COUNTER_CNTCR_FREQ0 (0) 32 | #define SYSTEM_COUNTER_CNTCR_FREQ1 (1) 33 | #define SYSTEM_COUNTER_CNTCR_FREQ2 (2) 34 | 35 | // Configures and enables the CNTCR (Counter Control Register) 36 | // hdbg - halt on debug mode 37 | // freq - frequency mode 38 | void initSystemCounter(uint32_t hdbg, uint32_t freq, uint32_t scaling); 39 | 40 | 41 | // Set the scaling factor (CNTSCR) 42 | // scale - Scaling factor (32-bit fixed point value, 8-bit integer with 24-bit fractional) 43 | // Returns 0 if successful 44 | // 1 if counter enabled (writing CNTSCR is UNPRED when counter enabled) 45 | // 2 if feature not supported 46 | uint32_t setSystemCounterScalingFactor(uint32_t scale); 47 | 48 | 49 | // Returns the value of CNTID (Counter ID register) 50 | uint32_t getCNTID(void); 51 | 52 | 53 | // Returns the value of the CNTSR 54 | uint32_t getCNTSR(void); 55 | 56 | 57 | // Returns the value of CNTCV (Counter Count Value register) 58 | uint64_t getCNTCV(void); 59 | 60 | 61 | // Sets the value of CNTCV (Counter Count Value register) 62 | // value - Sets the count value 63 | // 64 | // NOTE: This should only be called when the counter is disabled. 65 | // Calling while counter enabled is UNPREDICTABLE. 66 | void setCNTCV(uint64_t value); 67 | 68 | 69 | // Returns the value of the specified CNTFIDn register 70 | // entry - 71 | uint32_t getCNTFID(uint32_t entry); 72 | 73 | // Set the specified CNTFIDn register 74 | // entry - 75 | // value - 76 | void setCNTFID(uint32_t entry, uint32_t value); 77 | 78 | #endif 79 | 80 | // ---------------------------------------------------------- 81 | // End of system_counter.h 82 | // ---------------------------------------------------------- 83 | -------------------------------------------------------------------------------- /pre-build/image_basic.axf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaiZhiyuan/Baremetal_GICv3_v4/ed4a414e4788768867198dc93bb71390995f2303/pre-build/image_basic.axf -------------------------------------------------------------------------------- /pre-build/image_gicv31.axf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaiZhiyuan/Baremetal_GICv3_v4/ed4a414e4788768867198dc93bb71390995f2303/pre-build/image_gicv31.axf -------------------------------------------------------------------------------- /pre-build/image_lpi.axf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaiZhiyuan/Baremetal_GICv3_v4/ed4a414e4788768867198dc93bb71390995f2303/pre-build/image_lpi.axf -------------------------------------------------------------------------------- /pre-build/image_vlpi.axf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaiZhiyuan/Baremetal_GICv3_v4/ed4a414e4788768867198dc93bb71390995f2303/pre-build/image_vlpi.axf -------------------------------------------------------------------------------- /pre-build/image_vsgi.axf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaiZhiyuan/Baremetal_GICv3_v4/ed4a414e4788768867198dc93bb71390995f2303/pre-build/image_vsgi.axf -------------------------------------------------------------------------------- /scatter.txt: -------------------------------------------------------------------------------- 1 | LOAD 0x04000000 2 | { 3 | ; 4 | ; Trusted SRAM (256K) on Base Platform model 5 | ; 6 | 7 | ROM +0x0 8 | { 9 | *.o (BOOT, +FIRST) 10 | * (InRoot$$Sections) 11 | * (+RO) 12 | } 13 | 14 | RAM +0x0 15 | { 16 | * (+RW, +ZI) 17 | } 18 | 19 | ARM_LIB_STACKHEAP 0x04020000 EMPTY 0x0008000 20 | {} 21 | } -------------------------------------------------------------------------------- /scatter_virt.txt: -------------------------------------------------------------------------------- 1 | S_LOAD 0x04000000 2 | { 3 | ; 4 | ; Trusted SRAM (256K) on Base Platform model 5 | ; 6 | 7 | ROM +0x0 8 | { 9 | *.o (BOOT, +FIRST) 10 | * (InRoot$$Sections) 11 | * (+RO) 12 | } 13 | 14 | RAM +0x0 15 | { 16 | * (+RW, +ZI) 17 | } 18 | 19 | ARM_LIB_STACKHEAP 0x04020000 EMPTY 0x0008000 20 | { 21 | } 22 | } 23 | 24 | NS_LOAD 0x2E000000 25 | { 26 | ; 27 | ; Non-secure SRAM 28 | ; 29 | 30 | NS_RAM +0x0 31 | { 32 | secondary_virt.o (secondary_boot_ns) 33 | } 34 | } -------------------------------------------------------------------------------- /scripts/cluster0cpu1.asm: -------------------------------------------------------------------------------- 1 | 0 ps cluster0.cpu1 R cpsr 000003cd 2 | 0 ps cluster0.cpu1 R X0 0000000000000000 3 | 0 ps cluster0.cpu1 R X1 0000000000000000 4 | 0 ps cluster0.cpu1 R X2 0000000000000000 5 | 0 ps cluster0.cpu1 R X3 0000000000000000 6 | 0 ps cluster0.cpu1 R X4 0000000000000000 7 | 0 ps cluster0.cpu1 R X5 0000000000000000 8 | 0 ps cluster0.cpu1 R X6 0000000000000000 9 | 0 ps cluster0.cpu1 R X7 0000000000000000 10 | 0 ps cluster0.cpu1 R X8 0000000000000000 11 | 0 ps cluster0.cpu1 R X9 0000000000000000 12 | 0 ps cluster0.cpu1 R X10 0000000000000000 13 | 0 ps cluster0.cpu1 R X11 0000000000000000 14 | 0 ps cluster0.cpu1 R X12 0000000000000000 15 | 0 ps cluster0.cpu1 R X13 0000000000000000 16 | 0 ps cluster0.cpu1 R X14 0000000000000000 17 | 0 ps cluster0.cpu1 R X15 0000000000000000 18 | 0 ps cluster0.cpu1 R X16 0000000000000000 19 | 0 ps cluster0.cpu1 R X17 0000000000000000 20 | 0 ps cluster0.cpu1 R X18 0000000000000000 21 | 0 ps cluster0.cpu1 R X19 0000000000000000 22 | 0 ps cluster0.cpu1 R X20 0000000000000000 23 | 0 ps cluster0.cpu1 R X21 0000000000000000 24 | 0 ps cluster0.cpu1 R X22 0000000000000000 25 | 0 ps cluster0.cpu1 R X23 0000000000000000 26 | 0 ps cluster0.cpu1 R X24 0000000000000000 27 | 0 ps cluster0.cpu1 R X25 0000000000000000 28 | 0 ps cluster0.cpu1 R X26 0000000000000000 29 | 0 ps cluster0.cpu1 R X27 0000000000000000 30 | 0 ps cluster0.cpu1 R X28 0000000000000000 31 | 0 ps cluster0.cpu1 R X29 0000000000000000 32 | 0 ps cluster0.cpu1 R X30 0000000000000000 33 | 0 ps cluster0.cpu1 R q0 00000000000000000000000000000000 34 | 0 ps cluster0.cpu1 R q1 00000000000000000000000000000000 35 | 0 ps cluster0.cpu1 R q2 00000000000000000000000000000000 36 | 0 ps cluster0.cpu1 R q3 00000000000000000000000000000000 37 | 0 ps cluster0.cpu1 R q4 00000000000000000000000000000000 38 | 0 ps cluster0.cpu1 R q5 00000000000000000000000000000000 39 | 0 ps cluster0.cpu1 R q6 00000000000000000000000000000000 40 | 0 ps cluster0.cpu1 R q7 00000000000000000000000000000000 41 | 0 ps cluster0.cpu1 R q8 00000000000000000000000000000000 42 | 0 ps cluster0.cpu1 R q9 00000000000000000000000000000000 43 | 0 ps cluster0.cpu1 R q10 00000000000000000000000000000000 44 | 0 ps cluster0.cpu1 R q11 00000000000000000000000000000000 45 | 0 ps cluster0.cpu1 R q12 00000000000000000000000000000000 46 | 0 ps cluster0.cpu1 R q13 00000000000000000000000000000000 47 | 0 ps cluster0.cpu1 R q14 00000000000000000000000000000000 48 | 0 ps cluster0.cpu1 R q15 00000000000000000000000000000000 49 | 0 ps cluster0.cpu1 R q16 00000000000000000000000000000000 50 | 0 ps cluster0.cpu1 R q17 00000000000000000000000000000000 51 | 0 ps cluster0.cpu1 R q18 00000000000000000000000000000000 52 | 0 ps cluster0.cpu1 R q19 00000000000000000000000000000000 53 | 0 ps cluster0.cpu1 R q20 00000000000000000000000000000000 54 | 0 ps cluster0.cpu1 R q21 00000000000000000000000000000000 55 | 0 ps cluster0.cpu1 R q22 00000000000000000000000000000000 56 | 0 ps cluster0.cpu1 R q23 00000000000000000000000000000000 57 | 0 ps cluster0.cpu1 R q24 00000000000000000000000000000000 58 | 0 ps cluster0.cpu1 R q25 00000000000000000000000000000000 59 | 0 ps cluster0.cpu1 R q26 00000000000000000000000000000000 60 | 0 ps cluster0.cpu1 R q27 00000000000000000000000000000000 61 | 0 ps cluster0.cpu1 R q28 00000000000000000000000000000000 62 | 0 ps cluster0.cpu1 R q29 00000000000000000000000000000000 63 | 0 ps cluster0.cpu1 R q30 00000000000000000000000000000000 64 | 0 ps cluster0.cpu1 R q31 00000000000000000000000000000000 65 | 0 ps cluster0.cpu1 R fpexc 04000700 66 | 0 ps cluster0.cpu1 R NSACR 00000c00 67 | 0 ps cluster0.cpu1 R WFAR 00000000 68 | 0 ps cluster0.cpu1 R SPSR_irq 00000000 69 | 0 ps cluster0.cpu1 R SPSR_fiq 00000000 70 | 0 ps cluster0.cpu1 R SPSR_abt 00000000 71 | 0 ps cluster0.cpu1 R SPSR_und 00000000 72 | 0 ps cluster0.cpu1 R SDER 00000000 73 | 0 ps cluster0.cpu1 R DBGDSCRint 00000000 74 | 0 ps cluster0.cpu1 R DBGDSCRext 00000000 75 | 0 ps cluster0.cpu1 R EDSCR 03003c02 76 | 0 ps cluster0.cpu1 R TCR_EL2 80800000 77 | 0 ps cluster0.cpu1 R DACR32_EL2 00000000 78 | 0 ps cluster0.cpu1 R CSSELR_EL1 00000000 79 | 0 ps cluster0.cpu1 R CTIGATE 0000000f 80 | 0 ps cluster0.cpu1 R VPIDR_EL2 00000000 81 | 0 ps cluster0.cpu1 R ACTLR_EL1 00000000 82 | 0 ps cluster0.cpu1 R ACTLR_EL2 00000000 83 | 0 ps cluster0.cpu1 R ACTLR_EL3 00000000 84 | 0 ps cluster0.cpu1 R CPACR_EL1 00000000 85 | 0 ps cluster0.cpu1 R CPTR_EL2 000033ff 86 | 0 ps cluster0.cpu1 R CPTR_EL3 00000000 87 | 0 ps cluster0.cpu1 R MDCR_EL2 00000008 88 | 0 ps cluster0.cpu1 R HSTR_EL2 00000000 89 | 0 ps cluster0.cpu1 R HACR_EL2 00000000 90 | 0 ps cluster0.cpu1 R AFSR0_EL1 00000000 91 | 0 ps cluster0.cpu1 R AFSR1_EL1 00000000 92 | 0 ps cluster0.cpu1 R AFSR0_EL2 00000000 93 | 0 ps cluster0.cpu1 R AFSR1_EL2 00000000 94 | 0 ps cluster0.cpu1 R AFSR0_EL3 00000000 95 | 0 ps cluster0.cpu1 R AFSR1_EL3 00000000 96 | 0 ps cluster0.cpu1 R IFSR32_EL2 00000000 97 | 0 ps cluster0.cpu1 R TCR_EL3 0000000080800000 98 | 0 ps cluster0.cpu1 R TTBR0_EL3 0000000000000000 99 | 0 ps cluster0.cpu1 R MAIR_EL3 0000000000000000 100 | 0 ps cluster0.cpu1 R AMAIR_EL3 0000000000000000 101 | 0 ps cluster0.cpu1 R MAIR2_EL3 0000000000000000 102 | 0 ps cluster0.cpu1 R AMAIR2_EL3 0000000000000000 103 | 0 ps cluster0.cpu1 R TTBR0_EL2 0000000000000000 104 | 0 ps cluster0.cpu1 R MAIR_EL2 0000000000000000 105 | 0 ps cluster0.cpu1 R AMAIR_EL2 0000000000000000 106 | 0 ps cluster0.cpu1 R MAIR2_EL2 0000000000000000 107 | 0 ps cluster0.cpu1 R AMAIR2_EL2 0000000000000000 108 | 0 ps cluster0.cpu1 R VTTBR_EL2 0000000000000000 109 | 0 ps cluster0.cpu1 R VTCR_EL2 0000000080000000 110 | 0 ps cluster0.cpu1 R TCR_EL1 0000000000000000 111 | 0 ps cluster0.cpu1 R TTBR0_EL1 0000000000000000 112 | 0 ps cluster0.cpu1 R TTBR1_EL1 0000000000000000 113 | 0 ps cluster0.cpu1 R MAIR_EL1 0000000000000000 114 | 0 ps cluster0.cpu1 R AMAIR_EL1 0000000000000000 115 | 0 ps cluster0.cpu1 R MAIR2_EL1 0000000000000000 116 | 0 ps cluster0.cpu1 R AMAIR2_EL1 0000000000000000 117 | 0 ps cluster0.cpu1 R PAR_EL1 0000000000000000 118 | 0 ps cluster0.cpu1 R CONTEXTIDR_EL1 0000000000000000 119 | 0 ps cluster0.cpu1 R VMPIDR_EL2 0000000080000000 120 | 0 ps cluster0.cpu1 R SCTLR_EL1 0000000000c00800 121 | 0 ps cluster0.cpu1 R SCTLR_EL2 0000000030c50810 122 | 0 ps cluster0.cpu1 R SCTLR_EL3 0000000030c50830 123 | 0 ps cluster0.cpu1 R SCR_EL3 0000000000000030 124 | 0 ps cluster0.cpu1 R HCR_EL2 0000000000000000 125 | 0 ps cluster0.cpu1 R MDCR_EL3 0000000000000000 126 | 0 ps cluster0.cpu1 R ESR_EL1 0000000000000000 127 | 0 ps cluster0.cpu1 R ESR_EL2 0000000000000000 128 | 0 ps cluster0.cpu1 R ESR_EL3 0000000000000000 129 | 0 ps cluster0.cpu1 R FAR_EL1 0000000000000000 130 | 0 ps cluster0.cpu1 R FAR_EL2 0000000000000000 131 | 0 ps cluster0.cpu1 R FAR_EL3 0000000000000000 132 | 0 ps cluster0.cpu1 R HPFAR_EL2 0000000000000000 133 | 0 ps cluster0.cpu1 R VBAR_EL1 0000000000000000 134 | 0 ps cluster0.cpu1 R VBAR_EL2 0000000000000000 135 | 0 ps cluster0.cpu1 R VBAR_EL3 0000000000000000 136 | 0 ps cluster0.cpu1 R TPIDR_EL0 0000000000000000 137 | 0 ps cluster0.cpu1 R TPIDRRO_EL0 0000000000000000 138 | 0 ps cluster0.cpu1 R TPIDR_EL1 0000000000000000 139 | 0 ps cluster0.cpu1 R TPIDR_EL2 0000000000000000 140 | 0 ps cluster0.cpu1 R TPIDR_EL3 0000000000000000 141 | 0 ps cluster0.cpu1 R ELR_EL1 0000000000000000 142 | 0 ps cluster0.cpu1 R ELR_EL2 0000000000000000 143 | 0 ps cluster0.cpu1 R ELR_EL3 0000000000000000 144 | 0 ps cluster0.cpu1 R SPSR_EL1 0000000000000000 145 | 0 ps cluster0.cpu1 R SPSR_EL2 0000000000000000 146 | 0 ps cluster0.cpu1 R SPSR_EL3 0000000000000000 147 | 0 ps cluster0.cpu1 R MPIDR_EL1 0000000081000100 148 | 0 ps cluster0.cpu1 SIGNAL: SIGNAL=DebugReset STATE=N 149 | 0 ps cluster0.cpu1 SIGNAL: SIGNAL=ResetHold STATE=N 150 | 0 ps cluster0.cpu1 SIGNAL: SIGNAL=DebugReset STATE=N 151 | 0 ps cluster0.cpu1 SIGNAL: SIGNAL=ResetHold STATE=N 152 | 0 ps cluster0.cpu1 SIGNAL: SIGNAL=DebugReset STATE=N 153 | 0 ps cluster0.cpu1 SIGNAL: SIGNAL=ResetHold STATE=N 154 | 0 ps cluster0.cpu1 SIGNAL: SIGNAL=DebugReset STATE=N 155 | 0 ps cluster0.cpu1 SIGNAL: SIGNAL=ResetHold STATE=N 156 | 0 ps cluster0.cpu1 SIGNAL: SIGNAL=Abort STATE=N 157 | 0 ps cluster0.cpu1 SIGNAL: SIGNAL=DebugReset STATE=N 158 | 0 ps cluster0.cpu1 SIGNAL: SIGNAL=ResetHold STATE=N 159 | 0 ps cluster0.cpu1 SIGNAL: SIGNAL=DebugReset STATE=N 160 | 0 ps cluster0.cpu1 SIGNAL: SIGNAL=ResetHold STATE=N 161 | 0 ps cluster0.cpu1 SIGNAL: SIGNAL=Abort STATE=N 162 | 0 ps cluster0.cpu1 E 00000000:000000000000 00000000 CoreEvent_Reset 163 | 0 ps cluster0.cpu1 R cpsr 000003cd 164 | 10000 ps cluster0.cpu1 IT (1) 04000000 d2800000 O EL3h_s : MOV x0,#0 165 | 10000 ps cluster0.cpu1 R X0 0000000000000000 166 | 20000 ps cluster0.cpu1 IT (2) 04000004 d2800001 O EL3h_s : MOV x1,#0 167 | 20000 ps cluster0.cpu1 R X1 0000000000000000 168 | 30000 ps cluster0.cpu1 IT (3) 04000008 d2800002 O EL3h_s : MOV x2,#0 169 | 30000 ps cluster0.cpu1 R X2 0000000000000000 170 | 40000 ps cluster0.cpu1 IT (4) 0400000c d2800003 O EL3h_s : MOV x3,#0 171 | 40000 ps cluster0.cpu1 R X3 0000000000000000 172 | 50000 ps cluster0.cpu1 IT (5) 04000010 d2800004 O EL3h_s : MOV x4,#0 173 | 50000 ps cluster0.cpu1 R X4 0000000000000000 174 | 60000 ps cluster0.cpu1 IT (6) 04000014 d2800005 O EL3h_s : MOV x5,#0 175 | 60000 ps cluster0.cpu1 R X5 0000000000000000 176 | 70000 ps cluster0.cpu1 IT (7) 04000018 d2800006 O EL3h_s : MOV x6,#0 177 | 70000 ps cluster0.cpu1 R X6 0000000000000000 178 | 80000 ps cluster0.cpu1 IT (8) 0400001c d2800007 O EL3h_s : MOV x7,#0 179 | 80000 ps cluster0.cpu1 R X7 0000000000000000 180 | 90000 ps cluster0.cpu1 IT (9) 04000020 d2800008 O EL3h_s : MOV x8,#0 181 | 90000 ps cluster0.cpu1 R X8 0000000000000000 182 | 100000 ps cluster0.cpu1 IT (10) 04000024 d2800009 O EL3h_s : MOV x9,#0 183 | 100000 ps cluster0.cpu1 R X9 0000000000000000 184 | 110000 ps cluster0.cpu1 IT (11) 04000028 d280000a O EL3h_s : MOV x10,#0 185 | 110000 ps cluster0.cpu1 R X10 0000000000000000 186 | 120000 ps cluster0.cpu1 IT (12) 0400002c d280000b O EL3h_s : MOV x11,#0 187 | 120000 ps cluster0.cpu1 R X11 0000000000000000 188 | 130000 ps cluster0.cpu1 IT (13) 04000030 d280000c O EL3h_s : MOV x12,#0 189 | 130000 ps cluster0.cpu1 R X12 0000000000000000 190 | 140000 ps cluster0.cpu1 IT (14) 04000034 d280000d O EL3h_s : MOV x13,#0 191 | 140000 ps cluster0.cpu1 R X13 0000000000000000 192 | 150000 ps cluster0.cpu1 IT (15) 04000038 d280000e O EL3h_s : MOV x14,#0 193 | 150000 ps cluster0.cpu1 R X14 0000000000000000 194 | 160000 ps cluster0.cpu1 IT (16) 0400003c d280000f O EL3h_s : MOV x15,#0 195 | 160000 ps cluster0.cpu1 R X15 0000000000000000 196 | 170000 ps cluster0.cpu1 IT (17) 04000040 d2800010 O EL3h_s : MOV x16,#0 197 | 170000 ps cluster0.cpu1 R X16 0000000000000000 198 | 180000 ps cluster0.cpu1 IT (18) 04000044 d2800011 O EL3h_s : MOV x17,#0 199 | 180000 ps cluster0.cpu1 R X17 0000000000000000 200 | 190000 ps cluster0.cpu1 IT (19) 04000048 d2800012 O EL3h_s : MOV x18,#0 201 | 190000 ps cluster0.cpu1 R X18 0000000000000000 202 | 200000 ps cluster0.cpu1 IT (20) 0400004c d2800013 O EL3h_s : MOV x19,#0 203 | 200000 ps cluster0.cpu1 R X19 0000000000000000 204 | 210000 ps cluster0.cpu1 IT (21) 04000050 d2800014 O EL3h_s : MOV x20,#0 205 | 210000 ps cluster0.cpu1 R X20 0000000000000000 206 | 220000 ps cluster0.cpu1 IT (22) 04000054 d2800015 O EL3h_s : MOV x21,#0 207 | 220000 ps cluster0.cpu1 R X21 0000000000000000 208 | 230000 ps cluster0.cpu1 IT (23) 04000058 d2800016 O EL3h_s : MOV x22,#0 209 | 230000 ps cluster0.cpu1 R X22 0000000000000000 210 | 240000 ps cluster0.cpu1 IT (24) 0400005c d2800017 O EL3h_s : MOV x23,#0 211 | 240000 ps cluster0.cpu1 R X23 0000000000000000 212 | 250000 ps cluster0.cpu1 IT (25) 04000060 d2800018 O EL3h_s : MOV x24,#0 213 | 250000 ps cluster0.cpu1 R X24 0000000000000000 214 | 260000 ps cluster0.cpu1 IT (26) 04000064 d2800019 O EL3h_s : MOV x25,#0 215 | 260000 ps cluster0.cpu1 R X25 0000000000000000 216 | 270000 ps cluster0.cpu1 IT (27) 04000068 d280001a O EL3h_s : MOV x26,#0 217 | 270000 ps cluster0.cpu1 R X26 0000000000000000 218 | 280000 ps cluster0.cpu1 IT (28) 0400006c d280001b O EL3h_s : MOV x27,#0 219 | 280000 ps cluster0.cpu1 R X27 0000000000000000 220 | 290000 ps cluster0.cpu1 IT (29) 04000070 d280001c O EL3h_s : MOV x28,#0 221 | 290000 ps cluster0.cpu1 R X28 0000000000000000 222 | 300000 ps cluster0.cpu1 IT (30) 04000074 d280001d O EL3h_s : MOV x29,#0 223 | 300000 ps cluster0.cpu1 R X29 0000000000000000 224 | 310000 ps cluster0.cpu1 IT (31) 04000078 d280001e O EL3h_s : MOV x30,#0 225 | 310000 ps cluster0.cpu1 R X30 0000000000000000 226 | 320000 ps cluster0.cpu1 IT (32) 0400007c d2800000 O EL3h_s : MOV x0,#0 227 | 320000 ps cluster0.cpu1 R X0 0000000000000000 228 | 330000 ps cluster0.cpu1 IT (33) 04000080 d51e1140 O EL3h_s : MSR CPTR_EL3,x0 229 | 330000 ps cluster0.cpu1 R CPTR_EL3 00000000:00000000 230 | 340000 ps cluster0.cpu1 IT (34) 04000084 d51e111f O EL3h_s : MSR SCR_EL3,xzr 231 | 340000 ps cluster0.cpu1 R SCR_EL3 00000000:00000000 232 | 350000 ps cluster0.cpu1 IT (35) 04000088 d5033fdf O EL3h_s : ISB 233 | 360000 ps cluster0.cpu1 IT (36) 0400008c d2800020 O EL3h_s : MOV x0,#1 234 | 360000 ps cluster0.cpu1 R X0 0000000000000001 235 | 370000 ps cluster0.cpu1 IT (37) 04000090 d51ecca0 O EL3h_s : MSR ICC_SRE_EL3,x0 236 | 370000 ps cluster0.cpu1 R ICC_SRE_EL3 00000000:00000001 237 | 380000 ps cluster0.cpu1 IT (38) 04000094 d5033fdf O EL3h_s : ISB 238 | 390000 ps cluster0.cpu1 IT (39) 04000098 d518cca0 O EL3h_s : MSR ICC_SRE_EL1,x0 239 | 390000 ps cluster0.cpu1 R ICC_SRE_EL1 00000000:00000001 240 | 400000 ps cluster0.cpu1 IT (40) 0400009c d2800021 O EL3h_s : MOV x1,#1 241 | 400000 ps cluster0.cpu1 R X1 0000000000000001 242 | 410000 ps cluster0.cpu1 IT (41) 040000a0 d51e1101 O EL3h_s : MSR SCR_EL3,x1 243 | 410000 ps cluster0.cpu1 R SCR_EL3 00000000:00000001 244 | 420000 ps cluster0.cpu1 IT (42) 040000a4 d5033fdf O EL3h_s : ISB 245 | 430000 ps cluster0.cpu1 IT (43) 040000a8 d51cc9a0 O EL3h_s : MSR ICC_SRE_EL2,x0 246 | 430000 ps cluster0.cpu1 R ICC_SRE_EL2 00000000:00000001 247 | 440000 ps cluster0.cpu1 IT (44) 040000ac d5033fdf O EL3h_s : ISB 248 | 450000 ps cluster0.cpu1 IT (45) 040000b0 d518cca0 O EL3h_s : MSR ICC_SRE_EL1,x0 249 | 450000 ps cluster0.cpu1 R ICC_SRE_EL1 00000000:00000001 250 | 460000 ps cluster0.cpu1 IT (46) 040000b4 52800001 O EL3h_s : MOV w1,#0 251 | 460000 ps cluster0.cpu1 R X1 0000000000000000 252 | 470000 ps cluster0.cpu1 IT (47) 040000b8 32150021 O EL3h_s : ORR w1,w1,#0x800 253 | 470000 ps cluster0.cpu1 R X1 0000000000000800 254 | 480000 ps cluster0.cpu1 IT (48) 040000bc 32160021 O EL3h_s : ORR w1,w1,#0x400 255 | 480000 ps cluster0.cpu1 R X1 0000000000000C00 256 | 490000 ps cluster0.cpu1 IT (49) 040000c0 321d0021 O EL3h_s : ORR w1,w1,#8 257 | 490000 ps cluster0.cpu1 R X1 0000000000000C08 258 | 500000 ps cluster0.cpu1 IT (50) 040000c4 321e0021 O EL3h_s : ORR w1,w1,#4 259 | 500000 ps cluster0.cpu1 R X1 0000000000000C0C 260 | 510000 ps cluster0.cpu1 IT (51) 040000c8 321f0021 O EL3h_s : ORR w1,w1,#2 261 | 510000 ps cluster0.cpu1 R X1 0000000000000C0E 262 | 520000 ps cluster0.cpu1 IT (52) 040000cc d51e1101 O EL3h_s : MSR SCR_EL3,x1 263 | 520000 ps cluster0.cpu1 R SCR_EL3 00000000:00000c0e 264 | 530000 ps cluster0.cpu1 IT (53) 040000d0 d5033fdf O EL3h_s : ISB 265 | 540000 ps cluster0.cpu1 IT (54) 040000d4 d53800a0 O EL3h_s : MRS x0,MPIDR_EL1 266 | 540000 ps cluster0.cpu1 R X0 0000000081000100 267 | 550000 ps cluster0.cpu1 IT (55) 040000d8 b2405fe1 O EL3h_s : MOV x1,#0xffffff 268 | 550000 ps cluster0.cpu1 R X1 0000000000FFFFFF 269 | 560000 ps cluster0.cpu1 IT (56) 040000dc 8a010000 O EL3h_s : AND x0,x0,x1 270 | 560000 ps cluster0.cpu1 R X0 0000000000000100 271 | 570000 ps cluster0.cpu1 IS (57) 040000e0 b40000c0 O EL3h_s : CBZ x0,{pc}+0x18 ; 0x40000f8 272 | 580000 ps cluster0.cpu1 IT (58) 040000e4 d2802001 O EL3h_s : MOV x1,#0x100 273 | 580000 ps cluster0.cpu1 R X1 0000000000000100 274 | 590000 ps cluster0.cpu1 IT (59) 040000e8 eb01001f O EL3h_s : CMP x0,x1 275 | 590000 ps cluster0.cpu1 R cpsr 600003cd 276 | 600000 ps cluster0.cpu1 IT (60) 040000ec 5401b7e0 O EL3h_s : B.EQ {pc}+0x36fc ; 0x40037e8 277 | 610000 ps cluster0.cpu1 IT (61) 040037e8 58000580 O EL3h_s : LDR x0,{pc}+0xb0 ; 0x4003898 278 | 610000 ps cluster0.cpu1 MR8 04003898:000004003898 00000000_2e001000 279 | 610000 ps cluster0.cpu1 R X0 000000002E001000 280 | 620000 ps cluster0.cpu1 IT (62) 040037ec d51cc000 O EL3h_s : MSR VBAR_EL2,x0 281 | 620000 ps cluster0.cpu1 R VBAR_EL2 00000000:2e001000 282 | 630000 ps cluster0.cpu1 IT (63) 040037f0 d518c000 O EL3h_s : MSR VBAR_EL1,x0 283 | 630000 ps cluster0.cpu1 R VBAR_EL1 00000000:2e001000 284 | 640000 ps cluster0.cpu1 IT (64) 040037f4 d2a5e280 O EL3h_s : MOV x0,#0x2f140000 285 | 640000 ps cluster0.cpu1 R X0 000000002F140000 286 | 650000 ps cluster0.cpu1 IT (65) 040037f8 d2800281 O EL3h_s : MOV x1,#0x14 287 | 650000 ps cluster0.cpu1 R X1 0000000000000014 288 | 660000 ps cluster0.cpu1 IT (66) 040037fc 8b000021 O EL3h_s : ADD x1,x1,x0 289 | 660000 ps cluster0.cpu1 R X1 000000002F140014 290 | 670000 ps cluster0.cpu1 IT (67) 04003800 b900003f O EL3h_s : STR wzr,[x1,#0] 291 | 670000 ps cluster0.cpu1 MW4 2f140014:00002f140014 00000000 292 | 680000 ps cluster0.cpu1 IT (68) 04003804 d5033f9f O EL3h_s : DSB SY 293 | 690000 ps cluster0.cpu1 IT (69) 04003808 b9400020 O EL3h_s : LDR w0,[x1,#0] 294 | 690000 ps cluster0.cpu1 MR4 2f140014:00002f140014 00000000 295 | 690000 ps cluster0.cpu1 R X0 0000000000000000 296 | 700000 ps cluster0.cpu1 IT (70) 0400380c 121f0400 O EL3h_s : AND w0,w0,#6 297 | 700000 ps cluster0.cpu1 R X0 0000000000000000 298 | 710000 ps cluster0.cpu1 IS (71) 04003810 35ffffc0 O EL3h_s : CBNZ w0,{pc}-8 ; 0x4003808 299 | 720000 ps cluster0.cpu1 IT (72) 04003814 52801fe0 O EL3h_s : MOV w0,#0xff 300 | 720000 ps cluster0.cpu1 R X0 00000000000000FF 301 | 730000 ps cluster0.cpu1 IT (73) 04003818 d5184600 O EL3h_s : MSR ICC_PMR_EL1,x0 302 | 730000 ps cluster0.cpu1 R ICC_PMR_EL1 00000000:000000ff 303 | 740000 ps cluster0.cpu1 IT (74) 0400381c 52800060 O EL3h_s : MOV w0,#3 304 | 740000 ps cluster0.cpu1 R X0 0000000000000003 305 | 750000 ps cluster0.cpu1 IT (75) 04003820 d51ecce0 O EL3h_s : MSR ICC_IGRPEN1_EL3,x0 306 | 750000 ps cluster0.cpu1 R ICC_IGRPEN1_EL3 00000000:00000003 307 | 760000 ps cluster0.cpu1 IT (76) 04003824 d518ccc0 O EL3h_s : MSR ICC_IGRPEN0_EL1,x0 308 | 760000 ps cluster0.cpu1 R ICC_IGRPEN0_EL1 00000000:00000003 309 | 770000 ps cluster0.cpu1 IT (77) 04003828 d518101f O EL3h_s : MSR SCTLR_EL1,xzr 310 | 770000 ps cluster0.cpu1 R SCTLR_EL1 00000000:00000000 311 | 780000 ps cluster0.cpu1 IT (78) 0400382c d51c101f O EL3h_s : MSR SCTLR_EL2,xzr 312 | 780000 ps cluster0.cpu1 R SCTLR_EL2 00000000:00000000 313 | 790000 ps cluster0.cpu1 IT (79) 04003830 d2800020 O EL3h_s : MOV x0,#1 314 | 790000 ps cluster0.cpu1 R X0 0000000000000001 315 | 800000 ps cluster0.cpu1 IT (80) 04003834 b2760000 O EL3h_s : ORR x0,x0,#0x400 316 | 800000 ps cluster0.cpu1 R X0 0000000000000401 317 | 810000 ps cluster0.cpu1 IT (81) 04003838 d51e1100 O EL3h_s : MSR SCR_EL3,x0 318 | 810000 ps cluster0.cpu1 R SCR_EL3 00000000:00000401 319 | 820000 ps cluster0.cpu1 IT (82) 0400383c d2b00000 O EL3h_s : MOV x0,#0x80000000 320 | 820000 ps cluster0.cpu1 R X0 0000000080000000 321 | 830000 ps cluster0.cpu1 IT (83) 04003840 b27b0000 O EL3h_s : ORR x0,x0,#0x20 322 | 830000 ps cluster0.cpu1 R X0 0000000080000020 323 | 840000 ps cluster0.cpu1 IT (84) 04003844 b27c0000 O EL3h_s : ORR x0,x0,#0x10 324 | 840000 ps cluster0.cpu1 R X0 0000000080000030 325 | 850000 ps cluster0.cpu1 IT (85) 04003848 b27d0000 O EL3h_s : ORR x0,x0,#8 326 | 850000 ps cluster0.cpu1 R X0 0000000080000038 327 | 860000 ps cluster0.cpu1 IT (86) 0400384c d51c1100 O EL3h_s : MSR HCR_EL2,x0 328 | 860000 ps cluster0.cpu1 R HCR_EL2 00000000:80000038 329 | 870000 ps cluster0.cpu1 IT (87) 04003850 d51cc81f O EL3h_s : MSR ICH_AP0R0_EL2,xzr 330 | 870000 ps cluster0.cpu1 R ICH_AP0R0_EL2 00000000:00000000 331 | 880000 ps cluster0.cpu1 IT (88) 04003854 d51cc91f O EL3h_s : MSR ICH_AP1R0_EL2,xzr 332 | 880000 ps cluster0.cpu1 R ICH_AP1R0_EL2 00000000:00000000 333 | 890000 ps cluster0.cpu1 IT (89) 04003858 d2800020 O EL3h_s : MOV x0,#1 334 | 890000 ps cluster0.cpu1 R X0 0000000000000001 335 | 900000 ps cluster0.cpu1 IT (90) 0400385c b27f0000 O EL3h_s : ORR x0,x0,#2 336 | 900000 ps cluster0.cpu1 R X0 0000000000000003 337 | 910000 ps cluster0.cpu1 IT (91) 04003860 b27d0000 O EL3h_s : ORR x0,x0,#8 338 | 910000 ps cluster0.cpu1 R X0 000000000000000B 339 | 920000 ps cluster0.cpu1 IT (92) 04003864 b27c0000 O EL3h_s : ORR x0,x0,#0x10 340 | 920000 ps cluster0.cpu1 R X0 000000000000001B 341 | 930000 ps cluster0.cpu1 IT (93) 04003868 b2681c00 O EL3h_s : ORR x0,x0,#0xff000000 342 | 930000 ps cluster0.cpu1 R X0 00000000FF00001B 343 | 940000 ps cluster0.cpu1 IT (94) 0400386c d51ccbe0 O EL3h_s : MSR ICH_VMCR_EL2,x0 344 | 940000 ps cluster0.cpu1 R ICH_VMCR_EL2 00000000:ff00001b 345 | 950000 ps cluster0.cpu1 IT (95) 04003870 d2800020 O EL3h_s : MOV x0,#1 346 | 950000 ps cluster0.cpu1 R X0 0000000000000001 347 | 960000 ps cluster0.cpu1 IT (96) 04003874 d51ccb00 O EL3h_s : MSR ICH_HCR_EL2,x0 348 | 960000 ps cluster0.cpu1 R ICH_HCR_EL2 00000000:00000001 349 | 970000 ps cluster0.cpu1 IT (97) 04003878 d51ccc00 O EL3h_s : MSR ICH_LR0_EL2,x0 350 | 970000 ps cluster0.cpu1 R ICH_LR0_EL2 00000000:00000001 351 | 980000 ps cluster0.cpu1 IT (98) 0400387c aa1f03eb O EL3h_s : MOV x11,xzr 352 | 980000 ps cluster0.cpu1 R X11 0000000000000000 353 | 990000 ps cluster0.cpu1 IT (99) 04003880 58000100 O EL3h_s : LDR x0,{pc}+0x20 ; 0x40038a0 354 | 990000 ps cluster0.cpu1 MR8 040038a0:0000040038a0 00000000_2e000000 355 | 990000 ps cluster0.cpu1 R X0 000000002E000000 356 | 1000000 ps cluster0.cpu1 IT (100) 04003884 d51e4020 O EL3h_s : MSR ELR_EL3,x0 357 | 1000000 ps cluster0.cpu1 R ELR_EL3 00000000:2e000000 358 | 1010000 ps cluster0.cpu1 IT (101) 04003888 d28000a0 O EL3h_s : MOV x0,#5 359 | 1010000 ps cluster0.cpu1 R X0 0000000000000005 360 | 1020000 ps cluster0.cpu1 IT (102) 0400388c d51e4000 O EL3h_s : MSR SPSR_EL3,x0 361 | 1020000 ps cluster0.cpu1 R SPSR_EL3 00000000:00000005 362 | 1030000 ps cluster0.cpu1 IT (103) 04003890 d69f03e0 O EL3h_s : ERET 363 | 1030000 ps cluster0.cpu1 E 00000000:000000000000 EL1h 00000019 CoreEvent_ModeChange 364 | 1030000 ps cluster0.cpu1 R cpsr 00000005 365 | 1030000 ps cluster0.cpu1 SIGNAL: SIGNAL=DebugReset STATE=N 366 | 1030000 ps cluster0.cpu1 SIGNAL: SIGNAL=ResetHold STATE=N 367 | 1040000 ps cluster0.cpu1 IT (104) 2e000000 d503201f O EL1h_n : NOP 368 | 1050000 ps cluster0.cpu1 IT (105) 2e000004 d503207f O EL1h_n : WFI 369 | 5478450000 ps cluster0.cpu1 R ISR 00000080 370 | 5478450000 ps cluster0.cpu1 SIGNAL: SIGNAL=VIRQ STATE=Y 371 | 5478200000 ps cluster0.cpu1 E 2e000008:00002e000008_NS 00000085 CoreEvent_CURRENT_SPx_IRQ 372 | 5478200000 ps cluster0.cpu1 R cpsr 000003c5 373 | 5478200000 ps cluster0.cpu1 R ELR_EL1 000000002e000008 374 | 5478200000 ps cluster0.cpu1 R SPSR_EL1 0000000000000005 375 | 5478240000 ps cluster0.cpu1 IT (107) 2e001280 14000141 O EL1h_n : B {pc}+0x504 ; 0x2e001784 376 | 5478250000 ps cluster0.cpu1 IT (108) 2e001784 d538cc00 O EL1h_n : MRS x0,ICC_IAR1_EL1 377 | 5478250000 ps cluster0.cpu1 R X0 0000000000002000 378 | 5478250000 ps cluster0.cpu1 SIGNAL: SIGNAL=VIRQ STATE=N 379 | 5478260000 ps cluster0.cpu1 IT (109) 2e001788 580003c1 O EL1h_n : LDR x1,{pc}+0x78 ; 0x2e001800 380 | 5478260000 ps cluster0.cpu1 MR8 2e001800:00002e001800_NS 00000000_2e0017c0 381 | 5478260000 ps cluster0.cpu1 R X1 000000002E0017C0 382 | 5478270000 ps cluster0.cpu1 IT (110) 2e00178c 52800080 O EL1h_n : MOV w0,#4 383 | 5478270000 ps cluster0.cpu1 R X0 0000000000000004 384 | 5478280000 ps cluster0.cpu1 IT (111) 2e001790 d45e0000 O EL1h_n : HLT #0xf000 385 | 5478290000 ps cluster0.cpu1 IT (112) 2e001794 d518cc20 O EL1h_n : MSR ICC_EOIR1_EL1,x0 386 | 5478290000 ps cluster0.cpu1 R ICC_EOIR1_EL1 00000000:00000004 387 | 5478300000 ps cluster0.cpu1 IT (113) 2e001798 9100056b O EL1h_n : ADD x11,x11,#1 388 | 5478300000 ps cluster0.cpu1 R X11 0000000000000001 389 | 5478310000 ps cluster0.cpu1 IT (114) 2e00179c d69f03e0 O EL1h_n : ERET 390 | 5478310000 ps cluster0.cpu1 R cpsr 00000005 391 | 5478310000 ps cluster0.cpu1 R ISR 00000000 392 | 5478320000 ps cluster0.cpu1 IS (115) 2e000008 b4ffffeb O EL1h_n : CBZ x11,{pc}-4 ; 0x2e000004 393 | 5478330000 ps cluster0.cpu1 IT (116) 2e00000c 52800300 O EL1h_n : MOV w0,#0x18 394 | 5478330000 ps cluster0.cpu1 R X0 0000000000000018 395 | 5478340000 ps cluster0.cpu1 IT (117) 2e000010 d45e0000 O EL1h_n : HLT #0xf000 396 | -------------------------------------------------------------------------------- /scripts/run_gicv3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $# -lt 1 ];then 4 | echo "no arguments" 5 | else 6 | echo "application: $1" 7 | fi 8 | 9 | FVP_Base_RevC-2xAEMvA \ 10 | -C cluster0.NUM_CORES=1 \ 11 | -C cluster1.NUM_CORES=0 \ 12 | -C gic_distributor.GITS_BASER0-type=1 \ 13 | -C gic_distributor.GITS_BASER1-type=4 \ 14 | -C bp.secure_memory=0 \ 15 | -C gic_distributor.ITS-count=1 \ 16 | -C gic_distributor.ITS-use-physical-target-addresses=0 \ 17 | -C gic_distributor.GITS_BASER6-type=0 \ 18 | -C gic_distributor.extended-ppi-count=32 \ 19 | -C gic_distributor.extended-spi-count=32 \ 20 | --application=$1 21 | -------------------------------------------------------------------------------- /scripts/run_gicv4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $# -lt 1 ];then 4 | echo "no arguments" 5 | else 6 | echo "application: $1" 7 | fi 8 | 9 | FVP_Base_RevC-2xAEMvA \ 10 | -C has-gicv4.1=1 \ 11 | -C bp.secure_memory=0 \ 12 | -C gic_distributor.ITS-count=1 \ 13 | -C gic_distributor.ITS-use-physical-target-addresses=0 \ 14 | -C gic_distributor.GITS_BASER0-type=1 \ 15 | -C gic_distributor.GITS_BASER1-type=4 \ 16 | -C gic_distributor.GITS_BASER2-type=2 \ 17 | -C gic_distributor.GITS_BASER6-type=0 \ 18 | -C gic_distributor.virtual-lpi-support=1 \ 19 | -C gic_distributor.reg-base-per-redistributor=0.0.0.0=0x2f100000,0.0.1.0=0x2f140000,0.0.2.0=0x2f180000,0.0.3.0=0x2f1C0000,0.1.0.0=0x2f200000,0.1.1.0=0x2f240000,0.1.2.0=0x2f280000,0.1.3.0=0x2f2c0000 \ 20 | -C gic_distributor.common-lpi-configuration=2 \ 21 | -C gic_distributor.ITS-shared-vPE-table=2 \ 22 | -C gic_distributor.ITS-vmovp-bit=1 \ 23 | -C gic_distributor.has_VPENDBASER-dirty-flag-on-load=1 \ 24 | -C gic_distributor.extended-ppi-count=0 \ 25 | -C gic_distributor.extended-spi-count=1024 \ 26 | -C semihosting-enable=1 \ 27 | -C pctl.startup=0.*.*.0 \ 28 | --stat \ 29 | --application=$1 30 | -------------------------------------------------------------------------------- /scripts/run_gicv4_tarmac.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $# -lt 1 ];then 4 | echo "no arguments" 5 | else 6 | echo "application: $1" 7 | fi 8 | 9 | FVP_Base_RevC-2xAEMvA \ 10 | -C has-gicv4.1=1 \ 11 | -C bp.secure_memory=0 \ 12 | -C gic_distributor.ITS-count=1 \ 13 | -C gic_distributor.ITS-use-physical-target-addresses=0 \ 14 | -C gic_distributor.GITS_BASER0-type=1 \ 15 | -C gic_distributor.GITS_BASER1-type=4 \ 16 | -C gic_distributor.GITS_BASER2-type=2 \ 17 | -C gic_distributor.GITS_BASER6-type=0 \ 18 | -C gic_distributor.virtual-lpi-support=1 \ 19 | -C gic_distributor.reg-base-per-redistributor=0.0.0.0=0x2f100000,0.0.1.0=0x2f140000,0.0.2.0=0x2f180000,0.0.3.0=0x2f1C0000,0.1.0.0=0x2f200000,0.1.1.0=0x2f240000,0.1.2.0=0x2f280000,0.1.3.0=0x2f2c0000 \ 20 | -C gic_distributor.common-lpi-configuration=2 \ 21 | -C gic_distributor.ITS-shared-vPE-table=2 \ 22 | -C gic_distributor.ITS-vmovp-bit=1 \ 23 | -C gic_distributor.has_VPENDBASER-dirty-flag-on-load=1 \ 24 | -C gic_distributor.extended-ppi-count=0 \ 25 | -C gic_distributor.extended-spi-count=1024 \ 26 | -C semihosting-enable=1 \ 27 | -C pctl.startup=0.*.*.0 \ 28 | --plugin=/usr/local/src/Base_RevC_AEMvA_pkg/plugins/Linux64_GCC-9.3/TarmacTrace.so \ 29 | -C TRACE.TarmacTrace.trace-file=/root/gic.tarmac \ 30 | -C TRACE.TarmacTrace.trace_gicv3_its=1 \ 31 | -C TRACE.TarmacTrace.trace_gicv3=1 \ 32 | --stat \ 33 | --application=$1 34 | -------------------------------------------------------------------------------- /src/el3_vectors.s: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // 3 | // Copyright (C) Arm Limited, 2019 All rights reserved. 4 | // 5 | // The example code is provided to you as an aid to learning when working 6 | // with Arm-based technology, including but not limited to programming tutorials. 7 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 8 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 9 | // to use and copy the Software solely for the purpose of demonstration and 10 | // evaluation. 11 | // ------------------------------------------------------------ 12 | 13 | .section VECTORS,"ax" 14 | .align 12 15 | 16 | 17 | .global el3_vectors 18 | el3_vectors: 19 | 20 | .global fiqHandler 21 | 22 | // ------------------------------------------------------------ 23 | // Current EL with SP0 24 | // ------------------------------------------------------------ 25 | .balign 128 26 | sync_current_el_sp0: 27 | B . // Synchronous 28 | 29 | .balign 128 30 | irq_current_el_sp0: 31 | B . // IRQ 32 | 33 | .balign 128 34 | fiq_current_el_sp0: 35 | B fiqFirstLevelHandler // FIQ 36 | 37 | .balign 128 38 | serror_current_el_sp0: 39 | B . // SError 40 | 41 | // ------------------------------------------------------------ 42 | // Current EL with SPx 43 | // ------------------------------------------------------------ 44 | 45 | .balign 128 46 | sync_current_el_spx: 47 | B . // Synchronous 48 | 49 | .balign 128 50 | irq_current_el_spx: 51 | B . // IRQ 52 | 53 | .balign 128 54 | fiq_current_el_spx: 55 | B fiqFirstLevelHandler // FIQ 56 | 57 | .balign 128 58 | serror_current_el_spx: 59 | B . // SError 60 | 61 | // ------------------------------------------------------------ 62 | // Lower EL using AArch64 63 | // ------------------------------------------------------------ 64 | 65 | .balign 128 66 | sync_lower_el_aarch64: 67 | B . 68 | 69 | .balign 128 70 | irq_lower_el_aarch64: 71 | B . // IRQ 72 | 73 | .balign 128 74 | fiq_lower_el_aarch64: 75 | B fiqFirstLevelHandler // FIQ 76 | 77 | .balign 128 78 | serror_lower_el_aarch64: 79 | B . // SError 80 | 81 | // ------------------------------------------------------------ 82 | // Lower EL using AArch32 83 | // ------------------------------------------------------------ 84 | 85 | .balign 128 86 | sync_lower_el_aarch32: 87 | B . 88 | 89 | .balign 128 90 | irq_lower_el_aarch32: 91 | B . // IRQ 92 | 93 | .balign 128 94 | fiq_lower_el_aarch32: 95 | B fiqFirstLevelHandler // FIQ 96 | 97 | .balign 128 98 | serror_lower_el_aarch32: 99 | B . // SError 100 | 101 | 102 | // ------------------------------------------------------------ 103 | 104 | fiqFirstLevelHandler: 105 | STP x29, x30, [sp, #-16]! 106 | STP x18, x19, [sp, #-16]! 107 | STP x16, x17, [sp, #-16]! 108 | STP x14, x15, [sp, #-16]! 109 | STP x12, x13, [sp, #-16]! 110 | STP x10, x11, [sp, #-16]! 111 | STP x8, x9, [sp, #-16]! 112 | STP x6, x7, [sp, #-16]! 113 | STP x4, x5, [sp, #-16]! 114 | STP x2, x3, [sp, #-16]! 115 | STP x0, x1, [sp, #-16]! 116 | 117 | BL fiqHandler 118 | 119 | LDP x0, x1, [sp], #16 120 | LDP x2, x3, [sp], #16 121 | LDP x4, x5, [sp], #16 122 | LDP x6, x7, [sp], #16 123 | LDP x8, x9, [sp], #16 124 | LDP x10, x11, [sp], #16 125 | LDP x12, x13, [sp], #16 126 | LDP x14, x15, [sp], #16 127 | LDP x16, x17, [sp], #16 128 | LDP x18, x19, [sp], #16 129 | LDP x29, x30, [sp], #16 130 | ERET 131 | 132 | // ------------------------------------------------------------ 133 | // End of file 134 | // ------------------------------------------------------------ 135 | 136 | -------------------------------------------------------------------------------- /src/generic_timer.s: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // ARMv8-A AArch64 Generic Timer Access Functions 3 | // 4 | // Copyright (C) Arm Limited, 2019 All rights reserved. 5 | // 6 | // The example code is provided to you as an aid to learning when working 7 | // with Arm-based technology, including but not limited to programming tutorials. 8 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 9 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 10 | // to use and copy the Software solely for the purpose of demonstration and 11 | // evaluation. 12 | // ------------------------------------------------------------ 13 | 14 | 15 | 16 | .section AArch64_GenericTimer,"ax" 17 | .align 3 18 | 19 | // ------------------------------------------------------------ 20 | 21 | .global getCNTFRQ 22 | // uint32_t getCNTFRQ(void) 23 | // Returns the value of CNTFRQ_EL0 24 | .type getCNTFRQ, @function 25 | getCNTFRQ: 26 | MRS x0, CNTFRQ_EL0 27 | RET 28 | 29 | 30 | // ------------------------------------------------------------ 31 | 32 | .global setCNTFRQ 33 | // void setCNTFRQ(uint32_t freq) 34 | // Sets the value of CNTFRQ_EL0 (only possible at EL3) 35 | // w0 - freq - The value to be written into CNTFRQ_EL0 36 | .type setCNTFRQ, @function 37 | setCNTFRQ: 38 | MSR CNTFRQ_EL0, x0 39 | RET 40 | 41 | 42 | // ------------------------------------------------------------ 43 | 44 | .global getPhysicalCount 45 | // uint64_t getPhysicalCount(void) 46 | // Returns the current value of physical count (CNTPCT_EL0) 47 | .type getPhysicalCount, @function 48 | getPhysicalCount: 49 | ISB 50 | MRS x0, CNTPCT_EL0 51 | RET 52 | 53 | 54 | // ------------------------------------------------------------ 55 | 56 | .global getVirtualCount 57 | // uint64_t getVirtualCount(void) 58 | // Returns the current value of the virtual count register (CNTVCT_EL0) 59 | .type getVirtualCount, @function 60 | getVirtualCount: 61 | ISB 62 | MRS x0, CNTVCT_EL0 63 | RET 64 | 65 | 66 | // ------------------------------------------------------------ 67 | 68 | .global getEL1Ctrl 69 | // uint32_t getEL1Ctrl(void) 70 | // Returns the value of EL1 Timer Control Register (CNTKCTL_EL1) 71 | .type getEL1Ctrl, @function 72 | getEL1Ctrl: 73 | MRS x0, CNTKCTL_EL1 74 | RET 75 | 76 | 77 | // ------------------------------------------------------------ 78 | 79 | .global setEL1Ctrl 80 | // void setEL1Ctrl(uint32_t value) 81 | // Sets the value of Counter Non-secure EL1 Control Register (CNTKCTL_EL1) 82 | // 0 - value - The value to be written into CNTKCTL_EL1 83 | .type setEL1Ctrl, @function 84 | setEL1Ctrl: 85 | MSR CNTKCTL_EL1, x0 86 | RET 87 | 88 | 89 | // ------------------------------------------------------------ 90 | 91 | .global getEL2Ctrl 92 | // uint32_t getEL2Ctrl(void) 93 | // Returns the value of the EL2 Timer Control Register (CNTHCTL_EL2) 94 | .type getEL2Ctrl, @function 95 | getEL2Ctrl: 96 | MRS x0, CNTHCTL_EL2 97 | RET 98 | 99 | 100 | // ------------------------------------------------------------ 101 | 102 | .global setEL2Ctrl 103 | // void setEL2Ctrl(uint32_t value) 104 | // Sets the value of the EL2 Timer Control Register (CNTHCTL_EL2) 105 | // x0 - value - The value to be written into CNTHCTL_EL2 106 | .type setEL2Ctrl, @function 107 | setEL2Ctrl: 108 | MSR CNTHCTL_EL2, x0 109 | RET 110 | 111 | 112 | // ------------------------------------------------------------ 113 | // Non-secure Physical Timer 114 | // ------------------------------------------------------------ 115 | 116 | .global getNSEL1PhysicalCompValue 117 | // uint64_t getNSEL1PhysicalCompValue(void) 118 | // Returns the value of Non-secure EL1 Physical Compare Value Register (CNTP_CVAL_EL0) 119 | .type getNSEL1PhysicalCompValue, @function 120 | getNSEL1PhysicalCompValue: 121 | MRS x0, CNTP_CVAL_EL0 122 | RET 123 | 124 | 125 | // ------------------------------------------------------------ 126 | 127 | .global setNSEL1PhysicalCompValue 128 | // void setNSEL1PhysicalCompValue(uint64_t value) 129 | // Sets the value of the Non-secure EL1 Physical Compare Value Register (CNTP_CVAL_EL0) 130 | // x0 - value - The value to be written into CNTP_CVAL_EL0 131 | .type setNSEL1PhysicalCompValue, @function 132 | setNSEL1PhysicalCompValue: 133 | MSR CNTP_CVAL_EL0, x0 134 | RET 135 | 136 | 137 | // ------------------------------------------------------------ 138 | 139 | .global getNSEL1PhysicalTimerValue 140 | // uint32_t getNSEL1PhysicalTimerValue(void) 141 | // Returns the value of Non-secure EL1 Physical Timer Value Register (CNTP_TVAL_EL0) 142 | .type getNSEL1PhysicalTimerValue, @function 143 | getNSEL1PhysicalTimerValue: 144 | MRS x0, CNTP_TVAL_EL0 145 | RET 146 | 147 | 148 | // ------------------------------------------------------------ 149 | 150 | .global setNSEL1PhysicalTimerValue 151 | // void setNSEL1PhysicalTimerValue(uint32_t value) 152 | // Sets the value of the Non-secure EL1 Physical Timer Value Register (CNTP_TVAL_EL0) 153 | // w0 - value - The value to be written into CNTP_TVAL_EL0 154 | .type setNSEL1PhysicalTimerValue, @function 155 | setNSEL1PhysicalTimerValue: 156 | MSR CNTP_TVAL_EL0, x0 157 | RET 158 | 159 | 160 | // ------------------------------------------------------------ 161 | 162 | .global getNSEL1PhysicalTimerCtrl 163 | // uint32_t getNSEL1PhysicalTimerCtrl(void) 164 | // Returns the value of Non-secure EL1 Physical Timer Control Register (CNTP_CTL_EL0) 165 | .type getNSEL1PhysicalTimerCtrl, @function 166 | getNSEL1PhysicalTimerCtrl: 167 | MRS x0, CNTP_CTL_EL0 168 | RET 169 | 170 | 171 | // ------------------------------------------------------------ 172 | 173 | .global setNSEL1PhysicalTimerCtrl 174 | // void setNSEL1PhysicalTimerCtrl(uint32_t value) 175 | // Sets the value of the Non-secure EL1 Physical Timer Control Register (CNTP_CTL_EL0) 176 | // w0 - value - The value to be written into CNTP_CTL_EL0 177 | .type setNSEL1PhysicalTimerCtrl, @function 178 | setNSEL1PhysicalTimerCtrl: 179 | MSR CNTP_CTL_EL0, x0 180 | ISB 181 | RET 182 | 183 | 184 | // ------------------------------------------------------------ 185 | // Secure Physical Timer 186 | // ------------------------------------------------------------ 187 | 188 | .global getSEL1PhysicalCompValue 189 | // uint64_t getSEL1PhysicalCompValue(void) 190 | // Returns the value of Secure EL1 Physical Compare Value Register (CNTPS_CVAL_EL1) 191 | .type getSEL1PhysicalCompValue, @function 192 | getSEL1PhysicalCompValue: 193 | MRS x0, CNTPS_CVAL_EL1 194 | RET 195 | 196 | 197 | // ------------------------------------------------------------ 198 | 199 | .global setSEL1PhysicalCompValue 200 | // void setSEL1PhysicalCompValue(uint64_t value) 201 | // Sets the value of the Secure EL1 Physical Compare Value Register (CNTPS_CVAL_EL1) 202 | // x0 - value - The value to be written into CNTPS_CVAL_EL1 203 | .type setSEL1PhysicalCompValue, @function 204 | setSEL1PhysicalCompValue: 205 | MSR CNTPS_CVAL_EL1, x0 206 | RET 207 | 208 | 209 | 210 | // ------------------------------------------------------------ 211 | 212 | .global getSEL1PhysicalTimerValue 213 | // uint32_t getSEL1PhysicalTimerValue(void) 214 | // Returns the value of Secure EL1 Physical Timer Value Register (CNTPS_TVAL_EL1) 215 | .type getSEL1PhysicalTimerValue, @function 216 | getSEL1PhysicalTimerValue: 217 | MRS x0, CNTPS_TVAL_EL1 218 | RET 219 | 220 | 221 | // ------------------------------------------------------------ 222 | 223 | .global setSEL1PhysicalTimerValue 224 | // void setSEL1PhysicalTimerValue(uint32_t value) 225 | // Sets the value of the Secure EL1 Physical Timer Value Register (CNTPS_TVAL_EL1) 226 | // w0 - value - The value to be written into CNTPS_TVAL_EL1 227 | .type setSEL1PhysicalTimerValue, @function 228 | setSEL1PhysicalTimerValue: 229 | MSR CNTPS_TVAL_EL1, x0 230 | RET 231 | 232 | 233 | // ------------------------------------------------------------ 234 | 235 | .global getSEL1PhysicalTimerCtrl 236 | // uint32_t getSEL1PhysicalTimerCtrl(void) 237 | // Returns the value of Secure EL1 Physical Timer Control Register (CNTPS_CTL_EL1) 238 | .type getSEL1PhysicalTimerCtrl, @function 239 | getSEL1PhysicalTimerCtrl: 240 | MRS x0, CNTPS_CTL_EL1 241 | RET 242 | 243 | 244 | // ------------------------------------------------------------ 245 | 246 | .global setSEL1PhysicalTimerCtrl 247 | // void setSEL1PhysicalTimerCtrl(uint32_t value) 248 | // Sets the value of the Secure EL1 Physical Timer Control Register (CNTPS_CTL_EL1) 249 | // w0 - value - The value to be written into CNTPS_CTL_EL1 250 | .type setSEL1PhysicalTimerCtrl, @function 251 | setSEL1PhysicalTimerCtrl: 252 | MSR CNTPS_CTL_EL1, x0 253 | ISB 254 | RET 255 | 256 | 257 | // ------------------------------------------------------------ 258 | 259 | .global configSecureEL1TimerAccess 260 | // void configSecureEL1TimerAccess(unsigned int config)// 261 | // Sets the values of the SCR_EL3.ST bit (bit 11) based on the value in x0 262 | // EL3 accessible only! 263 | .type configSecureEL1TimerAccess, @function 264 | configSecureEL1TimerAccess: 265 | MRS x1, SCR_EL3 266 | BFI x1, x0, #11, #1 267 | MSR SCR_EL3, x1 268 | RET 269 | 270 | 271 | // ------------------------------------------------------------ 272 | // Virtual Timer 273 | // ------------------------------------------------------------ 274 | 275 | .global getEL1VirtualCompValue 276 | // uint64_t getEL1VirtualCompValue(void) 277 | // Returns the value of EL1 Virtual Compare Value Register (CNTV_CVAL_EL0) 278 | .type getEL1VirtualCompValue, @function 279 | getEL1VirtualCompValue: 280 | MRS x0, CNTV_CVAL_EL0 281 | RET 282 | 283 | 284 | // ------------------------------------------------------------ 285 | 286 | .global setEL1VirtualCompValue 287 | // void setEL1VirtualCompValue(uint64_t value) 288 | // Sets the value of the EL1 Virtual Compare Value Register (CNTV_CVAL_EL0) 289 | // x0 - value - The value to be written into CNTV_CVAL_EL0 290 | .type setEL1VirtualCompValue, @function 291 | setEL1VirtualCompValue: 292 | MSR CNTV_CVAL_EL0, x0 293 | RET 294 | 295 | 296 | // ------------------------------------------------------------ 297 | 298 | .global getEL1VirtualTimerValue 299 | // uint32_t getEL1VirtualTimerValue(void) 300 | // Returns the value of EL1 Virtual Timer Value Register (CNTV_TVAL_EL0) 301 | .type getEL1VirtualTimerValue, @function 302 | getEL1VirtualTimerValue: 303 | MRS x0, CNTV_TVAL_EL0 304 | RET 305 | 306 | 307 | // ------------------------------------------------------------ 308 | 309 | .global setEL1VirtualTimerValue 310 | // void setEL1VirtualTimerValue(uint32_t value) 311 | // Sets the value of the EL1 Virtual Timer Value Register (CNTV_TVAL_EL0) 312 | // w0 - value - The value to be written into CNTV_TVAL_EL0 313 | .type setEL1VirtualTimerValue, @function 314 | setEL1VirtualTimerValue: 315 | MSR CNTV_TVAL_EL0, x0 316 | RET 317 | 318 | 319 | // ------------------------------------------------------------ 320 | 321 | .global getEL1VirtualTimerCtrl 322 | // uint32_t getEL1VirtualTimerCtrl(void) 323 | // Returns the value of EL1 Virtual Timer Control Register (CNTV_CTL_EL0) 324 | .type getEL1VirtualTimerCtrl, @function 325 | getEL1VirtualTimerCtrl: 326 | MRS x0, CNTV_CTL_EL0 327 | RET 328 | 329 | 330 | // ------------------------------------------------------------ 331 | 332 | .global setEL1VirtualTimerCtrl 333 | // void setEL1VirtualTimerCtrl(uint32_t value) 334 | // Sets the value of the EL1 Virtual Timer Control Register (CNTV_CTL_EL0) 335 | // w0 - value - The value to be written into CNTV_CTL_EL0 336 | .type setEL1VirtualTimerCtrl, @function 337 | setEL1VirtualTimerCtrl: 338 | MSR CNTV_CTL_EL0, x0 339 | ISB 340 | RET 341 | 342 | 343 | // ------------------------------------------------------------ 344 | // Virtual Timer functions to be called by EL2 345 | // ------------------------------------------------------------ 346 | 347 | .global getVirtualCounterOffset 348 | // uint64_t getVirtualCounterOffset(void) 349 | // Returns the value of the Counter Virtual Offset Register (CNTVOFF_EL2) 350 | // EL2 and EL3 only 351 | .type getVirtualCounterOffset, @function 352 | getVirtualCounterOffset: 353 | MRS x0, CNTVOFF_EL2 354 | RET 355 | 356 | 357 | // ------------------------------------------------------------ 358 | 359 | .global setVirtualCounterOffset 360 | // void setVirtualCounterOffset(uint64_t offset) 361 | // Sets the value of the Counter Virtual Offset Register (CNTVOFF_EL2) 362 | // x0 - offset - The value to be written into CNTVOFF_EL2 363 | // EL2 and EL3 only 364 | .type setVirtualCounterOffset, @function 365 | setVirtualCounterOffset: 366 | MSR CNTVOFF_EL2, x0 367 | RET 368 | 369 | 370 | // ------------------------------------------------------------ 371 | // EL2 Physical Timer 372 | // ------------------------------------------------------------ 373 | 374 | .global getEL2PhysicalCompValue 375 | // uint64_t getEL2PhysicalCompValue(void) 376 | // Returns the value of EL2 Physical Compare Value Register (CNTHP_CVAL_EL2) 377 | .type getEL2PhysicalCompValue, @function 378 | getEL2PhysicalCompValue: 379 | MRS x0, CNTHP_CVAL_EL2 380 | RET 381 | 382 | 383 | // ------------------------------------------------------------ 384 | 385 | .global setEL2PhysicalCompValue 386 | // void setEL2PhysicalCompValue(uint64_t value) 387 | // Sets the value of the EL2 Physical Compare Value Register (CNTHP_CVAL_EL2) 388 | // x0 - value - The value to be written into CNTHP_CVAL_EL2 389 | .type setEL2PhysicalCompValue, @function 390 | setEL2PhysicalCompValue: 391 | MSR CNTHP_CVAL_EL2, x0 392 | RET 393 | 394 | 395 | 396 | // ------------------------------------------------------------ 397 | 398 | .global getEL2PhysicalTimerValue 399 | // uint32_t getEL2PhysicalTimerValue(void) 400 | // Returns the value of EL2 Physical Timer Value Register (CNTHP_TVAL_EL2) 401 | .type getEL2PhysicalTimerValue, @function 402 | getEL2PhysicalTimerValue: 403 | MRS x0, CNTHP_TVAL_EL2 404 | RET 405 | 406 | 407 | // ------------------------------------------------------------ 408 | 409 | .global setEL2PhysicalTimerValue 410 | // void setEL2PhysicalTimerValue(uint32_t value) 411 | // Sets the value of the EL2 Physical Timer Value Register (CNTHP_TVAL_EL2) 412 | // w0 - value - The value to be written into CNTHP_TVAL_EL2 413 | .type setEL2PhysicalTimerValue, @function 414 | setEL2PhysicalTimerValue: 415 | MSR CNTHP_TVAL_EL2, x0 416 | RET 417 | 418 | 419 | // ------------------------------------------------------------ 420 | 421 | .global getEL2PhysicalTimerCtrl 422 | // uint32_t getEL2PhysicalTimerCtrl(void) 423 | // Returns the value of EL2 Physical Timer Control Register (CNTHP_CTL_EL2) 424 | .type getEL2PhysicalTimerCtrl, @function 425 | getEL2PhysicalTimerCtrl: 426 | MRS x0, CNTHP_CTL_EL2 427 | RET 428 | 429 | 430 | // ------------------------------------------------------------ 431 | 432 | .global setEL2PhysicalTimerCtrl 433 | // void setEL2PhysicalTimerCtrl(uint32_t value) 434 | // Sets the value of the EL2 Physical Timer Control Register (CNTHP_CTL_EL2) 435 | // w0 - value - The value to be written into CNTHP_CTL_EL2 436 | .type setEL2PhysicalTimerCtrl, @function 437 | setEL2PhysicalTimerCtrl: 438 | MSR CNTHP_CTL_EL2, x0 439 | ISB 440 | RET 441 | 442 | 443 | // ------------------------------------------------------------ 444 | // End of code 445 | // ------------------------------------------------------------ 446 | -------------------------------------------------------------------------------- /src/gicv3_cpuif.S: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // ARMv8-A AArch64 - GICv3 CPU interface functions 3 | // 4 | // Copyright (C) Arm Limited, 2019 All rights reserved. 5 | // 6 | // The example code is provided to you as an aid to learning when working 7 | // with Arm-based technology, including but not limited to programming tutorials. 8 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 9 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 10 | // to use and copy the Software solely for the purpose of demonstration and 11 | // evaluation. 12 | // ------------------------------------------------------------ 13 | 14 | 15 | 16 | .section v8_aarch64_gicv3_cpuif,"ax" 17 | 18 | // ------------------------------------------------------------ 19 | 20 | .global setICC_SRE_EL1 21 | // void setICC_SRE_EL1(unsigned int value) 22 | .type setICC_SRE_EL1, @function 23 | setICC_SRE_EL1: 24 | MSR ICC_SRE_EL1, x0 25 | ISB 26 | RET 27 | 28 | 29 | 30 | // ------------------------------------------------------------ 31 | 32 | .global getICC_SRE_EL1 33 | // unsigned int getICC_SRE_EL1(void) 34 | .type getICC_SRE_EL1, @function 35 | getICC_SRE_EL1: 36 | MRS x0, ICC_SRE_EL1 37 | RET 38 | 39 | 40 | 41 | // ------------------------------------------------------------ 42 | 43 | .global setICC_SRE_EL2 44 | // void setICC_SRE_EL2(unsigned int value) 45 | .type setICC_SRE_EL2, @function 46 | setICC_SRE_EL2: 47 | MSR ICC_SRE_EL2, x0 48 | ISB 49 | RET 50 | 51 | 52 | 53 | // ------------------------------------------------------------ 54 | 55 | .global getICC_SRE_EL2 56 | // unsigned int getICC_SRE_EL2(void) 57 | .type getICC_SRE_EL2, @function 58 | getICC_SRE_EL2: 59 | MRS x0, ICC_SRE_EL2 60 | RET 61 | 62 | 63 | 64 | // ------------------------------------------------------------ 65 | 66 | .global setICC_SRE_EL3 67 | // void setICC_SRE_EL3(unsigned int value) 68 | .type setICC_SRE_EL3, @function 69 | setICC_SRE_EL3: 70 | MSR ICC_SRE_EL3, x0 71 | ISB 72 | RET 73 | 74 | 75 | 76 | // ------------------------------------------------------------ 77 | 78 | .global getICC_SRE_EL3 79 | // unsigned int getICC_SRE_EL3(void) 80 | .type getICC_SRE_EL3, @function 81 | getICC_SRE_EL3: 82 | MRS x0, ICC_SRE_EL3 83 | RET 84 | 85 | 86 | 87 | // ------------------------------------------------------------ 88 | 89 | .global enableGroup0Ints 90 | // void enableGroup0Ints(void) 91 | .type enableGroup0Ints, @function 92 | enableGroup0Ints: 93 | MOV w0, #1 94 | MSR ICC_IGRPEN0_EL1, x0 95 | ISB 96 | RET 97 | 98 | 99 | 100 | // ------------------------------------------------------------ 101 | 102 | .global disableGroup0Ints 103 | // void disableGroup0Ints(void) 104 | .type disableGroup0Ints, @function 105 | disableGroup0Ints: 106 | 107 | MOV w0, #0 108 | MSR ICC_IGRPEN0_EL1, x0 109 | ISB 110 | RET 111 | 112 | 113 | 114 | // ------------------------------------------------------------ 115 | 116 | .global enableGroup1Ints 117 | // void enableGroup1Ints((void)// 118 | .type enableGroup1Ints, @function 119 | enableGroup1Ints: 120 | MRS x0, ICC_IGRPEN1_EL1 121 | ORR w0, w0, #1 122 | MSR ICC_IGRPEN1_EL1, x0 123 | ISB 124 | RET 125 | 126 | 127 | // ------------------------------------------------------------ 128 | 129 | .global disableGroup1Ints 130 | // void disableGroup1Ints(void)// 131 | .type disableGroup1Ints, @function 132 | disableGroup1Ints: 133 | MOV w1, #1 134 | MRS x0, ICC_IGRPEN1_EL1 135 | BIC x0, x0, x1 136 | MSR ICC_IGRPEN1_EL1, x0 137 | ISB 138 | RET 139 | 140 | 141 | // ------------------------------------------------------------ 142 | 143 | .global enableNSGroup1Ints 144 | // void enableNSGroup1Ints(void) 145 | .type enableNSGroup1Ints, @function 146 | enableNSGroup1Ints: 147 | MRS x0, ICC_IGRPEN1_EL3 148 | ORR w0, w0, #1 149 | MSR ICC_IGRPEN1_EL3, x0 150 | ISB 151 | RET 152 | 153 | 154 | 155 | // ------------------------------------------------------------ 156 | 157 | .global disableNSGroup1Ints 158 | // void disableNSGroup1Ints(void) 159 | .type disableNSGroup1Ints, @function 160 | disableNSGroup1Ints: 161 | MOV w1, #0x1 162 | MRS x0, ICC_IGRPEN1_EL3 163 | BIC x0, x0, x1 164 | MSR ICC_IGRPEN1_EL3, x0 165 | ISB 166 | RET 167 | 168 | 169 | 170 | // ------------------------------------------------------------ 171 | 172 | .global getICC_CTLR_EL3 173 | // unsigned int getICC_CTLR_EL3(void)// 174 | .type getICC_CTLR_EL3, @function 175 | getICC_CTLR_EL3: 176 | MRS x0, ICC_CTLR_EL3 177 | RET 178 | 179 | 180 | // ------------------------------------------------------------ 181 | .global setICC_CTLR_EL3 182 | // void setICC_CTLR_EL3(unsigned int value) 183 | .type setICC_CTLR_EL3, @function 184 | setICC_CTLR_EL3: 185 | MSR ICC_CTLR_EL3, x0 186 | ISB 187 | RET 188 | 189 | 190 | 191 | // ------------------------------------------------------------ 192 | 193 | .global getICC_CTLR_EL1 194 | // unsigned int getICC_CTLR_EL1(void)// 195 | .type getICC_CTLR_EL1, @function 196 | getICC_CTLR_EL1: 197 | MRS x0, ICC_CTLR_EL1 198 | RET 199 | 200 | 201 | // ------------------------------------------------------------ 202 | 203 | .global setICC_CTLR_EL1 204 | // void setICC_CTLR_EL1(unsigned int value) 205 | .type setICC_CTLR_EL1, @function 206 | setICC_CTLR_EL1: 207 | MSR ICC_CTLR_EL1, x0 208 | ISB 209 | RET 210 | 211 | 212 | 213 | // ------------------------------------------------------------ 214 | 215 | .global readIARGrp0 216 | // unsigned int readIARGrp0(void)// 217 | .type readIARGrp0, @function 218 | readIARGrp0: 219 | MRS x0, ICC_IAR0_EL1 220 | RET 221 | 222 | 223 | // ------------------------------------------------------------ 224 | 225 | .global writeEOIGrp0 226 | // void writeEOIGrp0(unsigned int ID)// 227 | .type writeEOIGrp0, @function 228 | writeEOIGrp0: 229 | MSR ICC_EOIR0_EL1, x0 230 | ISB 231 | RET 232 | 233 | 234 | // ------------------------------------------------------------ 235 | 236 | .global writeDIR 237 | // void writeDIR(unsigned int ID)// 238 | .type writeDIR, @function 239 | writeDIR: 240 | MSR ICC_DIR_EL1, x0 241 | ISB 242 | RET 243 | 244 | 245 | // ------------------------------------------------------------ 246 | 247 | .global readIARGrp1 248 | // unsigned int readIARGrp1(void)// 249 | .type readIARGrp1, @function 250 | readIARGrp1: 251 | MRS x0, ICC_IAR1_EL1 252 | RET 253 | 254 | 255 | // ------------------------------------------------------------ 256 | 257 | .global writeEOIGrp1 258 | // void writeEOIGrp1(unsigned int ID)// 259 | .type writeEOIGrp1, @function 260 | writeEOIGrp1: 261 | MSR ICC_EOIR1_EL1, x0 262 | DSB SY 263 | RET 264 | 265 | 266 | // ------------------------------------------------------------ 267 | 268 | .global setPriorityMask 269 | // void setPriorityMask(unsigned int ID)// 270 | .type setPriorityMask, @function 271 | setPriorityMask: 272 | MSR ICC_PMR_EL1, x0 273 | RET 274 | 275 | 276 | // ------------------------------------------------------------ 277 | 278 | .global getBPR0 279 | // unsigned int getBPR0(void)// 280 | .type getBPR0, @function 281 | getBPR0: 282 | MRS x0, ICC_BPR0_EL1 283 | RET 284 | 285 | 286 | // ------------------------------------------------------------ 287 | 288 | .global setBPR0 289 | // void setBPR0(unsigned int INTID)// 290 | .type setBPR0, @function 291 | setBPR0: 292 | MSR ICC_BPR0_EL1, x0 293 | ISB 294 | RET 295 | 296 | 297 | // ------------------------------------------------------------ 298 | 299 | .global getBPR1 300 | // unsigned int getBPR1(void)// 301 | .type getBPR1, @function 302 | getBPR1: 303 | MRS x0, ICC_BPR1_EL1 304 | RET 305 | 306 | 307 | // ------------------------------------------------------------ 308 | 309 | .global setBPR1 310 | // void setBPR1(unsigned int ID)// 311 | .type setBPR1, @function 312 | setBPR1: 313 | MSR ICC_BPR1_EL1, x0 314 | ISB 315 | RET 316 | 317 | 318 | // ------------------------------------------------------------ 319 | 320 | .global getRunningPriority 321 | // unsigned int getRunningPriority(void)// 322 | .type getRunningPriority, @function 323 | getRunningPriority: 324 | MRS x0, ICC_RPR_EL1 325 | RET 326 | 327 | 328 | // ------------------------------------------------------------ 329 | // SGIs 330 | // ------------------------------------------------------------ 331 | 332 | .global sendGroup0SGI 333 | // void sendGroup0SGI(unsigned int ID, unsigned int mode, unsigned target_list)// 334 | .type sendGroup0SGI, @function 335 | sendGroup0SGI: 336 | ORR x0, x0, x1 337 | ORR x0, x0, x2 338 | MSR ICC_SGI0R_EL1, x0 339 | RET 340 | 341 | 342 | // ------------------------------------------------------------ 343 | 344 | .global sendGroup1SGI 345 | // void sendGroup1SGI(unsigned int ID, unsigned int mode, unsigned target_list)// 346 | .type sendGroup1SGI, @function 347 | sendGroup1SGI: 348 | ORR x0, x0, x1 349 | ORR x0, x0, x2 350 | MSR ICC_SGI1R_EL1, x0 351 | RET 352 | 353 | 354 | // ------------------------------------------------------------ 355 | 356 | .global sendOtherGroup1SGI 357 | // void sendOtherGroup1SGI(unsigned int ID, unsigned int mode, unsigned target_list)// 358 | .type sendOtherGroup1SGI, @function 359 | sendOtherGroup1SGI: 360 | ORR x0, x0, x1 361 | ORR x0, x0, x2 362 | MSR ICC_ASGI1R_EL1, x0 363 | RET 364 | 365 | 366 | 367 | // ------------------------------------------------------------ 368 | // End of code 369 | // ------------------------------------------------------------ 370 | 371 | 372 | // ------------------------------------------------------------ 373 | // End of v8_aarch64_gicv3_cpuif.s 374 | // ------------------------------------------------------------ 375 | -------------------------------------------------------------------------------- /src/gicv4_virt.c: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------- 2 | // GICv3 Physical LPI functions 3 | // 4 | // Copyright (C) Arm Limited, 2019 All rights reserved. 5 | // 6 | // The example code is provided to you as an aid to learning when working 7 | // with Arm-based technology, including but not limited to programming tutorials. 8 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 9 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 10 | // to use and copy the Software solely for the purpose of demonstration and 11 | // evaluation. 12 | // ------------------------------------------------------------ 13 | 14 | 15 | #include 16 | #include 17 | #include "gicv3_registers.h" 18 | #include "gicv4_virt.h" 19 | 20 | extern void itsAddCommand(uint8_t* command); 21 | 22 | // The first release of ARM Compiler 6 does not support the DSB 23 | // intrinsic. Re-creating manually. 24 | static __inline void __dsb(void) 25 | { 26 | asm("dsb sy"); 27 | } 28 | 29 | // ------------------------------------------------------------ 30 | // Setting location of interfaces 31 | // ------------------------------------------------------------ 32 | 33 | extern struct GICv3_its_ctlr_if* gic_its; 34 | extern struct GICv3_its_int_if* gic_its_ints; 35 | struct GICv3_its_sgi_if* gic_its_sgi; 36 | 37 | extern struct GICv3_rdist_if* gic_rdist; 38 | 39 | // ------------------------------------------------------------ 40 | // Address space set up 41 | // ------------------------------------------------------------ 42 | 43 | void setSGIBaseAddr(void) 44 | { 45 | gic_its_sgi = (struct GICv3_its_sgi_if*)((uint64_t)gic_its + 0x20000); 46 | } 47 | 48 | 49 | // ------------------------------------------------------------ 50 | // Discovery 51 | // ------------------------------------------------------------ 52 | 53 | uint32_t isGICv4x(uint32_t rd) 54 | { 55 | if (((gic_rdist[rd].lpis.GICR_TYPER[0] >> 1) & 0x1) == 0) 56 | return GICV3_v3X; // GICR_TYPER.VLPIS==0, so GICv3.x 57 | 58 | 59 | if (((gic_rdist[rd].lpis.GICR_TYPER[0] >> 7) & 0x1) == 0) 60 | return GICV3_v40; // GICR_TYPER.RVPEID==0, so GICv4.0 61 | 62 | // GICR_TYPER.{VLPIS,RVPEID}=={1,1} => GICv4.1 63 | return GICV3_v41; 64 | } 65 | 66 | // ------------------------------------------------------------ 67 | 68 | uint32_t hasVSGI(uint32_t rd) 69 | { 70 | uint32_t its_type, rd_type; 71 | 72 | its_type = (gic_its->GITS_TYPER >> 39) & 0x1; 73 | rd_type = (gic_rdist[rd].lpis.GICR_TYPER[0] >> 26) & 0x1; 74 | 75 | // Return 1 if both RD and ITS support vSGI, otherwise return 0 76 | return (its_type & rd_type); 77 | } 78 | 79 | // ------------------------------------------------------------ 80 | // Redistributor setup functions 81 | // ------------------------------------------------------------ 82 | 83 | uint32_t setVPEConfTableAddr(uint32_t rd, uint64_t addr, uint64_t attributes, uint32_t num_pages) 84 | { 85 | uint64_t tmp; 86 | 87 | addr = addr & (uint64_t)0x0000FFFFFFFFF000; 88 | num_pages = num_pages & 0x000000000000007F; 89 | 90 | #ifdef DEBUG 91 | printf("setVPEConfTableAddr:: Setting up vPE Configuration Table on RD%d at 0x%lx, with %d pages\n", rd, addr, num_pages); 92 | #endif 93 | 94 | // check number of pages is not 0 95 | if (num_pages == 0) 96 | { 97 | #ifdef DEBUG 98 | printf("setVPEConfTableAddr:: ERROR - Page count for Command Queue cannot be 0\n"); 99 | #endif 100 | return 1; 101 | } 102 | 103 | // check the number of pages is within the maximum 104 | if (num_pages > 127) 105 | { 106 | #ifdef DEBUG 107 | printf("setVPEConfTableAddr:: ERROR - Page count for Command Queue cannot be greater than 127\n"); 108 | #endif 109 | return 1; 110 | } 111 | 112 | // work out queue size in bytes, then zero memory 113 | // This code assumes that VA=PA for allocated memory 114 | tmp = num_pages * 4096; 115 | memset((void*)addr, 0, tmp); 116 | 117 | // Combine address, attributes and size 118 | // TBD add in attributes, current fixed as Device 119 | tmp = addr | (num_pages - 1) | ((uint64_t)1 << 52) | (uint64_t)1 << 63; 120 | 121 | gic_rdist[rd].vlpis.GICR_VPROPBASER = tmp; 122 | 123 | return 0; 124 | } 125 | 126 | // ------------------------------------------------------------ 127 | 128 | uint32_t makeResident(uint32_t rd, uint32_t vpeid, uint32_t g0, uint32_t g1) 129 | { 130 | 131 | #ifdef DEBUG 132 | printf("makeResident:: Making vPEID 0x%x resident on RD%d\n", vpeid, rd); 133 | #endif 134 | 135 | // Check there isn't already a vPE resident 136 | if ((gic_rdist[rd].vlpis.GICR_VPENDBASER & ((uint64_t)1 << 63)) == 1) 137 | { 138 | #ifdef DEBUG 139 | printf("makeResident:: ERROR - a vPE is already resident\n"); 140 | #endif 141 | return 0xFFFFFFFF; 142 | } 143 | 144 | gic_rdist[rd].vlpis.GICR_VPENDBASER = ((uint64_t)vpeid & 0xFFFF) | 145 | ((uint64_t)1 << 63) | 146 | ((uint64_t)(g1 & 0x1) << 59) | 147 | ((uint64_t)(g0 & 0x1) << 58); 148 | 149 | 150 | // Poll for residency to take affect 151 | while ((gic_rdist[rd].vlpis.GICR_VPENDBASER & ((uint64_t)0x1 << 60)) != 0) 152 | { 153 | printf("GICR_VPENDBASER[60] != 0 \n"); 154 | } 155 | 156 | return 0; 157 | } 158 | 159 | // ------------------------------------------------------------ 160 | 161 | // Enables LPIs for the currently selected Redistributor 162 | uint32_t makeNotResident(uint32_t rd, uint32_t db) 163 | { 164 | // First clear the valid bit 165 | gic_rdist[rd].vlpis.GICR_VPENDBASER = ((uint64_t)(db & 0x1) << 62); 166 | 167 | // Now poll for dirty==0 168 | while ((gic_rdist[rd].vlpis.GICR_VPENDBASER & ((uint64_t)0x1 << 60)) != 0) 169 | { 170 | //Nothing 171 | } 172 | 173 | // Return pending last 174 | return (gic_rdist[rd].vlpis.GICR_VPENDBASER & ((uint64_t)0x1 << 61)); 175 | } 176 | 177 | 178 | // ------------------------------------------------------------ 179 | // Configuring LPI functions 180 | // ------------------------------------------------------------ 181 | 182 | // Configures specified vLPI 183 | uint32_t configureVLPI(uint8_t* table, uint32_t ID, uint32_t enable, uint32_t priority) 184 | { 185 | uint8_t* config; 186 | 187 | #ifdef DEBUG 188 | printf("configureVLPI:: Configuring vINITD %d as priority 0x%x and enable=%d\n", ID, priority, enable); 189 | #endif 190 | 191 | // Check lower limit 192 | if (ID < 8192) 193 | { 194 | #ifdef DEBUG 195 | printf("configureVLPI:: ERROR - INTID %d is not a valid LPI\n", ID); 196 | #endif 197 | return 1; 198 | } 199 | 200 | // TBD - Check the upper limit, which requires knowing the table size. 201 | 202 | // Mask off unused bits of the priority and enable 203 | enable = enable & 0x1; 204 | priority = priority & 0x7C; 205 | 206 | // Combine priority and enable, write result into table 207 | // Note: bit 1 is RES1 208 | table[(ID - 8192)] = (0x2 | enable | priority); 209 | __dsb(); 210 | 211 | return 0; 212 | } 213 | 214 | // ------------------------------------------------------------ 215 | // ITS setup functions 216 | // ------------------------------------------------------------ 217 | 218 | uint32_t itsSharedTableSupport(void) 219 | { 220 | return ((gic_its->GITS_TYPER >> 41) & 0x3); 221 | } 222 | 223 | // ------------------------------------------------------------ 224 | 225 | uint32_t itsGetAffinity(void) 226 | { 227 | return gic_its->GITS_MPIDR; 228 | } 229 | 230 | // ------------------------------------------------------------ 231 | // vSGI 232 | // ------------------------------------------------------------ 233 | 234 | void itsSendSGI(uint32_t vintid, uint32_t vpeid) 235 | { 236 | gic_its_sgi->GITS_SGIR = (uint64_t)(vintid & 0xF) | ((uint64_t)(vpeid & 0xFF) << 32); 237 | 238 | return; 239 | } 240 | 241 | // ------------------------------------------------------------ 242 | // ITS commands 243 | // ------------------------------------------------------------ 244 | 245 | void itsVMAPP(uint32_t vpeid, uint32_t target, uint64_t conf_addr, uint64_t pend_addr, uint32_t alloc, uint32_t v, uint32_t doorbell, uint32_t size) 246 | { 247 | uint8_t command[32]; 248 | uint32_t i; 249 | 250 | // Fill command with 0s 251 | for (i=0; i<32; i++) 252 | command[i] = 0; 253 | 254 | // Check whether "target" is PA or Processor Number 255 | if ((gic_its->GITS_TYPER & (1 << 19)) != 0) 256 | target = target >> 16; 257 | 258 | // Construct command 259 | command[0] = 0x29; 260 | command[1] = alloc | 0x2; // Assume that memory is zeroed, so PTZ=1 261 | 262 | command[2] = (uint8_t)(0xFF & (conf_addr >> 16)); 263 | command[3] = (uint8_t)(0xFF & (conf_addr >> 24)); 264 | command[4] = (uint8_t)(0xFF & (conf_addr >> 32)); 265 | command[5] = (uint8_t)(0xFF & (conf_addr >> 40)); 266 | command[6] = (uint8_t)(0xFF & (conf_addr >> 48)); 267 | //command[7] 268 | 269 | command[8] = (uint8_t)(0xFF & doorbell); 270 | command[9] = (uint8_t)(0xFF & (doorbell >> 8)); 271 | command[10] = (uint8_t)(0xFF & (doorbell >> 16)); 272 | command[11] = (uint8_t)(0xFF & (doorbell >> 24)); 273 | 274 | command[12] = (uint8_t)(0xFF & vpeid); 275 | command[13] = (uint8_t)(0xFF & (vpeid >> 8)); 276 | //command[14] 277 | //command[15] 278 | 279 | //command[16] 280 | //command[17] 281 | command[18] = (uint8_t)(0xFF & target); 282 | command[19] = (uint8_t)(0xFF & (target >> 8)); 283 | command[20] = (uint8_t)(0xFF & (target >> 16)); 284 | command[21] = (uint8_t)(0xFF & (target >> 24)); 285 | //command[22] 286 | command[23] = (uint8_t)(v << 7); 287 | 288 | command[24] = size; 289 | //command[25] 290 | command[26] = (uint8_t)(0xFF & (pend_addr >> 16)); 291 | command[27] = (uint8_t)(0xFF & (pend_addr >> 24)); 292 | command[28] = (uint8_t)(0xFF & (pend_addr >> 32)); 293 | command[29] = (uint8_t)(0xFF & (pend_addr >> 40)); 294 | command[30] = (uint8_t)(0xFF & (pend_addr >> 48)); 295 | //command[31] 296 | 297 | // Add command to queue 298 | itsAddCommand(command); 299 | 300 | return; 301 | } 302 | 303 | // ------------------------------------------------------------ 304 | 305 | void itsVSYNC(uint32_t vpeid) 306 | { 307 | uint8_t command[32]; 308 | uint32_t i; 309 | 310 | // Fill command with 0s 311 | for (i=0; i<32; i++) 312 | command[i] = 0; 313 | 314 | // Construct command 315 | command[0] = 0x25; 316 | //command[1] 317 | //command[2] 318 | //command[3] 319 | //command[4] 320 | //command[5] 321 | //command[6] 322 | //command[7] 323 | 324 | //command[8] 325 | //command[9] 326 | //command[10] 327 | //command[11] 328 | 329 | command[12] = (uint8_t)(0xFF & vpeid); 330 | command[13] = (uint8_t)(0xFF & (vpeid >> 8)); 331 | //command[14] 332 | //command[15] 333 | 334 | //command[16] 335 | //command[17] 336 | //command[18] 337 | //command[19] 338 | //command[20] 339 | //command[21] 340 | //command[22] 341 | //command[23] 342 | 343 | //ocmmand[24] 344 | //command[25] 345 | //command[26] 346 | //command[27] 347 | //command[28] 348 | //command[29] 349 | //command[30] 350 | //command[31] 351 | 352 | // Add command to queue 353 | itsAddCommand(command); 354 | 355 | return; 356 | } 357 | 358 | // ------------------------------------------------------------ 359 | 360 | void itsVMAPTI(uint32_t DeviceID, uint32_t EventID, uint32_t doorbell, uint32_t vpeid, uint32_t vINTID) 361 | { 362 | uint8_t command[32]; 363 | uint32_t i; 364 | 365 | // Fill command with 0s 366 | for (i=0; i<32; i++) 367 | command[i] = 0; 368 | 369 | // Construct command 370 | command[0] = 0x2A; 371 | //command[1] 372 | //command[2] 373 | //command[3] 374 | 375 | command[4] = (uint8_t)(0xFF & DeviceID); 376 | command[5] = (uint8_t)(0xFF & (DeviceID >> 8)); 377 | command[6] = (uint8_t)(0xFF & (DeviceID >> 16)); 378 | command[7] = (uint8_t)(0xFF & (DeviceID >> 24)); 379 | 380 | command[8] = (uint8_t)(0xFF & EventID); 381 | command[9] = (uint8_t)(0xFF & (EventID >> 8)); 382 | command[10] = (uint8_t)(0xFF & (EventID >> 16)); 383 | command[11] = (uint8_t)(0xFF & (EventID >> 24)); 384 | 385 | command[12] = (uint8_t)(0xFF & vpeid); 386 | command[13] = (uint8_t)(0xFF & (vpeid >> 8)); 387 | //command[14] 388 | //command[15] 389 | 390 | command[16] = (uint8_t)(0xFF & vINTID); 391 | command[17] = (uint8_t)(0xFF & (vINTID >> 8)); 392 | command[18] = (uint8_t)(0xFF & (vINTID >> 16)); 393 | command[19] = (uint8_t)(0xFF & (vINTID >> 24)); 394 | 395 | command[20] = (uint8_t)(0xFF & doorbell); 396 | command[21] = (uint8_t)(0xFF & (doorbell >> 8)); 397 | command[22] = (uint8_t)(0xFF & (doorbell >> 16)); 398 | command[23] = (uint8_t)(0xFF & (doorbell >> 24)); 399 | 400 | 401 | // Add command to queue 402 | itsAddCommand(command); 403 | 404 | return; 405 | } 406 | 407 | // ------------------------------------------------------------ 408 | 409 | void itsINVDB(uint32_t vpeid) 410 | { 411 | uint8_t command[32]; 412 | uint32_t i; 413 | 414 | // Fill command with 0s 415 | for (i=0; i<32; i++) 416 | command[i] = 0; 417 | 418 | // Construct command 419 | command[0] = 0x2E; 420 | 421 | //command[1] 422 | //command[2] 423 | //command[3] 424 | 425 | //command[4] 426 | //command[5] 427 | //command[6] 428 | //command[7] 429 | 430 | //command[8] 431 | //command[9] 432 | //command[10] 433 | //command[11] 434 | 435 | command[12] = (uint8_t)(0xFF & vpeid); 436 | command[13] = (uint8_t)(0xFF & (vpeid >> 8)); 437 | //command[14] 438 | //command[15] 439 | 440 | 441 | // Add command to queue 442 | itsAddCommand(command); 443 | 444 | return; 445 | } 446 | 447 | // ------------------------------------------------------------ 448 | 449 | void itsVSGI(uint32_t vpeid, uint32_t vintid, uint32_t enable, uint32_t priority, uint32_t group, uint32_t clear) 450 | { 451 | uint8_t command[32]; 452 | uint32_t i; 453 | 454 | // Fill command with 0s 455 | for (i=0; i<32; i++) 456 | command[i] = 0; 457 | 458 | // Construct command 459 | command[0] = 0x23; 460 | 461 | if (clear==0) 462 | command[1] = (uint8_t)(enable | (group << 2)); 463 | else 464 | command[1] = 0x2; 465 | command[2] = (uint8_t)(0xF0 & priority); 466 | //command[3] 467 | 468 | command[4] = vintid; 469 | //command[5] 470 | //command[6] 471 | //command[7] 472 | 473 | //command[8] 474 | //command[9] 475 | //command[10] 476 | //command[11] 477 | 478 | command[12] = (uint8_t)(0xFF & vpeid); 479 | command[13] = (uint8_t)(0xFF & (vpeid >> 8)); 480 | //command[14] 481 | //command[15] 482 | 483 | 484 | // Add command to queue 485 | itsAddCommand(command); 486 | 487 | return; 488 | } 489 | 490 | // ------------------------------------------------------------ 491 | // End of giv3_virt.c 492 | // ------------------------------------------------------------ 493 | -------------------------------------------------------------------------------- /src/main_basic.c: -------------------------------------------------------------------------------- 1 | // Example of using the Generic Timer in AArch64 2 | // 3 | // Copyright (C) Arm Limited, 2019 All rights reserved. 4 | // 5 | // The example code is provided to you as an aid to learning when working 6 | // with Arm-based technology, including but not limited to programming tutorials. 7 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 8 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 9 | // to use and copy the Software solely for the purpose of demonstration and 10 | // evaluation. 11 | // ------------------------------------------------------------ 12 | 13 | #include 14 | #include "gicv3_basic.h" 15 | #include "generic_timer.h" 16 | #include "system_counter.h" 17 | #include "sp804_timer.h" 18 | 19 | extern uint32_t getAffinity(void); 20 | 21 | volatile unsigned int flag; 22 | 23 | // -------------------------------------------------------- 24 | 25 | #define DIST_BASE_ADDR (0x2F000000) 26 | #define RD_BASE_ADDR (0x2F100000) 27 | #define SYS_CONT_BASE_ADDR (0x2A430000) 28 | #define SP804_BASE_ADDR (0x1C110000) 29 | 30 | // -------------------------------------------------------- 31 | 32 | int main(void) 33 | { 34 | uint64_t current_time; 35 | uint32_t rd, affinity; 36 | 37 | affinity = getAffinity(); 38 | 39 | // 40 | // Configure the interrupt controller 41 | // 42 | // Set location of GIC 43 | setGICAddr((void*)DIST_BASE_ADDR, (void*)RD_BASE_ADDR); 44 | 45 | // Enable GIC 46 | enableGIC(); 47 | 48 | // Get the ID of the Redistributor connected to this PE 49 | rd = getRedistID(getAffinity()); 50 | 51 | // Mark this core as being active 52 | wakeUpRedist(rd); 53 | 54 | // Configure the CPU interface 55 | // This assumes that the SRE bits are already set 56 | setPriorityMask(0xFF); 57 | enableGroup0Ints(); 58 | enableGroup1Ints(); 59 | enableNSGroup1Ints(); // This call only works as example runs at EL3 60 | 61 | // 62 | // Configure interrupt sources 63 | // 64 | 65 | // Secure Physical Timer (INTID 29) 66 | setIntPriority(29, rd, 0); 67 | setIntGroup(29, rd, GICV3_GROUP0); 68 | enableInt(29, rd); 69 | 70 | // Non-secure EL1 Physical Timer (INTID 30) 71 | setIntPriority(30, rd, 0); 72 | setIntGroup(30, rd, GICV3_GROUP0); 73 | enableInt(30, rd); 74 | 75 | // SP804 Timer (INTID 34) 76 | setIntPriority(34, 0, 0); 77 | setIntGroup(34, 0, GICV3_GROUP0); 78 | setIntRoute(34, GICV3_ROUTE_MODE_COORDINATE, affinity); 79 | setIntType(34, 0, GICV3_CONFIG_LEVEL); 80 | enableInt(34, 0); 81 | 82 | // Note: RD argument not needed for SPIs 83 | 84 | // 85 | // Configure and enable the System Counter and Generic Time 86 | // Used to generate the two PPIs 87 | // 88 | setSystemCounterBaseAddr(SYS_CONT_BASE_ADDR); // Address of the System Counter 89 | initSystemCounter(SYSTEM_COUNTER_CNTCR_nHDBG, 90 | SYSTEM_COUNTER_CNTCR_FREQ0, 91 | SYSTEM_COUNTER_CNTCR_nSCALE); 92 | 93 | // Configure the Secure Physical Timer 94 | // This uses the CVAL/comparator to set an absolute time for the timer to fire 95 | current_time = getPhysicalCount(); 96 | setSEL1PhysicalCompValue(current_time + 10000); 97 | setSEL1PhysicalTimerCtrl(CNTPS_CTL_ENABLE); 98 | 99 | // Configure the Non-secure Physical Timer 100 | // This uses the TVAL/timer to fire the timer in X ticks 101 | setNSEL1PhysicalTimerValue(20000); 102 | setNSEL1PhysicalTimerCtrl(CNTP_CTL_ENABLE); 103 | 104 | // 105 | // Configure SP804 peripheral 106 | // Used to generate the SPI 107 | // 108 | 109 | // Configure the SP804 timer to generate an interrupt 110 | setTimerBaseAddress(SP804_BASE_ADDR); 111 | initTimer(0x1, SP804_SINGLESHOT, SP804_GENERATE_IRQ); 112 | startTimer(); 113 | 114 | 115 | // NOTE: 116 | // This code assumes that the IRQ and FIQ exceptions 117 | // have been routed to the appropriate Exception level 118 | // and that the PSTATE masks are clear. In this example 119 | // this is done in the startup.s file 120 | 121 | // 122 | // Spin until interrupt 123 | // 124 | while(flag < 3) 125 | { 126 | // Nothing 127 | } 128 | 129 | printf("Main(): Test end\n"); 130 | 131 | return 1; 132 | } 133 | 134 | // -------------------------------------------------------- 135 | 136 | void fiqHandler(void) 137 | { 138 | unsigned int ID; 139 | 140 | // Read the IAR to get the INTID of the interrupt taken 141 | ID = readIARGrp0(); 142 | 143 | printf("FIQ: Received INTID %d\n", ID); 144 | 145 | switch (ID) 146 | { 147 | case 29: 148 | setSEL1PhysicalTimerCtrl(0); // Disable timer to clear interrupt 149 | printf("FIQ: Secure Physical Timer\n"); 150 | break; 151 | case 30: 152 | setNSEL1PhysicalTimerCtrl(0); // Disable timer to clear interrupt 153 | printf("FIQ: Non-secure EL1 Physical Timer\n"); 154 | break; 155 | case 34: 156 | clearTimerIrq(); 157 | printf("FIQ: SP804 timer\n"); 158 | break; 159 | case 1023: 160 | printf("FIQ: Interrupt was spurious\n"); 161 | return; 162 | default: 163 | printf("FIQ: Panic, unexpected INTID\n"); 164 | } 165 | 166 | // Write EOIR to deactivate interrupt 167 | writeEOIGrp0(ID); 168 | 169 | flag++; 170 | return; 171 | } 172 | -------------------------------------------------------------------------------- /src/main_gicv31.c: -------------------------------------------------------------------------------- 1 | // Example of using the Generic Timer in AArch64 2 | // 3 | // Copyright (C) Arm Limited, 2019 All rights reserved. 4 | // 5 | // The example code is provided to you as an aid to learning when working 6 | // with Arm-based technology, including but not limited to programming tutorials. 7 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 8 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 9 | // to use and copy the Software solely for the purpose of demonstration and 10 | // evaluation. 11 | // ------------------------------------------------------------ 12 | 13 | #include 14 | #include "gicv3_basic.h" 15 | 16 | extern uint32_t getAffinity(void); 17 | uint32_t initGIC(void); 18 | uint32_t checkGICModel(void); 19 | 20 | volatile unsigned int flag; 21 | 22 | // -------------------------------------------------------- 23 | 24 | #define DIST_BASE_ADDR (0x2F000000) 25 | #define RD_BASE_ADDR (0x2F100000) 26 | 27 | // -------------------------------------------------------- 28 | 29 | int main(void) 30 | { 31 | uint64_t current_time; 32 | uint32_t rd, affinity; 33 | 34 | affinity = getAffinity(); 35 | 36 | // 37 | // Configure the interrupt controller 38 | // 39 | rd = initGIC(); 40 | 41 | // Check that the model has been launched with the correct configuration 42 | if (checkGICModel() != 0) 43 | return 1; 44 | 45 | 46 | // 47 | // Configure interrupt sources 48 | // 49 | 50 | // GICv3.1 Extended PPI range (INTID 1056) 51 | setIntPriority(1056, rd, 0); 52 | setIntGroup(1056, rd, GICV3_GROUP0); 53 | enableInt(1056, rd); 54 | 55 | // GICv3.1 Extended SPI range (INTID 4096) 56 | setIntPriority(4096, 0, 0); 57 | setIntGroup(4096, 0, GICV3_GROUP0); 58 | setIntRoute(4096, GICV3_ROUTE_MODE_COORDINATE, affinity); 59 | setIntType(4096, 0, GICV3_CONFIG_EDGE); 60 | enableInt(4096, 0); 61 | 62 | 63 | // 64 | // Trigger PPI in GICv3.1 extended range 65 | // 66 | 67 | // Setting the interrupt as pending manually, as the 68 | // Base Platform model does not have a peripheral 69 | // connected within this range 70 | setIntPending(1056, rd); 71 | 72 | 73 | // 74 | // Trigger SPI in GICv3.1 extended range 75 | // 76 | 77 | // Setting the interrupt as pending manually, as the 78 | // Base Platform model does not have a peripheral 79 | // connected within this range 80 | setIntPending(4096, 0); 81 | 82 | // NOTE: 83 | // This code assumes that the IRQ and FIQ exceptions 84 | // have been routed to the appropriate Exception level 85 | // and that the PSTATE masks are clear. In this example 86 | // this is done in the startup.s file 87 | 88 | // 89 | // Spin until interrupt 90 | // 91 | while(flag < 2) 92 | { 93 | // Nothing 94 | } 95 | 96 | printf("Main(): Test end\n"); 97 | 98 | return 1; 99 | } 100 | 101 | // -------------------------------------------------------- 102 | 103 | void fiqHandler(void) 104 | { 105 | unsigned int ID; 106 | 107 | // Read the IAR to get the INTID of the interrupt taken 108 | ID = readIARGrp0(); 109 | 110 | printf("FIQ: Received INTID %d\n", ID); 111 | 112 | switch (ID) 113 | { 114 | case 1023: 115 | printf("FIQ: Interrupt was spurious\n"); 116 | return; 117 | case 1056: 118 | printf("FIQ: GICv3.1 extended PPI range interrupt\n"); 119 | break; 120 | case 4096: 121 | printf("FIQ: GICv3.1 extended SPI range interrupt\n"); 122 | // No need to clear the interrut, as we configured it as edge-triggered 123 | break; 124 | default: 125 | printf("FIQ: Panic, unexpected INTID\n"); 126 | } 127 | 128 | // Write EOIR to deactivate interrupt 129 | writeEOIGrp0(ID); 130 | 131 | flag++; 132 | return; 133 | } 134 | 135 | // -------------------------------------------------------- 136 | 137 | uint32_t initGIC(void) 138 | { 139 | uint32_t rd; 140 | 141 | // Set location of GIC 142 | setGICAddr((void*)DIST_BASE_ADDR, (void*)RD_BASE_ADDR); 143 | 144 | // Enable GIC 145 | enableGIC(); 146 | 147 | // Get the ID of the Redistributor connected to this PE 148 | rd = getRedistID(getAffinity()); 149 | 150 | // Mark this core as beign active 151 | wakeUpRedist(rd); 152 | 153 | // Configure the CPU interface 154 | // This assumes that the SRE bits are already set 155 | setPriorityMask(0xFF); 156 | enableGroup0Ints(); 157 | enableGroup1Ints(); 158 | enableNSGroup1Ints(); // This call only works as example runs at EL3 159 | 160 | return rd; 161 | } 162 | 163 | // -------------------------------------------------------- 164 | 165 | uint32_t checkGICModel(void) 166 | { 167 | // Check that the GICv3.1 extended PPI range is implemented 168 | if (getExtPPI(0) == 32) 169 | { 170 | printf("checkGICModel() - GICR_TYPER.PPInum reports no extended PPI support.\n"); 171 | return 1; 172 | } 173 | 174 | // Check that the GICv3.1 extended SPI range is implemented 175 | if (getExtSPI() == 0) 176 | { 177 | printf("checkGICModel() - GICD_TYPER.ESPI reports no extended SPI support.\n"); 178 | return 1; 179 | } 180 | 181 | return 0; 182 | } 183 | 184 | -------------------------------------------------------------------------------- /src/main_lpi.c: -------------------------------------------------------------------------------- 1 | // GICv3 Physical LPI Example 2 | // 3 | // Copyright (C) Arm Limited, 2019 All rights reserved. 4 | // 5 | // The example code is provided to you as an aid to learning when working 6 | // with Arm-based technology, including but not limited to programming tutorials. 7 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 8 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 9 | // to use and copy the Software solely for the purpose of demonstration and 10 | // evaluation. 11 | // ------------------------------------------------------------ 12 | 13 | #include 14 | #include "gicv3_basic.h" 15 | #include "gicv3_lpis.h" 16 | 17 | extern void sendLPI(uint32_t, uint32_t); 18 | 19 | extern uint32_t getAffinity(void); 20 | uint32_t initGIC(void); 21 | uint32_t checkGICModel(void); 22 | 23 | volatile unsigned int flag; 24 | 25 | // -------------------------------------------------------- 26 | // These locations are based on the memory map of the Base Platform model 27 | 28 | #define CONFIG_TABLE (0x80020000) 29 | #define PENDING_TABLE (0x80030000) 30 | 31 | #define CMD_QUEUE (0x80040000) 32 | #define DEVICE_TABLE (0x80050000) 33 | #define COLLECTION_TABLE (0x80060000) 34 | 35 | #define ITT (0x80070000) 36 | 37 | #define DIST_BASE_ADDR (0x2F000000) 38 | #define RD_BASE_ADDR (0x2F100000) 39 | #define ITS_BASE_ADDR (0x2F020000) 40 | 41 | // -------------------------------------------------------- 42 | int main(void) 43 | { 44 | uint32_t type, entry_size; 45 | uint32_t rd, target_rd; 46 | 47 | // 48 | // Configure the interrupt controller 49 | // 50 | rd = initGIC(); 51 | 52 | 53 | // 54 | // Set up Redistributor structures used for LPIs 55 | // 56 | 57 | setLPIConfigTableAddr(rd, CONFIG_TABLE, GICV3_LPI_DEVICE_nGnRnE /*Attributes*/, 15 /* Number of ID bits */); 58 | setLPIPendingTableAddr(rd, PENDING_TABLE, GICV3_LPI_DEVICE_nGnRnE /*Attributes*/, 15 /* Number of ID bits */); 59 | enableLPIs(rd); 60 | 61 | // 62 | // Configure ITS 63 | // 64 | 65 | setITSBaseAddress((void*)ITS_BASE_ADDR); 66 | 67 | // Check that the model has been launched with the correct configuration 68 | if (checkGICModel() != 0) 69 | return 1; 70 | 71 | // Allocated memory for the ITS command queue 72 | initITSCommandQueue(CMD_QUEUE, GICV3_ITS_CQUEUE_VALID /*Attributes*/, 1 /*num_pages*/); 73 | 74 | // Allocate Device table 75 | setITSTableAddr(0 /*index*/, 76 | DEVICE_TABLE /* addr */, 77 | (GICV3_ITS_TABLE_PAGE_VALID | GICV3_ITS_TABLE_PAGE_DIRECT | GICV3_ITS_TABLE_PAGE_DEVICE_nGnRnE), 78 | GICV3_ITS_TABLE_PAGE_SIZE_4K, 79 | 16 /*num_pages*/); 80 | 81 | //Allocate Collection table 82 | setITSTableAddr(1 /*index*/, 83 | COLLECTION_TABLE /* addr */, 84 | (GICV3_ITS_TABLE_PAGE_VALID | GICV3_ITS_TABLE_PAGE_DIRECT | GICV3_ITS_TABLE_PAGE_DEVICE_nGnRnE), 85 | GICV3_ITS_TABLE_PAGE_SIZE_4K, 86 | 16 /*num_pages*/); 87 | 88 | // Enable the ITS 89 | enableITS(); 90 | 91 | // 92 | // Create ITS mapping 93 | // 94 | 95 | if (getITSPTA() == 1) 96 | { 97 | printf("main(): GITS_TYPER.PTA==1, this example expects PTA==0\n"); 98 | return 1; 99 | } 100 | target_rd = getRdProcNumber(rd); 101 | 102 | // Set up a mapping 103 | itsMAPD(0 /*DeviceID*/, ITT /*addr of ITT*/, 2 /*bit width of ID*/); // Map a DeviceID to a ITT 104 | itsMAPTI(0 /*DeviceID*/, 0 /*EventID*/, 8193 /*intid*/, 0 /*collection*/); // Map an EventID to an INTD and collection (DeviceID specific) 105 | itsMAPC(target_rd /* target Redistributor*/, 0 /*collection*/); // Map a Collection to a Redistributor 106 | itsSYNC(target_rd /* target Redistributor*/); // Sync the changes 107 | 108 | // 109 | // Configure and generate an LPI 110 | // 111 | 112 | configureLPI(rd, 8193 /*INTID*/, GICV3_LPI_ENABLE, 0 /*Priority*/); 113 | printf("main(): Sending LPI 8193\n"); 114 | itsINV(0 /*DeviceID*/, 0 /*EventID*/); 115 | itsINT(0 /*DeviceID*/, 0 /*EventID*/); 116 | 117 | 118 | // NOTE: 119 | // This code assumes that the IRQ and FIQ exceptions 120 | // have been routed to the appropriate Exception level 121 | // and that the PSTATE masks are clear. In this example 122 | // this is done in the startup.s file 123 | 124 | // 125 | // Spin until interrupt 126 | // 127 | while(flag < 1) 128 | { 129 | // Nothing 130 | } 131 | 132 | printf("Main(): Test end\n"); 133 | 134 | return 1; 135 | } 136 | 137 | // -------------------------------------------------------- 138 | 139 | void fiqHandler(void) 140 | { 141 | uint32_t ID; 142 | uint32_t group = 0; 143 | 144 | // Read the IAR to get the INTID of the interrupt taken 145 | ID = readIARGrp0(); 146 | 147 | printf("FIQ: Received INTID %d\n", ID); 148 | 149 | switch (ID) 150 | { 151 | case 1021: 152 | printf("FIQ: Received Non-secure interrupt from the ITS\n"); 153 | ID = readIARGrp1(); 154 | printf("FIQ: Read INTID %d from IAR1\n", ID); 155 | group = 1; 156 | break; 157 | case 1023: 158 | printf("FIQ: Interrupt was spurious\n"); 159 | return; 160 | default: 161 | printf("FIQ: Panic, unexpected INTID\n"); 162 | } 163 | 164 | // Write EOIR to deactivate interrupt 165 | if (group == 0) 166 | writeEOIGrp0(ID); 167 | else 168 | writeEOIGrp1(ID); 169 | 170 | flag++; 171 | return; 172 | } 173 | 174 | // -------------------------------------------------------- 175 | 176 | uint32_t initGIC(void) 177 | { 178 | uint32_t rd; 179 | 180 | // Set location of GIC 181 | setGICAddr((void*)DIST_BASE_ADDR, (void*)RD_BASE_ADDR); 182 | 183 | // Enable GIC 184 | enableGIC(); 185 | 186 | // Get the ID of the Redistributor connected to this PE 187 | rd = getRedistID(getAffinity()); 188 | 189 | // Mark this core as beign active 190 | wakeUpRedist(rd); 191 | 192 | // Configure the CPU interface 193 | // This assumes that the SRE bits are already set 194 | setPriorityMask(0xFF); 195 | enableGroup0Ints(); 196 | enableGroup1Ints(); 197 | enableNSGroup1Ints(); // This call only works as example runs at EL3 198 | 199 | return rd; 200 | } 201 | 202 | // -------------------------------------------------------- 203 | 204 | // 205 | // This function checks the model has been configured the way the example expects 206 | // 207 | 208 | uint32_t checkGICModel(void) 209 | { 210 | uint32_t type, entry_size; 211 | 212 | // 213 | // Check that LPIs supported 214 | // 215 | if (getMaxLPI(0) == 0) 216 | { 217 | printf("checkGICModel(): Physical LPIs not supported\n"); 218 | return 1; 219 | } 220 | 221 | // 222 | // Check the model used to identify RD's in ITS commands 223 | // 224 | if (getITSPTA() == 1) 225 | { 226 | printf("checkGICModel(): GITS_TYPER.PTA==1, this example expects PTA==0\n"); 227 | return 1; 228 | } 229 | 230 | // 231 | // Check the GITS_BASER types 232 | // 233 | getITSTableType(0 /*index*/, &type, &entry_size); 234 | if (type != GICV3_ITS_TABLE_TYPE_DEVICE) 235 | { 236 | printf("checkGICModel() - GITS_BASER0 not expected value (seeing 0x%x, expected 0x%x).\n", type, GICV3_ITS_TABLE_TYPE_DEVICE); 237 | return 1; 238 | } 239 | 240 | getITSTableType(1 /*index*/, &type, &entry_size); 241 | if (type != GICV3_ITS_TABLE_TYPE_COLLECTION) 242 | { 243 | printf("checkGICModel() - GITS_BASER1 not expected value (seeing 0x%x, expected 0x%x).\n", type, GICV3_ITS_TABLE_TYPE_COLLECTION); 244 | return 1; 245 | } 246 | 247 | return 0; 248 | } 249 | 250 | -------------------------------------------------------------------------------- /src/main_vlpi.c: -------------------------------------------------------------------------------- 1 | // GICv3 Physical LPI Example 2 | // 3 | // Copyright (C) Arm Limited, 2019 All rights reserved. 4 | // 5 | // The example code is provided to you as an aid to learning when working 6 | // with Arm-based technology, including but not limited to programming tutorials. 7 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 8 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 9 | // to use and copy the Software solely for the purpose of demonstration and 10 | // evaluation. 11 | // ------------------------------------------------------------ 12 | 13 | #include 14 | #include 15 | #include "gicv3_basic.h" 16 | #include "gicv3_lpis.h" 17 | #include "gicv4_virt.h" 18 | 19 | extern uint32_t getAffinity(void); 20 | uint32_t initGIC(void); 21 | uint32_t checkGICModel(void); 22 | 23 | volatile unsigned int flag; 24 | 25 | // -------------------------------------------------------- 26 | // These locations are based on the memory map of the Base Platform model 27 | // refs: Fast Models Version 11.20 Reference Guide 28 | // Table 8-6: Base Platform memory map. 29 | 30 | #define CONFIG_TABLE (0x80020000) 31 | #define PENDING0_TABLE (0x80030000) 32 | #define PENDING1_TABLE (0x80040000) 33 | 34 | #define CMD_QUEUE (0x80050000) 35 | #define DEVICE_TABLE (0x80060000) 36 | #define COLLECTION_TABLE (0x80070000) 37 | 38 | #define VPE_TABLE (0x80080000) 39 | #define VCONFIG_TABLE (0x80090000) 40 | #define VPENDING_TABLE (0x800A0000) 41 | 42 | #define ITT (0x800B0000) 43 | 44 | #define ITS_BASE_ADDR (0x2F020000) 45 | 46 | // -------------------------------------------------------- 47 | 48 | int main(void) 49 | { 50 | uint32_t type, entry_size; 51 | uint32_t rd0, rd1, target_rd0, target_rd1; 52 | 53 | // 54 | // Configure the interrupt controller 55 | // 56 | 57 | rd0 = initGIC(); 58 | 59 | // 60 | // The example sends the vLPI to 0.0.1.0, so we also need its RD number 61 | // 62 | 63 | rd1 = getRedistID(0x00000100); 64 | 65 | // 66 | // Before we start, ensure the tables initially contain zeros 67 | // 68 | 69 | memset((void*)VCONFIG_TABLE, 0, 8192); 70 | memset((void*)VPENDING_TABLE, 0, 8192); 71 | 72 | // 73 | // Set up Redistributor structures used for LPIs 74 | // LPI configuration is global. 75 | // Each Redistributor maintains entries in a separate LPI Pending table. 76 | // InnerCache & OuterCache : Device-nGnRnE 77 | // shareability : Non-shareable 78 | setLPIConfigTableAddr(rd0, CONFIG_TABLE, GICV3_LPI_DEVICE_nGnRnE /*Attributes*/, 15 /* Number of ID bits */); 79 | setLPIPendingTableAddr(rd0, PENDING0_TABLE, GICV3_LPI_DEVICE_nGnRnE /*Attributes*/, 15 /* Number of ID bits */); 80 | enableLPIs(rd0); 81 | 82 | setLPIConfigTableAddr(rd1, CONFIG_TABLE, GICV3_LPI_DEVICE_nGnRnE /*Attributes*/, 15 /* Number of ID bits */); 83 | setLPIPendingTableAddr(rd1, PENDING1_TABLE, GICV3_LPI_DEVICE_nGnRnE /*Attributes*/, 15 /* Number of ID bits */); 84 | enableLPIs(rd1); 85 | 86 | setVPEConfTableAddr(rd0, VPE_TABLE, 0 /*attributes*/, 1 /*num_pages*/); 87 | setVPEConfTableAddr(rd1, VPE_TABLE, 0 /*attributes*/, 1 /*num_pages*/); 88 | 89 | 90 | // 91 | // Configure virtual interrupt 92 | // 93 | 94 | configureVLPI((uint8_t*)(VCONFIG_TABLE), 8192 /*INTID*/, GICV3_LPI_ENABLE, 0 /*Priority*/); 95 | 96 | 97 | // 98 | // Configure physical doorbell interrupt 99 | // 100 | 101 | configureLPI(rd0, 8192 /*INTID*/, GICV3_LPI_ENABLE, 0 /*Priority*/); // We'll use this as a Default Doorbell 102 | 103 | 104 | // 105 | // Configure ITS 106 | // 107 | 108 | setITSBaseAddress((void*)ITS_BASE_ADDR); 109 | 110 | // Check that the model has been launched with the correct configuration 111 | if (checkGICModel() != 0) 112 | return 1; 113 | 114 | // Allocated memory for the ITS command queue 115 | initITSCommandQueue(CMD_QUEUE, GICV3_ITS_CQUEUE_VALID /*Attributes*/, 1 /*num_pages*/); 116 | 117 | // Allocate Device table 118 | setITSTableAddr(0 /*index*/, 119 | DEVICE_TABLE /* addr */, 120 | (GICV3_ITS_TABLE_PAGE_VALID | GICV3_ITS_TABLE_PAGE_DIRECT | GICV3_ITS_TABLE_PAGE_DEVICE_nGnRnE), 121 | GICV3_ITS_TABLE_PAGE_SIZE_4K, 122 | 16 /*num_pages*/); 123 | 124 | // Allocate Collection table 125 | setITSTableAddr(1 /*index*/, 126 | COLLECTION_TABLE /* addr */, 127 | (GICV3_ITS_TABLE_PAGE_VALID | GICV3_ITS_TABLE_PAGE_DIRECT | GICV3_ITS_TABLE_PAGE_DEVICE_nGnRnE), 128 | GICV3_ITS_TABLE_PAGE_SIZE_4K, 129 | 16 /*num_pages*/); 130 | 131 | 132 | // Allocate vPE table 133 | setITSTableAddr(2 /*index*/, 134 | VPE_TABLE /* addr */, 135 | (GICV3_ITS_TABLE_PAGE_VALID | GICV3_ITS_TABLE_PAGE_DIRECT | GICV3_ITS_TABLE_PAGE_DEVICE_nGnRnE), 136 | GICV3_ITS_TABLE_PAGE_SIZE_4K, 137 | 1 /*num_pages*/); 138 | 139 | // NOTE: This example assumes that the following parameters are set on the Base Platform Model: 140 | // gic_distributor.GITS_BASER0-type=1 141 | // gic_distributor.GITS_BASER1-type=4 142 | // gic_distributor.GITS_BASER2-type=2 143 | 144 | // Enable the ITS 145 | enableITS(); 146 | 147 | // 148 | // Create ITS mapping 149 | // 150 | 151 | // Get IDs in format used by ITS commands 152 | target_rd0 = getRdProcNumber(rd0); 153 | target_rd1 = getRdProcNumber(rd1); 154 | 155 | // Set up a mapping 156 | 157 | /* 158 | gic_distributor.ITS0 DECODE 0x00000000 0000000000000008:0000000000000001:80000000800b0000:0000000000000000 MAPD 159 | gic_distributor.ITS0 EXEC MAPD VALID:1 DEVICE:0x00000000 ITT_ADDRESS:0x00000000800b0000 SIZE:0x01 160 | gic_distributor.ITS0 TABLE_RD DEVICE_ID:0x00000000 FAULT 161 | gic_distributor.ITS0 TABLE_WR DEVICE_MAP DEVICE_ID:0x00000000 ITT_ADDRESS:0x00000000800b0000 INTERRUPT_BITS:0x02 162 | gic_distributor.ITS0 EXEC_END MAPD 163 | */ 164 | itsMAPD(0 /*DeviceID*/, ITT /*addr of ITT*/, 2 /*bit width of EventID*/); // Map a DeviceID to a ITT 165 | 166 | /* 167 | gic_distributor.ITS0 DECODE 0x00000020 0000000080090329:0000000000002000:8000000000000000:00000000800a000e VMAPP 168 | gic_distributor.ITS0 TABLE_WR VCPU_MAP VCPU:0x0000 TARGET_ADDRESS:0x000000002f100000 VPT_ADDRESS:0x00000000800a0000 169 | gic_distributor.ITS0 EXEC_END VMAPP 170 | */ 171 | itsVMAPP(0 /*vpeid*/, target_rd0, VCONFIG_TABLE, VPENDING_TABLE, 1 /*alloc*/, 1 /*v*/, 8192 /*default doorbell*/, 14 /*size*/); 172 | 173 | /* 174 | gic_distributor.ITS0 DECODE 0x00000040 000000000000002e:0000000000000000:0000000000000000:0000000000000000 INVDB 175 | gic_distributor.ITS0 TABLE_RD VCPU VCPU:0x0000 TARGET:0x000000002f100000 VPT_ADDRESS:0x000000000000800a VINTERRUPT_BITS:0x0f 176 | gic_distributor.ITS0 EXEC_END INVDB 177 | */ 178 | itsINVDB(0 /*vpeid*/); 179 | 180 | /* 181 | gic_distributor.ITS0 DECODE 0x00000060 000000000000002a:0000000000000000:000003ff00002000:0000000000000000 VMAPVI 182 | gic_distributor.ITS0 EXEC VMAPVI DEVICE:0x0000 VCPU:0x0000 ID:0x00000000 VIRTUAL_ID:0x00002000 PHYSICAL_ID:0x000003ff 183 | gic_distributor.ITS0 TABLE_RD DEVICE DEVICE_ID:0x00000000 ITT_ADDRESS:0x00000000800b0000 INTERRUPT_BITS:0x02 184 | gic_distributor.ITS0 TABLE_RD VCPU VCPU:0x0000 TARGET:0x000000002f100000 VPT_ADDRESS:0x000000000000800a VINTERRUPT_BITS:0x0f 185 | gic_distributor.ITS0 TABLE_WR ITT_VMAP DEVICE_ID:0x00000000 ITT_ADDRESS:0x00000000800b0000 ID:0x00000000 PHYSICAL_ID:0x000003ff VIRTUAL_ID:0x00002000 VCPU:0x0000 186 | gic_distributor.ITS0 EXEC_END VMAPVI 187 | */ 188 | itsVMAPTI(0 /*DeviceID*/, 0 /*EventID*/, 1023 /*individual doorbell*/, 0 /*vpeid*/, 8192 /*vINTID*/); 189 | 190 | /* 191 | gic_distributor.ITS0 DECODE 0x00000080 0000000000000025:0000000000000000:0000000000000000:0000000000000000 VSYNC 192 | gic_distributor.EXEC VSYNC VCPU:0x0000 193 | gic_distributor.TABLE_RD VCPU VCPU:0x0000 TARGET:0x000000002f100000 VPT_ADDRESS:0x000000000000800a VINTERRUPT_BITS:0x0f 194 | gic_distributor.ITS0 EXEC_END VSYNC 195 | */ 196 | itsVSYNC(0 /*vpeid*/); 197 | 198 | // 199 | // Generate interrupt 200 | // 201 | 202 | printf("main(): Sending vLPI 8192 to vPEID 0\n"); 203 | 204 | /* 205 | gic_distributor.ITS0 DECODE 0x000000a0 000000000000000c:0000000000000000:0000000000000000:0000000000000000 INV 206 | gic_distributor.ITS0 EXEC INV DEVICE:0x00000000 ID:0x00000000 207 | gic_distributor.ITS0 TABLE_RD DEVICE DEVICE_ID:0x00000000 ITT_ADDRESS:0x00000000800b0000 INTERRUPT_BITS:0x02 208 | gic_distributor.ITS0 TABLE_RD ITT_VLPI ITT_ADDRESS:0x00000000800b0000 ID:0x00000000 PHYSICAL_ID:0x00002000 VCPU:0x0000 209 | gic_distributor.ITS0 TABLE_RD VCPU VCPU:0x0000 TARGET:0x000000002f100000 VPT_ADDRESS:0x000000000000800a VINTERRUPT_BITS:0x0f 210 | gic_distributor.ITS0 EXEC_END INV 211 | */ 212 | itsINV(0 /*DeviceID*/, 0 /*EventID*/); 213 | 214 | /* 215 | gic_distributor.ITS0 DECODE 0x000000c0 0000000000000003:0000000000000000:0000000000000000:0000000000000000 INT 216 | gic_distributor.ITS0 EXEC INT DEVICE:0x00000000 ID:0x00000000 217 | gic_distributor.ITS0 TABLE_RD DEVICE DEVICE_ID:0x00000000 ITT_ADDRESS:0x00000000800b0000 INTERRUPT_BITS:0x02 218 | gic_distributor.ITS0 TABLE_RD ITT_VLPI ITT_ADDRESS:0x00000000800b0000 ID:0x00000000 PHYSICAL_ID:0x00002000 VCPU:0x0000 219 | gic_distributor.ITS0 TABLE_RD VCPU VCPU:0x0000 TARGET:0x000000002f100000 VPT_ADDRESS:0x000000000000800a VINTERRUPT_BITS:0x0f 220 | gic_distributor.ITS0 EXEC_END INT 221 | */ 222 | itsINT(0 /*DeviceID*/, 0 /*EventID*/); 223 | 224 | /* gic_distributor.rd_0_0_0_0 VSETPEND 0x00002000 VPT_ADDR 0x00000000800a0000 */ 225 | 226 | // Wait for interrupt 227 | while(flag < 1) 228 | { 229 | // Nothing 230 | } 231 | 232 | // Make vPE resident on RD1 (0.0.1.0) 233 | // 0.0.0.0 and 0.0.1.0 are within the same CommonLPIAff group 234 | makeResident(rd1, 0 /*vpeid*/, 1 /*g0*/, 1 /*g1*/); 235 | 236 | // NOTE: 237 | // This code assumes that the IRQ and FIQ exceptions 238 | // have been routed to the appropriate Exception level 239 | // and that the PSTATE masks are clear. In this example 240 | // this is done in the startup_virt.s file 241 | 242 | 243 | printf("main(): Test end\n"); 244 | 245 | // Semihosting halt will be called from 0.0.1.0 246 | while(1) 247 | { 248 | // Nothing 249 | } 250 | 251 | return 1; 252 | } 253 | 254 | // -------------------------------------------------------- 255 | 256 | void fiqHandler(void) 257 | { 258 | uint32_t ID; 259 | uint32_t group = 0; 260 | 261 | // Read the IAR to get the INTID of the interrupt taken 262 | ID = readIARGrp0(); 263 | 264 | printf("FIQ: Received INTID %d\n", ID); 265 | 266 | switch (ID) 267 | { 268 | case 1021: 269 | printf("FIQ: Received Non-secure interrupt from the ITS\n"); 270 | ID = readIARGrp1(); 271 | printf("FIQ: Read INTID %d from IAR1\n", ID); 272 | group = 1; 273 | break; 274 | case 1023: 275 | printf("FIQ: Interrupt was spurious\n"); 276 | return; 277 | default: 278 | printf("FIQ: Panic, unexpected INTID\n"); 279 | } 280 | 281 | // Write EOIR to deactivate interrupt 282 | if (group == 0) 283 | writeEOIGrp0(ID); 284 | else 285 | writeEOIGrp1(ID); 286 | 287 | flag++; 288 | return; 289 | } 290 | 291 | // -------------------------------------------------------- 292 | 293 | uint32_t initGIC(void) 294 | { 295 | uint32_t rd; 296 | 297 | // Set location of GIC 298 | setGICAddr((void*)0x2F000000 /*Distributor*/, (void*)0x2F100000 /*Redistributor*/); 299 | 300 | // Enable GIC 301 | enableGIC(); 302 | 303 | // Get the ID of the Redistributor connected to this PE 304 | rd = getRedistID(getAffinity()); 305 | 306 | // Mark this core as beign active 307 | wakeUpRedist(rd); 308 | 309 | // Configure the CPU interface 310 | // This assumes that the SRE bits are already set 311 | setPriorityMask(0xFF); 312 | enableGroup0Ints(); 313 | enableGroup1Ints(); 314 | enableNSGroup1Ints(); // This call only works as example runs at EL3 315 | 316 | return rd; 317 | } 318 | 319 | // -------------------------------------------------------- 320 | 321 | uint32_t checkGICModel(void) 322 | { 323 | uint32_t type, entry_size; 324 | 325 | // 326 | // Check GICv4.1 is implemented 327 | // 328 | if (isGICv4x(0) != GICV3_v41) 329 | { 330 | printf("checkGICModel(): GITS_TYPER.{VLPIS,RVEPID}!={1,1}, GICv4.1 not supported\n"); 331 | return 1; 332 | } 333 | 334 | // 335 | // Check the model used to identify RD's in ITS commands 336 | // 337 | if (getITSPTA() == 1) 338 | { 339 | printf("checkGICModel(): GITS_TYPER.PTA==1, this example expects PTA==0\n"); 340 | return 1; 341 | } 342 | 343 | // 344 | // Check Individual doorbell interrupt^M 345 | // 346 | #ifdef DEBUG 347 | printf("feature check: Individual doorbell interrupt %s\n", getITSNID() ? "not supported.":"supported."); 348 | #endif 349 | 350 | // 351 | // Check the GITS_BASER types 352 | // 353 | getITSTableType(0 /*index*/, &type, &entry_size); 354 | if (type != GICV3_ITS_TABLE_TYPE_DEVICE) 355 | { 356 | printf("checkGICModel() - GITS_BASER0 not expected value (seeing 0x%x, expected 0x%x).\n", type, GICV3_ITS_TABLE_TYPE_DEVICE); 357 | return 1; 358 | } 359 | 360 | getITSTableType(1 /*index*/, &type, &entry_size); 361 | if (type != GICV3_ITS_TABLE_TYPE_COLLECTION) 362 | { 363 | printf("checkGICModel() - GITS_BASER1 not expected value (seeing 0x%x, expected 0x%x).\n", type, GICV3_ITS_TABLE_TYPE_COLLECTION); 364 | return 1; 365 | } 366 | 367 | getITSTableType(2 /*index*/, &type, &entry_size); 368 | if (type != GICV3_ITS_TABLE_TYPE_VIRTUAL) 369 | { 370 | printf("checkGICModel() - GITS_BASER2 not expected value (seeing 0x%x, expected 0x%x).\n", type, GICV3_ITS_TABLE_TYPE_VIRTUAL); 371 | return 1; 372 | } 373 | 374 | // 375 | // Check whether the ITS thinks it shares the vPE Configuration Table with the RDs 376 | // 377 | if (itsSharedTableSupport() != 0x2) 378 | { 379 | printf("checkGICModel() - GITS_TYPER.SVE not expected value (seeing 0x%x, expected 0x2).\n", itsSharedTableSupport()); 380 | return 1; 381 | } 382 | 383 | // 384 | // Check the CommonLPIAff group the ITS believes it shares the table with 385 | // 386 | if (itsGetAffinity() !=0) 387 | { 388 | printf("checkGICModel() - GITS_MPIDR does not report 0x0\n"); 389 | return 1; 390 | } 391 | 392 | return 0; 393 | } 394 | -------------------------------------------------------------------------------- /src/main_vsgi.c: -------------------------------------------------------------------------------- 1 | // GICv3 Physical LPI Example 2 | // 3 | // Copyright (C) Arm Limited, 2019 All rights reserved. 4 | // 5 | // The example code is provided to you as an aid to learning when working 6 | // with Arm-based technology, including but not limited to programming tutorials. 7 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 8 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 9 | // to use and copy the Software solely for the purpose of demonstration and 10 | // evaluation. 11 | // ------------------------------------------------------------ 12 | 13 | #include 14 | #include 15 | #include "gicv3_basic.h" 16 | #include "gicv3_lpis.h" 17 | #include "gicv4_virt.h" 18 | 19 | extern uint32_t getAffinity(void); 20 | uint32_t initGIC(void); 21 | uint32_t checkGICModel(void); 22 | 23 | volatile unsigned int flag; 24 | 25 | // -------------------------------------------------------- 26 | // These locations are based on the memory map of the Base Platform model 27 | 28 | #define CONFIG_TABLE (0x80020000) 29 | #define PENDING0_TABLE (0x80030000) 30 | #define PENDING1_TABLE (0x80040000) 31 | 32 | #define CMD_QUEUE (0x80050000) 33 | #define DEVICE_TABLE (0x80060000) 34 | #define COLLECTION_TABLE (0x80070000) 35 | 36 | #define VPE_TABLE (0x80080000) 37 | #define VCONFIG_TABLE (0x80090000) 38 | #define VPENDING_TABLE (0x800A0000) 39 | 40 | #define ITT (0x800B0000) 41 | 42 | #define ITS_BASE_ADDR (0x2F020000) 43 | 44 | // -------------------------------------------------------- 45 | int main(void) 46 | { 47 | uint32_t type, entry_size; 48 | uint32_t rd0, rd1, target_rd0, target_rd1; 49 | 50 | // 51 | // Configure the interrupt controller 52 | // 53 | rd0 = initGIC(); 54 | 55 | 56 | // 57 | // Dump GICD_TYPER information 58 | // 59 | getGICDTyper(); 60 | 61 | // 62 | // Dump GICR_TYPER information 63 | // 64 | getGICRTyper(); 65 | 66 | // The example sends the vLPI to 0.0.1.0, so we also need its RD number 67 | rd1 = getRedistID(0x00000100); 68 | 69 | // 70 | // Before we start, ensure the tables initially contain zeros 71 | // 72 | memset((void*)VCONFIG_TABLE, 0, 8192); 73 | memset((void*)VPENDING_TABLE, 0, 8192); 74 | 75 | // 76 | // Set up Redistributor structures used for LPIs 77 | // 78 | 79 | setLPIConfigTableAddr(rd0, CONFIG_TABLE, GICV3_LPI_DEVICE_nGnRnE /*Attributes*/, 15 /* Number of ID bits */); 80 | setLPIPendingTableAddr(rd0, PENDING0_TABLE, GICV3_LPI_DEVICE_nGnRnE /*Attributes*/, 15 /* Number of ID bits */); 81 | enableLPIs(rd0); 82 | 83 | setLPIConfigTableAddr(rd1, CONFIG_TABLE, GICV3_LPI_DEVICE_nGnRnE /*Attributes*/, 15 /* Number of ID bits */); 84 | setLPIPendingTableAddr(rd1, PENDING1_TABLE, GICV3_LPI_DEVICE_nGnRnE /*Attributes*/, 15 /* Number of ID bits */); 85 | enableLPIs(rd1); 86 | 87 | setVPEConfTableAddr(rd0, VPE_TABLE, 0 /*attributes*/, 1 /*num_pages*/); 88 | setVPEConfTableAddr(rd1, VPE_TABLE, 0 /*attributes*/, 1 /*num_pages*/); 89 | 90 | 91 | // 92 | // Configure default doorbell, which is a physical LPI 93 | // 94 | 95 | configureLPI(rd0, 8192 /*INTID*/, GICV3_LPI_ENABLE, 0 /*Priority*/); // We'll use this as a Default Doorbell 96 | 97 | 98 | // 99 | // Configure ITS 100 | // 101 | 102 | setITSBaseAddress((void*)ITS_BASE_ADDR); 103 | setSGIBaseAddr(); 104 | 105 | // Check that the model has been launched with the correct configuration 106 | if (checkGICModel() != 0) 107 | return 1; 108 | 109 | // Allocated memory for the ITS command queue 110 | initITSCommandQueue(CMD_QUEUE, GICV3_ITS_CQUEUE_VALID /*Attributes*/, 1 /*num_pages*/); 111 | 112 | // Allocate Device table 113 | setITSTableAddr(0 /*index*/, 114 | DEVICE_TABLE /* addr */, 115 | (GICV3_ITS_TABLE_PAGE_VALID | GICV3_ITS_TABLE_PAGE_DIRECT | GICV3_ITS_TABLE_PAGE_DEVICE_nGnRnE), 116 | GICV3_ITS_TABLE_PAGE_SIZE_4K, 117 | 16 /*num_pages*/); 118 | 119 | // Allocate Collection table 120 | setITSTableAddr(1 /*index*/, 121 | COLLECTION_TABLE /* addr */, 122 | (GICV3_ITS_TABLE_PAGE_VALID | GICV3_ITS_TABLE_PAGE_DIRECT | GICV3_ITS_TABLE_PAGE_DEVICE_nGnRnE), 123 | GICV3_ITS_TABLE_PAGE_SIZE_4K, 124 | 16 /*num_pages*/); 125 | 126 | 127 | // Allocate vPE table 128 | setITSTableAddr(2 /*index*/, 129 | VPE_TABLE /* addr */, 130 | (GICV3_ITS_TABLE_PAGE_VALID | GICV3_ITS_TABLE_PAGE_DIRECT | GICV3_ITS_TABLE_PAGE_DEVICE_nGnRnE), 131 | GICV3_ITS_TABLE_PAGE_SIZE_4K, 132 | 1 /*num_pages*/); 133 | 134 | // NOTE: This example assumes that the following parameters are set on the Base Platform Model: 135 | // gic_distributor.GITS_BASER0-type=1 136 | // gic_distributor.GITS_BASER1-type=4 137 | // gic_distributor.GITS_BASER2-type=2 138 | 139 | // Enable the ITS 140 | enableITS(); 141 | 142 | // 143 | // Create ITS mapping 144 | // 145 | 146 | // Get IDs in format used by ITS commands 147 | target_rd1 = getRdProcNumber(rd1); 148 | target_rd0 = getRdProcNumber(rd0); 149 | 150 | printf("main(): Creating vPEID 0, mapped to Redistributor 0.0.0.0\n"); 151 | itsVMAPP(0 /*vpeid*/, target_rd0, VCONFIG_TABLE, VPENDING_TABLE, 1 /*alloc*/, 1 /*v*/, 8192 /*doorbell*/, 14 /*size*/); 152 | itsINVDB(0 /*vpeid*/); 153 | itsSYNC(target_rd0); 154 | itsVSYNC(0 /*vPEID*/); 155 | 156 | 157 | // 158 | // Configure vSGI 159 | // 160 | 161 | itsVSGI(0 /*vpeid*/, 0 /*vintid*/, 1 /*enable*/, 0 /*priority*/, 1 /*group*/, 0 /*clear*/); 162 | 163 | 164 | // 165 | // Generate interrupt 166 | // 167 | 168 | printf("main(): Sending vSGI 0 to vPEID 0\n"); 169 | itsSendSGI(0 /*vintid*/, 0 /*vpeid*/); 170 | 171 | while(flag < 1) 172 | { 173 | // Nothing 174 | } 175 | 176 | // Make vPE resident on RD1 (0.0.1.0) 177 | printf("main(): Making vPEID 0 resident on 0.0.1.0\nTest ends here\n"); 178 | makeResident(rd1, 0 /*vpeid*/, 1 /*g0*/, 1 /*g1*/); 179 | 180 | // Semihosting halt will be called from 0.0.1.0 181 | while(1){ 182 | // Nothing 183 | } 184 | 185 | return 1; 186 | } 187 | 188 | // -------------------------------------------------------- 189 | 190 | void fiqHandler(void) 191 | { 192 | uint32_t ID; 193 | uint32_t group = 0; 194 | 195 | // Read the IAR to get the INTID of the interrupt taken 196 | ID = readIARGrp0(); 197 | 198 | printf("FIQ: Received INTID %d\n", ID); 199 | 200 | switch (ID) 201 | { 202 | case 1021: 203 | printf("FIQ: Received Non-secure interrupt from the ITS\n"); 204 | ID = readIARGrp1(); 205 | printf("FIQ: Read INTID %d from IAR1\n", ID); 206 | group = 1; 207 | break; 208 | case 1023: 209 | printf("FIQ: Interrupt was spurious\n"); 210 | return; 211 | default: 212 | printf("FIQ: Panic, unexpected INTID\n"); 213 | } 214 | 215 | // Write EOIR to deactivate interrupt 216 | if (group == 0) 217 | writeEOIGrp0(ID); 218 | else 219 | writeEOIGrp1(ID); 220 | 221 | flag++; 222 | return; 223 | } 224 | 225 | // -------------------------------------------------------- 226 | 227 | uint32_t initGIC(void) 228 | { 229 | uint32_t rd; 230 | 231 | // Set location of GIC 232 | setGICAddr((void*)0x2F000000 /*Distributor*/, (void*)0x2F100000 /*Redistributor*/); 233 | 234 | // Enable GIC 235 | enableGIC(); 236 | 237 | // Get the ID of the Redistributor connected to this PE 238 | rd = getRedistID(getAffinity()); 239 | 240 | // Mark this core as beign active 241 | wakeUpRedist(rd); 242 | 243 | // Configure the CPU interface 244 | // This assumes that the SRE bits are already set 245 | setPriorityMask(0xFF); 246 | enableGroup0Ints(); 247 | enableGroup1Ints(); 248 | enableNSGroup1Ints(); // This call only works as example runs at EL3 249 | 250 | return rd; 251 | } 252 | 253 | // -------------------------------------------------------- 254 | 255 | uint32_t checkGICModel(void) 256 | { 257 | uint32_t type, entry_size; 258 | 259 | // 260 | // Check GICv4.1 is implemented 261 | // 262 | if (isGICv4x(0) != GICV3_v41) 263 | { 264 | printf("checkGICModel(): GITS_TYPER.{VLPIS,RVEPID}!={1,1}, GICv4.1 not supported\n"); 265 | return 1; 266 | } 267 | 268 | 269 | // 270 | // Check vSGI is implemented 271 | // 272 | if (hasVSGI(0) == 0) 273 | { 274 | printf("checkGICModel(): GITS_TYPER.VSGI!=1 or GICR_TYPER.VSGI!=1, GICv4.1 vSGIs not supported\n"); 275 | return 1; 276 | } 277 | 278 | // 279 | // Check the model used to identify RD's in ITS commands 280 | // 281 | if (getITSPTA() == 1) 282 | { 283 | printf("checkGICModel(): GITS_TYPER.PTA==1, this example expects PTA==0\n"); 284 | return 1; 285 | } 286 | 287 | // 288 | // Check the GITS_BASER types 289 | // 290 | getITSTableType(0 /*index*/, &type, &entry_size); 291 | if (type != GICV3_ITS_TABLE_TYPE_DEVICE) 292 | { 293 | printf("checkGICModel() - GITS_BASER0 not expected value (seeing 0x%x, expected 0x%x).\n", type, GICV3_ITS_TABLE_TYPE_DEVICE); 294 | return 1; 295 | } 296 | 297 | getITSTableType(1 /*index*/, &type, &entry_size); 298 | if (type != GICV3_ITS_TABLE_TYPE_COLLECTION) 299 | { 300 | printf("checkGICModel() - GITS_BASER1 not expected value (seeing 0x%x, expected 0x%x).\n", type, GICV3_ITS_TABLE_TYPE_COLLECTION); 301 | return 1; 302 | } 303 | 304 | getITSTableType(2 /*index*/, &type, &entry_size); 305 | if (type != GICV3_ITS_TABLE_TYPE_VIRTUAL) 306 | { 307 | printf("checkGICModel() - GITS_BASER2 not expected value (seeing 0x%x, expected 0x%x).\n", type, GICV3_ITS_TABLE_TYPE_VIRTUAL); 308 | return 1; 309 | } 310 | 311 | // 312 | // Check whether the ITS thinks it shares the vPE Configuration Table with the RDs 313 | // 314 | if (itsSharedTableSupport() != 0x2) 315 | { 316 | printf("checkGICModel() - GITS_TYPER.SVE not expected value (seeing 0x%x, expected 0x2).\n", itsSharedTableSupport()); 317 | return 1; 318 | } 319 | 320 | // 321 | // Check the CommonLPIAff group the ITS believes it shares the table with 322 | // 323 | if (itsGetAffinity() !=0) 324 | { 325 | printf("checkGICModel() - GITS_MPIDR does not report 0x0\n"); 326 | return 1; 327 | } 328 | 329 | return 0; 330 | } 331 | -------------------------------------------------------------------------------- /src/secondary_virt.s: -------------------------------------------------------------------------------- 1 | //================================================================== 2 | // GICv4.1 Example, code for secondary core (0.0.1.0) 3 | // 4 | // Copyright (C) Arm Limited, 2019 All rights reserved. 5 | // 6 | // The example code is provided to you as an aid to learning when working 7 | // with Arm-based technology, including but not limited to programming tutorials. 8 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 9 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 10 | // to use and copy the Software solely for the purpose of demonstration and 11 | // evaluation. 12 | //================================================================== 13 | 14 | .section secondary_boot,"ax" 15 | .align 3 16 | 17 | // ------------------------------------------------------------ 18 | 19 | .equ AArch32_Mode_USR, 0x10 20 | .equ AArch32_Mode_FIQ, 0x11 21 | .equ AArch32_Mode_IRQ, 0x12 22 | .equ AArch32_Mode_SVC, 0x13 23 | .equ AArch32_Mode_ABT, 0x17 24 | .equ AArch32_Mode_UNDEF, 0x1B 25 | .equ AArch32_Mode_SYS, 0x1F 26 | .equ AArch32_Mode_HYP, 0x1A 27 | .equ AArch32_Mode_MON, 0x16 28 | 29 | .equ AArch64_EL2_SP2, 0x09 // EL2h 30 | .equ AArch64_EL2_SP0, 0x08 // EL2t 31 | .equ AArch64_EL1_SP1, 0x05 // EL1h 32 | .equ AArch64_EL1_SP0, 0x04 // EL1t 33 | .equ AArch64_EL0_SP0, 0x00 34 | 35 | .equ AArch64_SPSR_I, (1 << 7) 36 | .equ AArch64_SPSR_F, (1 << 6) 37 | 38 | .equ AArch32_State_Thumb, 0x20 39 | .equ AArch32_State_ARM, 0x00 40 | 41 | // ------------------------------------------------------------ 42 | 43 | .equ GICDbase, 0x2F000000 44 | 45 | .equ GICD_CTLRoffset, 0x0 46 | .equ GICD_CTLR.ARE_S, (1<<4) 47 | .equ GICD_CTLR.ARE_NS, (1<<5) 48 | .equ GICD_CTLR.EnableG0, 1 49 | .equ GICD_CTLR.EnableG1NS, (1<<1) 50 | .equ GICD_CTLR.EnableG1S, (1<<2) 51 | .equ GICD_CTLR.DS, (1<<6) 52 | 53 | .equ GICD_IGROUPRoffset, 0x080 54 | .equ GICD_ISENABLERoffset, 0x100 55 | .equ GICD_ICENABLERoffset, 0x180 56 | .equ GICD_ISPENDRoffset, 0x200 57 | .equ GICD_ICPENDRoffset, 0x280 58 | .equ GICD_IPRIORITYRoffset, 0x400 59 | .equ GICD_ICFGRoffset, 0xC00 60 | .equ GICD_IGRPMODRoffset, 0xD00 61 | .equ GICD_NSACRoffset, 0xE00 62 | .equ GICD_SGIR, 0xF00 63 | 64 | .equ GICD_IROUTERoffset, 0x6000 65 | .equ GICD_IROUTER.RM, (1<<31) 66 | 67 | // ------------------------------------------------------------ 68 | 69 | .equ ICC_SRE_ELn.Enable, (1<<3) 70 | .equ ICC_SRE_ELn.SRE, (1) 71 | 72 | // ------------------------------------------------------------ 73 | 74 | .equ RDbase, 0x2F140000 75 | 76 | .equ GICR_WAKERoffset, 0x14 77 | .equ GICR_WAKER.ProcessorSleep, (1<<2) 78 | .equ GICR_WAKER.ChildrenAsleep, (1<<3) 79 | 80 | .equ GICR_CTLRoffset, 0x0 81 | 82 | // ------------------------------------------------------------ 83 | 84 | .equ SGIbase, (RDbase + 0x10000) 85 | 86 | .equ GICR_IGROUPRoffset, 0x080 87 | .equ GICR_ISENABLERoffset, 0x100 88 | .equ GICR_ICENABLERoffset, 0x180 89 | .equ GICR_ISPENDRoffset, 0x200 90 | .equ GICR_ICPENDRoffset, 0x280 91 | .equ GICR_IPRIORITYRoffset, 0x400 92 | .equ GICR_ICFGRoffset, 0xC00 93 | .equ GICR_IGRPMODRoffset, 0xD00 94 | .equ GICR_NSACRoffset, 0xE00 95 | 96 | // ------------------------------------------------------------ 97 | 98 | .global secondary 99 | .type secondary, @function 100 | secondary: 101 | 102 | // 103 | // Install vector tables 104 | // 105 | LDR x0, =el1_vectors 106 | MSR VBAR_EL2, x0 107 | MSR VBAR_EL1, x0 108 | 109 | 110 | // NOTE: Nothing will happen at this point, as the PE is not configured 111 | 112 | // 113 | // Mark core as awake in GICR_WAKER 114 | // 115 | MOV x0, #RDbase 116 | MOV x1, #GICR_WAKERoffset 117 | ADD x1, x1, x0 // rd, rn, op2 ==> rd = rn + op2 118 | STR wzr, [x1] // rt, [addr] ==> [addr]N = rt 119 | DSB SY // Data Synchronization Barrier (Full system) 120 | wait: // We now have to wait for ChildrenAsleep to read 0 121 | LDR w0, [x1] // rt, [addr] ==> rt = [addr] 122 | AND w0, w0, #0x6 // rd, rn, op2 ==> rd = rn & op2 123 | CBNZ w0, wait // rn, rel ==> if(rn != 0) goto rel 124 | 125 | 126 | // 127 | // Set Priority Mask 128 | // 129 | MOV w0, #0xFF 130 | MSR ICC_PMR_EL1, x0 131 | 132 | // 133 | // Set Group enables 134 | // 135 | MOV w0, #3 136 | MSR ICC_IGRPEN1_EL3, x0 137 | MSR ICC_IGRPEN0_EL1, x0 138 | 139 | // 140 | // Enter NS.EL1 141 | // 142 | 143 | // Put SCTLR_EL1/2 into known state 144 | MSR SCTLR_EL1, xzr 145 | MSR SCTLR_EL2, xzr 146 | 147 | // Set up SCR_EL3 148 | MOV x0, #1 149 | ORR x0, x0, #(1 << 10) // Set RW bit (EL1 is AArch64, as this is the Secure world) 150 | MSR SCR_EL3, x0 // Set NS bit, lower ELs are Non-secure 151 | 152 | // Set up HCR_EL2 153 | MOV x0, #(1 << 31) // Set RW bit, routing bits 0 (async exceptions routed to NS.EL1) 154 | ORR x0, x0, #(1 << 5) // Set AMO bit 155 | ORR x0, x0, #(1 << 4) // Set FMO bit (must be set to allow vFIQ) 156 | ORR x0, x0, #(1 << 3) // Set IMO bit (must be set to allow vIRQ) 157 | MSR HCR_EL2, x0 158 | 159 | // Initialize Active Priority registers, to show no interrupts 160 | MSR ICH_AP0R0_EL2, xzr 161 | MSR ICH_AP1R0_EL2, xzr 162 | 163 | // Initialize ICH_VMCR_EL2 (ordinarily, this would be done by the Guest) 164 | MOV x0, #1 // Set VENG0 165 | ORR x0, x0, #(1 << 1) // Set VENG1 166 | // Leave VAvkCtl as 0 167 | ORR x0, x0, #(1 << 3) // Set VFIQEn 168 | ORR x0, x0, #(1 << 4) // Set VCBPR (common binary point for vG0 and vG1) 169 | // Leave VEOIM as 0 170 | ORR x0, x0, #(0xFF << 24) // Set VPMR==0xFF 171 | MSR ICH_VMCR_EL2, x0 172 | 173 | // Initialize ICH_HCR_EL2 174 | MOV x0, #1 // Set En bit (virtual if enabled) 175 | // No maintenance interrupts enabled 176 | MSR ICH_HCR_EL2, x0 177 | MSR ICH_LR0_EL2, x0 178 | 179 | // Intialize flag (used to detect test end) 180 | MOV x11, xzr 181 | 182 | LDR x0, =el1_entry_aarch64 183 | MSR ELR_EL3, x0 // When taking an exception to EL3, holds the address to return to. 184 | 185 | MOV x0, #AArch64_EL1_SP1 // 0x05(0b0101) EL1h. Holds the saved process state when an exception is taken to EL3. 186 | MSR spsr_el3, x0 187 | ERET 188 | 189 | // ------------------------------------------------------------ 190 | // Non-secure EL1 code 191 | // ------------------------------------------------------------ 192 | 193 | .section secondary_boot_ns,"ax" 194 | .align 3 195 | 196 | // 197 | // NS.EL1 198 | // 199 | 200 | el1_entry_aarch64: 201 | NOP 202 | 203 | loop: 204 | WFI 205 | CBZ x11, loop 206 | // Semihosting call(SYS_EXIT) to stop simulation 207 | MOV w0, #0x18 208 | HLT #0xf000 209 | 210 | 211 | // ------------------------------------------------------------ 212 | // Vector Table 213 | // ------------------------------------------------------------ 214 | 215 | .align 12 216 | 217 | .global el1_vectors 218 | el1_vectors: 219 | 220 | // ------------------------------------------------------------ 221 | // Current EL with SP0 222 | // ------------------------------------------------------------ 223 | .balign 128 224 | sync_current_el_sp0: 225 | B . // Synchronous 226 | 227 | .balign 128 228 | irq_current_el_sp0: 229 | B irqFirstLevelHandler // IRQ 230 | 231 | .balign 128 232 | fiq_current_el_sp0: 233 | B fiqFirstLevelHandler // FIQ 234 | 235 | .balign 128 236 | serror_current_el_sp0: 237 | B . // SError 238 | 239 | // ------------------------------------------------------------ 240 | // Current EL with SPx 241 | // ------------------------------------------------------------ 242 | 243 | .balign 128 244 | sync_current_el_spx: 245 | B . // Synchronous 246 | 247 | .balign 128 248 | irq_current_el_spx: 249 | B irqFirstLevelHandler // IRQ 250 | 251 | .balign 128 252 | fiq_current_el_spx: 253 | B fiqFirstLevelHandler // FIQ 254 | 255 | .balign 128 256 | serror_current_el_spx: 257 | B . // SError 258 | 259 | // ------------------------------------------------------------ 260 | // Lower EL using AArch64 261 | // ------------------------------------------------------------ 262 | 263 | .balign 128 264 | sync_lower_el_aarch64: 265 | B . 266 | 267 | .balign 128 268 | irq_lower_el_aarch64: 269 | B irqFirstLevelHandler // IRQ 270 | 271 | .balign 128 272 | fiq_lower_el_aarch64: 273 | B fiqFirstLevelHandler // FIQ 274 | 275 | .balign 128 276 | serror_lower_el_aarch64: 277 | B . // SError 278 | 279 | // ------------------------------------------------------------ 280 | // Lower EL using AArch32 281 | // ------------------------------------------------------------ 282 | 283 | .balign 128 284 | sync_lower_el_aarch32: 285 | B . 286 | 287 | .balign 128 288 | irq_lower_el_aarch32: 289 | B irqFirstLevelHandler // IRQ 290 | 291 | .balign 128 292 | fiq_lower_el_aarch32: 293 | B fiqFirstLevelHandler // FIQ 294 | 295 | .balign 128 296 | serror_lower_el_aarch32: 297 | B . // SError 298 | 299 | 300 | // ------------------------------------------------------------ 301 | 302 | irqFirstLevelHandler: 303 | // 304 | // This is not a proper handler!!! 305 | // 306 | 307 | // Read IAR 308 | MRS x0, ICC_IAR1_EL1 // When read from NS.EL1 with HCR_EL2.IMO==0, this will access ICV_IAR1_EL1 309 | 310 | // Semihosting call(SYS_WRITE0) write a null-terminated string to the debug channel. 311 | LDR x1, =irq_msg 312 | MOV w0, #0x04 313 | HLT #0xf000 314 | 315 | MSR ICC_EOIR1_EL1, x0 // When read from NS.EL1 with HCR_EL2.IMO==0, this will access ICV_EOIR1_EL1 316 | 317 | ADD x11, x11, #1 // Update flag 318 | ERET 319 | 320 | 321 | fiqFirstLevelHandler: 322 | // 323 | // This is not a proper handler!!! 324 | // 325 | 326 | // Read IAR 327 | MRS x0, ICC_IAR0_EL1 // When read from NS.EL1 with HCR_EL2.FMO==0, this will access ICV_IAR0_EL1 328 | 329 | // Semihosting call(SYS_WRITE0) write a null-terminated string to the debug channel. 330 | LDR x1, =fiq_msg 331 | MOV w0, #0x04 332 | HLT #0xf000 333 | 334 | MSR ICC_EOIR0_EL1, x0 // When read from NS.EL1 with HCR_EL2.FMO==0, this will access ICV_EOIR0_EL1 335 | 336 | ADD x11, x11, #1 // Update flag 337 | ERET 338 | 339 | //================================================================== 340 | // Messages 341 | //================================================================== 342 | .align 3 343 | 344 | irq_msg: 345 | .string "Secondary Core in IRQ handler\n\n" 346 | 347 | fiq_msg: 348 | .string "Secondary Core in FIQ handler\n\n" 349 | 350 | // ------------------------------------------------------------ 351 | // End of file 352 | // ------------------------------------------------------------ 353 | -------------------------------------------------------------------------------- /src/sp804_timer.c: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------- 2 | // SP804 Dual Timer 3 | // 4 | // Copyright (C) Arm Limited, 2019 All rights reserved. 5 | // 6 | // The example code is provided to you as an aid to learning when working 7 | // with Arm-based technology, including but not limited to programming tutorials. 8 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 9 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 10 | // to use and copy the Software solely for the purpose of demonstration and 11 | // evaluation. 12 | // ------------------------------------------------------------ 13 | 14 | #include "sp804_timer.h" 15 | 16 | #define TIMER_SP804_CTRL_TIMEREN (1 << 7) 17 | #define TIMER_SP804_CTRL_TIMERMODE (1 << 6) // Bit 6: 18 | #define TIMER_SP804_CTRL_INTENABLE (1 << 5) 19 | #define TIMER_SP804_CTRL_TIMERSIZE (1 << 1) // Bit 1: 0=16bit, 1=32bit 20 | #define TIMER_SP804_CTRL_ONESHOT (1 << 0) // Bit 0: 0=wrapping, 1=one-shot 21 | 22 | #define TIMER_SP804_CTRL_PRESCALE_1 (0 << 2) // clk/1 23 | #define TIMER_SP804_CTRL_PRESCALE_4 (1 << 2) // clk/4 24 | #define TIMER_SP804_CTRL_PRESCALE_8 (2 << 2) // clk/8 25 | 26 | struct sp804_timer 27 | { 28 | volatile uint32_t Time1Load; // +0x00 29 | const volatile uint32_t Time1Value; // +0x04 - RO 30 | volatile uint32_t Timer1Control; // +0x08 31 | volatile uint32_t Timer1IntClr; // +0x0C - WO 32 | const volatile uint32_t Timer1RIS; // +0x10 - RO 33 | const volatile uint32_t Timer1MIS; // +0x14 - RO 34 | volatile uint32_t Timer1BGLoad; // +0x18 35 | 36 | volatile uint32_t Time2Load; // +0x20 37 | volatile uint32_t Time2Value; // +0x24 38 | volatile uint8_t Timer2Control; // +0x28 39 | volatile uint32_t Timer2IntClr; // +0x2C - WO 40 | const volatile uint32_t Timer2RIS; // +0x30 - RO 41 | const volatile uint32_t Timer2MIS; // +0x34 - RO 42 | volatile uint32_t Timer2BGLoad; // +0x38 43 | 44 | // Not including ID registers 45 | 46 | }; 47 | 48 | // Instance of the dual timer, will be placed using the scatter file 49 | struct sp804_timer* dual_timer; 50 | 51 | 52 | // Set base address of timer 53 | // address - virtual address of SP804 timer 54 | void setTimerBaseAddress(uint64_t address) 55 | { 56 | dual_timer = (struct sp804_timer*)address; 57 | return; 58 | } 59 | 60 | 61 | // Sets up the private timer 62 | // load_value - Initial value of timer 63 | // auto_reload - Peroidic (SP804_SINGLESHOT) or one shot (SP804_SINGLESHOT) 64 | // interrupt - Whether to generate an interrupt 65 | void initTimer(uint32_t load_value, uint32_t auto_reload, uint32_t interrupt) 66 | { 67 | uint32_t tmp = 0; 68 | 69 | dual_timer->Time1Load = load_value; 70 | 71 | // Fixed setting: 32 bit, no prescaling 72 | tmp = TIMER_SP804_CTRL_TIMERSIZE | TIMER_SP804_CTRL_PRESCALE_1 | TIMER_SP804_CTRL_TIMERMODE; 73 | 74 | // Settings from parameters: interrupt generation & reload 75 | tmp = tmp | interrupt | auto_reload; 76 | 77 | 78 | // Write control register 79 | dual_timer->Timer1Control = tmp; 80 | 81 | return; 82 | } 83 | 84 | 85 | void startTimer(void) 86 | { 87 | uint32_t tmp; 88 | 89 | tmp = dual_timer->Timer1Control; 90 | tmp = tmp | TIMER_SP804_CTRL_TIMEREN; // Set TimerEn (bit 7) 91 | dual_timer->Timer1Control = tmp; 92 | 93 | return; 94 | } 95 | 96 | 97 | void stopTimer(void) 98 | { 99 | uint32_t tmp; 100 | 101 | tmp = dual_timer->Timer1Control; 102 | tmp = tmp & ~TIMER_SP804_CTRL_TIMEREN; // Clear TimerEn (bit 7) 103 | dual_timer->Timer1Control = tmp; 104 | 105 | return; 106 | } 107 | 108 | 109 | // Returns the current timer count 110 | uint32_t getTimerCount(void) 111 | { 112 | return dual_timer->Time1Value; 113 | } 114 | 115 | 116 | void clearTimerIrq(void) 117 | { 118 | // A write to this register, of any value, clears the interrupt 119 | dual_timer->Timer1IntClr = 1; 120 | } 121 | 122 | 123 | // ------------------------------------------------------------ 124 | // End of sp804_timer.c 125 | // ------------------------------------------------------------ 126 | -------------------------------------------------------------------------------- /src/startup.s: -------------------------------------------------------------------------------- 1 | //================================================================== 2 | // Armv8-A Startup Code 3 | // 4 | // Copyright (C) Arm Limited, 2019 All rights reserved. 5 | // 6 | // The example code is provided to you as an aid to learning when working 7 | // with Arm-based technology, including but not limited to programming tutorials. 8 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 9 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 10 | // to use and copy the Software solely for the purpose of demonstration and 11 | // evaluation. 12 | // ------------------------------------------------------------ 13 | 14 | .section BOOT,"ax" 15 | .align 3 16 | 17 | // ------------------------------------------------------------ 18 | 19 | .global start64 20 | .type start64, @function 21 | start64: 22 | 23 | // Clear registers 24 | // --------------- 25 | // This is primarily for RTL simulators, to avoid 26 | // possibility of X propagation 27 | MOV x0, #0 28 | MOV x1, #0 29 | MOV x2, #0 30 | MOV x3, #0 31 | MOV x4, #0 32 | MOV x5, #0 33 | MOV x6, #0 34 | MOV x7, #0 35 | MOV x8, #0 36 | MOV x9, #0 37 | MOV x10, #0 38 | MOV x11, #0 39 | MOV x12, #0 40 | MOV x13, #0 41 | MOV x14, #0 42 | MOV x15, #0 43 | MOV x16, #0 44 | MOV x17, #0 45 | MOV x18, #0 46 | MOV x19, #0 47 | MOV x20, #0 48 | MOV x21, #0 49 | MOV x22, #0 50 | MOV x23, #0 51 | MOV x24, #0 52 | MOV x25, #0 53 | MOV x26, #0 54 | MOV x27, #0 55 | MOV x28, #0 56 | MOV x29, #0 57 | MOV x30, #0 58 | 59 | // Check which core is running 60 | // ---------------------------- 61 | // Core 0.0.0.0 should continue to execute 62 | // All other cores should be put into sleep (WFI) 63 | MRS x0, MPIDR_EL1 64 | UBFX x1, x0, #32, #8 // Extract Aff3 65 | BFI w0, w1, #24, #8 // Insert Aff3 into bits [31:24], so that [31:0] 66 | // is now Aff3.Aff2.Aff1.Aff0 67 | // Using w register means bits [63:32] are zeroed 68 | CBZ w0, primary_core // If 0.0.0.0, branch to code for primary core 69 | 70 | sleep: 71 | WFI // If not 0.0.0.0, then go to sleep 72 | B sleep 73 | 74 | primary_core: 75 | 76 | 77 | // Disable trapping of CPTR_EL3 accesses or use of Adv.SIMD/FPU 78 | // ------------------------------------------------------------- 79 | MOV x0, #0 // Clear all trap bits 80 | MSR CPTR_EL3, x0 81 | 82 | // Install vector table 83 | // --------------------- 84 | .global el3_vectors 85 | LDR x0, =el3_vectors 86 | MSR VBAR_EL3, x0 87 | 88 | // Configure GIC CPU IF 89 | // ------------------- 90 | // For processors that do not support legacy operation 91 | // these steps could be omitted. 92 | MSR SCR_EL3, xzr // Ensure NS bit is clear 93 | ISB 94 | MOV x0, #1 95 | MSR ICC_SRE_EL3, x0 96 | ISB 97 | MSR ICC_SRE_EL1, x0 98 | 99 | // Now do the NS SRE bits 100 | 101 | MOV x1, #1 // Set NS bit, to access Non-secure registers 102 | MSR SCR_EL3, x1 103 | ISB 104 | MSR ICC_SRE_EL2, x0 105 | ISB 106 | MSR ICC_SRE_EL1, x0 107 | 108 | // Configure SCR_EL3 109 | // ------------------ 110 | // Have interrupts routed to EL3 111 | MOV w1, #0 // Initial value of register is unknown 112 | ORR w1, w1, #(1 << 11) // Set ST bit (Secure EL1 can access CNTPS_TVAL_EL1, CNTPS_CTL_EL1 & CNTPS_CVAL_EL1) 113 | ORR w1, w1, #(1 << 10) // Set RW bit (EL1 is AArch64, as this is the Secure world) 114 | ORR w1, w1, #(1 << 3) // Set EA bit (SError routed to EL3) 115 | ORR w1, w1, #(1 << 2) // Set FIQ bit (FIQs routed to EL3) 116 | ORR w1, w1, #(1 << 1) // Set IRQ bit (IRQs routed to EL3) 117 | MSR SCR_EL3, x1 118 | 119 | // Ensure changes to system register are visible 120 | ISB 121 | 122 | // Enable Interrupts 123 | // ------------------ 124 | MSR DAIFClr, 0x3 125 | 126 | // Branch to scatter loading and C library init code 127 | // ------------------------------------------------- 128 | .global __main 129 | B __main 130 | 131 | // ------------------------------------------------------------ 132 | 133 | .type getAffinity, "function" 134 | .cfi_startproc 135 | .global getAffinity 136 | getAffinity: 137 | MRS x0, MPIDR_EL1 138 | UBFX x1, x0, #32, #8 139 | BFI w0, w1, #24, #8 140 | RET 141 | .cfi_endproc 142 | 143 | // ------------------------------------------------------------ 144 | // End of file 145 | // ------------------------------------------------------------ 146 | -------------------------------------------------------------------------------- /src/startup_virt.s: -------------------------------------------------------------------------------- 1 | //================================================================== 2 | // Armv8-A Startup Code 3 | // 4 | // Copyright (C) Arm Limited, 2019 All rights reserved. 5 | // 6 | // The example code is provided to you as an aid to learning when working 7 | // with Arm-based technology, including but not limited to programming tutorials. 8 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 9 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 10 | // to use and copy the Software solely for the purpose of demonstration and 11 | // evaluation. 12 | // ------------------------------------------------------------ 13 | 14 | .section BOOT,"ax" 15 | .align 3 16 | 17 | // ------------------------------------------------------------ 18 | 19 | .global start64 20 | .type start64, @function 21 | start64: 22 | 23 | // Clear registers 24 | // --------------- 25 | // This is primarily for RTL simulators, to avoid 26 | // possibility of X propagation 27 | 28 | MOV x0, #0 29 | MOV x1, #0 30 | MOV x2, #0 31 | MOV x3, #0 32 | MOV x4, #0 33 | MOV x5, #0 34 | MOV x6, #0 35 | MOV x7, #0 36 | MOV x8, #0 37 | MOV x9, #0 38 | MOV x10, #0 39 | MOV x11, #0 40 | MOV x12, #0 41 | MOV x13, #0 42 | MOV x14, #0 43 | MOV x15, #0 44 | MOV x16, #0 45 | MOV x17, #0 46 | MOV x18, #0 47 | MOV x19, #0 48 | MOV x20, #0 49 | MOV x21, #0 50 | MOV x22, #0 51 | MOV x23, #0 52 | MOV x24, #0 53 | MOV x25, #0 54 | MOV x26, #0 55 | MOV x27, #0 56 | MOV x28, #0 57 | MOV x29, #0 58 | MOV x30, #0 59 | 60 | // Disable trapping of CPTR_EL3 accesses or use of Adv.SIMD/FPU 61 | // ------------------------------------------------------------- 62 | 63 | MOV x0, #0 // Clear all trap bits 64 | MSR CPTR_EL3, x0 65 | 66 | 67 | // Configure GIC CPU IF 68 | // ------------------- 69 | // For processors that do not support legacy operation 70 | // these steps could be omitted. 71 | 72 | MSR SCR_EL3, xzr // Ensure NS bit is clear 73 | ISB 74 | MOV x0, #1 75 | MSR ICC_SRE_EL3, x0 // Enable System Register interface 76 | ISB 77 | MSR ICC_SRE_EL1, x0 78 | 79 | 80 | // Now do the NS SRE bits 81 | MOV x1, #1 // Set NS bit, to access Non-secure registers 82 | MSR SCR_EL3, x1 83 | ISB 84 | MSR ICC_SRE_EL2, x0 85 | ISB 86 | MSR ICC_SRE_EL1, x0 87 | 88 | // Configure SCR_EL3 89 | // ------------------ 90 | // Have interrupts routed to EL3 91 | 92 | MOV w1, #0 // Initial value of register is unknown 93 | ORR w1, w1, #(1 << 11) // Set ST bit (Secure EL1 can access CNTPS_TVAL_EL1, CNTPS_CTL_EL1 & CNTPS_CVAL_EL1) 94 | ORR w1, w1, #(1 << 10) // Set RW bit (EL1 is AArch64, as this is the Secure world) 95 | ORR w1, w1, #(1 << 3) // Set EA bit (SError routed to EL3) 96 | ORR w1, w1, #(1 << 2) // Set FIQ bit (FIQs routed to EL3) 97 | ORR w1, w1, #(1 << 1) // Set IRQ bit (IRQs routed to EL3) 98 | MSR SCR_EL3, x1 99 | 100 | // Ensure changes to system register are visible 101 | ISB 102 | 103 | // Which core am I 104 | // ---------------- 105 | 106 | MRS x0, MPIDR_EL1 107 | MOV x1, #0xFFFFFF 108 | AND x0, x0, x1 // Mask off to leave Aff2.Aff1.Aff0 109 | CBZ x0, primary // If core 0, run the primary init code 110 | MOV x1, #0x100 111 | CMP x0, x1 // If core 1, run the secondary init code 112 | .global secondary 113 | B.EQ secondary 114 | 115 | // Otherwise go to sleep 116 | sleep: 117 | WFI 118 | B sleep 119 | 120 | // ------------------------------------------------------------ 121 | // Primary core 122 | // ------------------------------------------------------------ 123 | 124 | primary: 125 | 126 | // Install vector table 127 | // --------------------- 128 | .global el3_vectors 129 | LDR x0, =el3_vectors 130 | MSR VBAR_EL3, x0 131 | 132 | 133 | // Enable Interrupts 134 | // ------------------ 135 | MSR DAIFClr, 0x3 136 | 137 | 138 | // Branch to scatter loading and C library init code 139 | // ------------------------------------------------- 140 | .global __main 141 | B __main 142 | 143 | 144 | // ------------------------------------------------------------ 145 | // Helper functions 146 | // ------------------------------------------------------------ 147 | 148 | .type getAffinity, "function" 149 | .cfi_startproc 150 | .global getAffinity 151 | getAffinity: 152 | MRS x0, MPIDR_EL1 153 | UBFX x1, x0, #32, #8 // rd, rn, #p, #n ==> x1 = x0[39:31] 154 | BFI w0, w1, #24, #8 // rd, rn, #p, #n ==> w0[31:24] = w1[7:0] 155 | RET 156 | .cfi_endproc 157 | 158 | // ------------------------------------------------------------ 159 | // End of file 160 | // ------------------------------------------------------------ 161 | -------------------------------------------------------------------------------- /src/system_counter.c: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------- 2 | // System Counter 3 | // 4 | // Copyright (C) Arm Limited, 2019 All rights reserved. 5 | // 6 | // The example code is provided to you as an aid to learning when working 7 | // with Arm-based technology, including but not limited to programming tutorials. 8 | // Arm hereby grants to you, subject to the terms and conditions of this Licence, 9 | // a non-exclusive, non-transferable, non-sub-licensable, free-of-charge licence, 10 | // to use and copy the Software solely for the purpose of demonstration and 11 | // evaluation. 12 | // ------------------------------------------------------------ 13 | 14 | #include "system_counter.h" 15 | 16 | struct memory_mapped_timer_module 17 | { 18 | volatile uint32_t CNTCR; // +0x0000 - RW - Counter Control Register 19 | const volatile uint32_t CNTSR; // +0x0004 - RO - Counter Status Register 20 | volatile uint64_t CNTCV; // +0x0008 - RW - Counter Count Value register 21 | volatile uint32_t CNTSCR; // +0x0010 - RW - Counter Scaling Value (ARMv8.4-CNTSC) 22 | const volatile uint32_t padding0[2]; // +0x0014 - RESERVED 23 | const volatile uint32_t CNTID; // +0x001C - RO - Counter ID register 24 | volatile uint32_t CNTFID[4]; // +0x0020 - RW - Counter Access Control Register N 25 | }; 26 | 27 | // ------------------------------------------------------------ 28 | // Setting location of interfaces 29 | // ------------------------------------------------------------ 30 | 31 | 32 | struct memory_mapped_timer_module* counter_module; 33 | 34 | // Sets the address of memory mapped counter module 35 | // addr - virtual address of counter module 36 | void setSystemCounterBaseAddr(uint64_t addr) 37 | { 38 | counter_module = (struct memory_mapped_timer_module*)addr; 39 | return; 40 | } 41 | 42 | // ------------------------------------------------------------ 43 | // Functions 44 | // ------------------------------------------------------------ 45 | 46 | // Configures and enables the CNTCR (Counter Control Register) 47 | // hdbg - halt on debug mode 48 | // freq - frequency mode 49 | void initSystemCounter( uint32_t hdbg, uint32_t freq, uint32_t scaling) 50 | { 51 | counter_module->CNTCR = (0x1 | ((0x1 & hdbg) << 1) | ((0x1 & scaling) << 2) | ((0x3FF & freq) << 8)); 52 | return; 53 | } 54 | 55 | // Set the scaling factor (CNTSCR) 56 | // scale - Scaling factor (32-bit fixed point value, 8-bit integer with 24-bit fractional) 57 | // Returns 0 if successful 58 | // 1 if counter enabled (writing CNTSCR is UNPRED when counter enabled) 59 | // 2 if feature not supported 60 | uint32_t setSystemCounterScalingFactor(uint32_t scale) 61 | { 62 | if ((counter_module->CNTCR & 0x1) == 0x1) 63 | return 1; // Counter running, cannot set scaling factor 64 | 65 | if ((counter_module->CNTID & 0xF) == 0x0) 66 | return 2; // Scaling factor 67 | 68 | counter_module->CNTSCR = scale; 69 | return 0; 70 | } 71 | 72 | 73 | // Returns the value of CNTID (Counter ID register) 74 | uint32_t getCNTID(void) 75 | { 76 | return counter_module->CNTID; 77 | } 78 | 79 | 80 | // Returns the value of the CNTSR 81 | // Can be used to frequency changes (via init function) have taken effect 82 | uint32_t getCNTSR(void) 83 | { 84 | return (counter_module->CNTSR); 85 | } 86 | 87 | 88 | // Returns the value of CNTCV (Counter Count Value register) 89 | uint64_t getCNTCV(void) 90 | { 91 | return (counter_module->CNTCV); 92 | } 93 | 94 | 95 | // Sets the value of CNTCV (Counter Count Value register) 96 | // value - Sets the count value 97 | // 98 | // NOTE: This should only be called when the counter is disabled. 99 | // Calling while counter enabled is UNPREDICTABLE. 100 | void setCNTCV(uint64_t value) 101 | { 102 | counter_module->CNTCV = value; 103 | return; 104 | } 105 | 106 | 107 | uint32_t getCNTFID(uint32_t entry) 108 | { 109 | return (counter_module->CNTFID[entry]); 110 | } 111 | 112 | 113 | void setCNTFID(uint32_t entry, uint32_t value) 114 | { 115 | counter_module->CNTFID[entry] = value; 116 | return; 117 | } 118 | 119 | 120 | // ------------------------------------------------------------ 121 | // End of system_counter.c 122 | // ------------------------------------------------------------ 123 | --------------------------------------------------------------------------------