~galfy/helenos/bird-port-mainline

« back to all changes in this revision

Viewing changes to kernel/arch/amd64/src/amd64.c

  • Committer: Martin Decky
  • Date: 2009-08-04 11:19:19 UTC
  • Revision ID: martin@uranus.dsrg.hide.ms.mff.cuni.cz-20090804111919-evyclddlr3v5lhmp
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <arch/types.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
 
 
70
/** Disable I/O on non-privileged levels
 
71
 *
 
72
 * Clean IOPL(12,13) and NT(14) flags in EFLAGS register
 
73
 */
 
74
static void clean_IOPL_NT_flags(void)
 
75
{
 
76
        asm volatile (
 
77
                "pushfq\n"
 
78
                "pop %%rax\n"
 
79
                "and $~(0x7000), %%rax\n"
 
80
                "pushq %%rax\n"
 
81
                "popfq\n"
 
82
                ::: "%rax"
 
83
        );
 
84
}
 
85
 
 
86
/** Disable alignment check
 
87
 *
 
88
 * Clean AM(18) flag in CR0 register 
 
89
 */
 
90
static void clean_AM_flag(void)
 
91
{
 
92
        asm volatile (
 
93
                "mov %%cr0, %%rax\n"
 
94
                "and $~(0x40000), %%rax\n"
 
95
                "mov %%rax, %%cr0\n"
 
96
                ::: "%rax"
 
97
        );
 
98
}
 
99
 
 
100
/** Perform amd64-specific initialization before main_bsp() is called.
 
101
 *
 
102
 * @param signature Should contain the multiboot signature.
 
103
 * @param mi        Pointer to the multiboot information structure.
 
104
 */
 
105
void arch_pre_main(uint32_t signature, const multiboot_info_t *mi)
 
106
{
 
107
        /* Parse multiboot information obtained from the bootloader. */
 
108
        multiboot_info_parse(signature, mi);
 
109
        
 
110
#ifdef CONFIG_SMP
 
111
        /* Copy AP bootstrap routines below 1 MB. */
 
112
        memcpy((void *) AP_BOOT_OFFSET, (void *) BOOT_OFFSET,
 
113
            (size_t) &_hardcoded_unmapped_size);
 
114
#endif
 
115
}
 
116
 
 
117
void arch_pre_mm_init(void)
 
118
{
 
119
        /* Enable no-execute pages */
 
120
        set_efer_flag(AMD_NXE_FLAG);
 
121
        /* Enable FPU */
 
122
        cpu_setup_fpu();
 
123
 
 
124
        /* Initialize segmentation */
 
125
        pm_init();
 
126
        
 
127
        /* Disable I/O on nonprivileged levels
 
128
         * clear the NT (nested-thread) flag 
 
129
         */
 
130
        clean_IOPL_NT_flags();
 
131
        /* Disable alignment check */
 
132
        clean_AM_flag();
 
133
 
 
134
        if (config.cpu_active == 1) {
 
135
                interrupt_init();
 
136
                bios_init();
 
137
                
 
138
                /* PIC */
 
139
                i8259_init();
 
140
        }
 
141
}
 
142
 
 
143
 
 
144
void arch_post_mm_init(void)
 
145
{
 
146
        if (config.cpu_active == 1) {
 
147
                /* Initialize IRQ routing */
 
148
                irq_init(IRQ_COUNT, IRQ_COUNT);
 
149
                
 
150
                /* hard clock */
 
151
                i8254_init();
 
152
                
 
153
#ifdef CONFIG_FB
 
154
                if (vesa_present()) 
 
155
                        vesa_init();
 
156
                else
 
157
#endif
 
158
#ifdef CONFIG_EGA
 
159
                        ega_init(EGA_BASE, EGA_VIDEORAM);  /* video */
 
160
#else
 
161
                        {}
 
162
#endif
 
163
                
 
164
                /* Enable debugger */
 
165
                debugger_init();
 
166
                /* Merge all memory zones to 1 big zone */
 
167
                zone_merge_all();
 
168
        }
 
169
        
 
170
        /* Setup fast SYSCALL/SYSRET */
 
171
        syscall_setup_cpu();
 
172
}
 
173
 
 
174
void arch_post_cpu_init()
 
175
{
 
176
#ifdef CONFIG_SMP
 
177
        if (config.cpu_active > 1) {
 
178
                l_apic_init();
 
179
                l_apic_debug();
 
180
        }
 
181
#endif
 
182
}
 
183
 
 
184
void arch_pre_smp_init(void)
 
185
{
 
186
        if (config.cpu_active == 1) {
 
187
#ifdef CONFIG_SMP
 
188
                acpi_init();
 
189
#endif /* CONFIG_SMP */
 
190
        }
 
191
}
 
192
 
 
193
void arch_post_smp_init(void)
 
194
{
 
195
#ifdef CONFIG_PC_KBD
 
196
        /*
 
197
         * Initialize the i8042 controller. Then initialize the keyboard
 
198
         * module and connect it to i8042. Enable keyboard interrupts.
 
199
         */
 
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();
 
203
                if (kbrd_instance) {
 
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);
 
208
                }
 
209
        }
 
210
        
 
211
        /*
 
212
         * This is the necessary evil until the userspace driver is entirely
 
213
         * self-sufficient.
 
214
         */
 
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);
 
221
#endif
 
222
}
 
223
 
 
224
void calibrate_delay_loop(void)
 
225
{
 
226
        i8254_calibrate_delay_loop();
 
227
        if (config.cpu_active == 1) {
 
228
                /*
 
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.
 
231
                 */
 
232
                i8254_normal_operation();
 
233
        }
 
234
}
 
235
 
 
236
/** Set thread-local-storage pointer
 
237
 *
 
238
 * TLS pointer is set in FS register. Unfortunately the 64-bit
 
239
 * part can be set only in CPL0 mode.
 
240
 *
 
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.
 
243
 */
 
244
unative_t sys_tls_set(unative_t addr)
 
245
{
 
246
        THREAD->arch.tls = addr;
 
247
        write_msr(AMD_MSR_FS, addr);
 
248
        return 0;
 
249
}
 
250
 
 
251
/** Acquire console back for kernel
 
252
 *
 
253
 */
 
254
void arch_grab_console(void)
 
255
{
 
256
#ifdef CONFIG_FB
 
257
        if (vesa_present())
 
258
                vesa_redraw();
 
259
        else
 
260
#endif
 
261
#ifdef CONFIG_EGA
 
262
                ega_redraw();
 
263
#else
 
264
                {}
 
265
#endif
 
266
}
 
267
 
 
268
/** Return console to userspace
 
269
 *
 
270
 */
 
271
void arch_release_console(void)
 
272
{
 
273
}
 
274
 
 
275
/** Construct function pointer
 
276
 *
 
277
 * @param fptr   function pointer structure
 
278
 * @param addr   function address
 
279
 * @param caller calling function address
 
280
 *
 
281
 * @return address of the function pointer
 
282
 *
 
283
 */
 
284
void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller)
 
285
{
 
286
        return addr;
 
287
}
 
288
 
 
289
void arch_reboot(void)
 
290
{
 
291
#ifdef CONFIG_PC_KBD
 
292
        i8042_cpu_reset((i8042_t *) I8042_BASE);
 
293
#endif
 
294
}
 
295
 
 
296
/** @}
 
297
 */