source: mainline/kernel/arch/amd64/src/amd64.c@ 901b302

ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 901b302 was 98a935e, checked in by jxsvoboda <5887334+jxsvoboda@…>, 4 years ago

Configure NS16550 transmission format settings on initialization on PCs.

Currently, the NS116550 serial line controller is left with its
settings as it was left by the boot firmware and/or bootloader.
On my computer, this was an invalid configuration, and it left me
with a really slow booting system, since each output character
had to go through the full timeout loop in ns16550_sendb().

This patch adds the necessary bit and register descriptions to configure
the baud rate and transmission settings, as well as configuring them on
post-SMP initialization on ia32 and amd64, currently with values matching
the ns8250 userspace character device driver (38400 baud, 8-bit words,
2 stop bits, no parity).

This could perhaps be changed to be adjustable with a kernel command-line
argument, or through the configuration system.

This change does not affect emulators, since those largely ignore these
settings.

  • Property mode set to 100644
File size: 7.2 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 kernel_amd64
30 * @{
31 */
32/** @file
33 */
34
35#include <arch.h>
36#include <arch/arch.h>
37#include <stdint.h>
38#include <errno.h>
39#include <mem.h>
40#include <interrupt.h>
41#include <console/console.h>
42#include <syscall/syscall.h>
43#include <sysinfo/sysinfo.h>
44#include <arch/bios/bios.h>
45#include <arch/boot/boot.h>
46#include <arch/drivers/i8254.h>
47#include <arch/syscall.h>
48#include <genarch/acpi/acpi.h>
49#include <genarch/drivers/ega/ega.h>
50#include <genarch/drivers/i8042/i8042.h>
51#include <genarch/drivers/i8259/i8259.h>
52#include <genarch/drivers/ns16550/ns16550.h>
53#include <genarch/drivers/legacy/ia32/io.h>
54#include <genarch/fb/bfb.h>
55#include <genarch/kbrd/kbrd.h>
56#include <genarch/srln/srln.h>
57#include <genarch/multiboot/multiboot.h>
58#include <genarch/multiboot/multiboot2.h>
59#include <arch/pm.h>
60#include <arch/vreg.h>
61#include <arch/kseg.h>
62#include <genarch/pic/pic_ops.h>
63
64#ifdef CONFIG_SMP
65#include <arch/smp/apic.h>
66#endif
67
68static void amd64_pre_mm_init(void);
69static void amd64_post_mm_init(void);
70static void amd64_post_cpu_init(void);
71static void amd64_pre_smp_init(void);
72static void amd64_post_smp_init(void);
73
74arch_ops_t amd64_ops = {
75 .pre_mm_init = amd64_pre_mm_init,
76 .post_mm_init = amd64_post_mm_init,
77 .post_cpu_init = amd64_post_cpu_init,
78 .pre_smp_init = amd64_pre_smp_init,
79 .post_smp_init = amd64_post_smp_init
80};
81
82arch_ops_t *arch_ops = &amd64_ops;
83
84/** Perform amd64-specific initialization before main_bsp() is called.
85 *
86 * @param signature Multiboot signature.
87 * @param info Multiboot information structure.
88 *
89 */
90void amd64_pre_main(uint32_t signature, void *info)
91{
92 /* Parse multiboot information obtained from the bootloader. */
93 multiboot_info_parse(signature, (multiboot_info_t *) info);
94 multiboot2_info_parse(signature, (multiboot2_info_t *) info);
95
96#ifdef CONFIG_SMP
97 size_t unmapped_size = (uintptr_t) unmapped_end - BOOT_OFFSET;
98 /* Copy AP bootstrap routines below 1 MB. */
99 memcpy((void *) AP_BOOT_OFFSET, (void *) BOOT_OFFSET, unmapped_size);
100#endif
101}
102
103void amd64_pre_mm_init(void)
104{
105 /* Enable no-execute pages */
106 write_msr(AMD_MSR_EFER, read_msr(AMD_MSR_EFER) | AMD_NXE);
107 /* Enable FPU */
108 cpu_setup_fpu();
109
110 /* Initialize segmentation */
111 pm_init();
112
113 /* Disable I/O on nonprivileged levels, clear the nested-thread flag */
114 write_rflags(read_rflags() & ~(RFLAGS_IOPL | RFLAGS_NT));
115 /* Disable alignment check */
116 write_cr0(read_cr0() & ~CR0_AM);
117
118 if (config.cpu_active == 1) {
119 interrupt_init();
120 bios_init();
121
122 /* PIC */
123 i8259_init((i8259_t *) I8259_PIC0_BASE,
124 (i8259_t *) I8259_PIC1_BASE, IVT_IRQBASE);
125
126 /* Set PIC operations. */
127 pic_ops = &i8259_pic_ops;
128 }
129}
130
131void amd64_post_mm_init(void)
132{
133 vreg_init();
134 kseg_init();
135
136 if (config.cpu_active == 1) {
137 /* Initialize IRQ routing */
138 irq_init(IRQ_COUNT, IRQ_COUNT);
139
140 /* hard clock */
141 i8254_init();
142
143#if (defined(CONFIG_FB) || defined(CONFIG_EGA))
144 bool bfb = false;
145#endif
146
147#ifdef CONFIG_FB
148 bfb = bfb_init();
149#endif
150
151#ifdef CONFIG_EGA
152 if (!bfb) {
153 outdev_t *egadev = ega_init(EGA_BASE, EGA_VIDEORAM);
154 if (egadev)
155 stdout_wire(egadev);
156 }
157#endif
158
159 /* Merge all memory zones to 1 big zone */
160 zone_merge_all();
161 }
162
163 /* Setup fast SYSCALL/SYSRET */
164 syscall_setup_cpu();
165}
166
167void amd64_post_cpu_init(void)
168{
169#ifdef CONFIG_SMP
170 if (config.cpu_active > 1) {
171 l_apic_init();
172 l_apic_debug();
173 }
174#endif
175}
176
177void amd64_pre_smp_init(void)
178{
179 if (config.cpu_active == 1) {
180#ifdef CONFIG_SMP
181 acpi_init();
182#endif /* CONFIG_SMP */
183 }
184}
185
186void amd64_post_smp_init(void)
187{
188 /* Currently the only supported platform for amd64 is 'pc'. */
189 static const char *platform = "pc";
190
191 sysinfo_set_item_data("platform", NULL, (void *) platform,
192 str_size(platform));
193
194#ifdef CONFIG_PC_KBD
195 /*
196 * Initialize the i8042 controller. Then initialize the keyboard
197 * module and connect it to i8042. Enable keyboard interrupts.
198 */
199 i8042_instance_t *i8042_instance = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD);
200 if (i8042_instance) {
201 kbrd_instance_t *kbrd_instance = kbrd_init();
202 if (kbrd_instance) {
203 indev_t *sink = stdin_wire();
204 indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
205 i8042_wire(i8042_instance, kbrd);
206 pic_ops->enable_irqs(1 << IRQ_KBD);
207 pic_ops->enable_irqs(1 << IRQ_MOUSE);
208 }
209 }
210#endif
211
212#if (defined(CONFIG_NS16550) || defined(CONFIG_NS16550_OUT))
213 /*
214 * Initialize the ns16550 controller.
215 */
216#ifdef CONFIG_NS16550_OUT
217 outdev_t *ns16550_out;
218 outdev_t **ns16550_out_ptr = &ns16550_out;
219#else
220 outdev_t **ns16550_out_ptr = NULL;
221#endif
222 ns16550_instance_t *ns16550_instance =
223 ns16550_init(NS16550_BASE, 0, IRQ_NS16550, NULL, NULL,
224 ns16550_out_ptr);
225 if (ns16550_instance) {
226 ns16550_format_set(ns16550_instance, 38400,
227 LCR_PARITY_NONE | LCR_STOP_BIT_TWO | LCR_WORD_LEN_8);
228#ifdef CONFIG_NS16550
229 srln_instance_t *srln_instance = srln_init();
230 if (srln_instance) {
231 indev_t *sink = stdin_wire();
232 indev_t *srln = srln_wire(srln_instance, sink);
233 ns16550_wire(ns16550_instance, srln);
234 pic_ops->enable_irqs(1 << IRQ_NS16550);
235 }
236#endif
237#ifdef CONFIG_NS16550_OUT
238 if (ns16550_out) {
239 stdout_wire(ns16550_out);
240 }
241#endif
242 }
243#endif
244
245 sysinfo_set_item_val(pic_ops->get_name(), NULL, true);
246}
247
248void calibrate_delay_loop(void)
249{
250 i8254_calibrate_delay_loop();
251 if (config.cpu_active == 1) {
252 /*
253 * This has to be done only on UP.
254 * On SMP, i8254 is not used for time keeping and its interrupt pin remains masked.
255 */
256 i8254_normal_operation();
257 }
258}
259
260/** Construct function pointer
261 *
262 * @param fptr function pointer structure
263 * @param addr function address
264 * @param caller calling function address
265 *
266 * @return address of the function pointer
267 *
268 */
269void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller)
270{
271 return addr;
272}
273
274void arch_reboot(void)
275{
276#ifdef CONFIG_PC_KBD
277 i8042_cpu_reset((i8042_t *) I8042_BASE);
278#endif
279}
280
281void irq_initialize_arch(irq_t *irq)
282{
283 (void) irq;
284}
285
286/** @}
287 */
Note: See TracBrowser for help on using the repository browser.