Commit e0fd87812f411342d88ada38a8b1d674c40b8173

Authored by bellard
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;
... ...