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,7 +121,8 @@ static void apic_bus_deliver(uint32_t deliver_bitmask, uint8_t delivery_mode, | ||
| 121 | /* normal INIT IPI sent to processors */ | 121 | /* normal INIT IPI sent to processors */ |
| 122 | for (apic_iter = first_local_apic; apic_iter != NULL; | 122 | for (apic_iter = first_local_apic; apic_iter != NULL; |
| 123 | apic_iter = apic_iter->next_apic) { | 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 | return; | 127 | return; |
| 127 | 128 | ||
| @@ -317,7 +318,7 @@ static void apic_init_ipi(APICState *s) | @@ -317,7 +318,7 @@ static void apic_init_ipi(APICState *s) | ||
| 317 | s->tpr = 0; | 318 | s->tpr = 0; |
| 318 | s->spurious_vec = 0xff; | 319 | s->spurious_vec = 0xff; |
| 319 | s->log_dest = 0; | 320 | s->log_dest = 0; |
| 320 | - s->dest_mode = 0; | 321 | + s->dest_mode = 0xf; |
| 321 | memset(s->isr, 0, sizeof(s->isr)); | 322 | memset(s->isr, 0, sizeof(s->isr)); |
| 322 | memset(s->tmr, 0, sizeof(s->tmr)); | 323 | memset(s->tmr, 0, sizeof(s->tmr)); |
| 323 | memset(s->irr, 0, sizeof(s->irr)); | 324 | memset(s->irr, 0, sizeof(s->irr)); |
| @@ -331,6 +332,18 @@ static void apic_init_ipi(APICState *s) | @@ -331,6 +332,18 @@ static void apic_init_ipi(APICState *s) | ||
| 331 | s->next_time = 0; | 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 | static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode, | 347 | static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode, |
| 335 | uint8_t delivery_mode, uint8_t vector_num, | 348 | uint8_t delivery_mode, uint8_t vector_num, |
| 336 | uint8_t polarity, uint8_t trigger_mode) | 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,10 +352,26 @@ static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode, | ||
| 339 | int dest_shorthand = (s->icr[0] >> 18) & 3; | 352 | int dest_shorthand = (s->icr[0] >> 18) & 3; |
| 340 | APICState *apic_iter; | 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 | switch (delivery_mode) { | 370 | switch (delivery_mode) { |
| 343 | case APIC_DM_LOWPRI: | 371 | case APIC_DM_LOWPRI: |
| 344 | - /* XXX: serch for focus processor, arbitration */ | 372 | + /* XXX: search for focus processor, arbitration */ |
| 345 | dest = s->id; | 373 | dest = s->id; |
| 374 | + break; | ||
| 346 | 375 | ||
| 347 | case APIC_DM_INIT: | 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,28 +393,12 @@ static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode, | ||
| 364 | for (apic_iter = first_local_apic; apic_iter != NULL; | 393 | for (apic_iter = first_local_apic; apic_iter != NULL; |
| 365 | apic_iter = apic_iter->next_apic) { | 394 | apic_iter = apic_iter->next_apic) { |
| 366 | if (deliver_bitmask & (1 << apic_iter->id)) { | 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 | return; | 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 | apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity, | 402 | apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity, |
| 390 | trigger_mode); | 403 | trigger_mode); |
| 391 | } | 404 | } |
| @@ -534,13 +547,13 @@ static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr) | @@ -534,13 +547,13 @@ static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr) | ||
| 534 | case 0x28: | 547 | case 0x28: |
| 535 | val = s->esr; | 548 | val = s->esr; |
| 536 | break; | 549 | break; |
| 537 | - case 0x32 ... 0x37: | ||
| 538 | - val = s->lvt[index - 0x32]; | ||
| 539 | - break; | ||
| 540 | case 0x30: | 550 | case 0x30: |
| 541 | case 0x31: | 551 | case 0x31: |
| 542 | val = s->icr[index & 1]; | 552 | val = s->icr[index & 1]; |
| 543 | break; | 553 | break; |
| 554 | + case 0x32 ... 0x37: | ||
| 555 | + val = s->lvt[index - 0x32]; | ||
| 556 | + break; | ||
| 544 | case 0x38: | 557 | case 0x38: |
| 545 | val = s->initial_count; | 558 | val = s->initial_count; |
| 546 | break; | 559 | break; |
| @@ -581,10 +594,15 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) | @@ -581,10 +594,15 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) | ||
| 581 | case 0x02: | 594 | case 0x02: |
| 582 | s->id = (val >> 24); | 595 | s->id = (val >> 24); |
| 583 | break; | 596 | break; |
| 597 | + case 0x03: | ||
| 598 | + break; | ||
| 584 | case 0x08: | 599 | case 0x08: |
| 585 | s->tpr = val; | 600 | s->tpr = val; |
| 586 | apic_update_irq(s); | 601 | apic_update_irq(s); |
| 587 | break; | 602 | break; |
| 603 | + case 0x09: | ||
| 604 | + case 0x0a: | ||
| 605 | + break; | ||
| 588 | case 0x0b: /* EOI */ | 606 | case 0x0b: /* EOI */ |
| 589 | apic_eoi(s); | 607 | apic_eoi(s); |
| 590 | break; | 608 | break; |
| @@ -598,6 +616,11 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) | @@ -598,6 +616,11 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) | ||
| 598 | s->spurious_vec = val & 0x1ff; | 616 | s->spurious_vec = val & 0x1ff; |
| 599 | apic_update_irq(s); | 617 | apic_update_irq(s); |
| 600 | break; | 618 | break; |
| 619 | + case 0x10 ... 0x17: | ||
| 620 | + case 0x18 ... 0x1f: | ||
| 621 | + case 0x20 ... 0x27: | ||
| 622 | + case 0x28: | ||
| 623 | + break; | ||
| 601 | case 0x30: | 624 | case 0x30: |
| 602 | s->icr[0] = val; | 625 | s->icr[0] = val; |
| 603 | apic_deliver(s, (s->icr[1] >> 24) & 0xff, (s->icr[0] >> 11) & 1, | 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,6 +643,8 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) | ||
| 620 | s->initial_count_load_time = qemu_get_clock(vm_clock); | 643 | s->initial_count_load_time = qemu_get_clock(vm_clock); |
| 621 | apic_timer_update(s, s->initial_count_load_time); | 644 | apic_timer_update(s, s->initial_count_load_time); |
| 622 | break; | 645 | break; |
| 646 | + case 0x39: | ||
| 647 | + break; | ||
| 623 | case 0x3e: | 648 | case 0x3e: |
| 624 | { | 649 | { |
| 625 | int v; | 650 | int v; |