Subversion Repositories HelenOS-historic

Rev

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

Rev 513 Rev 514
Line 60... Line 60...
60
volatile __u32 *l_apic = (__u32 *) 0xfee00000;
60
volatile __u32 *l_apic = (__u32 *) 0xfee00000;
61
volatile __u32 *io_apic = (__u32 *) 0xfec00000;
61
volatile __u32 *io_apic = (__u32 *) 0xfec00000;
62
 
62
 
63
__u32 apic_id_mask = 0;
63
__u32 apic_id_mask = 0;
64
 
64
 
65
int apic_poll_errors(void);
65
static int apic_poll_errors(void);
-
 
66
 
-
 
67
static char *delmod_str[] = {
-
 
68
    "Fixed",
-
 
69
    "Lowest Priority",
-
 
70
    "SMI",
-
 
71
    "Reserved",
-
 
72
    "NMI",
-
 
73
    "INIT",
-
 
74
    "STARTUP",
-
 
75
    "ExtInt"
-
 
76
};
-
 
77
 
-
 
78
static char *destmod_str[] = {
-
 
79
    "Physical",
-
 
80
    "Logical"
-
 
81
};
-
 
82
 
-
 
83
static char *trigmod_str[] = {
-
 
84
    "Edge",
-
 
85
    "Level"
-
 
86
};
-
 
87
 
-
 
88
static char *mask_str[] = {
-
 
89
    "Unmasked",
-
 
90
    "Masked"
-
 
91
};
-
 
92
 
-
 
93
static char *delivs_str[] = {
-
 
94
    "Idle",
-
 
95
    "Send Pending"
-
 
96
};
-
 
97
 
-
 
98
static char *tm_mode_str[] = {
-
 
99
    "One-shot",
-
 
100
    "Periodic"
-
 
101
};
-
 
102
 
-
 
103
static char *intpol_str[] = {
-
 
104
    "Polarity High",
-
 
105
    "Polarity Low"
-
 
106
};
66
 
107
 
67
/** Initialize APIC on BSP. */
108
/** Initialize APIC on BSP. */
68
void apic_init(void)
109
void apic_init(void)
69
{
110
{
70
    __u32 tmp, id, i;
111
    __u32 tmp, id, i;
Line 112... Line 153...
112
     */
153
     */
113
    l_apic_init();
154
    l_apic_init();
114
    l_apic_debug();
155
    l_apic_debug();
115
}
156
}
116
 
157
 
-
 
158
/** APIC spurious interrupt handler.
-
 
159
 *
-
 
160
 * @param n Interrupt vector.
-
 
161
 * @param stack Interrupted stack.
-
 
162
 */
117
void apic_spurious(__u8 n, __native stack[])
163
void apic_spurious(__u8 n, __native stack[])
118
{
164
{
119
    printf("cpu%d: APIC spurious interrupt\n", CPU->id);
165
    printf("cpu%d: APIC spurious interrupt\n", CPU->id);
120
}
166
}
121
 
167
 
-
 
168
/** Poll for APIC errors.
-
 
169
 *
-
 
170
 * Examine Error Status Register and report all errors found.
-
 
171
 *
-
 
172
 * @return 0 on error, 1 on success.
-
 
173
 */
122
int apic_poll_errors(void)
174
int apic_poll_errors(void)
123
{
175
{
124
    __u32 esr;
176
    esr_t esr;
125
   
177
   
126
    esr = l_apic[ESR] & ~ESRClear;
178
    esr.value = l_apic[ESR];
127
   
179
   
128
    if ((esr>>0) & 1)
180
    if (esr.send_checksum_error)
129
        printf("Send CS Error\n");
181
        printf("Send CS Error\n");
130
    if ((esr>>1) & 1)
182
    if (esr.receive_checksum_error)
131
        printf("Receive CS Error\n");
183
        printf("Receive CS Error\n");
132
    if ((esr>>2) & 1)
184
    if (esr.send_accept_error)
133
        printf("Send Accept Error\n");
185
        printf("Send Accept Error\n");
134
    if ((esr>>3) & 1)
186
    if (esr.receive_accept_error)
135
        printf("Receive Accept Error\n");
187
        printf("Receive Accept Error\n");
136
    if ((esr>>5) & 1)
188
    if (esr.send_illegal_vector)
137
        printf("Send Illegal Vector\n");
189
        printf("Send Illegal Vector\n");
138
    if ((esr>>6) & 1)
190
    if (esr.received_illegal_vector)
139
        printf("Received Illegal Vector\n");
191
        printf("Received Illegal Vector\n");
140
    if ((esr>>7) & 1)
192
    if (esr.illegal_register_address)
141
        printf("Illegal Register Address\n");
193
        printf("Illegal Register Address\n");
142
 
194
 
143
    return !esr;
195
    return !esr.err_bitmap;
144
}
196
}
145
 
