From f9d7cb3acc2b4eb9cfb8c30e67fb8349d4a8f401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Thu, 30 Jan 2003 21:24:50 +0000 Subject: [PATCH] Now uses the arch/x86/smp_apic.h header; changed apic_read/write() to accept offsets as parameter to specify the APIC register. Added an obviously missing apic_write() call. Code cleanup. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2606 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kernel/boot/arch/x86/smp_boot.c | 237 +++++++++++++++------------- 1 file changed, 126 insertions(+), 111 deletions(-) diff --git a/src/kernel/boot/arch/x86/smp_boot.c b/src/kernel/boot/arch/x86/smp_boot.c index 6e6603d63e..5e61fe559b 100644 --- a/src/kernel/boot/arch/x86/smp_boot.c +++ b/src/kernel/boot/arch/x86/smp_boot.c @@ -6,26 +6,34 @@ #include #include +#include #include #define NO_SMP 0 -#define CHATTY_SMP 0 -static unsigned int mp_mem_phys = 0; -static unsigned int mp_mem_virt = 0; +#define TRACE_SMP 1 +#if TRACE_SMP +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif + + +static uint32 mp_mem_phys = 0; +static uint32 mp_mem_virt = 0; static struct mp_flt_struct *mp_flt_ptr = NULL; static kernel_args *saved_ka = NULL; -static unsigned int kernel_entry_point = 0; +static uint32 kernel_entry_point = 0; static int smp_get_current_cpu(kernel_args *ka); -static unsigned int -map_page(kernel_args *ka, unsigned int paddr, unsigned int vaddr) +static uint32 +map_page(kernel_args *ka, uint32 paddr, uint32 vaddr) { - unsigned int *pentry; - unsigned int *pgdir = (unsigned int *)(ka->arch_args.page_hole + (4*1024*1024-PAGE_SIZE)); + uint32 *pentry; + uint32 *pgdir = (uint32 *)(ka->arch_args.page_hole + (4*1024*1024-PAGE_SIZE)); // check to see if a page table exists for this range if (pgdir[vaddr / PAGE_SIZE / 1024] == 0) { @@ -39,10 +47,10 @@ map_page(kernel_args *ka, unsigned int paddr, unsigned int vaddr) pgdir[vaddr / PAGE_SIZE / 1024] = (pgtable & ADDR_MASK) | DEFAULT_PAGE_FLAGS; // zero it out in it's new mapping - memset((unsigned int *)((unsigned int *)ka->arch_args.page_hole + (vaddr / PAGE_SIZE / 1024) * PAGE_SIZE), 0, PAGE_SIZE); + memset((uint32 *)((uint32 *)ka->arch_args.page_hole + (vaddr / PAGE_SIZE / 1024) * PAGE_SIZE), 0, PAGE_SIZE); } // now, fill in the pentry - pentry = (unsigned int *)((unsigned int *)ka->arch_args.page_hole + vaddr / PAGE_SIZE); + pentry = (uint32 *)((uint32 *)ka->arch_args.page_hole + vaddr / PAGE_SIZE); *pentry = (paddr & ADDR_MASK) | DEFAULT_PAGE_FLAGS; @@ -52,16 +60,17 @@ map_page(kernel_args *ka, unsigned int paddr, unsigned int vaddr) } -static unsigned int -apic_read(unsigned int *addr) +static uint32 +apic_read(uint32 offset) { - return *addr; + return *(uint32 *)((uint32)saved_ka->arch_args.apic + offset); } static void -apic_write(unsigned int *addr, unsigned int data) +apic_write(uint32 offset, uint32 data) { + uint32 *addr = (uint32 *)((uint32)saved_ka->arch_args.apic + offset); *addr = data; } @@ -76,20 +85,20 @@ mp_virt_to_phys(void *ptr) static void * mp_phys_to_virt(void *ptr) { - return ((void *)(((unsigned int)ptr - mp_mem_phys) + mp_mem_virt)); + return ((void *)(((uint32)ptr - mp_mem_phys) + mp_mem_virt)); } -static unsigned int * -smp_probe(unsigned int base, unsigned int limit) +static uint32 * +smp_probe(uint32 base, uint32 limit) { - unsigned int *ptr; + uint32 *ptr; -// dprintf("smp_probe: entry base 0x%x, limit 0x%x\n", base, limit); + TRACE(("smp_probe: entry base 0x%x, limit 0x%x\n", base, limit)); - for (ptr = (unsigned int *) base; (unsigned int) ptr < limit; ptr++) { + for (ptr = (uint32 *) base; (uint32)ptr < limit; ptr++) { if (*ptr == MP_FLT_SIGNATURE) { -// dprintf("smp_probe: found floating pointer structure at 0x%x\n", ptr); + TRACE(("smp_probe: found floating pointer structure at 0x%x\n", ptr)); return ptr; } } @@ -106,8 +115,10 @@ smp_do_config(kernel_args *ka) struct mp_ext_pe *pe; struct mp_ext_ioapic *io; struct mp_ext_bus *bus; -// const char *cpu_family[] = { "", "", "", "", "Intel 486", -// "Intel Pentium", "Intel Pentium Pro", "Intel Pentium II" }; +#if TRACE_SMP + const char *cpu_family[] = { "", "", "", "", "Intel 486", + "Intel Pentium", "Intel Pentium Pro", "Intel Pentium II" }; +#endif /* * we are not running in standard configuration, so we have to look through @@ -120,18 +131,18 @@ smp_do_config(kernel_args *ka) /* print out our new found configuration. */ ptr = (char *) &(mpc->oem[0]); -#if CHATTY_SMP - dprintf ("smp: oem id: %c%c%c%c%c%c%c%c product id: " + + TRACE(("smp: oem id: %c%c%c%c%c%c%c%c product id: " "%c%c%c%c%c%c%c%c%c%c%c%c\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15], ptr[16], ptr[17], ptr[18], ptr[19], - ptr[20]); - dprintf("smp: base table has %d entries, extended section %d bytes\n", - mpc->num_entries, mpc->ext_len); -#endif - ka->arch_args.apic_phys = (unsigned int)mpc->apic; + ptr[20])); + TRACE(("smp: base table has %d entries, extended section %d bytes\n", + mpc->num_entries, mpc->ext_len)); - ptr = (char *) ((unsigned int) mpc + sizeof (struct mp_config_table)); + ka->arch_args.apic_phys = (uint32)mpc->apic; + + ptr = (char *)((uint32)mpc + sizeof(struct mp_config_table)); for (i = 0; i < mpc->num_entries; i++) { switch (*ptr) { case MP_EXT_PE: @@ -139,31 +150,31 @@ smp_do_config(kernel_args *ka) ka->arch_args.cpu_apic_id[ka->num_cpus] = pe->apic_id; ka->arch_args.cpu_os_id[pe->apic_id] = ka->num_cpus; ka->arch_args.cpu_apic_version[ka->num_cpus] = pe->apic_version; -#if CHATTY_SMP - dprintf ("smp: cpu#%d: %s, apic id %d, version %d%s\n", + + TRACE(("smp: cpu#%d: %s, apic id %d, version %d%s\n", ka->num_cpus, cpu_family[(pe->signature & 0xf00) >> 8], pe->apic_id, pe->apic_version, (pe->cpu_flags & 0x2) ? - ", BSP" : ""); -#endif + ", BSP" : "")); + ptr += 20; ka->num_cpus++; break; case MP_EXT_BUS: bus = (struct mp_ext_bus *)ptr; -#if CHATTY_SMP - dprintf("smp: bus%d: %c%c%c%c%c%c\n", bus->bus_id, + + TRACE(("smp: bus%d: %c%c%c%c%c%c\n", bus->bus_id, bus->name[0], bus->name[1], bus->name[2], bus->name[3], - bus->name[4], bus->name[5]); -#endif + bus->name[4], bus->name[5])); + ptr += 8; break; case MP_EXT_IO_APIC: io = (struct mp_ext_ioapic *) ptr; - ka->arch_args.ioapic_phys = (unsigned int)io->addr; -#if CHATTY_SMP - dprintf("smp: found io apic with apic id %d, version %d\n", - io->ioapic_id, io->ioapic_version); -#endif + ka->arch_args.ioapic_phys = (uint32)io->addr; + + TRACE(("smp: found io apic with apic id %d, version %d\n", + io->ioapic_id, io->ioapic_version)); + ptr += 8; break; case MP_EXT_IO_INT: @@ -174,20 +185,19 @@ smp_do_config(kernel_args *ka) break; } } - dprintf("smp: apic @ 0x%x, i/o apic @ 0x%x, total %d processors detected\n", - (unsigned int)ka->arch_args.apic_phys, (unsigned int)ka->arch_args.ioapic_phys, ka->num_cpus); + dprintf("smp: apic @ %p, i/o apic @ %p, total %d processors detected\n", + (void *)ka->arch_args.apic_phys, (void *)ka->arch_args.ioapic_phys, ka->num_cpus); // this BIOS looks broken, because it didn't report any cpus (VMWare) - if(ka->num_cpus == 0) { + if (ka->num_cpus == 0) ka->num_cpus = 1; - } } struct smp_scan_spots_struct { - unsigned int start; - unsigned int stop; - unsigned int len; + uint32 start; + uint32 stop; + uint32 len; }; static struct smp_scan_spots_struct smp_scan_spots[] = { @@ -206,7 +216,7 @@ smp_find_mp_config(kernel_args *ka) for (i = 0; smp_scan_spots[i].len > 0; i++) { mp_flt_ptr = (struct mp_flt_struct *)smp_probe(smp_scan_spots[i].start, smp_scan_spots[i].stop); - if(mp_flt_ptr != NULL) + if (mp_flt_ptr != NULL) break; } #if NO_SMP @@ -217,11 +227,10 @@ smp_find_mp_config(kernel_args *ka) mp_mem_phys = smp_scan_spots[i].start; mp_mem_virt = smp_scan_spots[i].start; -#if CHATTY_SMP - dprintf ("smp_boot: intel mp version %s, %s", (mp_flt_ptr->mp_rev == 1) ? "1.1" : + TRACE(("smp_boot: intel mp version %s, %s", (mp_flt_ptr->mp_rev == 1) ? "1.1" : "1.4", (mp_flt_ptr->mp_feature_2 & 0x80) ? - "imcr and pic compatibility mode.\n" : "virtual wire compatibility mode.\n"); -#endif + "imcr and pic compatibility mode.\n" : "virtual wire compatibility mode.\n")); + if (mp_flt_ptr->mpc == 0) { // XXX need to implement #if 1 @@ -230,7 +239,7 @@ smp_find_mp_config(kernel_args *ka) #else /* this system conforms to one of the default configurations */ // mp_num_def_config = mp_flt_ptr->mp_feature_1; - dprintf ("smp: standard configuration %d\n", mp_flt_ptr->mp_feature_1); + TRACE(("smp: standard configuration %d\n", mp_flt_ptr->mp_feature_1)); /* num_cpus = 2; ka->cpu_apic_id[0] = 0; ka->cpu_apic_id[1] = 1; @@ -253,8 +262,9 @@ smp_find_mp_config(kernel_args *ka) static int smp_setup_apic(kernel_args *ka) { - unsigned int config; -// dprintf("setting up the apic..."); + uint32 config; + + TRACE(("setting up the apic...")); /* set spurious interrupt vector to 0xff */ config = apic_read(APIC_SIVR) & 0xfffffc00; @@ -294,26 +304,27 @@ smp_setup_apic(kernel_args *ka) config = apic_read(APIC_SIVR); apic_write(APIC_EOI, 0); -// dprintf("done\n"); + TRACE((" done\n")); return 0; } -// target function of the trampoline code -// The trampoline code should have the pgdir and a gdt set up for us, -// along with us being on the final stack for this processor. We need -// to set up the local APIC and load the global idt and gdt. When we're -// done, we'll jump into the kernel with the cpu number as an argument. +/** Target function of the trampoline code. + * The trampoline code should have the pgdir and a gdt set up for us, + * along with us being on the final stack for this processor. We need + * to set up the local APIC and load the global idt and gdt. When we're + * done, we'll jump into the kernel with the cpu number as an argument. + */ static int smp_cpu_ready(void) { kernel_args *ka = saved_ka; - unsigned int curr_cpu = smp_get_current_cpu(ka); + uint32 curr_cpu = smp_get_current_cpu(ka); struct gdt_idt_descr idt_descr; struct gdt_idt_descr gdt_descr; -// dprintf("smp_cpu_ready: entry cpu %d\n", curr_cpu); + TRACE(("smp_cpu_ready: entry cpu %d\n", curr_cpu)); // Important. Make sure supervisor threads can fault on read only pages... asm("movl %%eax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1)); @@ -324,14 +335,14 @@ smp_cpu_ready(void) // Set up the final idt idt_descr.a = IDT_LIMIT - 1; - idt_descr.b = (unsigned int *)ka->arch_args.vir_idt; + idt_descr.b = (uint32 *)ka->arch_args.vir_idt; asm("lidt %0;" : : "m" (idt_descr)); // Set up the final gdt gdt_descr.a = GDT_LIMIT - 1; - gdt_descr.b = (unsigned int *)ka->arch_args.vir_gdt; + gdt_descr.b = (uint32 *)ka->arch_args.vir_gdt; asm("lgdt %0;" : : "m" (gdt_descr)); @@ -339,7 +350,7 @@ smp_cpu_ready(void) asm("pushl %0; " // push the cpu number "pushl %1; " // kernel args "pushl $0x0;" // dummy retval for call to main - "pushl %2; " // this is the start address + "pushl %2; " // this is the start address "ret; " // jump. : : "r" (curr_cpu), "m" (ka), "g" (kernel_entry_point)); @@ -351,9 +362,9 @@ smp_cpu_ready(void) static int smp_boot_all_cpus(kernel_args *ka) { - unsigned int trampoline_code; - unsigned int trampoline_stack; - unsigned int i; + uint32 trampoline_code; + uint32 trampoline_stack; + uint32 i; // XXX assume low 1 meg is identity mapped by the 1st stage bootloader // and nothing important is in 0x9e000 & 0x9f000 @@ -367,21 +378,21 @@ smp_boot_all_cpus(kernel_args *ka) // copy the trampoline code over memcpy((char *)trampoline_code, &smp_trampoline, - (unsigned int)&smp_trampoline_end - (unsigned int)&smp_trampoline); + (uint32)&smp_trampoline_end - (uint32)&smp_trampoline); // boot the cpus for (i = 1; i < ka->num_cpus; i++) { - unsigned int *final_stack; - unsigned int *final_stack_ptr; - unsigned int *tramp_stack_ptr; - unsigned int config; - unsigned int num_startups; - unsigned int j; + uint32 *final_stack; + uint32 *final_stack_ptr; + uint32 *tramp_stack_ptr; + uint32 config; + uint32 num_startups; + uint32 j; // create a final stack the trampoline code will put the ap processor on ka->cpu_kstack[i].start = ka->virt_alloc_range[0].start + ka->virt_alloc_range[0].size; ka->cpu_kstack[i].size = STACK_SIZE * PAGE_SIZE; - for(j=0; jcpu_kstack[i].size/PAGE_SIZE; j++) { + for (j = 0; j < ka->cpu_kstack[i].size / PAGE_SIZE; j++) { // map the pages in map_page(ka, ka->phys_alloc_range[0].start + ka->phys_alloc_range[0].size, ka->virt_alloc_range[0].start + ka->virt_alloc_range[0].size); @@ -390,26 +401,27 @@ smp_boot_all_cpus(kernel_args *ka) } // set this stack up - final_stack = (unsigned int *)ka->cpu_kstack[i].start; + final_stack = (uint32 *)ka->cpu_kstack[i].start; memset(final_stack, 0, STACK_SIZE * PAGE_SIZE); - final_stack_ptr = (final_stack + (STACK_SIZE * PAGE_SIZE) / sizeof(unsigned int)) - 1; - *final_stack_ptr = (unsigned int)&smp_cpu_ready; + final_stack_ptr = (final_stack + (STACK_SIZE * PAGE_SIZE) / sizeof(uint32)) - 1; + *final_stack_ptr = (uint32)&smp_cpu_ready; final_stack_ptr--; // set the trampoline stack up - tramp_stack_ptr = (unsigned int *)(trampoline_stack + PAGE_SIZE - 4); + tramp_stack_ptr = (uint32 *)(trampoline_stack + PAGE_SIZE - 4); // final location of the stack - *tramp_stack_ptr = ((unsigned int)final_stack) + STACK_SIZE * PAGE_SIZE - sizeof(unsigned int); + *tramp_stack_ptr = ((uint32)final_stack) + STACK_SIZE * PAGE_SIZE - sizeof(uint32); tramp_stack_ptr--; // page dir *tramp_stack_ptr = ka->arch_args.phys_pgdir; tramp_stack_ptr--; // put a gdt descriptor at the bottom of the stack - *((unsigned short *)trampoline_stack) = 0x18-1; // LIMIT - *((unsigned int *)(trampoline_stack + 2)) = trampoline_stack + 8; + *((uint16 *)trampoline_stack) = 0x18 - 1; // LIMIT + *((uint32 *)(trampoline_stack + 2)) = trampoline_stack + 8; + // put the gdt at the bottom - memcpy(&((unsigned int *)trampoline_stack)[2], (void *)ka->arch_args.vir_gdt, 6*4); + memcpy(&((uint32 *)trampoline_stack)[2], (void *)ka->arch_args.vir_gdt, 6*4); /* clear apic errors */ if (ka->arch_args.cpu_apic_version[i] & 0xf0) { @@ -424,16 +436,18 @@ smp_boot_all_cpus(kernel_args *ka) apic_write(APIC_ICR1, config); // wait for pending to end - while ((apic_read(APIC_ICR1) & 0x00001000) == 0x00001000); + while ((apic_read(APIC_ICR1) & 0x00001000) == 0x00001000) + ; /* deassert INIT */ config = (apic_read(APIC_ICR2) & 0x00ffffff) | (ka->arch_args.cpu_apic_id[i] << 24); apic_write(APIC_ICR2, config); config = (apic_read(APIC_ICR1) & 0xfff00000) | 0x00008500; + apic_write(APIC_ICR1, config); // wait for pending to end - while ((apic_read(APIC_ICR1) & 0x00001000) == 0x00001000); -// dprintf("0x%x\n", apic_read(APIC_ICR1)); + while ((apic_read(APIC_ICR1) & 0x00001000) == 0x00001000) + ; /* wait 10ms */ sleep(10000); @@ -456,7 +470,8 @@ smp_boot_all_cpus(kernel_args *ka) /* wait */ sleep(200); - while ((apic_read(APIC_ICR1)& 0x00001000) == 0x00001000); + while ((apic_read(APIC_ICR1)& 0x00001000) == 0x00001000) + ; } } @@ -467,9 +482,9 @@ smp_boot_all_cpus(kernel_args *ka) static void calculate_apic_timer_conversion_factor(kernel_args *ka) { - long long t1, t2; - unsigned int config; - unsigned int count; + int64 t1, t2; + uint32 config; + uint32 count; // setup the timer config = apic_read(APIC_LVTT); @@ -489,14 +504,14 @@ calculate_apic_timer_conversion_factor(kernel_args *ka) count = 0xffffffff - count; - ka->arch_args.apic_time_cv_factor = (unsigned int)((1000000.0/(t2 - t1)) * count); + ka->arch_args.apic_time_cv_factor = (uint32)((1000000.0/(t2 - t1)) * count); - dprintf("APIC ticks/sec = %d\n", ka->arch_args.apic_time_cv_factor); + TRACE(("APIC ticks/sec = %d\n", ka->arch_args.apic_time_cv_factor)); } int -smp_boot(kernel_args *ka, unsigned int kernel_entry) +smp_boot(kernel_args *ka, uint32 kernel_entry) { // dprintf("smp_boot: entry\n"); @@ -504,23 +519,23 @@ smp_boot(kernel_args *ka, unsigned int kernel_entry) saved_ka = ka; if (smp_find_mp_config(ka) > 1) { -// dprintf("smp_boot: had found > 1 cpus\n"); -// dprintf("post config:\n"); -// dprintf("num_cpus = 0x%p\n", ka->num_cpus); -// dprintf("apic_phys = 0x%p\n", ka->arch_args.apic_phys); -// dprintf("ioapic_phys = 0x%p\n", ka->arch_args.ioapic_phys); + TRACE(("smp_boot: had found > 1 cpus\n")); + TRACE(("post config:\n")); + TRACE(("num_cpus = %ld\n", ka->num_cpus)); + TRACE(("apic_phys = %p\n", ka->arch_args.apic_phys)); + TRACE(("ioapic_phys = %p\n", ka->arch_args.ioapic_phys)); // map in the apic & ioapic map_page(ka, ka->arch_args.apic_phys, ka->virt_alloc_range[0].start + ka->virt_alloc_range[0].size); - ka->arch_args.apic = (unsigned int *)(ka->virt_alloc_range[0].start + ka->virt_alloc_range[0].size); + ka->arch_args.apic = (uint32 *)(ka->virt_alloc_range[0].start + ka->virt_alloc_range[0].size); ka->virt_alloc_range[0].size += PAGE_SIZE; map_page(ka, ka->arch_args.ioapic_phys, ka->virt_alloc_range[0].start + ka->virt_alloc_range[0].size); - ka->arch_args.ioapic = (unsigned int *)(ka->virt_alloc_range[0].start + ka->virt_alloc_range[0].size); + ka->arch_args.ioapic = (uint32 *)(ka->virt_alloc_range[0].start + ka->virt_alloc_range[0].size); ka->virt_alloc_range[0].size += PAGE_SIZE; -// dprintf("apic = 0x%p\n", ka->arch_args.apic); -// dprintf("ioapic = 0x%p\n", ka->arch_args.ioapic); + TRACE(("apic = %p\n", ka->arch_args.apic)); + TRACE(("ioapic = %p\n", ka->arch_args.ioapic)); // set up the apic smp_setup_apic(ka); @@ -528,12 +543,12 @@ smp_boot(kernel_args *ka, unsigned int kernel_entry) // calculate how fast the apic timer is calculate_apic_timer_conversion_factor(ka); -// dprintf("trampolining other cpus\n"); + TRACE(("trampolining other cpus\n")); smp_boot_all_cpus(ka); -// dprintf("done trampolining\n"); + TRACE(("done trampolining\n")); } -// dprintf("smp_boot: exit\n"); + TRACE(("smp_boot: exit\n")); return 0; }