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