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/>.
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))
33 unsigned char lapic_id
;
34 unsigned char lapic_ver
;
35 unsigned char cpu_flags
;
36 unsigned cpu_signature
;
37 unsigned cpu_features
;
41 unsigned char signature
[4];
42 unsigned short base_table_len
;
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
;
51 unsigned short ext_table_len
;
52 unsigned char ext_table_sum
;
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 */
68 struct smp_scan_spots_struct
{
73 static struct smp_scan_spots_struct smp_scan_spots
[] = {
80 static unsigned *arch_smp_probe (unsigned base
, unsigned limit
)
84 for (ptr
= (char *) base
; (unsigned) ptr
< limit
; ptr
++) {
86 if (!strncmp (ptr
, "_MP_", 4))
87 return (unsigned *) ptr
;
93 static struct mp_flt_ptr
*arch_smp_find_mp_config ()
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
);
108 static char *arch_smp_mpc_entry (char *entry
)
110 unsigned type
= (unsigned) *entry
;
111 struct mp_cpu_entry
*cpu
;
115 cpu
= (struct mp_cpu_entry
*) entry
;
118 if (!(cpu
->cpu_flags
& 1))
121 smp_arch_x86
*arch_spec
= (smp_arch_x86
*) kmalloc (sizeof (smp_arch_x86
));
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
))
144 static void arch_smp_sleep (int t
)
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);*/
166 extern void gdt_smp ();
168 unsigned arch_smp_trampoline ()
175 /* enable protected mode on AP cpu */
188 /* hang up processor - TODO */
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 */
204 /* check for intel spec. */
205 if (mp_flt
->feature_1
) {
209 mpc_ptr
= mp_flt
->mpc_ptr
;
214 /* verify MP Configuration Table signature */
215 if (strncmp (mpc_ptr
->signature
, "PCMP", 4))
218 /* save lapic address */
219 ipi_lapic_init (mpc_ptr
->lapic_addr
);
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
));
231 while (cpu
= smp_cpu_getnextcpu (cpu
)) {
232 /* check for AP processor */
233 if (cpu
->flags
!= SMP_FLAGS_CPU_AP
)
236 smp_arch_x86
*arch_spec
= cpu
->arch_spec
;
241 /* try to boot AP processor */
242 if (arch_smp_cpuboot (arch_spec
->lapic_id
))
243 cpu
->state
= SMP_STATE_CPU_UP
;