2
* Copyright (c) 2005 Ondrej Palkovsky
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
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.
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.
37
#include <arch/types.h>
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>
53
#include <arch/smp/apic.h>
56
#include <arch/bios/bios.h>
59
#include <arch/cpuid.h>
60
#include <genarch/acpi/acpi.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>
68
#include <sysinfo/sysinfo.h>
70
/** Disable I/O on non-privileged levels
72
* Clean IOPL(12,13) and NT(14) flags in EFLAGS register
74
static void clean_IOPL_NT_flags(void)
79
"and $~(0x7000), %%rax\n"
86
/** Disable alignment check
88
* Clean AM(18) flag in CR0 register
90
static void clean_AM_flag(void)
94
"and $~(0x40000), %%rax\n"
100
/** Perform amd64-specific initialization before main_bsp() is called.
102
* @param signature Should contain the multiboot signature.
103
* @param mi Pointer to the multiboot information structure.
105
void arch_pre_main(uint32_t signature, const multiboot_info_t *mi)
107
/* Parse multiboot information obtained from the bootloader. */
108
multiboot_info_parse(signature, mi);
111
/* Copy AP bootstrap routines below 1 MB. */
112
memcpy((void *) AP_BOOT_OFFSET, (void *) BOOT_OFFSET,
113
(size_t) &_hardcoded_unmapped_size);
117
void arch_pre_mm_init(void)
119
/* Enable no-execute pages */
120
set_efer_flag(AMD_NXE_FLAG);
124
/* Initialize segmentation */
127
/* Disable I/O on nonprivileged levels
128
* clear the NT (nested-thread) flag
130
clean_IOPL_NT_flags();
131
/* Disable alignment check */
134
if (config.cpu_active == 1) {
144
void arch_post_mm_init(void)
146
if (config.cpu_active == 1) {
147
/* Initialize IRQ routing */
148
irq_init(IRQ_COUNT, IRQ_COUNT);
159
ega_init(EGA_BASE, EGA_VIDEORAM); /* video */
164
/* Enable debugger */
166
/* Merge all memory zones to 1 big zone */
170
/* Setup fast SYSCALL/SYSRET */
174
void arch_post_cpu_init()
177
if (config.cpu_active > 1) {
184
void arch_pre_smp_init(void)
186
if (config.cpu_active == 1) {
189
#endif /* CONFIG_SMP */
193
void arch_post_smp_init(void)
197
* Initialize the i8042 controller. Then initialize the keyboard
198
* module and connect it to i8042. Enable keyboard interrupts.
200
i8042_instance_t *i8042_instance = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD);
201
if (i8042_instance) {
202
kbrd_instance_t *kbrd_instance = kbrd_init();
204
indev_t *sink = stdin_wire();
205
indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
206
i8042_wire(i8042_instance, kbrd);
207
trap_virtual_enable_irqs(1 << IRQ_KBD);
212
* This is the necessary evil until the userspace driver is entirely
215
sysinfo_set_item_val("kbd", NULL, true);
216
sysinfo_set_item_val("kbd.inr", NULL, IRQ_KBD);
217
sysinfo_set_item_val("kbd.address.physical", NULL,
218
(uintptr_t) I8042_BASE);
219
sysinfo_set_item_val("kbd.address.kernel", NULL,
220
(uintptr_t) I8042_BASE);
224
void calibrate_delay_loop(void)
226
i8254_calibrate_delay_loop();
227
if (config.cpu_active == 1) {
229
* This has to be done only on UP.
230
* On SMP, i8254 is not used for time keeping and its interrupt pin remains masked.
232
i8254_normal_operation();
236
/** Set thread-local-storage pointer
238
* TLS pointer is set in FS register. Unfortunately the 64-bit
239
* part can be set only in CPL0 mode.
241
* The specs say, that on %fs:0 there is stored contents of %fs register,
242
* we need not to go to CPL0 to read it.
244
unative_t sys_tls_set(unative_t addr)
246
THREAD->arch.tls = addr;
247
write_msr(AMD_MSR_FS, addr);
251
/** Acquire console back for kernel
254
void arch_grab_console(void)
268
/** Return console to userspace
271
void arch_release_console(void)
275
/** Construct function pointer
277
* @param fptr function pointer structure
278
* @param addr function address
279
* @param caller calling function address
281
* @return address of the function pointer
284
void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller)
289
void arch_reboot(void)
292
i8042_cpu_reset((i8042_t *) I8042_BASE);