Changeset a26ddd1 in mainline for arch/ia32/src/smp/mps.c


Ignore:
Timestamp:
2005-07-18T12:37:11Z (20 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
232e3ec7
Parents:
6b7c36f
Message:

Create IA-32 interface for bringing SMP up.
This interface hides differences between ACPI MADT and MPS configuration tables.
Provide MPS implementation thereof.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • arch/ia32/src/smp/mps.c

    r6b7c36f ra26ddd1  
    2929#ifdef __SMP__
    3030
    31 #include <arch/pm.h>
    3231#include <config.h>
    3332#include <print.h>
    34 #include <panic.h>
     33#include <debug.h>
    3534#include <arch/smp/mps.h>
    36 #include <arch/smp/ap.h>
    3735#include <arch/smp/apic.h>
     36#include <arch/smp/smp.h>
    3837#include <func.h>
    3938#include <arch/types.h>
    4039#include <typedefs.h>
    41 #include <synch/waitq.h>
    42 #include <time/delay.h>
    43 #include <mm/heap.h>
    4440#include <mm/page.h>
    45 #include <mm/frame.h>
    4641#include <cpu.h>
    47 #include <arch/i8259.h>
    4842#include <arch/asm.h>
    4943#include <arch/bios/bios.h>
    50 #include <arch/acpi/madt.h>
    5144
    5245/*
     
    8881waitq_t ap_completion_wq;
    8982waitq_t kmp_completion_wq;
     83
     84
     85/*
     86 * Implementation of IA-32 SMP configuration interface.
     87 */
     88static count_t get_cpu_count(void);
     89static bool is_cpu_enabled(index_t i);
     90static bool is_bsp(index_t i);
     91static __u8 get_cpu_apic_id(index_t i);
     92
     93struct smp_config_operations mps_config_operations = {
     94        .cpu_count = get_cpu_count,
     95        .cpu_enabled = is_cpu_enabled,
     96        .cpu_bootstrap = is_bsp,
     97        .cpu_apic_id = get_cpu_apic_id
     98};
     99
     100count_t get_cpu_count(void)
     101{
     102        return processor_entry_cnt;
     103}
     104
     105bool is_cpu_enabled(index_t i)
     106{
     107        ASSERT(i < processor_entry_cnt);
     108        return processor_entries[i].cpu_flags & 0x1;
     109}
     110
     111bool is_bsp(index_t i)
     112{
     113        ASSERT(i < processor_entry_cnt);
     114        return processor_entries[i].cpu_flags & 0x2;
     115}
     116
     117__u8 get_cpu_apic_id(index_t i)
     118{
     119        ASSERT(i < processor_entry_cnt);
     120        return processor_entries[i].l_apic_id;
     121}
     122
    90123
    91124/*
     
    393426}
    394427
    395 
    396 /*
    397  * Kernel thread for bringing up application processors. It becomes clear
    398  * that we need an arrangement like this (AP's being initialized by a kernel
    399  * thread), for a thread has its dedicated stack. (The stack used during the
    400  * BSP initialization (prior the very first call to scheduler()) will be used
    401  * as an initialization stack for each AP.)
    402  */
    403 void kmp(void *arg)
    404 {
    405         struct __processor_entry *pr;
    406         __address src, dst;
    407         int i;
    408 
    409         waitq_initialize(&ap_completion_wq);
    410 
    411         /*
    412          * Processor entries immediately follow the configuration table header.
    413          */
    414         pr = processor_entries;
    415 
    416         /*
    417          * We need to access data in frame 0.
    418          * We boldly make use of kernel address space mapping.
    419          */
    420 
    421         /*
    422          * Set the warm-reset vector to the real-mode address of 4K-aligned ap_boot()
    423          */
    424         *((__u16 *) (PA2KA(0x467+0))) =  ((__address) ap_boot) >> 4;    /* segment */
    425         *((__u16 *) (PA2KA(0x467+2))) =  0;                             /* offset */
    426        
    427         /*
    428          * Save 0xa to address 0xf of the CMOS RAM.
    429          * BIOS will not do the POST after the INIT signal.
    430          */
    431         outb(0x70,0xf);
    432         outb(0x71,0xa);
    433 
    434         cpu_priority_high();
    435 
    436         pic_disable_irqs(0xffff);
    437         apic_init();
    438 
    439         for (i = 0; i < processor_entry_cnt; i++) {
    440                 struct descriptor *gdt_new;
    441        
    442                 /*
    443                  * Skip processors marked unusable.
    444                  */
    445                 if (pr[i].cpu_flags & (1<<0) == 0)
    446                         continue;
    447 
    448                 /*
    449                  * The bootstrap processor is already up.
    450                  */
    451                 if (pr[i].cpu_flags & (1<<1))
    452                         continue;
    453 
    454                 if (pr[i].l_apic_id == l_apic_id()) {
    455                         printf("%L: bad processor entry #%d, will not send IPI to myself\n", &pr[i], i);
    456                         continue;
    457                 }
    458                
    459                 /*
    460                  * Prepare new GDT for CPU in question.
    461                  */
    462                 if (!(gdt_new = (struct descriptor *) malloc(GDT_ITEMS*sizeof(struct descriptor))))
    463                         panic("couldn't allocate memory for GDT\n");
    464 
    465                 memcopy(gdt, gdt_new, GDT_ITEMS*sizeof(struct descriptor));
    466                 memsetb(&gdt_new[TSS_DES], sizeof(struct descriptor), 0);
    467                 gdtr.base = KA2PA((__address) gdt_new);
    468 
    469                 if (l_apic_send_init_ipi(pr[i].l_apic_id)) {
    470                         /*
    471                          * There may be just one AP being initialized at
    472                          * the time. After it comes completely up, it is
    473                          * supposed to wake us up.
    474                          */
    475                         waitq_sleep(&ap_completion_wq);
    476                         cpu_priority_high();
    477                 }
    478                 else {
    479                         printf("INIT IPI for l_apic%d failed\n", pr[i].l_apic_id);
    480                 }
    481         }
    482 
    483         /*
    484          * Wakeup the kinit thread so that
    485          * system initialization can go on.
    486          */
    487         waitq_wakeup(&kmp_completion_wq, WAKEUP_FIRST);
    488 }
    489 
    490428int mps_irq_to_pin(int irq)
    491429{
Note: See TracChangeset for help on using the changeset viewer.