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; | ... | ... |