Cleanup in elf.c with .bss section clean; adm command mounts cdrom instead of floppy...
[ZeXOS.git] / kernel / arch / i386 / smp.c
blob851308b2f5a3698484614dd8b7aed2c395a851ce
1 /*
2 * ZeX/OS
3 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <smp.h>
21 #include <arch/ipi.h>
23 #define MPC_ENTRY_CPU 0
24 #define MPC_ENTRY_BUS 1
25 #define MPC_ENTRY_IOAPIC 2
26 #define MPC_ENTRY_IOINT 3
27 #define MPC_ENTRY_LINT 4
29 #define __PACKED__ __attribute__ ((packed))
31 struct mp_cpu_entry {
32 unsigned char type;
33 unsigned char lapic_id;
34 unsigned char lapic_ver;
35 unsigned char cpu_flags;
36 unsigned cpu_signature;
37 unsigned cpu_features;
38 } __PACKED__;
40 struct mp_cfg_table {
41 unsigned char signature[4];
42 unsigned short base_table_len;
43 unsigned char rev;
44 unsigned char checksum;
45 unsigned char oem_id[8];
46 unsigned char product_id[12];
47 unsigned oem_table_ptr;
48 unsigned short oem_table_size;
49 unsigned short entry_cnt;
50 unsigned lapic_addr;
51 unsigned short ext_table_len;
52 unsigned char ext_table_sum;
53 } __PACKED__;
55 struct mp_flt_ptr {
56 unsigned char signature[4]; /* ASCII signature "_MP_" */
57 struct mp_cfg_table *mpc_ptr; /* pointer to the MP configuration structure */
58 unsigned char len; /* length of this structure in 16 byte paragraphs */
59 unsigned char rev; /* version of the multiprocessing specification */
60 unsigned char checksum; /* sum of all bytes in this structure */
61 unsigned char feature_1; /* feature flags */
62 unsigned char feature_2; /* presence of the ICMR */
63 unsigned char feature_3; /* reserved */
64 unsigned char feature_4; /* reserved */
65 unsigned char feature_5; /* reserved */
66 } __PACKED__;
68 struct smp_scan_spots_struct {
69 unsigned start;
70 unsigned stop;
73 static struct smp_scan_spots_struct smp_scan_spots[] = {
74 { 0x9fc00, 0xa0000},
75 { 0xf0000, 0x100000},
76 { 0, 0 }
80 static unsigned *arch_smp_probe (unsigned base, unsigned limit)
82 char *ptr;
84 for (ptr = (char *) base; (unsigned) ptr < limit; ptr ++) {
85 if (*ptr == '_') {
86 if (!strncmp (ptr, "_MP_", 4))
87 return (unsigned *) ptr;
90 return 0;
93 static struct mp_flt_ptr *arch_smp_find_mp_config ()
95 int i;
96 struct mp_flt_ptr *mp_flt = 0;
98 for (i = 0; smp_scan_spots[i].stop; i ++) {
99 mp_flt = (struct mp_flt_ptr *) arch_smp_probe (smp_scan_spots[i].start, smp_scan_spots[i].stop);
101 if (mp_flt)
102 break;
105 return mp_flt;
108 static char *arch_smp_mpc_entry (char *entry)
110 unsigned type = (unsigned) *entry;
111 struct mp_cpu_entry *cpu;
113 switch (type) {
114 case MPC_ENTRY_CPU:
115 cpu = (struct mp_cpu_entry *) entry;
116 entry += 20;
118 if (!(cpu->cpu_flags & 1))
119 break;
121 smp_arch_x86 *arch_spec = (smp_arch_x86 *) kmalloc (sizeof (smp_arch_x86));
123 if (!arch_spec)
124 return 0;
126 arch_spec->lapic_id = cpu->lapic_id;
127 arch_spec->lapic_ver = cpu->lapic_ver;
128 arch_spec->cpuid = cpu->cpu_signature;
129 arch_spec->features = cpu->cpu_features;
131 if (!smp_cpu_register (SMP_ARCH_x86, (cpu->cpu_flags & 2) ? SMP_STATE_CPU_UP : SMP_STATE_CPU_DOWN,
132 (cpu->cpu_flags & 2) ? SMP_FLAGS_CPU_BS : SMP_FLAGS_CPU_AP, arch_spec))
133 return 0;
135 break;
136 default:
137 entry += 8;
138 break;
141 return entry;
144 static void arch_smp_sleep (int t)
146 int_enable ();
147 timer_wait (t);
148 int_enable ();
151 static unsigned arch_smp_cpuboot (unsigned lapic_id)
153 arch_ipi_send (lapic_id, IPI_TYPE_INIT, 0);
155 arch_smp_sleep (100);
157 arch_ipi_send (lapic_id, IPI_TYPE_SIPI, SMP_ARCH_x86_TRAMPOLINE / 0x1000);
159 /*arch_smp_sleep (200);
160 arch_ipi_send (lapic_id, IPI_TYPE_SIPI, 0x07);
161 arch_smp_sleep (200);*/
163 return 1;
166 extern void gdt_smp ();
168 unsigned arch_smp_trampoline ()
170 /* asm volatile (
171 "mov %cs, %ax;"
172 "mov %ax, %ds;"
173 );*/
175 /* enable protected mode on AP cpu */
176 /*asm volatile (
177 "movl %cr0, %eax;"
178 "orl $(1<<0), %eax;"
179 "movl %eax, %cr0;"
180 );*/
182 /*asm volatile (
183 "mov $0x4F02, %ax;"
184 "int $0x10;"
185 "sti;"
186 );*/
188 /* hang up processor - TODO */
189 while (1)
190 asm ("hlt");
192 return 1;
195 unsigned arch_smp_init ()
197 struct mp_cfg_table *mpc_ptr = 0;
198 struct mp_flt_ptr *mp_flt = arch_smp_find_mp_config ();
200 /* this pc is not smp capable */
201 if (!mp_flt)
202 return 0;
204 /* check for intel spec. */
205 if (mp_flt->feature_1) {
206 /* TODO */
207 return 0;
208 } else
209 mpc_ptr = mp_flt->mpc_ptr;
211 if (!mpc_ptr)
212 return 0;
214 /* verify MP Configuration Table signature */
215 if (strncmp (mpc_ptr->signature, "PCMP", 4))
216 return 0;
218 /* save lapic address */
219 ipi_lapic_init (mpc_ptr->lapic_addr);
221 unsigned i;
222 char *entry_ptr = (char *) mpc_ptr + 44;
224 for (i = 0; i < mpc_ptr->entry_cnt; i ++)
225 entry_ptr = arch_smp_mpc_entry (entry_ptr);
227 memcpy (SMP_ARCH_x86_TRAMPOLINE, &arch_smp_trampoline, sizeof (&arch_smp_trampoline));
229 smp_cpu_t *cpu = 0;
231 while (cpu = smp_cpu_getnextcpu (cpu)) {
232 /* check for AP processor */
233 if (cpu->flags != SMP_FLAGS_CPU_AP)
234 continue;
236 smp_arch_x86 *arch_spec = cpu->arch_spec;
238 if (!arch_spec)
239 continue;
241 /* try to boot AP processor */
242 if (arch_smp_cpuboot (arch_spec->lapic_id))
243 cpu->state = SMP_STATE_CPU_UP;
246 return 1;