Subversion Repositories HelenOS

Rev

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

Rev 34 Rev 128
Line 25... Line 25...
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
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
#include <smp/smp.h>
29
#include <smp/smp.h>
-
 
30
#include <arch/smp/smp.h>
-
 
31
#include <arch/smp/mps.h>
-
 
32
#include <arch/smp/ap.h>
30
#include <arch/acpi/acpi.h>
33
#include <arch/acpi/acpi.h>
31
#include <arch/acpi/madt.h>
34
#include <arch/acpi/madt.h>
32
#include <arch/smp/mps.h>
-
 
33
#include <config.h>
35
#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>
34
 
45
 
35
#ifdef __SMP__
46
#ifdef __SMP__
36
 
47
 
-
 
48
static struct smp_config_operations *ops = NULL;
-
 
49
 
37
void smp_init(void)
50
void smp_init(void)
38
{
51
{
39
    if (acpi_madt) {
52
    if (acpi_madt) {
40
        acpi_madt_parse();
53
        acpi_madt_parse();
41
    }
54
    }
42
    if (config.cpu_count == 1)
55
    if (config.cpu_count == 1) {
43
        mps_init();
56
        mps_init();
-
 
57
        ops = &mps_config_operations;
-
 
58
    }
44
}
59
}
45
 
60
 
-
 
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
 */
-
 
68
void 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
}
46
 
150
 
47
#endif /* __SMP__ */
151
#endif /* __SMP__ */