Subversion Repositories HelenOS-historic

Rev

Rev 125 | Rev 131 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 125 Rev 128
Line 26... Line 26...
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
#ifdef __SMP__
29
#ifdef __SMP__
30
 
30
 
31
#include <arch/pm.h>
-
 
32
#include <config.h>
31
#include <config.h>
33
#include <print.h>
32
#include <print.h>
34
#include <panic.h>
33
#include <debug.h>
35
#include <arch/smp/mps.h>
34
#include <arch/smp/mps.h>
36
#include <arch/smp/ap.h>
-
 
37
#include <arch/smp/apic.h>
35
#include <arch/smp/apic.h>
-
 
36
#include <arch/smp/smp.h>
38
#include <func.h>
37
#include <func.h>
39
#include <arch/types.h>
38
#include <arch/types.h>
40
#include <typedefs.h>
39
#include <typedefs.h>
41
#include <synch/waitq.h>
-
 
42
#include <time/delay.h>
-
 
43
#include <mm/heap.h>
-
 
44
#include <mm/page.h>
40
#include <mm/page.h>
45
#include <mm/frame.h>
-
 
46
#include <cpu.h>
41
#include <cpu.h>
47
#include <arch/i8259.h>
-
 
48
#include <arch/asm.h>
42
#include <arch/asm.h>
49
#include <arch/bios/bios.h>
43
#include <arch/bios/bios.h>
50
#include <arch/acpi/madt.h>
-
 
51
 
44
 
52
/*
45
/*
53
 * MultiProcessor Specification detection code.
46
 * MultiProcessor Specification detection code.
54
 */
47
 */
55
 
48
 
Line 86... Line 79...
86
int l_intr_entry_cnt = 0;
79
int l_intr_entry_cnt = 0;
87
 
80
 
88
waitq_t ap_completion_wq;
81
waitq_t ap_completion_wq;
89
waitq_t kmp_completion_wq;
82
waitq_t kmp_completion_wq;
90
 
83
 
-
 
84
 
-
 
85
/*
-
 
86
 * Implementation of IA-32 SMP configuration interface.
-
 
87
 */
-
 
88
static count_t get_cpu_count(void);
-
 
89
static bool is_cpu_enabled(index_t i);
-
 
90
static bool is_bsp(index_t i);
-
 
91
static __u8 get_cpu_apic_id(index_t i);
-
 
92
 
-
 
93
struct 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
 
-
 
100
count_t get_cpu_count(void)
-
 
101
{
-
 
102
    return processor_entry_cnt;
-
 
103
}
-
 
104
 
-
 
105
bool is_cpu_enabled(index_t i)
-
 
106
{
-
 
107
    ASSERT(i < processor_entry_cnt);
-
 
108
    return processor_entries[i].cpu_flags & 0x1;
-
 
109
}
-
 
110
 
-
 
111
bool 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
 
-
 
123
 
91
/*
124
/*
92
 * Used to check the integrity of the MP Floating Structure.
125
 * Used to check the integrity of the MP Floating Structure.
93
 */
126
 */
94
int mps_fs_check(__u8 *base)
127
int mps_fs_check(__u8 *base)
95
{
128
{
Line 390... Line 423...
390
                break;
423
                break;
391
        }
424
        }
392
    }
425
    }
393
}
426
}
394
 
427
 
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
 
-
 
490
int mps_irq_to_pin(int irq)
428
int mps_irq_to_pin(int irq)
491
{
429
{
492
    int i;
430
    int i;
493
   
431
   
494
    for(i=0;i<io_intr_entry_cnt;i++) {
432
    for(i=0;i<io_intr_entry_cnt;i++) {