gic.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. #ifndef LKMC_GIC_H
  2. #define LKMC_GIC_H
  3. #include <lkmc/aarch64.h>
  4. #if LKMC_QEMU
  5. /* info qtree contains:
  6. *
  7. * dev: arm_gic, id ""
  8. * mmio 0000000008000000/0000000000001000
  9. * mmio 0000000008010000/0000000000002000 */
  10. #define GIC_GICD_BASE 0x08000000
  11. #define GIC_GICC_BASE 0x08010000
  12. #define TIMER_IRQ 27
  13. #elif LKMC_GEM5
  14. /* On source at: https://github.com/gem5/gem5/blob/f525028c126af33da532f6703a152d81d900dcf7/src/dev/arm/RealView.py#L952
  15. *
  16. * On m5out/config.ini at:
  17. *
  18. * * system.realview.gic.dist_addr=738201600
  19. * * system.realview.gic.cpu_addr=738205696
  20. *
  21. * On auto-generated DTB in m5out/system.dtb after converstion to dts:
  22. *
  23. * interrupt-controller {
  24. * compatible = "gem5,gic", "arm,cortex-a15-gic", "arm,cortex-a9-gic";
  25. * reg = <0x0 0x2c001000 0x0 0x1000 0x0 0x2c002000 0x0 0x1000 0x0 0x2c004000 0x0 0x2000 0x0 0x2c006000 0x0 0x2000>; * */
  26. #define GIC_GICD_BASE 0x2c001000
  27. #define GIC_GICC_BASE 0x2c002000
  28. #define TIMER_IRQ 30
  29. #endif
  30. #define GIC_INT_MAX 64
  31. #define GIC_PRIO_MAX 16
  32. #define GIC_INTNO_SGI0 0
  33. #define GIC_INTNO_PPI0 16
  34. #define GIC_INTNO_SPI0 32
  35. #define GIC_PRI_SHIFT 4
  36. #define GIC_PRI_MASK 0x0f
  37. typedef int32_t irq_no;
  38. #define GIC_GICD_INT_PER_REG (32)
  39. #define GIC_GICD_IPRIORITY_PER_REG (4)
  40. #define GIC_GICD_IPRIORITY_SIZE_PER_REG (8)
  41. #define GIC_GICD_ITARGETSR_CORE0_TARGET_BMAP (0x01010101)
  42. #define GIC_GICD_ITARGETSR_PER_REG (4)
  43. #define GIC_GICD_ITARGETSR_SIZE_PER_REG (8)
  44. #define GIC_GICD_ICFGR_PER_REG (16)
  45. #define GIC_GICD_ICFGR_SIZE_PER_REG (2)
  46. #define GIC_GICD_ICENABLER_PER_REG (32)
  47. #define GIC_GICD_ISENABLER_PER_REG (32)
  48. #define GIC_GICD_ICPENDR_PER_REG (32)
  49. #define GIC_GICD_ISPENDR_PER_REG (32)
  50. /* 8.12 The GIC CPU interface register map */
  51. #define GIC_GICC_CTLR (GIC_GICC_BASE + 0x000) /* CPU Interface Control Register */
  52. #define GIC_GICC_PMR (GIC_GICC_BASE + 0x004) /* Interrupt Priority Mask Register */
  53. #define GIC_GICC_BPR (GIC_GICC_BASE + 0x008) /* Binary Point Register */
  54. #define GIC_GICC_IAR (GIC_GICC_BASE + 0x00C) /* Interrupt Acknowledge Register */
  55. #define GIC_GICC_EOIR (GIC_GICC_BASE + 0x010) /* End of Interrupt Register */
  56. #define GIC_GICC_RPR (GIC_GICC_BASE + 0x014) /* Running Priority Register */
  57. #define GIC_GICC_HPIR (GIC_GICC_BASE + 0x018) /* Highest Pending Interrupt Register */
  58. #define GIC_GICC_ABPR (GIC_GICC_BASE + 0x01C) /* Aliased Binary Point Register */
  59. #define GIC_GICC_IIDR (GIC_GICC_BASE + 0x0FC) /* CPU Interface Identification Register */
  60. /* 8.13.7 GICC_CTLR, CPU Interface Control Register */
  61. #define GICC_CTLR_ENABLE (0x1) /* Enable GICC */
  62. #define GICC_CTLR_DISABLE (0x0) /* Disable GICC */
  63. /* 8.13.14 GICC_PMR, CPU Interface Priority Mask Register */
  64. #define GICC_PMR_PRIO_MIN (0xff) /* The lowest level mask */
  65. #define GICC_PMR_PRIO_HIGH (0x0) /* The highest level mask */
  66. /* 8.13.6 GICC_BPR, CPU Interface Binary Point Register */
  67. /* In systems that support only one Security state, when GICC_CTLR.CBPR == 0,
  68. this register determines only Group 0 interrupt preemption. */
  69. #define GICC_BPR_NO_GROUP (0x0) /* handle all interrupts */
  70. /* 8.13.11 GICC_IAR, CPU Interface Interrupt Acknowledge Register */
  71. #define GICC_IAR_INTR_IDMASK (0x3ff) /* 0-9 bits means Interrupt ID */
  72. #define GICC_IAR_SPURIOUS_INTR (0x3ff) /* 1023 means spurious interrupt */
  73. /* 8.8 The GIC Distributor register map */
  74. #define GIC_GICD_CTLR (GIC_GICD_BASE + 0x000) /* Distributor Control Register */
  75. #define GIC_GICD_TYPER (GIC_GICD_BASE + 0x004) /* Interrupt Controller Type Register */
  76. #define GIC_GICD_IIDR (GIC_GICD_BASE + 0x008) /* Distributor Implementer Identification Register */
  77. #define GIC_GICD_IGROUPR(n) (GIC_GICD_BASE + 0x080 + ( (n) * 4 ) ) /* Interrupt Group Registers */
  78. #define GIC_GICD_ISENABLER(n) (GIC_GICD_BASE + 0x100 + ( (n) * 4 ) ) /* Interrupt Set-Enable Registers */
  79. #define GIC_GICD_ICENABLER(n) (GIC_GICD_BASE + 0x180 + ( (n) * 4 ) ) /* Interrupt Clear-Enable Registers */
  80. #define GIC_GICD_ISPENDR(n) (GIC_GICD_BASE + 0x200 + ( (n) * 4 ) ) /* Interrupt Set-Pending Registers */
  81. #define GIC_GICD_ICPENDR(n) (GIC_GICD_BASE + 0x280 + ( (n) * 4 ) ) /* Interrupt Clear-Pending Registers */
  82. #define GIC_GICD_ISACTIVER(n) (GIC_GICD_BASE + 0x300 + ( (n) * 4 ) ) /* Interrupt Set-Active Registers */
  83. #define GIC_GICD_ICACTIVER(n) (GIC_GICD_BASE + 0x380 + ( (n) * 4 ) ) /* Interrupt Clear-Active Registers */
  84. #define GIC_GICD_IPRIORITYR(n) (GIC_GICD_BASE + 0x400 + ( (n) * 4 ) ) /* Interrupt Priority Registers */
  85. #define GIC_GICD_ITARGETSR(n) (GIC_GICD_BASE + 0x800 + ( (n) * 4 ) ) /* Interrupt Processor Targets Registers */
  86. #define GIC_GICD_ICFGR(n) (GIC_GICD_BASE + 0xc00 + ( (n) * 4 ) ) /* Interrupt Configuration Registers */
  87. #define GIC_GICD_NSCAR(n) (GIC_GICD_BASE + 0xe00 + ( (n) * 4 ) ) /* Non-secure Access Control Registers */
  88. #define GIC_GICD_SGIR (GIC_GICD_BASE + 0xf00 ) /* Software Generated Interrupt Register */
  89. #define GIC_GICD_CPENDSGIR(n) (GIC_GICD_BASE + 0xf10 + ( (n) * 4 ) ) /* SGI Clear-Pending Registers */
  90. #define GIC_GICD_SPENDSGIR(n) (GIC_GICD_BASE + 0xf20 + ( (n) * 4 ) ) /* SGI Set-Pending Registers */
  91. /* 8.9.4 GICD_CTLR, Distributor Control Register */
  92. #define GIC_GICD_CTLR_ENABLE (0x1) /* Enable GICD */
  93. #define GIC_GICD_CTLR_DISABLE (0x0) /* Disable GICD */
  94. /* 8.9.7 GICD_ICFGR<n>, Interrupt Configuration Registers */
  95. #define GIC_GICD_ICFGR_LEVEL (0x0) /* level-sensitive */
  96. #define GIC_GICD_ICFGR_EDGE (0x2) /* edge-triggered */
  97. /* Register access macros for GICC */
  98. #define REG_GIC_GICC_CTLR ((volatile uint32_t *)(uintptr_t)GIC_GICC_CTLR)
  99. #define REG_GIC_GICC_PMR ((volatile uint32_t *)(uintptr_t)GIC_GICC_PMR)
  100. #define REG_GIC_GICC_BPR ((volatile uint32_t *)(uintptr_t)GIC_GICC_BPR)
  101. #define REG_GIC_GICC_IAR ((volatile uint32_t *)(uintptr_t)GIC_GICC_IAR)
  102. #define REG_GIC_GICC_EOIR ((volatile uint32_t *)(uintptr_t)GIC_GICC_EOIR)
  103. #define REG_GIC_GICC_RPR ((volatile uint32_t *)(uintptr_t)GIC_GICC_RPR)
  104. #define REG_GIC_GICC_HPIR ((volatile uint32_t *)(uintptr_t)GIC_GICC_HPIR)
  105. #define REG_GIC_GICC_ABPR ((volatile uint32_t *)(uintptr_t)GIC_GICC_ABPR)
  106. #define REG_GIC_GICC_IIDR ((volatile uint32_t *)(uintptr_t)GIC_GICC_IIDR)
  107. /* Register access macros for GICD */
  108. #define REG_GIC_GICD_CTLR ((volatile uint32_t *)(uintptr_t)GIC_GICD_CTLR)
  109. #define REG_GIC_GICD_TYPE ((volatile uint32_t *)(uintptr_t)GIC_GICD_TYPE)
  110. #define REG_GIC_GICD_IIDR ((volatile uint32_t *)(uintptr_t)GIC_GICD_IIDR)
  111. #define REG_GIC_GICD_IGROUPR(n) ((volatile uint32_t *)(uintptr_t)GIC_GICD_IGROUPR(n))
  112. #define REG_GIC_GICD_ISENABLER(n) ((volatile uint32_t *)(uintptr_t)GIC_GICD_ISENABLER(n))
  113. #define REG_GIC_GICD_ICENABLER(n) ((volatile uint32_t *)(uintptr_t)GIC_GICD_ICENABLER(n))
  114. #define REG_GIC_GICD_ISPENDR(n) ((volatile uint32_t *)(uintptr_t)GIC_GICD_ISPENDR(n))
  115. #define REG_GIC_GICD_ICPENDR(n) ((volatile uint32_t *)(uintptr_t)GIC_GICD_ICPENDR(n))
  116. #define REG_GIC_GICD_ISACTIVER(n) ((volatile uint32_t *)(uintptr_t)GIC_GICD_ISACTIVER(n))
  117. #define REG_GIC_GICD_ICACTIVER(n) ((volatile uint32_t *)(uintptr_t)GIC_GICD_ICACTIVER(n))
  118. #define REG_GIC_GICD_IPRIORITYR(n) ((volatile uint32_t *)(uintptr_t)GIC_GICD_IPRIORITYR(n))
  119. #define REG_GIC_GICD_ITARGETSR(n) ((volatile uint32_t *)(uintptr_t)GIC_GICD_ITARGETSR(n))
  120. #define REG_GIC_GICD_ICFGR(n) ((volatile uint32_t *)(uintptr_t)GIC_GICD_ICFGR(n))
  121. #define REG_GIC_GICD_NSCAR(n) ((volatile uint32_t *)(uintptr_t)GIC_GICD_NSCAR(n))
  122. #define REG_GIC_GICD_SGIR ((volatile uint32_t *)(uintptr_t)GIC_GICD_SGIR)
  123. #define REG_GIC_GICD_CPENDSGIR(n) ((volatile uint32_t *)(uintptr_t)GIC_GICD_CPENDSGIR(n))
  124. #define REG_GIC_GICD_SPENDSGIR(n) ((volatile uint32_t *)(uintptr_t)GIC_GICD_SPENDSGIR(n))
  125. void gic_initialize(void);
  126. void gic_eoi(irq_no irq);
  127. int gic_find_pending_irq(
  128. LkmcVectorExceptionFrame *exc __attribute__((unused)),
  129. irq_no *irqp
  130. );
  131. void gicd_disable_int(irq_no irq);
  132. void gicd_enable_int(irq_no irq);
  133. void gicd_clear_pending(irq_no irq);
  134. /* Initialize GIC Controller */
  135. static void init_gicc(void) {
  136. uint32_t pending_irq;
  137. /* Disable CPU interface */
  138. *REG_GIC_GICC_CTLR = GICC_CTLR_DISABLE;
  139. /* Set the priority level as the lowest priority.
  140. * Note: Higher priority corresponds to a lower Priority field value in the GIC_PMR.
  141. * In addition to this, writing 255 to the GICC_PMR always sets it to the
  142. * largest supported priority field value.
  143. */
  144. *REG_GIC_GICC_PMR = GICC_PMR_PRIO_MIN;
  145. /* Handle all of interrupts in a single group */
  146. *REG_GIC_GICC_BPR = GICC_BPR_NO_GROUP;
  147. /* Clear all of the active interrupts */
  148. for (
  149. pending_irq = (*REG_GIC_GICC_IAR & GICC_IAR_INTR_IDMASK);
  150. pending_irq != GICC_IAR_SPURIOUS_INTR;
  151. pending_irq = (*REG_GIC_GICC_IAR & GICC_IAR_INTR_IDMASK)
  152. )
  153. *REG_GIC_GICC_EOIR = *REG_GIC_GICC_IAR;
  154. /* Enable CPU interface */
  155. *REG_GIC_GICC_CTLR = GICC_CTLR_ENABLE;
  156. }
  157. static void init_gicd(void) {
  158. int32_t i, regs_nr;
  159. /* Diable distributor */
  160. *REG_GIC_GICD_CTLR = GIC_GICD_CTLR_DISABLE;
  161. /* Disable all IRQs */
  162. regs_nr = (GIC_INT_MAX + GIC_GICD_INT_PER_REG - 1) / GIC_GICD_INT_PER_REG;
  163. for (i = 0; regs_nr > i; ++i)
  164. *REG_GIC_GICD_ICENABLER(i) = ~((uint32_t)(0));
  165. /* Clear all pending IRQs */
  166. regs_nr = (GIC_INT_MAX + GIC_GICD_INT_PER_REG - 1) / GIC_GICD_INT_PER_REG;
  167. for (i = 0; regs_nr > i; ++i)
  168. *REG_GIC_GICD_ICPENDR(i) = ~((uint32_t)(0));
  169. /* Set all of interrupt priorities as the lowest priority */
  170. regs_nr = ( GIC_INT_MAX + GIC_GICD_IPRIORITY_PER_REG - 1) /
  171. GIC_GICD_IPRIORITY_PER_REG ;
  172. for (i = 0; regs_nr > i; i++)
  173. *REG_GIC_GICD_IPRIORITYR(i) = ~((uint32_t)(0));
  174. /* Set target of all of shared peripherals to processor 0 */
  175. for (i = GIC_INTNO_SPI0 / GIC_GICD_ITARGETSR_PER_REG;
  176. ( (GIC_INT_MAX + (GIC_GICD_ITARGETSR_PER_REG - 1) ) /
  177. GIC_GICD_ITARGETSR_PER_REG ) > i; ++i)
  178. *REG_GIC_GICD_ITARGETSR(i) =
  179. (uint32_t)GIC_GICD_ITARGETSR_CORE0_TARGET_BMAP;
  180. /* Set trigger type for all peripheral interrupts level triggered */
  181. for (i = GIC_INTNO_PPI0 / GIC_GICD_ICFGR_PER_REG;
  182. (GIC_INT_MAX + (GIC_GICD_ICFGR_PER_REG - 1)) / GIC_GICD_ICFGR_PER_REG > i; ++i)
  183. *REG_GIC_GICD_ICFGR(i) = GIC_GICD_ICFGR_LEVEL;
  184. /* Enable distributor */
  185. *REG_GIC_GICD_CTLR = GIC_GICD_CTLR_ENABLE;
  186. }
  187. /* Disable IRQ
  188. * @param[in] irq IRQ number
  189. */
  190. void gicd_disable_int(irq_no irq) {
  191. *REG_GIC_GICD_ICENABLER( (irq / GIC_GICD_ICENABLER_PER_REG) ) =
  192. 1U << ( irq % GIC_GICD_ICENABLER_PER_REG );
  193. }
  194. /* Enable IRQ
  195. * @param[in] irq IRQ number
  196. */
  197. void gicd_enable_int(irq_no irq) {
  198. *REG_GIC_GICD_ISENABLER( (irq / GIC_GICD_ISENABLER_PER_REG) ) =
  199. 1U << ( irq % GIC_GICD_ISENABLER_PER_REG );
  200. }
  201. /* Clear a pending interrupt
  202. * @param[in] irq IRQ number
  203. */
  204. void gicd_clear_pending(irq_no irq) {
  205. *REG_GIC_GICD_ICPENDR( (irq / GIC_GICD_ICPENDR_PER_REG) ) =
  206. 1U << ( irq % GIC_GICD_ICPENDR_PER_REG );
  207. }
  208. /* Probe pending interrupt
  209. * @param[in] irq IRQ number
  210. */
  211. static int gicd_probe_pending(irq_no irq) {
  212. int is_pending;
  213. is_pending = ( *REG_GIC_GICD_ISPENDR( (irq / GIC_GICD_ISPENDR_PER_REG) ) &
  214. ( 1U << ( irq % GIC_GICD_ISPENDR_PER_REG ) ) );
  215. return ( is_pending != 0 );
  216. }
  217. /* Set an interrupt target processor
  218. * @param[in] irq IRQ number
  219. * @param[in] p Target processor mask
  220. * 0x1 processor 0
  221. * 0x2 processor 1
  222. * 0x4 processor 2
  223. * 0x8 processor 3
  224. */
  225. static void gicd_set_target(irq_no irq, uint32_t p){
  226. uint32_t shift;
  227. uint32_t reg;
  228. shift = (irq % GIC_GICD_ITARGETSR_PER_REG) * GIC_GICD_ITARGETSR_SIZE_PER_REG;
  229. reg = *REG_GIC_GICD_ITARGETSR(irq / GIC_GICD_ITARGETSR_PER_REG);
  230. reg &= ~( ((uint32_t)(0xff)) << shift);
  231. reg |= (p << shift);
  232. *REG_GIC_GICD_ITARGETSR(irq / GIC_GICD_ITARGETSR_PER_REG) = reg;
  233. }
  234. /* Set an interrupt priority
  235. * @param[in] irq IRQ number
  236. * @param[in] prio Interrupt priority in Arm specific expression
  237. */
  238. static void gicd_set_priority(irq_no irq, uint32_t prio){
  239. uint32_t shift;
  240. uint32_t reg;
  241. shift = (irq % GIC_GICD_IPRIORITY_PER_REG) * GIC_GICD_IPRIORITY_SIZE_PER_REG;
  242. reg = *REG_GIC_GICD_IPRIORITYR(irq / GIC_GICD_IPRIORITY_PER_REG);
  243. reg &= ~(((uint32_t)(0xff)) << shift);
  244. reg |= (prio << shift);
  245. *REG_GIC_GICD_IPRIORITYR(irq / GIC_GICD_IPRIORITY_PER_REG) = reg;
  246. }
  247. /* Configure IRQ
  248. * @param[in] irq IRQ number
  249. * @param[in] config Configuration value for GICD_ICFGR
  250. */
  251. static void gicd_config(irq_no irq, unsigned int config) {
  252. uint32_t shift;
  253. uint32_t reg;
  254. shift = (irq % GIC_GICD_ICFGR_PER_REG) * GIC_GICD_ICFGR_SIZE_PER_REG; /* GICD_ICFGR has 16 fields, each field has 2bits. */
  255. reg = *REG_GIC_GICD_ICFGR( irq / GIC_GICD_ICFGR_PER_REG);
  256. reg &= ~( ( (uint32_t)(0x03) ) << shift ); /* Clear the field */
  257. reg |= ( ( (uint32_t)config ) << shift ); /* Set the value to the field correponding to irq */
  258. *REG_GIC_GICD_ICFGR( irq / GIC_GICD_ICFGR_PER_REG) = reg;
  259. }
  260. /* Send End of Interrupt to IRQ line for GIC
  261. * @param[in] ctrlr IRQ controller information
  262. * @param[in] irq IRQ number
  263. */
  264. void gic_eoi(irq_no irq) {
  265. gicd_clear_pending(irq);
  266. }
  267. /* Initialize GIC IRQ controller */
  268. /* RyanYao: 2018/07/20
  269. * I supppose the current access is security, because GICD_CTLR.DS is 0b0 and
  270. * we can access.
  271. */
  272. void gic_initialize(void) {
  273. init_gicd();
  274. init_gicc();
  275. gicd_config(TIMER_IRQ, GIC_GICD_ICFGR_EDGE);
  276. gicd_set_priority(TIMER_IRQ, 0 << GIC_PRI_SHIFT);
  277. gicd_set_target(TIMER_IRQ, 0x1); /* processor 0 */
  278. gicd_clear_pending(TIMER_IRQ);
  279. gicd_enable_int(TIMER_IRQ);
  280. }
  281. /* Find pending IRQ
  282. * @param[in] exc An exception frame
  283. * @param[in,out] irqp An IRQ number to be processed
  284. * @return 0 if found, 1 if not found
  285. */
  286. int gic_find_pending_irq(
  287. LkmcVectorExceptionFrame *exc __attribute__((unused)),
  288. irq_no *irqp
  289. ) {
  290. int rc;
  291. irq_no i;
  292. for (i = 0; GIC_INT_MAX > i; ++i) {
  293. if (gicd_probe_pending(i)) {
  294. rc = 0;
  295. *irqp = i;
  296. goto found;
  297. }
  298. }
  299. rc = 1;
  300. found:
  301. return rc;
  302. }
  303. #endif