AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
cpu.h
Go to the documentation of this file.
1#ifndef _X86_CPU_H
2#define _X86_CPU_H
3
4#include <core/system.h>
5
6/* x86: the CPU's structures (the interrupt frame, the GDT and TSS), the
7 * control registers, and the functions of arch/i386/cpu/. */
8
12struct x86_regs {
13#if ARCH_BITS==32
15 edi, esi, ebp, ebx, ecx, edx, eax,
16 gs, fs, es, ds,
17 vec, err, /* pushed by the stub: the vector, the error code (or 0) */
18 eip, cs, eflags, esp, ss;
19#else
23 vec, err, /* pushed by the stub: the vector, the error code (or 0) */
25#endif
26};
27
28/* Prints the saved registers, for a panic. */
29static inline void x86_dump_registers(struct x86_regs *regs)
30{
31 printk("Registers dump:\n");
32#if ARCH_BITS==32
33 printk("edi = %p\n", regs->edi);
34 printk("esi = %p\n", regs->esi);
35 printk("ebp = %p\n", regs->ebp);
36 printk("ebx = %p\n", regs->ebx);
37 printk("ecx = %p\n", regs->ecx);
38 printk("edx = %p\n", regs->edx);
39 printk("eax = %p\n", regs->eax);
40 printk("gs = %p\n", regs->gs );
41 printk("fs = %p\n", regs->fs );
42 printk("es = %p\n", regs->es );
43 printk("ds = %p\n", regs->ds );
44 printk("eip = %p\n", regs->eip);
45 printk("cs = %p\n", regs->cs );
46 printk("eflags = %p\n", regs->eflags);
47 printk("esp = %p\n", regs->esp);
48 printk("ss = %p\n", regs->ss);
49#else
50 printk("r15 = %p\n", regs->r15);
51 printk("r14 = %p\n", regs->r14);
52 printk("r13 = %p\n", regs->r13);
53 printk("r12 = %p\n", regs->r12);
54 printk("r11 = %p\n", regs->r11);
55 printk("r10 = %p\n", regs->r10);
56 printk("r9 = %p\n", regs->r9);
57 printk("r8 = %p\n", regs->r8);
58 printk("rdi = %p\n", regs->rdi);
59 printk("rsi = %p\n", regs->rsi);
60 printk("rbp = %p\n", regs->rbp);
61 printk("rbx = %p\n", regs->rbx);
62 printk("rcx = %p\n", regs->rcx);
63 printk("rdx = %p\n", regs->rdx);
64 printk("rax = %p\n", regs->rax);
65 printk("rip = %p\n", regs->rip);
66 printk("cs = %p\n", regs->cs );
67 printk("rflags = %p\n", regs->rflags);
68 printk("rsp = %p\n", regs->rsp);
69 printk("ss = %p\n", regs->ss);
70#endif
71}
72
75 uint32_t limit_lo : 16; /* the limit, bits 0 to 15 */
76 uint32_t base_lo : 16; /* the base, bits 0 to 15 */
77
78 uint32_t base_mid : 8; /* the base, bits 16 to 23 */
79 uint32_t type : 4; /* the segment's type */
80 uint32_t s : 1; /* 0 for a system segment, 1 for code or data */
81 uint32_t dpl : 2; /* its privilege level */
82 uint32_t p : 1; /* present */
83
84 uint32_t limit_hi : 4; /* the limit, bits 16 to 19 */
85 uint32_t avl : 1; /* free for the system's use */
86 uint32_t l : 1; /* a 64-bit code segment (x86_64) */
87 uint32_t db : 1; /* the default operation size (32-bit) */
88 uint32_t g : 1; /* the limit counts 4 KiB pages, not bytes */
89 uint32_t base_hi : 8; /* the base, bits 24 to 31 */
90} __aligned(8);
91
92/* The task state segment. The kernel only uses it for the stack that
93 * interrupts from user mode switch to. */
94#if ARCH_BITS==32
95struct x86_tss {
96 uint32_t link;
98 uint32_t ss;
99 uint32_t _[23]; /* the other fields, unused (see Intel's manuals) */
100} __packed;
101#else
102struct x86_tss {
105 uint32_t __[23]; /* the other fields, unused (see Intel's manuals) */
106} __packed;
107#endif
108
109/*
110 * Each CPU has its own GDT, with the same segments but its own TSS (a TSS
111 * is busy on the CPU that loaded it) and, on i386, the segment that %gs
112 * selects in the kernel: its struct cpu.
113 */
114#define X86_GDT_TSS 5 /* 5 and 6 on x86_64 */
115#define X86_GDT_CPU 7
116#define X86_GDT_NR 8
117
118#define X86_SEL_CPU (X86_GDT_CPU << 3)
119
120struct pmap;
121struct thread;
122
124struct arch_cpu {
125 uint32_t apic_id; /* its local APIC's ID */
128 struct pmap *pmap; /* the page tables in its CR3 (pmap_switch) */
129 struct thread *fpu_thread; /* the thread whose state its FPU holds */
130 struct x86_regs *irq_regs; /* the interrupted context, for the tick */
131 int tick_switch; /* the tick asked for a switch (irq.c) */
132 int ticking; /* its local APIC's timer is running */
133 uintptr_t idle_stack; /* the top of its idle loop's stack */
134 uint64_t tlb_flushes; /* TLB flushes done for another CPU (mm/tlb.c) */
135 uint64_t kernel_gen; /* the generation of the kernel's mappings its TLB has */
136};
137
138/* The running CPU's struct cpu. Its first member points to itself, and
139 * is at %gs:0: on i386 through the X86_SEL_CPU segment, on x86_64 through
140 * the GS base (user mode's is swapped in and out with swapgs). */
141struct cpu;
142
143static inline struct cpu *curcpu(void)
144{
145 struct cpu *cpu;
146#if ARCH_BITS==32
147 asm volatile("movl %%gs:0, %0" : "=r"(cpu));
148#else
149 asm volatile("movq %%gs:0, %0" : "=r"(cpu));
150#endif
151 return cpu;
152}
153
154/* CR0's bits */
155#define CR0_PG _BV(31)
156#define CR0_WP _BV(16) /* read-only pages are read-only for the kernel too */
157#define CR0_MP _BV(1)
158#define CR0_EM _BV(2)
159#define CR0_TS _BV(3)
160#define CR0_NE _BV(5)
161
162/* CR4's bits */
163#define CR4_PSE _BV(4)
164#define CR4_OSFXSR _BV(9)
165#define CR4_OSXMMEXCPT _BV(10)
166
167/* Read and write the control registers. */
168static inline uintptr_t read_cr0(void)
169{
170 uint32_t retval = 0;
171#if ARCH_BITS==32
172 asm volatile("mov %%cr0, %%eax":"=a"(retval));
173#else
174 asm volatile("movq %%cr0, %%rax":"=a"(retval));
175#endif
176 return retval;
177}
178
179static inline uintptr_t read_cr1(void)
180{
181 uintptr_t retval = 0;
182#if ARCH_BITS==32
183 asm volatile("mov %%cr1, %%eax":"=a"(retval));
184#else
185 asm volatile("movq %%cr1, %%rax":"=a"(retval));
186#endif
187 return retval;
188}
189
190static inline uintptr_t read_cr2(void)
191{
192 uintptr_t retval = 0;
193#if ARCH_BITS==32
194 asm volatile("mov %%cr2, %%eax":"=a"(retval));
195#else
196 asm volatile("movq %%cr2, %%rax":"=a"(retval));
197#endif
198 return retval;
199}
200
201static inline uintptr_t read_cr3(void)
202{
203 uintptr_t retval = 0;
204#if ARCH_BITS==32
205 asm volatile("mov %%cr3, %%eax":"=a"(retval));
206#else
207 asm volatile("movq %%cr3, %%rax":"=a"(retval));
208#endif
209 return retval;
210}
211
212static inline uintptr_t read_cr4(void)
213{
214 uintptr_t retval = 0;
215#if ARCH_BITS==32
216 asm volatile("mov %%cr4, %%eax":"=a"(retval));
217#else
218 asm volatile("movq %%cr4, %%rax":"=a"(retval));
219#endif
220 return retval;
221}
222
223static inline void write_cr0(uintptr_t val)
224{
225#if ARCH_BITS==32
226 asm volatile("mov %%eax, %%cr0"::"a"(val));
227#else
228 asm volatile("movq %%rax, %%cr0"::"a"(val));
229#endif
230}
231
232static inline void write_cr1(uintptr_t val)
233{
234#if ARCH_BITS==32
235 asm volatile("mov %%eax, %%cr1"::"a"(val));
236#else
237 asm volatile("movq %%rax, %%cr1"::"a"(val));
238#endif
239}
240
241static inline void write_cr2(uintptr_t val)
242{
243#if ARCH_BITS==32
244 asm volatile("mov %%eax, %%cr2"::"a"(val));
245#else
246 asm volatile("movq %%rax, %%cr2"::"a"(val));
247#endif
248}
249
250static inline void write_cr3(uintptr_t val)
251{
252#if ARCH_BITS==32
253 asm volatile("mov %%eax, %%cr3"::"a"(val));
254#else
255 asm volatile("movq %%rax, %%cr3"::"a"(val));
256#endif
257}
258
259static inline void write_cr4(uintptr_t val)
260{
261#if ARCH_BITS==32
262 asm volatile("mov %%eax, %%cr4"::"a"(val));
263#else
264 asm volatile("movq %%rax, %%cr4"::"a"(val));
265#endif
266}
267
268/* cpu/gdt.c */
269void x86_gdt_setup(struct cpu *cpu, uintptr_t sp);
271
272/* cpu/idt.c */
273void x86_idt_setup(void);
274void x86_idt_gate_set(uint32_t id, uintptr_t offset);
276
277/* cpu/isr.c */
278void x86_isr_setup(void);
279
280/* cpu/fpu.c */
281void x86_fpu_setup(void);
282void x86_fpu_enable(void);
283void x86_fpu_disable(void);
284void x86_fpu_trap(void);
285void x86_fpu_switch_out(void);
286int x86_fpu_save_to(void *buf);
287void x86_fpu_reset(void);
288void x86_fpu_load_from(const void *buf, int valid);
289
290/* sys/signal.c: delivers the pending signals on the way back to user
291 * mode from the context `r` */
292void x86_return_to_user(struct x86_regs *r, int syscall);
293
294#include_next <cpu/cpu.h>
295
296#endif /* ! _X86_CPU_H */
static struct cpu * curcpu(void)
Returns the running CPU's struct cpu, which TPIDR_EL1, the register meant for it, holds.
Definition cpu.h:62
static uintptr_t read_cr0(void)
Definition cpu.h:168
#define X86_GDT_NR
Definition cpu.h:116
static void write_cr1(uintptr_t val)
Definition cpu.h:232
static uintptr_t read_cr2(void)
Definition cpu.h:190
static void write_cr3(uintptr_t val)
Definition cpu.h:250
static void write_cr2(uintptr_t val)
Definition cpu.h:241
static void write_cr4(uintptr_t val)
Definition cpu.h:259
void x86_return_to_user(struct x86_regs *r, int syscall)
Delivers the current process's pending signals on the way back to user mode: stops and default action...
Definition signal.c:246
static void x86_dump_registers(struct x86_regs *regs)
Definition cpu.h:29
static uintptr_t read_cr4(void)
Definition cpu.h:212
static void write_cr0(uintptr_t val)
Definition cpu.h:223
static uintptr_t read_cr3(void)
Definition cpu.h:201
static uintptr_t read_cr1(void)
Definition cpu.h:179
void x86_fpu_load_from(const void *buf, int valid)
Gives the current thread back the FPU state saved in a signal frame, at sigreturn.
Definition fpu.c:239
void x86_fpu_trap(void)
Handles #NM, the current thread's first FPU or SSE instruction since it was switched in: it saves the...
Definition fpu.c:131
int x86_fpu_save_to(void *buf)
Copies the current thread's FPU state, for a signal handler's frame (sys/signal.c).
Definition fpu.c:198
void x86_fpu_disable(void)
Makes the next FPU instruction trap (sets CR0.TS).
Definition fpu.c:88
void x86_fpu_setup(void)
Sets up the FPU on the running CPU, at boot: CR0.TS set so that the first FPU or SSE instruction rais...
Definition fpu.c:50
void x86_fpu_enable(void)
Lets the running CPU use the FPU without trapping (clears CR0.TS).
Definition fpu.c:82
void x86_fpu_reset(void)
Makes the current thread start with a clean FPU state at its next use of the FPU, as a signal handler...
Definition fpu.c:218
void x86_fpu_switch_out(void)
Saves the current thread's FPU state when it is switched out, if the FPU holds it,...
Definition fpu.c:178
void x86_kernel_stack_set(uintptr_t sp)
Sets the kernel stack that interrupts from user mode switch to, on the running CPU: the thread that i...
Definition gdt.c:152
void x86_gdt_setup(struct cpu *cpu, uintptr_t sp)
Sets up and loads the running CPU's GDT and TSS, and points gs (or the GS base, on x86_64) at its str...
Definition gdt.c:79
void x86_idt_gate_user_set(uint32_t id, uintptr_t offset)
Sets an interrupt gate that user mode may raise with int too: the system call vector.
Definition idt.c:67
void x86_idt_gate_set(uint32_t id, uintptr_t offset)
Sets an interrupt gate that only the hardware (and the kernel) can raise: an exception or a device in...
Definition idt.c:45
void x86_idt_setup()
Loads the IDT on the running CPU.
Definition idt.c:82
#define __packed
Definition system.h:30
#define __aligned(n)
Definition system.h:31
void x86_isr_setup(void)
Sets the IDT's gates for the exceptions and the system call vector.
Definition isr.c:253
int printk(const char *fmt,...)
Writes a kernel message, to the message buffer and the consoles.
Definition printk.c:249
__SIZE_TYPE__ uintptr_t
Definition stddef.h:12
unsigned int uint32_t
Definition stddef.h:22
unsigned long long int uint64_t
Definition stddef.h:23
A CPU's aarch64 state (struct cpu's arch).
Definition cpu.h:51
uint64_t kernel_gen
Definition cpu.h:135
struct x86_tss tss
Definition cpu.h:127
struct thread * fpu_thread
Definition cpu.h:129
int tick_switch
Definition cpu.h:53
uintptr_t idle_stack
Definition cpu.h:55
uint32_t apic_id
Definition cpu.h:125
uint64_t tlb_flushes
Definition cpu.h:134
struct pmap * pmap
Definition cpu.h:52
struct x86_gdt_entry gdt[X86_GDT_NR]
Definition cpu.h:126
struct x86_regs * irq_regs
Definition cpu.h:130
int ticking
Definition cpu.h:132
A processor, and what runs on it.
Definition cpu.h:11
A filesystem type.
Definition vfs.h:98
An address space's page tables, on x86.
Definition pmap.h:9
A thread.
Definition thread.h:23
A segment descriptor, an entry of the GDT.
Definition cpu.h:74
uint32_t s
Definition cpu.h:80
uint32_t base_lo
Definition cpu.h:76
uint32_t dpl
Definition cpu.h:81
uint32_t limit_lo
Definition cpu.h:75
uint32_t l
Definition cpu.h:86
uint32_t base_mid
Definition cpu.h:78
uint32_t type
Definition cpu.h:79
uint32_t base_hi
Definition cpu.h:89
uint32_t p
Definition cpu.h:82
uint32_t g
Definition cpu.h:88
uint32_t avl
Definition cpu.h:85
uint32_t db
Definition cpu.h:87
uint32_t limit_hi
Definition cpu.h:84
The registers an interrupt or exception saved, on the kernel stack, as cpu.S's stubs push them: the g...
Definition cpu.h:12
uint64_t rcx
Definition cpu.h:22
uint64_t rsi
Definition cpu.h:22
uint64_t cs
Definition cpu.h:24
uint64_t r15
Definition cpu.h:21
uint64_t r14
Definition cpu.h:21
uint64_t err
Definition cpu.h:23
uint64_t rbp
Definition cpu.h:22
uint64_t vec
Definition cpu.h:23
uint64_t r10
Definition cpu.h:21
uint64_t rdx
Definition cpu.h:22
uint64_t r13
Definition cpu.h:21
uint64_t r12
Definition cpu.h:21
uint64_t rip
Definition cpu.h:24
uint64_t rax
Definition cpu.h:22
uint64_t rflags
Definition cpu.h:24
uint64_t ss
Definition cpu.h:24
uint64_t rsp
Definition cpu.h:24
uint64_t rdi
Definition cpu.h:22
uint64_t r9
Definition cpu.h:21
uint64_t r11
Definition cpu.h:21
uint64_t r8
Definition cpu.h:21
uint64_t rbx
Definition cpu.h:22
Definition cpu.h:102
uint32_t __[23]
Definition cpu.h:105
uint32_t _
Definition cpu.h:103
uint64_t sp
Definition cpu.h:104