Commit e0fd87812f411342d88ada38a8b1d674c40b8173
1 parent
6a00d601
APIC fixes - SIPI support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1641 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
48 additions
and
23 deletions
hw/apic.c
... | ... | @@ -121,7 +121,8 @@ static void apic_bus_deliver(uint32_t deliver_bitmask, uint8_t delivery_mode, |
121 | 121 | /* normal INIT IPI sent to processors */ |
122 | 122 | for (apic_iter = first_local_apic; apic_iter != NULL; |
123 | 123 | apic_iter = apic_iter->next_apic) { |
124 | - apic_init_ipi(apic_iter); | |
124 | + if (deliver_bitmask & (1 << apic_iter->id)) | |
125 | + apic_init_ipi(apic_iter); | |
125 | 126 | } |
126 | 127 | return; |
127 | 128 | |
... | ... | @@ -317,7 +318,7 @@ static void apic_init_ipi(APICState *s) |
317 | 318 | s->tpr = 0; |
318 | 319 | s->spurious_vec = 0xff; |
319 | 320 | s->log_dest = 0; |
320 | - s->dest_mode = 0; | |
321 | + s->dest_mode = 0xf; | |
321 | 322 | memset(s->isr, 0, sizeof(s->isr)); |
322 | 323 | memset(s->tmr, 0, sizeof(s->tmr)); |
323 | 324 | memset(s->irr, 0, sizeof(s->irr)); |
... | ... | @@ -331,6 +332,18 @@ static void apic_init_ipi(APICState *s) |
331 | 332 | s->next_time = 0; |
332 | 333 | } |
333 | 334 | |
335 | +/* send a SIPI message to the CPU to start it */ | |
336 | +static void apic_startup(APICState *s, int vector_num) | |
337 | +{ | |
338 | + CPUState *env = s->cpu_env; | |
339 | + if (!env->cpu_halted) | |
340 | + return; | |
341 | + env->eip = 0; | |
342 | + cpu_x86_load_seg_cache(env, R_CS, vector_num << 8, vector_num << 12, | |
343 | + 0xffff, 0); | |
344 | + env->cpu_halted = 0; | |
345 | +} | |
346 | + | |
334 | 347 | static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode, |
335 | 348 | uint8_t delivery_mode, uint8_t vector_num, |
336 | 349 | uint8_t polarity, uint8_t trigger_mode) |
... | ... | @@ -339,10 +352,26 @@ static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode, |
339 | 352 | int dest_shorthand = (s->icr[0] >> 18) & 3; |
340 | 353 | APICState *apic_iter; |
341 | 354 | |
355 | + switch (dest_shorthand) { | |
356 | + case 0: | |
357 | + deliver_bitmask = apic_get_delivery_bitmask(dest, dest_mode); | |
358 | + break; | |
359 | + case 1: | |
360 | + deliver_bitmask = (1 << s->id); | |
361 | + break; | |
362 | + case 2: | |
363 | + deliver_bitmask = 0xffffffff; | |
364 | + break; | |
365 | + case 3: | |
366 | + deliver_bitmask = 0xffffffff & ~(1 << s->id); | |
367 | + break; | |
368 | + } | |
369 | + | |
342 | 370 | switch (delivery_mode) { |
343 | 371 | case APIC_DM_LOWPRI: |
344 | - /* XXX: serch for focus processor, arbitration */ | |
372 | + /* XXX: search for focus processor, arbitration */ | |
345 | 373 | dest = s->id; |
374 | + break; | |
346 | 375 | |
347 | 376 | case APIC_DM_INIT: |
348 | 377 | { |
... | ... | @@ -364,28 +393,12 @@ static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode, |
364 | 393 | for (apic_iter = first_local_apic; apic_iter != NULL; |
365 | 394 | apic_iter = apic_iter->next_apic) { |
366 | 395 | if (deliver_bitmask & (1 << apic_iter->id)) { |
367 | - /* XXX: SMP support */ | |
368 | - /* apic_startup(apic_iter); */ | |
396 | + apic_startup(apic_iter, vector_num); | |
369 | 397 | } |
370 | 398 | } |
371 | 399 | return; |
372 | 400 | } |
373 | 401 | |
374 | - switch (dest_shorthand) { | |
375 | - case 0: | |
376 | - deliver_bitmask = apic_get_delivery_bitmask(dest, dest_mode); | |
377 | - break; | |
378 | - case 1: | |
379 | - deliver_bitmask = (1 << s->id); | |
380 | - break; | |
381 | - case 2: | |
382 | - deliver_bitmask = 0xffffffff; | |
383 | - break; | |
384 | - case 3: | |
385 | - deliver_bitmask = 0xffffffff & ~(1 << s->id); | |
386 | - break; | |
387 | - } | |
388 | - | |
389 | 402 | apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity, |
390 | 403 | trigger_mode); |
391 | 404 | } |
... | ... | @@ -534,13 +547,13 @@ static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr) |
534 | 547 | case 0x28: |
535 | 548 | val = s->esr; |
536 | 549 | break; |
537 | - case 0x32 ... 0x37: | |
538 | - val = s->lvt[index - 0x32]; | |
539 | - break; | |
540 | 550 | case 0x30: |
541 | 551 | case 0x31: |
542 | 552 | val = s->icr[index & 1]; |
543 | 553 | break; |
554 | + case 0x32 ... 0x37: | |
555 | + val = s->lvt[index - 0x32]; | |
556 | + break; | |
544 | 557 | case 0x38: |
545 | 558 | val = s->initial_count; |
546 | 559 | break; |
... | ... | @@ -581,10 +594,15 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) |
581 | 594 | case 0x02: |
582 | 595 | s->id = (val >> 24); |
583 | 596 | break; |
597 | + case 0x03: | |
598 | + break; | |
584 | 599 | case 0x08: |
585 | 600 | s->tpr = val; |
586 | 601 | apic_update_irq(s); |
587 | 602 | break; |
603 | + case 0x09: | |
604 | + case 0x0a: | |
605 | + break; | |
588 | 606 | case 0x0b: /* EOI */ |
589 | 607 | apic_eoi(s); |
590 | 608 | break; |
... | ... | @@ -598,6 +616,11 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) |
598 | 616 | s->spurious_vec = val & 0x1ff; |
599 | 617 | apic_update_irq(s); |
600 | 618 | break; |
619 | + case 0x10 ... 0x17: | |
620 | + case 0x18 ... 0x1f: | |
621 | + case 0x20 ... 0x27: | |
622 | + case 0x28: | |
623 | + break; | |
601 | 624 | case 0x30: |
602 | 625 | s->icr[0] = val; |
603 | 626 | apic_deliver(s, (s->icr[1] >> 24) & 0xff, (s->icr[0] >> 11) & 1, |
... | ... | @@ -620,6 +643,8 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) |
620 | 643 | s->initial_count_load_time = qemu_get_clock(vm_clock); |
621 | 644 | apic_timer_update(s, s->initial_count_load_time); |
622 | 645 | break; |
646 | + case 0x39: | |
647 | + break; | |
623 | 648 | case 0x3e: |
624 | 649 | { |
625 | 650 | int v; | ... | ... |