Commit 678e12cc9054e8a9eafc43a5b4b65d335d6651d4

Authored by Gleb Natapov
Committed by Anthony Liguori
1 parent c4f31a0a

Don't use cpu_index as apic_id.

(patch is on top of "Apic creation should not depend on pci" series)

Currently cpu_index is used as cpu apic id on x86.  This is incorrect
since apic ids not have to be continuous (they can also encode cpu
hierarchy information). This patch uses cpuid_apic_id for initial apic id
value. For now cpuid_apic_id is set to be equal to cpu_index so behaviour
is fully backward compatible, but it allows us to add qemu option to
provide other values for cpu apic id.

Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Showing 3 changed files with 40 additions and 13 deletions
hw/apic.c
... ... @@ -83,12 +83,13 @@ typedef struct APICState {
83 83 int count_shift;
84 84 uint32_t initial_count;
85 85 int64_t initial_count_load_time, next_time;
  86 + uint32_t idx;
86 87 QEMUTimer *timer;
87 88 } APICState;
88 89  
89 90 static int apic_io_memory;
90 91 static APICState *local_apics[MAX_APICS + 1];
91   -static int last_apic_id = 0;
  92 +static int last_apic_idx = 0;
92 93 static int apic_irq_delivered;
93 94  
94 95  
... ... @@ -400,6 +401,23 @@ static void apic_eoi(APICState *s)
400 401 apic_update_irq(s);
401 402 }
402 403  
  404 +static int apic_find_dest(uint8_t dest)
  405 +{
  406 + APICState *apic = local_apics[dest];
  407 + int i;
  408 +
  409 + if (apic && apic->id == dest)
  410 + return dest; /* shortcut in case apic->id == apic->idx */
  411 +
  412 + for (i = 0; i < MAX_APICS; i++) {
  413 + apic = local_apics[i];
  414 + if (apic && apic->id == dest)
  415 + return i;
  416 + }
  417 +
  418 + return -1;
  419 +}
  420 +
403 421 static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
404 422 uint8_t dest, uint8_t dest_mode)
405 423 {
... ... @@ -410,8 +428,10 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
410 428 if (dest == 0xff) {
411 429 memset(deliver_bitmask, 0xff, MAX_APIC_WORDS * sizeof(uint32_t));
412 430 } else {
  431 + int idx = apic_find_dest(dest);
413 432 memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t));
414   - set_bit(deliver_bitmask, dest);
  433 + if (idx >= 0)
  434 + set_bit(deliver_bitmask, idx);
415 435 }
416 436 } else {
417 437 /* XXX: cluster mode */
... ... @@ -457,8 +477,7 @@ static void apic_init_ipi(APICState *s)
457 477  
458 478 cpu_reset(s->cpu_env);
459 479  
460   - if (!(s->apicbase & MSR_IA32_APICBASE_BSP))
461   - s->cpu_env->halted = 1;
  480 + s->cpu_env->halted = !(s->apicbase & MSR_IA32_APICBASE_BSP);
462 481 }
463 482  
464 483 /* send a SIPI message to the CPU to start it */
... ... @@ -487,14 +506,14 @@ static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode,
487 506 break;
488 507 case 1:
489 508 memset(deliver_bitmask, 0x00, sizeof(deliver_bitmask));
490   - set_bit(deliver_bitmask, s->id);
  509 + set_bit(deliver_bitmask, s->idx);
491 510 break;
492 511 case 2:
493 512 memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
494 513 break;
495 514 case 3:
496 515 memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
497   - reset_bit(deliver_bitmask, s->id);
  516 + reset_bit(deliver_bitmask, s->idx);
498 517 break;
499 518 }
500 519  
... ... @@ -870,13 +889,14 @@ static int apic_load(QEMUFile *f, void *opaque, int version_id)
870 889 static void apic_reset(void *opaque)
871 890 {
872 891 APICState *s = opaque;
  892 + int bsp = cpu_is_bsp(s->cpu_env);
873 893  
874 894 s->apicbase = 0xfee00000 |
875   - (s->id ? 0 : MSR_IA32_APICBASE_BSP) | MSR_IA32_APICBASE_ENABLE;
  895 + (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE;
876 896  
877 897 apic_init_ipi(s);
878 898  
879   - if (s->id == 0) {
  899 + if (bsp) {
880 900 /*
881 901 * LINT0 delivery mode on CPU #0 is set to ExtInt at initialization
882 902 * time typically by BIOS, so PIC interrupt can be delivered to the
... ... @@ -902,12 +922,12 @@ int apic_init(CPUState *env)
902 922 {
903 923 APICState *s;
904 924  
905   - if (last_apic_id >= MAX_APICS)
  925 + if (last_apic_idx >= MAX_APICS)
906 926 return -1;
907 927 s = qemu_mallocz(sizeof(APICState));
908 928 env->apic_state = s;
909   - s->id = last_apic_id++;
910   - env->cpuid_apic_id = s->id;
  929 + s->idx = last_apic_idx++;
  930 + s->id = env->cpuid_apic_id;
911 931 s->cpu_env = env;
912 932  
913 933 apic_reset(s);
... ... @@ -923,10 +943,10 @@ int apic_init(CPUState *env)
923 943 }
924 944 s->timer = qemu_new_timer(vm_clock, apic_timer, s);
925 945  
926   - register_savevm("apic", s->id, 2, apic_save, apic_load, s);
  946 + register_savevm("apic", s->idx, 2, apic_save, apic_load, s);
927 947 qemu_register_reset(apic_reset, 0, s);
928 948  
929   - local_apics[s->id] = s;
  949 + local_apics[s->idx] = s;
930 950 return 0;
931 951 }
932 952  
... ...
... ... @@ -830,6 +830,11 @@ static int load_option_rom(const char *oprom, target_phys_addr_t start,
830 830 return size;
831 831 }
832 832  
  833 +int cpu_is_bsp(CPUState *env)
  834 +{
  835 + return env->cpuid_apic_id == 0;
  836 +}
  837 +
833 838 /* PC hardware initialisation */
834 839 static void pc_init1(ram_addr_t ram_size,
835 840 const char *boot_device,
... ... @@ -877,6 +882,7 @@ static void pc_init1(ram_addr_t ram_size,
877 882 exit(1);
878 883 }
879 884 if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) {
  885 + env->cpuid_apic_id = env->cpu_index;
880 886 apic_init(env);
881 887 }
882 888 qemu_register_reset(main_cpu_reset, 0, env);
... ...
... ... @@ -162,4 +162,5 @@ void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
162 162  
163 163 void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd);
164 164  
  165 +int cpu_is_bsp(CPUState *env);
165 166 #endif
... ...