Skip to content

Commit aa0fb81

Browse files
committed
Lesson 02 - Exercise 02
1 parent 7d5c787 commit aa0fb81

File tree

11 files changed

+323
-1
lines changed

11 files changed

+323
-1
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#ifndef _ENTRY_H
2+
#define _ENTRY_H
3+
4+
#define S_FRAME_SIZE 256 // size of all saved registers
5+
6+
#define SYNC_INVALID_EL1t 0
7+
#define IRQ_INVALID_EL1t 1
8+
#define FIQ_INVALID_EL1t 2
9+
#define ERROR_INVALID_EL1t 3
10+
11+
#define SYNC_INVALID_EL1h 4
12+
#define IRQ_INVALID_EL1h 5
13+
#define FIQ_INVALID_EL1h 6
14+
#define ERROR_INVALID_EL1h 7
15+
16+
#define SYNC_INVALID_EL0_64 8
17+
#define IRQ_INVALID_EL0_64 9
18+
#define FIQ_INVALID_EL0_64 10
19+
#define ERROR_INVALID_EL0_64 11
20+
21+
#define SYNC_INVALID_EL0_32 12
22+
#define IRQ_INVALID_EL0_32 13
23+
#define FIQ_INVALID_EL0_32 14
24+
#define ERROR_INVALID_EL0_32 15
25+
26+
#endif
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifndef _IRQ_H
2+
#define _IRQ_H
3+
4+
void enable_interrupt_controller( void );
5+
6+
void irq_vector_init( void );
7+
void enable_irq( void );
8+
void disable_irq( void );
9+
10+
#endif /*_IRQ_H */

exercises/lesson02/2/szediwy/include/peripherals/base.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,14 @@
77
// 0x7E000000 (legacy) -> 0x4_7E00_0000 (35-bit) -> 0x0_FE00_0000 (low peripheral)
88
#define PBASE 0xFE000000
99

