Changeset a26ddd1 in mainline for arch/ia32/src/smp/smp.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/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.