197
 
-
 
198
/** Send all CPUs excluding CPU IPI vector.
-
 
199
 *
-
 
200
 * @param vector Interrupt vector to be sent.
146
/*
201
 *
147
 * Send all CPUs excluding CPU IPI vector.
202
 * @return 0 on failure, 1 on success.
148
 */
203
 */
149
int l_apic_broadcast_custom_ipi(__u8 vector)
204
int l_apic_broadcast_custom_ipi(__u8 vector)
150
{
205
{
151
    icr_t icr;
206
    icr_t icr;
152
 
207
 
Line 165... Line 220...
165
        printf("IPI is pending.\n");
220
        printf("IPI is pending.\n");
166
 
221
 
167
    return apic_poll_errors();
222
    return apic_poll_errors();
168
}
223
}
169
 
224
 
-
 
225
/** Universal Start-up Algorithm for bringing up the AP processors.
170
/*
226
 *
171
 * Universal Start-up Algorithm for bringing up the AP processors.
227
 * @param apicid APIC ID of the processor to be brought up.
-
 
228
 *
-
 
229
 * @return 0 on failure, 1 on success.
172
 */
230
 */
173
int l_apic_send_init_ipi(__u8 apicid)
231
int l_apic_send_init_ipi(__u8 apicid)
174
{
232
{
175
    icr_t icr;
233
    icr_t icr;
176
    int i;
234
    int i;
Line 236... Line 294...
236
   
294
   
237
   
295
   
238
    return apic_poll_errors();
296
    return apic_poll_errors();
239
}
297
}
240
 
298
 
-
 
299
/** Initialize Local APIC. */
241
void l_apic_init(void)
300
void l_apic_init(void)
242
{
301
{
243
    lvt_error_t error;
302
    lvt_error_t error;
244
    lvt_lint_t lint;
303
    lvt_lint_t lint;
245
    svr_t svr;
304
    svr_t svr;
246
    lvt_tm_t tm;
-
 
247
    icr_t icr;
305
    icr_t icr;
-
 
306
    tdcr_t tdcr;
-
 
307
    lvt_tm_t tm;
248
    __u32 t1, t2;
308
    __u32 t1, t2;
249
 
309
 
250
    /* Initialize LVT Error register. */
310
    /* Initialize LVT Error register. */
251
    error.value = l_apic[LVT_Err];
311
    error.value = l_apic[LVT_Err];
252
    error.masked = true;
312
    error.masked = true;
Line 280... Line 340...
280
    icr.level = LEVEL_DEASSERT;
340
    icr.level = LEVEL_DEASSERT;
281
    icr.shorthand = SHORTHAND_ALL_INCL;
341
    icr.shorthand = SHORTHAND_ALL_INCL;
282
    icr.trigger_mode = TRIGMOD_LEVEL;
342
    icr.trigger_mode = TRIGMOD_LEVEL;
283
    l_apic[ICRlo] = icr.lo;
343
    l_apic[ICRlo] = icr.lo;
284
   
344
   
285
    /*
-
 
286
     * Program the timer for periodic mode and respective vector.
345
    /* Timer Divide Configuration Register initialization. */
287
     */
346
    tdcr.value = l_apic[TDCR];
288
 
-
 
289
    l_apic[TDCR] &= TDCRClear;
347
    tdcr.div_value = DIVIDE_1;
290
    l_apic[TDCR] |= 0xb;
348
    l_apic[TDCR] = tdcr.value;
291
 
349
 
-
 
350
    /* Program local timer. */
292
    tm.value = l_apic[LVT_Tm];
351
    tm.value = l_apic[LVT_Tm];
293
    tm.vector = VECTOR_CLK;
352
    tm.vector = VECTOR_CLK;
294
    tm.mode = TIMER_PERIODIC;
353
    tm.mode = TIMER_PERIODIC;
295
    tm.masked = false;
354
    tm.masked = false;
296
    l_apic[LVT_Tm] = tm.value;
355
    l_apic[LVT_Tm] = tm.value;
297
 
356
 
-
 
357
    /* Measure and configure the timer to generate timer interrupt each ms. */
298
    t1 = l_apic[CCRT];
358
    t1 = l_apic[CCRT];
299
    l_apic[ICRT] = 0xffffffff;
359
    l_apic[ICRT] = 0xffffffff;
300
 
360
 
301
    while (l_apic[CCRT] == t1)
361
    while (l_apic[CCRT] == t1)
302
        ;
362
        ;
Line 307... Line 367...
307
   
367
   
308
    l_apic[ICRT] = t1-t2;
368
    l_apic[ICRT] = t1-t2;
309
   
369
   
310
}
370
}
311
 
