b00d266fcac21af992cd477f359ff3a160cc666f
[lunaix-os.git] / lunaix-os / scripts / x86_idt_generator.py
1 from pathlib import Path
2
3 intr_handler_h = "arch/x86/intrhnds.h"
4 intr_handler_c = "kernel/asm/x86/intrhnds.c"
5 intr_handler_s = "kernel/asm/x86/intrhnds.S"
6
7
8 # default value for each interrupt vector config
9
10 config = {
11     '8': {
12         'with_errno': True
13     },
14     '10': {
15         'with_errno': True
16     },
17     '11': {
18         'with_errno': True
19     },
20     '12': {
21         'with_errno': True
22     },
23     '13': {
24         'with_errno': True
25     },
26     '14': {
27         'with_errno': True
28     },
29     '17': {
30         'with_errno': True
31     },
32     '33': {
33         'dpl': 3
34     },
35     'default': {
36         'seg': 0x8,
37         'dpl': 0,
38         'vtype': 'IDT_INTERRUPT',
39         'with_errno': False
40     }
41 }
42
43
44 def get_workspace() -> Path:
45     file = Path(__file__)
46     return file.parent.parent.absolute()
47
48
49 def export_h(src: Path):
50     hfile = src.joinpath("includes", intr_handler_h)
51     code = '\n'.join(["ISR(%s)" % x for x in range(0, 256)])
52     with hfile.open(mode='w+') as f:
53         f.write(f'''
54 #ifndef __LUNAIX_INTRHNDS_H
55 #define __LUNAIX_INTRHNDS_H
56 #define ISR(iv) void _asm_isr##iv();
57 {code}
58 #endif
59 ''')
60
61
62 def get_vector_config(vec_num, cfg_name):
63     vn = str(vec_num)
64     if vn not in config:
65         return config['default'][cfg_name]
66     attr = config[vn]
67     if cfg_name not in attr:
68         return config['default'][cfg_name]
69     return attr[cfg_name]
70
71
72 def export_c(src: Path):
73     cfile = src.joinpath(intr_handler_c)
74     expr_list = []
75     for i in range(0, 256):
76         seg = get_vector_config(i, "seg")
77         dpl = get_vector_config(i, "dpl")
78         vtype = get_vector_config(i, "vtype")
79         expr_list.append(
80             f'    _set_idt_entry({i}, {seg}, _asm_isr{i}, {dpl}, {vtype});')
81     code = '\n'.join(expr_list)
82     with cfile.open(mode='w+') as f:
83         f.write(f'''
84 #include <arch/x86/idt.h>
85 #include <stdint.h>
86 #include <{intr_handler_h}>
87
88 #define IDT_ENTRY 256
89
90 u64_t _idt[IDT_ENTRY];
91 u16_t _idt_limit = sizeof(_idt) - 1;
92 static inline void
93 _set_idt_entry(u32_t vector,
94                u16_t seg_selector,
95                void (*isr)(),
96                u8_t dpl,
97                u8_t type)
98 {{
99     ptr_t offset = (ptr_t)isr;
100     _idt[vector] = (offset & 0xffff0000) | IDT_ATTR(dpl, type);
101     _idt[vector] <<= 32;
102     _idt[vector] |= (seg_selector << 16) | (offset & 0x0000ffff);
103 }}
104
105 void _init_idt() {{
106 {code}
107 }}
108 ''')
109
110
111 def export_s(src: Path):
112     sfile = src.joinpath(intr_handler_s)
113     expr_list = []
114     for i in range(0, 256):
115         has_errno = get_vector_config(i, "with_errno")
116         expr_list.append(
117             f"    isr_template {i}, no_error_code={'0' if has_errno else '1'}")
118
119     code = '\n'.join(expr_list)
120     marco = '''.macro isr_template vector, no_error_code=1
121     .global _asm_isr\\vector
122     .type _asm_isr\\vector, @function
123     _asm_isr\\vector:
124         .if \\no_error_code
125             pushl $0x0
126         .endif
127         pushl $\\vector
128         jmp interrupt_wrapper
129 .endm'''
130     with sfile.open(mode='w+') as f:
131         f.write(f'''
132 #define __ASM__
133 {marco}
134 .section .text
135 {code}
136 ''')
137
138
139 def main():
140     src = get_workspace()
141     export_h(src)
142     export_c(src)
143     export_s(src)
144
145
146 if __name__ == "__main__":
147     main()