00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00035 #include <smp/smp.h>
00036 #include <arch/smp/smp.h>
00037 #include <arch/smp/mps.h>
00038 #include <arch/smp/ap.h>
00039 #include <arch/boot/boot.h>
00040 #include <genarch/acpi/acpi.h>
00041 #include <genarch/acpi/madt.h>
00042 #include <config.h>
00043 #include <synch/waitq.h>
00044 #include <synch/synch.h>
00045 #include <arch/pm.h>
00046 #include <func.h>
00047 #include <panic.h>
00048 #include <debug.h>
00049 #include <arch/asm.h>
00050 #include <mm/frame.h>
00051 #include <mm/page.h>
00052 #include <mm/slab.h>
00053 #include <mm/as.h>
00054 #include <print.h>
00055 #include <memstr.h>
00056 #include <arch/drivers/i8259.h>
00057
00058 #ifdef CONFIG_SMP
00059
00060 static struct smp_config_operations *ops = NULL;
00061
00062 void smp_init(void)
00063 {
00064 int status;
00065 __address l_apic_address, io_apic_address;
00066
00067 if (acpi_madt) {
00068 acpi_madt_parse();
00069 ops = &madt_config_operations;
00070 }
00071 if (config.cpu_count == 1) {
00072 mps_init();
00073 ops = &mps_config_operations;
00074 }
00075
00076 l_apic_address = PA2KA(PFN2ADDR(frame_alloc_rc(ONE_FRAME, FRAME_ATOMIC | FRAME_KA, &status)));
00077 if (status != FRAME_OK)
00078 panic("cannot allocate address for l_apic\n");
00079
00080 io_apic_address = PA2KA(PFN2ADDR(frame_alloc_rc(ONE_FRAME, FRAME_ATOMIC | FRAME_KA, &status)));
00081 if (status != FRAME_OK)
00082 panic("cannot allocate address for io_apic\n");
00083
00084 if (config.cpu_count > 1) {
00085 page_mapping_insert(AS_KERNEL, l_apic_address, (__address) l_apic,
00086 PAGE_NOT_CACHEABLE);
00087 page_mapping_insert(AS_KERNEL, io_apic_address, (__address) io_apic,
00088 PAGE_NOT_CACHEABLE);
00089
00090 l_apic = (__u32 *) l_apic_address;
00091 io_apic = (__u32 *) io_apic_address;
00092 }
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102 void kmp(void *arg)
00103 {
00104 int i;
00105
00106 ASSERT(ops != NULL);
00107
00108 waitq_initialize(&ap_completion_wq);
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 *((__u16 *) (PA2KA(0x467+0))) = ((__address) ap_boot) >> 4;
00119 *((__u16 *) (PA2KA(0x467+2))) = 0;
00120
00121
00122
00123
00124
00125 outb(0x70,0xf);
00126 outb(0x71,0xa);
00127
00128 pic_disable_irqs(0xffff);
00129 apic_init();
00130
00131 for (i = 0; i < ops->cpu_count(); i++) {
00132 struct descriptor *gdt_new;
00133
00134
00135
00136
00137 if (!ops->cpu_enabled(i))
00138 continue;
00139
00140
00141
00142
00143 if (ops->cpu_bootstrap(i))
00144 continue;
00145
00146 if (ops->cpu_apic_id(i) == l_apic_id()) {
00147 printf("%s: bad processor entry #%d, will not send IPI to myself\n", __FUNCTION__, i);
00148 continue;
00149 }
00150
00151
00152
00153
00154 if (!(gdt_new = (struct descriptor *) malloc(GDT_ITEMS*sizeof(struct descriptor), FRAME_ATOMIC)))
00155 panic("couldn't allocate memory for GDT\n");
00156
00157 memcpy(gdt_new, gdt, GDT_ITEMS * sizeof(struct descriptor));
00158 memsetb((__address)(&gdt_new[TSS_DES]), sizeof(struct descriptor), 0);
00159 protected_ap_gdtr.limit = GDT_ITEMS * sizeof(struct descriptor);
00160 protected_ap_gdtr.base = KA2PA((__address) gdt_new);
00161 gdtr.base = (__address) gdt_new;
00162
00163 if (l_apic_send_init_ipi(ops->cpu_apic_id(i))) {
00164
00165
00166
00167
00168
00169 if (waitq_sleep_timeout(&ap_completion_wq, 1000000, SYNCH_FLAGS_NONE) == ESYNCH_TIMEOUT)
00170 printf("%s: waiting for cpu%d (APIC ID = %d) timed out\n", __FUNCTION__, config.cpu_active > i ? config.cpu_active : i, ops->cpu_apic_id(i));
00171 } else
00172 printf("INIT IPI for l_apic%d failed\n", ops->cpu_apic_id(i));
00173 }
00174 }
00175
00176 int smp_irq_to_pin(int irq)
00177 {
00178 ASSERT(ops != NULL);
00179 return ops->irq_to_pin(irq);
00180 }
00181
00182 #endif
00183