371
 
-
 
372
/** Local APIC End of Interrupt. */
312
void l_apic_eoi(void)
373
void l_apic_eoi(void)
313
{
374
{
314
    l_apic[EOI] = 0;
375
    l_apic[EOI] = 0;
315
}
376
}
316
 
377
 
-
 
378
/** Dump content of Local APIC registers. */
317
void l_apic_debug(void)
379
void l_apic_debug(void)
318
{
380
{
319
#ifdef LAPIC_VERBOSE
381
#ifdef LAPIC_VERBOSE
-
 
382
    lvt_tm_t tm;
320
    int i, lint;
383
    lvt_lint_t lint;
-
 
384
    lvt_error_t error; 
321
 
385
   
322
    printf("LVT on cpu%d, LAPIC ID: %d\n", CPU->id, l_apic_id());
386
    printf("LVT on cpu%d, LAPIC ID: %d\n", CPU->id, l_apic_id());
323
 
387
 
324
    printf("LVT_Tm: ");
388
    tm.value = l_apic[LVT_Tm];
325
    if (l_apic[LVT_Tm] & (1<<17)) printf("periodic"); else printf("one-shot"); putchar(',');   
-
 
326
    if (l_apic[LVT_Tm] & (1<<16)) printf("masked"); else printf("not masked"); putchar(',');
389
    printf("LVT Tm: vector=%B, %s, %s, %s\n", tm.vector, delivs_str[tm.delivs], mask_str[tm.masked], tm_mode_str[tm.mode]);
327
    if (l_apic[LVT_Tm] & (1<<12)) printf("send pending"); else printf("idle"); putchar(',');
-
 
328
    printf("%B\n", l_apic[LVT_Tm] & 0xff);
-
 
329
   
-
 
330
    for (i=0; i<2; i++) {
-
 
331
        lint = i ? LVT_LINT1 : LVT_LINT0;
390
    lint.value = l_apic[LVT_LINT0];
332
        printf("LVT_LINT%d: ", i);
-
 
333
        if (l_apic[lint] & (1<<16)) printf("masked"); else printf("not masked"); putchar(',');
391
    printf("LVT LINT0: vector=%B, %s, %s, %s, irr=%d, %s, %s\n", tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs], intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode], mask_str[lint.masked]);
334
        if (l_apic[lint] & (1<<15)) printf("level"); else printf("edge"); putchar(',');
-
 
335
        printf("%d", l_apic[lint] & (1<<14)); putchar(',');
-
 
336
        printf("%d", l_apic[lint] & (1<<13)); putchar(',');
-
 
337
        if (l_apic[lint] & (1<<12)) printf("send pending"); else printf("idle"); putchar(',');
-
 
338
   
-
 
339
        switch ((l_apic[lint]>>8)&7) {
-
 
340
            case 0: printf("fixed"); break;
-
 
341
            case 4: printf("NMI"); break;
-
 
342
            case 7: printf("ExtINT"); break;
-
 
343
        }
-
 
344
        putchar(',');
-
 
345
        printf("%B\n", l_apic[lint] & 0xff);   
392
    lint.value = l_apic[LVT_LINT1];
346
    }
