Changeset a26ddd1 in mainline


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.

Location:
arch/ia32
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • arch/ia32/include/smp/mps.h

    r6b7c36f ra26ddd1  
    3434#include <synch/waitq.h>
    3535#include <config.h>
     36#include <arch/smp/smp.h>
    3637
    3738#define CT_EXT_ENTRY_TYPE               0
     
    118119extern waitq_t kmp_completion_wq;
    119120
     121extern struct smp_config_operations mps_config_operations;
     122
    120123extern int mps_irq_to_pin(int irq);
    121124
  • 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{
  • arch/ia32/src/smp/smp.c

    r6b7c36f ra26ddd1  
    2828
    2929#include <smp/smp.h>
     30#include <arch/smp/smp.h>
     31#include <arch/smp/mps.h>
     32#include <arch/smp/ap.h>
    3033#include <arch/acpi/acpi.h>
    3134#include <arch/acpi/madt.h>
    32 #include <arch/smp/mps.h>
    3335#include <config.h>
     36#include <synch/waitq.h>
     37#include <arch/pm.h>
     38#include <func.h>
     39#include <panic.h>
     40#include <debug.h>
     41#include <arch/asm.h>
     42#include <mm/frame.h>
     43#include <mm/page.h>
     44#include <mm/heap.h>
    3445
    3546#ifdef __SMP__
     47
     48static struct smp_config_operations *ops = NULL;
    3649
    3750void smp_init(void)
     
    4053                acpi_madt_parse();
    4154        }
    42         if (config.cpu_count == 1)
     55        if (config.cpu_count == 1) {
    4356                mps_init();
     57                ops = &mps_config_operations;
     58        }
    4459}
    4560
     61/*
     62 * Kernel thread for bringing up application processors. It becomes clear
     63 * that we need an arrangement like this (AP's being initialized by a kernel
     64 * thread), for a thread has its dedicated stack. (The stack used during the
     65 * BSP initialization (prior the very first call to scheduler()) will be used
     66 * as an initialization stack for each AP.)
     67 */
     68void kmp(void *arg)
     69{
     70        __address src, dst;
     71        int i;
     72
     73        ASSERT(ops != NULL);
     74
     75        waitq_initialize(&ap_completion_wq);
     76
     77        /*
     78         * We need to access data in frame 0.
     79         * We boldly make use of kernel address space mapping.
     80         */
     81
     82        /*
     83         * Set the warm-reset vector to the real-mode address of 4K-aligned ap_boot()
     84         */
     85        *((__u16 *) (PA2KA(0x467+0))) =  ((__address) ap_boot) >> 4;    /* segment */
     86        *((__u16 *) (PA2KA(0x467+2))) =  0;                             /* offset */
     87       
     88        /*
     89         * Save 0xa to address 0xf of the CMOS RAM.
     90         * BIOS will not do the POST after the INIT signal.
     91         */
     92        outb(0x70,0xf);
     93        outb(0x71,0xa);
     94
     95        cpu_priority_high();
     96
     97        pic_disable_irqs(0xffff);
     98        apic_init();
     99
     100        for (i = 0; i < ops->cpu_count(); i++) {
     101                struct descriptor *gdt_new;
     102       
     103                /*
     104                 * Skip processors marked unusable.
     105                 */
     106                if (!ops->cpu_enabled(i))
     107                        continue;
     108
     109                /*
     110                 * The bootstrap processor is already up.
     111                 */
     112                if (ops->cpu_bootstrap(i))
     113                        continue;
     114
     115                if (ops->cpu_apic_id(i) == l_apic_id()) {
     116                        printf("kmp: bad processor entry #%d, will not send IPI to myself\n", i);
     117                        continue;
     118                }
     119               
     120                /*
     121                 * Prepare new GDT for CPU in question.
     122                 */
     123                if (!(gdt_new = (struct descriptor *) malloc(GDT_ITEMS*sizeof(struct descriptor))))
     124                        panic("couldn't allocate memory for GDT\n");
     125
     126                memcopy(gdt, gdt_new, GDT_ITEMS*sizeof(struct descriptor));
     127                memsetb(&gdt_new[TSS_DES], sizeof(struct descriptor), 0);
     128                gdtr.base = KA2PA((__address) gdt_new);
     129
     130                if (l_apic_send_init_ipi(ops->cpu_apic_id(i))) {
     131                        /*
     132                         * There may be just one AP being initialized at
     133                         * the time. After it comes completely up, it is
     134                         * supposed to wake us up.
     135                         */
     136                        waitq_sleep(&ap_completion_wq);
     137                        cpu_priority_high();
     138                }
     139                else {
     140                        printf("INIT IPI for l_apic%d failed\n", ops->cpu_apic_id(i));
     141                }
     142        }
     143
     144        /*
     145         * Wakeup the kinit thread so that
     146         * system initialization can go on.
     147         */
     148        waitq_wakeup(&kmp_completion_wq, WAKEUP_FIRST);
     149}
    46150
    47151#endif /* __SMP__ */
Note: See TracChangeset for help on using the changeset viewer.