source: mainline/kernel/arch/amd64/src/amd64.c@ acc7ce4

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since acc7ce4 was acc7ce4, checked in by Martin Decky <martin@…>, 15 years ago

uspace interrupt controller drivers for i8259 and APIC (non-functional yet)
convert NE2000 driver to use these drivers (not enabling the IRQ in kernel), this solves the "spurious interrupt" issue
(however, on SMP machines this renders the driver unusable for now since the APIC driver does not do anything yet)

  • Property mode set to 100644
File size: 6.9 KB
Line 
1/*
2 * Copyright (c) 2005 Ondrej Palkovsky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup amd64
30 * @{
31 */
32/** @file
33 */
34
35#include <arch.h>
36
37#include <typedefs.h>
38
39#include <config.h>
40
41#include <proc/thread.h>
42#include <genarch/multiboot/multiboot.h>
43#include <genarch/drivers/legacy/ia32/io.h>
44#include <genarch/drivers/ega/ega.h>
45#include <arch/drivers/vesa.h>
46#include <genarch/drivers/i8042/i8042.h>
47#include <genarch/kbrd/kbrd.h>
48#include <arch/drivers/i8254.h>
49#include <arch/drivers/i8259.h>
50#include <arch/boot/boot.h>
51
52#ifdef CONFIG_SMP
53#include <arch/smp/apic.h>
54#endif
55
56#include <arch/bios/bios.h>
57#include <arch/cpu.h>
58#include <print.h>
59#include <arch/cpuid.h>
60#include <genarch/acpi/acpi.h>
61#include <panic.h>
62#include <interrupt.h>
63#include <arch/syscall.h>
64#include <arch/debugger.h>
65#include <syscall/syscall.h>
66#include <console/console.h>
67#include <ddi/irq.h>
68#include <sysinfo/sysinfo.h>
69#include <memstr.h>
70
71/** Disable I/O on non-privileged levels
72 *
73 * Clean IOPL(12,13) and NT(14) flags in EFLAGS register
74 */
75static void clean_IOPL_NT_flags(void)
76{
77 asm volatile (
78 "pushfq\n"
79 "pop %%rax\n"
80 "and $~(0x7000), %%rax\n"
81 "pushq %%rax\n"
82 "popfq\n"
83 ::: "%rax"
84 );
85}
86
87/** Disable alignment check
88 *
89 * Clean AM(18) flag in CR0 register
90 */
91static void clean_AM_flag(void)
92{
93 asm volatile (
94 "mov %%cr0, %%rax\n"
95 "and $~(0x40000), %%rax\n"
96 "mov %%rax, %%cr0\n"
97 ::: "%rax"
98 );
99}
100
101/** Perform amd64-specific initialization before main_bsp() is called.
102 *
103 * @param signature Should contain the multiboot signature.
104 * @param mi Pointer to the multiboot information structure.
105 */
106void arch_pre_main(uint32_t signature, const multiboot_info_t *mi)
107{
108 /* Parse multiboot information obtained from the bootloader. */
109 multiboot_info_parse(signature, mi);
110
111#ifdef CONFIG_SMP
112 /* Copy AP bootstrap routines below 1 MB. */
113 memcpy((void *) AP_BOOT_OFFSET, (void *) BOOT_OFFSET,
114 (size_t) &_hardcoded_unmapped_size);
115#endif
116}
117
118void arch_pre_mm_init(void)
119{
120 /* Enable no-execute pages */
121 set_efer_flag(AMD_NXE_FLAG);
122 /* Enable FPU */
123 cpu_setup_fpu();
124
125 /* Initialize segmentation */
126 pm_init();
127
128 /* Disable I/O on nonprivileged levels
129 * clear the NT (nested-thread) flag
130 */
131 clean_IOPL_NT_flags();
132 /* Disable alignment check */
133 clean_AM_flag();
134
135 if (config.cpu_active == 1) {
136 interrupt_init();
137 bios_init();
138
139 /* PIC */
140 i8259_init();
141 }
142}
143
144
145void arch_post_mm_init(void)
146{
147 if (config.cpu_active == 1) {
148 /* Initialize IRQ routing */
149 irq_init(IRQ_COUNT, IRQ_COUNT);
150
151 /* hard clock */
152 i8254_init();
153
154#if (defined(CONFIG_FB) || defined(CONFIG_EGA))
155 bool vesa = false;
156#endif
157
158#ifdef CONFIG_FB
159 vesa = vesa_init();
160#endif
161
162#ifdef CONFIG_EGA
163 if (!vesa) {
164 outdev_t *egadev = ega_init(EGA_BASE, EGA_VIDEORAM);
165 if (egadev)
166 stdout_wire(egadev);
167 }
168#endif
169
170 /* Enable debugger */
171 debugger_init();
172 /* Merge all memory zones to 1 big zone */
173 zone_merge_all();
174 }
175
176 /* Setup fast SYSCALL/SYSRET */
177 syscall_setup_cpu();
178}
179
180void arch_post_cpu_init()
181{
182#ifdef CONFIG_SMP
183 if (config.cpu_active > 1) {
184 l_apic_init();
185 l_apic_debug();
186 }
187#endif
188}
189
190void arch_pre_smp_init(void)
191{
192 if (config.cpu_active == 1) {
193#ifdef CONFIG_SMP
194 acpi_init();
195#endif /* CONFIG_SMP */
196 }
197}
198
199void arch_post_smp_init(void)
200{
201 /* Currently the only supported platform for amd64 is 'pc'. */
202 static const char *platform = "pc";
203
204 sysinfo_set_item_data("platform", NULL, (void *) platform,
205 str_size(platform));
206
207#ifdef CONFIG_PC_KBD
208 /*
209 * Initialize the i8042 controller. Then initialize the keyboard
210 * module and connect it to i8042. Enable keyboard interrupts.
211 */
212 i8042_instance_t *i8042_instance = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD);
213 if (i8042_instance) {
214 kbrd_instance_t *kbrd_instance = kbrd_init();
215 if (kbrd_instance) {
216 indev_t *sink = stdin_wire();
217 indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
218 i8042_wire(i8042_instance, kbrd);
219 trap_virtual_enable_irqs(1 << IRQ_KBD);
220 trap_virtual_enable_irqs(1 << IRQ_MOUSE);
221 }
222 }
223
224 /*
225 * This is the necessary evil until the userspace driver is entirely
226 * self-sufficient.
227 */
228 sysinfo_set_item_val("i8042", NULL, true);
229 sysinfo_set_item_val("i8042.inr_a", NULL, IRQ_KBD);
230 sysinfo_set_item_val("i8042.inr_b", NULL, IRQ_MOUSE);
231 sysinfo_set_item_val("i8042.address.physical", NULL,
232 (uintptr_t) I8042_BASE);
233 sysinfo_set_item_val("i8042.address.kernel", NULL,
234 (uintptr_t) I8042_BASE);
235#endif
236
237 if (irqs_info != NULL)
238 sysinfo_set_item_val(irqs_info, NULL, true);
239
240 sysinfo_set_item_val("netif.dp8390.inr", NULL, IRQ_DP8390);
241}
242
243void calibrate_delay_loop(void)
244{
245 i8254_calibrate_delay_loop();
246 if (config.cpu_active == 1) {
247 /*
248 * This has to be done only on UP.
249 * On SMP, i8254 is not used for time keeping and its interrupt pin remains masked.
250 */
251 i8254_normal_operation();
252 }
253}
254
255/** Set thread-local-storage pointer
256 *
257 * TLS pointer is set in FS register. Unfortunately the 64-bit
258 * part can be set only in CPL0 mode.
259 *
260 * The specs say, that on %fs:0 there is stored contents of %fs register,
261 * we need not to go to CPL0 to read it.
262 */
263sysarg_t sys_tls_set(sysarg_t addr)
264{
265 THREAD->arch.tls = addr;
266 write_msr(AMD_MSR_FS, addr);
267
268 return 0;
269}
270
271/** Construct function pointer
272 *
273 * @param fptr function pointer structure
274 * @param addr function address
275 * @param caller calling function address
276 *
277 * @return address of the function pointer
278 *
279 */
280void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller)
281{
282 return addr;
283}
284
285void arch_reboot(void)
286{
287#ifdef CONFIG_PC_KBD
288 i8042_cpu_reset((i8042_t *) I8042_BASE);
289#endif
290}
291
292void irq_initialize_arch(irq_t *irq)
293{
294 (void) irq;
295}
296
297/** @}
298 */
Note: See TracBrowser for help on using the repository browser.