-
 
347
 
-
 
348
    printf("LVT_Err: ");
-
 
349
    if (l_apic[LVT_Err] & (1<<16)) printf("masked"); else printf("not masked"); putchar(',');
393
    printf("LVT LINT1: vector=%B, %s, %s, %s, irr=%d, %s, %s\n", tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs], intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode], mask_str[lint.masked]);   
350
    if (l_apic[LVT_Err] & (1<<12)) printf("send pending"); else printf("idle"); putchar(',');
-
 
351
    printf("%B\n", l_apic[LVT_Err] & 0xff);
394
    error.value = l_apic[LVT_Err];
352
 
-
 
353
    /*
-
 
354
     * This register is supported only on P6 and higher.
-
 
355
     */
-
 
356
    if (CPU->arch.family > 5) {
-
 
357
        printf("LVT_PCINT: ");
-
 
358
        if (l_apic[LVT_PCINT] & (1<<16)) printf("masked"); else printf("not masked"); putchar(',');
395
    printf("LVT Err: vector=%B, %s, %s\n", error.vector, delivs_str[error.delivs], mask_str[error.masked]);
359
        if (l_apic[LVT_PCINT] & (1<<12)) printf("send pending"); else printf("idle"); putchar(',');
-
 
360
        switch ((l_apic[LVT_PCINT] >> 8)&7) {
-
 
361
            case 0: printf("fixed"); break;
-
 
362
            case 4: printf("NMI"); break;
-
 
363
            case 7: printf("ExtINT"); break;
-
 
364
        }
-
 
365
        putchar(',');
-
 
366
        printf("%B\n", l_apic[LVT_PCINT] & 0xff);
-
 
367
    }
-
 
368
#endif
396
#endif
369
}
397
}
370
 
398
 
-
 
399
/** Local APIC Timer Interrupt.
-
 
400
 *
-
 
401
 * @param n Interrupt vector number.
-
 
402
 * @param stack Interrupted stack.
-
 
403
 */
371
void l_apic_timer_interrupt(__u8 n, __native stack[])
404
void l_apic_timer_interrupt(__u8 n, __native stack[])
372
{
405
{
373
    l_apic_eoi();
406
    l_apic_eoi();
374
    clock();
407
    clock();
375
}
408
}
376
 
409
 
-
 
410
/** Get Local APIC ID.
-
 
411
 *
-
 
412
 * @return Local APIC ID.
-
 
413
 */
377
__u8 l_apic_id(void)
414
__u8 l_apic_id(void)
378
{
415
{
-
 
416
    lapic_id_t lapic_id;
-
 
417
   
379
    return (l_apic[L_APIC_ID] >> L_APIC_IDShift)&L_APIC_IDMask;
418
    lapic_id.value = l_apic[L_APIC_ID];
-
 
419
    return lapic_id.apic_id;
380
}
420
}
381
 
421
 
-
 
422
/** Read from IO APIC register.
-
 
423
 *
-
 
424
 * @param address IO APIC register address.
-
 
425
 *
-
 
426
 * @return Content of the addressed IO APIC register.
-
 
427
 */
382
__u32 io_apic_read(__u8 address)
428
__u32 io_apic_read(__u8 address)
383
{
429
{
384
    __u32 tmp;
430
    io_regsel_t regsel;
385
   
431
   
386
    tmp = io_apic[IOREGSEL] & ~0xf;
432
    regsel.value = io_apic[IOREGSEL];
-
 
433
    regsel.reg_addr = address;
387
    io_apic[IOREGSEL] = tmp | address;
434
    io_apic[IOREGSEL] = regsel.value;
388
    return io_apic[IOWIN];
435
    return io_apic[IOWIN];
389
}
436
}
390
 
437
 
-
 
438
/** Write to IO APIC register.
-
 
439
 *
-
 
440
 * @param address IO APIC register address.
-
 
441
 * @param Content to be written to the addressed IO APIC register.
-
 
442
 */