10+
// The base address of the GIC-400 is 0x4c0040000. Note that, unlike other peripheral addresses in this document, this is an
11+
// ARM-only address and not a legacy master address. If Low Peripheral mode is enabled this base address becomes
12+
// 0xff840000.
13+
// The GIC-400 is configured with "NUM_CPUS=4" and "NUM_SPIS=192". For full register details, please refer to the ARM
14+
// GIC-400 documentation on the ARM Developer website.
15+
#define GIC_BASE 0xFF840000
16+
17+
// The ARMC register base address is 0x7e00b000 -> 0x4_7E00B000 -> 0x0FE00B000
18+
#define ARMC_BASE 0x0FE00B000
19+
1020
#endif /*_P_BASE_H */
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#ifndef _P_IRQ_H
2+
#define _P_IRQ_H
3+
4+
#include "peripherals/base.h"
5+
6+
#define IRQ_PENDING_0_CORE_0 (PBASE+0x0000B200)
7+
#define IRQ_PENDING_1_CORE_0 (PBASE+0x0000B204)
8+
#define IRQ_PENDING_2_CORE_0 (PBASE+0x0000B208)
9+
//#define FIQ_CONTROL (PBASE+0x0000B20C)
10+
#define ENABLE_IRQS_0_CORE_0 (PBASE+0x0000B210)
11+
#define ENABLE_IRQS_1_CORE_0 (PBASE+0x0000B214)
12+
#define ENABLE_IRQS_2_CORE_0 (PBASE+0x0000B218)
13+
14+
#define DISABLE_IRQS_0_CORE_0 (PBASE+0x0000B220)
15+
#define DISABLE_IRQS_1_CORE_0 (PBASE+0x0000B224)
16+
#define DISABLE_IRQS_2_CORE_0 (PBASE+0x0000B228)
17+
18+
#define SYSTEM_TIMER_IRQ_0 (1 << 0)
19+
#define SYSTEM_TIMER_IRQ_1 (1 << 1)
20+
#define SYSTEM_TIMER_IRQ_2 (1 << 2)
21+
#define SYSTEM_TIMER_IRQ_3 (1 << 3)
22+
23+
#endif /*_P_IRQ_H */
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef _P_TIMER_H
2+
#define _P_TIMER_H
3+
4+
#include "peripherals/base.h"
5+
6+
#define TIMER_CS (PBASE+0x00003000)
7+
#define TIMER_CLO (PBASE+0x00003004)
8+
#define TIMER_CHI (PBASE+0x00003008)
9+
#define TIMER_C0 (PBASE+0x0000300C)
10+
#define TIMER_C1 (PBASE+0x00003010)
11+
#define TIMER_C2 (PBASE+0x00003014)
12+
#define TIMER_C3 (PBASE+0x00003018)
13+
14+
#define TIMER_CS_M0 (1 << 0)
15+
#define TIMER_CS_M1 (1 << 1)
16+
#define TIMER_CS_M2 (1 << 2)
17+
#define TIMER_CS_M3 (1 << 3)
18+
19+
#endif /*_P_TIMER_H */
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#ifndef _TIMER_H
2+
#define _TIMER_H
3+
4+
void timer_init ( void );
5+
void handle_timer_irq ( void );
6+
7+
#endif /*_TIMER_H */
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
#include "entry.h"
2+
3+
.macro handle_invalid_entry type
4+
kernel_entry
5+
mov x0, #\type
6+
mrs x1, esr_el1
7+
mrs x2, elr_el1
8+
bl show_invalid_entry_message
9+
b err_hang
10+
.endm
11+
12+
.macro ventry label
13+
.align 7
14+
b \label
15+
.endm
16+
17+
.macro kernel_entry
18+
sub sp, sp, #S_FRAME_SIZE
19+
stp x0, x1, [sp, #16 * 0]
20+
stp x2, x3, [sp, #16 * 1]
21+
stp x4, x5, [sp, #16 * 2]
22+
stp x6, x7, [sp, #16 * 3]
23+
stp x8, x9, [sp, #16 * 4]
24+
stp x10, x11, [sp, #16 * 5]
25+
stp x12, x13, [sp, #16 * 6]
26+
stp x14, x15, [sp, #16 * 7]
27+
stp x16, x17, [sp, #16 * 8]
28+
stp x18, x19, [sp, #16 * 9]
29+
stp x20, x21, [sp, #16 * 10]
30+
stp x22, x23, [sp, #16 * 11]
31+
stp x24, x25, [sp, #16 * 12]
32+
stp x26, x27, [sp, #16 * 13]
33+
stp x28, x29, [sp, #16 * 14]
34+
str x30, [sp, #16 * 15]
35+
.endm
36+
37+
.macro kernel_exit
38+
ldp x0, x1, [sp, #16 * 0]
39+
ldp x2, x3, [sp, #16 * 1]
40+
ldp x4, x5, [sp, #16 * 2]
41+
ldp x6, x7, [sp, #16 * 3]
42+
ldp x8, x9, [sp, #16 * 4]
43+
ldp x10, x11, [sp, #16 * 5]
44+
ldp x12, x13, [sp, #16 * 6]
45+
ldp x14, x15, [sp, #16 * 7]
46+
ldp x16, x17, [sp, #16 * 8]
47+
ldp x18, x19, [sp, #16 * 9]
48+
ldp x20, x21, [sp, #16 * 10]
49+
ldp x22, x23, [sp, #16 * 11]
50+
ldp x24, x25, [sp, #16 * 12]
51+
ldp x26, x27, [sp, #16 * 13]
52+
ldp x28, x29, [sp, #16 * 14]
53+
ldr x30, [sp, #16 * 15]
54+
add sp, sp, #S_FRAME_SIZE
55+
eret
56+
.endm
57+
58+
59+
/*
60+
* Exception vectors.
61+
*/
62+
.align 11
63+
.globl vectors
64+
vectors:
65+
ventry sync_invalid_el1t // Synchronous EL1t
66+
ventry irq_invalid_el1t // IRQ EL1t
67+
ventry fiq_invalid_el1t // FIQ EL1t
68+
ventry error_invalid_el1t // Error EL1t
69+
70+
ventry sync_invalid_el1h // Synchronous EL1h
71+
ventry el1_irq // IRQ EL1h
72+
ventry fiq_invalid_el1h // FIQ EL1h
73+
ventry error_invalid_el1h // Error EL1h
74+
75+
ventry sync_invalid_el0_64 // Synchronous 64-bit EL0
76+
ventry irq_invalid_el0_64 // IRQ 64-bit EL0
77+
ventry fiq_invalid_el0_64 // FIQ 64-bit EL0
78+
ventry error_invalid_el0_64 // Error 64-bit EL0
79+
80+
ventry sync_invalid_el0_32 // Synchronous 32-bit EL0
81+
ventry irq_invalid_el0_32 // IRQ 32-bit EL0
82+
ventry fiq_invalid_el0_32 // FIQ 32-bit EL0
83+
ventry error_invalid_el0_32 // Error 32-bit EL0
84+
85+
sync_invalid_el1t:
86+
handle_invalid_entry SYNC_INVALID_EL1t
87+
88+
irq_invalid_el1t:
89+
handle_invalid_entry IRQ_INVALID_EL1t
90+
91+
fiq_invalid_el1t:
92+
handle_invalid_entry FIQ_INVALID_EL1t
93+
94+
error_invalid_el1t:
95+
handle_invalid_entry ERROR_INVALID_EL1t
96+
97+
sync_invalid_el1h:
98+
handle_invalid_entry SYNC_INVALID_EL1h
99+
100+
fiq_invalid_el1h:
101+
handle_invalid_entry FIQ_INVALID_EL1h
102+
103+
error_invalid_el1h:
104+
handle_invalid_entry ERROR_INVALID_EL1h
105+
106+
sync_invalid_el0_64:
107+
handle_invalid_entry SYNC_INVALID_EL0_64
108+
109+
irq_invalid_el0_64:
110+
handle_invalid_entry IRQ_INVALID_EL0_64
111+
112+
fiq_invalid_el0_64:
113+
handle_invalid_entry FIQ_INVALID_EL0_64
114+
115+
error_invalid_el0_64:
116+
handle_invalid_entry ERROR_INVALID_EL0_64
117+
118+
sync_invalid_el0_32:
119+
handle_invalid_entry SYNC_INVALID_EL0_32
120+
121+
irq_invalid_el0_32:
122+
handle_invalid_entry IRQ_INVALID_EL0_32
123+
124+
fiq_invalid_el0_32:
125+
handle_invalid_entry FIQ_INVALID_EL0_32
126+
127+
error_invalid_el0_32:
128+
handle_invalid_entry ERROR_INVALID_EL0_32
129+
130+
el1_irq:
131+
kernel_entry
132+
bl handle_irq
133+
kernel_exit
134+
135+
.globl err_hang
136+
err_hang: b err_hang
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
.globl irq_vector_init
2+
irq_vector_init:
3+
adr x0, vectors // load VBAR_EL1 with virtual
4+
msr vbar_el1, x0 // vector table address
5+
ret
6+
7+
.globl enable_irq
8+
enable_irq:
9+
msr daifclr, #2
10+
ret
11+
12+
.globl disable_irq
13+
disable_irq:
14+
msr daifset, #2
15+
ret
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#include "utils.h"
2+
#include "printf.h"
3+
#include "timer.h"
4+
#include "entry.h"
5+
#include "peripherals/irq.h"
6+
7+
const char *entry_error_messages[] = {
8+
"SYNC_INVALID_EL1t",
9+
"IRQ_INVALID_EL1t",
10+
"FIQ_INVALID_EL1t",
11+
"ERROR_INVALID_EL1T",
12+
13+
"SYNC_INVALID_EL1h",
14+
"IRQ_INVALID_EL1h",
15+
"FIQ_INVALID_EL1h",
16+
"ERROR_INVALID_EL1h",
17+
18+
"SYNC_INVALID_EL0_64",
19+
"IRQ_INVALID_EL0_64",
20+
"FIQ_INVALID_EL0_64",
21+
"ERROR_INVALID_EL0_64",
22+
23+
"SYNC_INVALID_EL0_32",
24+
"IRQ_INVALID_EL0_32",
25+
"FIQ_INVALID_EL0_32",
26+
"ERROR_INVALID_EL0_32"
27+
};
28+
29+
void enable_interrupt_controller()
30+
{
31+
put32(ENABLE_IRQS_0_CORE_0, SYSTEM_TIMER_IRQ_1);
32+
}
33+
34+
void show_invalid_entry_message(int type, unsigned long esr, unsigned long address)
35+
{
36+
printf("%s, ESR: %x, address: %x\r\n", entry_error_messages[type], esr, address);
37+
}
38+
39+
void handle_irq(void)
40+
{
41+
unsigned int irq = get32(IRQ_PENDING_0_CORE_0);
42+
switch (irq) {
43+
case (SYSTEM_TIMER_IRQ_1):
44+
handle_timer_irq();
45+
break;
46+
default:
47+
printf("Unknown pending irq: %x\r\n", irq);
48+
}
49+
}

exercises/lesson02/2/szediwy/src/kernel.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include "custom_printf.h"
2+
#include "timer.h"
23
#include "utils.h"
34
#include "mini_uart.h"
5+
#include "irq.h"
46

57
void kernel_main(unsigned long processor_index)
68
{
@@ -9,7 +11,11 @@ void kernel_main(unsigned long processor_index)
911
if (processor_index == 0)
1012
{
1113
uart_init();
12-
init_printf(0, putc);
14+
init_printf(0, putc);
15+
irq_vector_init();
16+
timer_init();
17+
enable_interrupt_controller();
18+
enable_irq();
1319
}
1420

1521
while (processor_index != current_processor_index)

0 commit comments

Comments
 (0)