391
void io_apic_write(__u8 address, __u32 x)
443
void io_apic_write(__u8 address, __u32 x)
392
{
444
{
393
    __u32 tmp;
445
    io_regsel_t regsel;
394
 
446
   
395
    tmp = io_apic[IOREGSEL] & ~0xf;
447
    regsel.value = io_apic[IOREGSEL];
-
 
448
    regsel.reg_addr = address;
396
    io_apic[IOREGSEL] = tmp | address;
449
    io_apic[IOREGSEL] = regsel.value;
397
    io_apic[IOWIN] = x;
450
    io_apic[IOWIN] = x;
398
}
451
}
399
 
452
 
-
 
453
/** Change some attributes of one item in I/O Redirection Table.
-
 
454
 *
-
 
455
 * @param pin IO APIC pin number.
-
 
456
 * @param dest Interrupt destination address.
-
 
457
 * @param v Interrupt vector to trigger.
-
 
458
 * @param flags Flags.
-
 
459
 */
400
void io_apic_change_ioredtbl(int signal, int dest, __u8 v, int flags)
460
void io_apic_change_ioredtbl(int pin, int dest, __u8 v, int flags)
401
{
461
{
402
    io_redirection_reg_t reg;
462
    io_redirection_reg_t reg;
403
    int dlvr = 0;
463
    int dlvr = DELMOD_FIXED;
404
   
464
   
405
    if (flags & LOPRI)
465
    if (flags & LOPRI)
406
        dlvr = DELMOD_LOWPRI;
466
        dlvr = DELMOD_LOWPRI;
407
 
467
 
408
   
468
   
409
    reg.lo = io_apic_read(IOREDTBL + signal*2);
469
    reg.lo = io_apic_read(IOREDTBL + pin*2);
410
    reg.hi = io_apic_read(IOREDTBL + signal*2 + 1);
470
    reg.hi = io_apic_read(IOREDTBL + pin*2 + 1);
411
   
471
   
412
    reg.dest =  dest;
472
    reg.dest =  dest;
413
    reg.destmod = DESTMOD_LOGIC;
473
    reg.destmod = DESTMOD_LOGIC;
414
    reg.trigger_mode = TRIGMOD_EDGE;
474
    reg.trigger_mode = TRIGMOD_EDGE;
415
    reg.intpol = POLARITY_HIGH;
475
    reg.intpol = POLARITY_HIGH;
416
    reg.delmod = dlvr;
476
    reg.delmod = dlvr;
417
    reg.intvec = v;
477
    reg.intvec = v;
418
 
478
 
419
    io_apic_write(IOREDTBL + signal*2, reg.lo);
479
    io_apic_write(IOREDTBL + pin*2, reg.lo);
420
    io_apic_write(IOREDTBL + signal*2 + 1, reg.hi);
480
    io_apic_write(IOREDTBL + pin*2 + 1, reg.hi);
421
}
481
}
422
 
482
 
-
 
483
/** Mask IRQs in IO APIC.
-
 
484
 *
-
 
485
 * @param irqmask Bitmask of IRQs to be masked (0 = do not mask, 1 = mask).
-
 
486
 */
423
void io_apic_disable_irqs(__u16 irqmask)
487
void io_apic_disable_irqs(__u16 irqmask)
424
{
488
{
425
    io_redirection_reg_t reg;
489
    io_redirection_reg_t reg;
426
    int i, pin;
490
    int i, pin;
427
   
491
   
Line 440... Line 504...
440
           
504
           
441
        }
505
        }
442
    }
506
    }
443
}
507
}
444
 
508
 
-
 
509
/** Unmask IRQs in IO APIC.
-
 
510
 *
-
 
511
 * @param irqmask Bitmask of IRQs to be unmasked (0 = do not unmask, 1 = unmask).
-
 
512
 */
445
void io_apic_enable_irqs(__u16 irqmask)
513
void io_apic_enable_irqs(__u16 irqmask)
446
{
514
{
447
    int i, pin;
515
    int i, pin;
448
    io_redirection_reg_t reg;  
516
    io_redirection_reg_t reg;  
449
   
517