Commit d3e9db933f416c9f1c04df4834d36e2315952e42
1 parent
01dbbdf1
initial support for up to 255 CPUs
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1707 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
160 additions
and
100 deletions
hw/apic.c
@@ -60,6 +60,9 @@ | @@ -60,6 +60,9 @@ | ||
60 | 60 | ||
61 | #define APIC_SV_ENABLE (1 << 8) | 61 | #define APIC_SV_ENABLE (1 << 8) |
62 | 62 | ||
63 | +#define MAX_APICS 255 | ||
64 | +#define MAX_APIC_WORDS 8 | ||
65 | + | ||
63 | typedef struct APICState { | 66 | typedef struct APICState { |
64 | CPUState *cpu_env; | 67 | CPUState *cpu_env; |
65 | uint32_t apicbase; | 68 | uint32_t apicbase; |
@@ -81,8 +84,6 @@ typedef struct APICState { | @@ -81,8 +84,6 @@ typedef struct APICState { | ||
81 | uint32_t initial_count; | 84 | uint32_t initial_count; |
82 | int64_t initial_count_load_time, next_time; | 85 | int64_t initial_count_load_time, next_time; |
83 | QEMUTimer *timer; | 86 | QEMUTimer *timer; |
84 | - | ||
85 | - struct APICState *next_apic; | ||
86 | } APICState; | 87 | } APICState; |
87 | 88 | ||
88 | struct IOAPICState { | 89 | struct IOAPICState { |
@@ -94,14 +95,95 @@ struct IOAPICState { | @@ -94,14 +95,95 @@ struct IOAPICState { | ||
94 | }; | 95 | }; |
95 | 96 | ||
96 | static int apic_io_memory; | 97 | static int apic_io_memory; |
97 | -static APICState *first_local_apic = NULL; | 98 | +static APICState *local_apics[MAX_APICS + 1]; |
98 | static int last_apic_id = 0; | 99 | static int last_apic_id = 0; |
99 | 100 | ||
100 | static void apic_init_ipi(APICState *s); | 101 | static void apic_init_ipi(APICState *s); |
101 | static void apic_set_irq(APICState *s, int vector_num, int trigger_mode); | 102 | static void apic_set_irq(APICState *s, int vector_num, int trigger_mode); |
102 | static void apic_update_irq(APICState *s); | 103 | static void apic_update_irq(APICState *s); |
103 | 104 | ||
104 | -static void apic_bus_deliver(uint32_t deliver_bitmask, uint8_t delivery_mode, | 105 | +/* Find first bit starting from msb. Return 0 if value = 0 */ |
106 | +static int fls_bit(uint32_t value) | ||
107 | +{ | ||
108 | + unsigned int ret = 0; | ||
109 | + | ||
110 | +#if defined(HOST_I386) | ||
111 | + __asm__ __volatile__ ("bsr %1, %0\n" : "+r" (ret) : "rm" (value)); | ||
112 | + return ret; | ||
113 | +#else | ||
114 | + if (value > 0xffff) | ||
115 | + value >>= 16, ret = 16; | ||
116 | + if (value > 0xff) | ||
117 | + value >>= 8, ret += 8; | ||
118 | + if (value > 0xf) | ||
119 | + value >>= 4, ret += 4; | ||
120 | + if (value > 0x3) | ||
121 | + value >>= 2, ret += 2; | ||
122 | + return ret + (value >> 1); | ||
123 | +#endif | ||
124 | +} | ||
125 | + | ||
126 | +/* Find first bit starting from lsb. Return 0 if value = 0 */ | ||
127 | +static int ffs_bit(uint32_t value) | ||
128 | +{ | ||
129 | + unsigned int ret = 0; | ||
130 | + | ||
131 | +#if defined(HOST_I386) | ||
132 | + __asm__ __volatile__ ("bsf %1, %0\n" : "+r" (ret) : "rm" (value)); | ||
133 | + return ret; | ||
134 | +#else | ||
135 | + if (!value) | ||
136 | + return 0; | ||
137 | + if (!(value & 0xffff)) | ||
138 | + value >>= 16, ret = 16; | ||
139 | + if (!(value & 0xff)) | ||
140 | + value >>= 8, ret += 8; | ||
141 | + if (!(value & 0xf)) | ||
142 | + value >>= 4, ret += 4; | ||
143 | + if (!(value & 0x3)) | ||
144 | + value >>= 2, ret += 2; | ||
145 | + if (!(value & 0x1)) | ||
146 | + ret++; | ||
147 | + return ret; | ||
148 | +#endif | ||
149 | +} | ||
150 | + | ||
151 | +static inline void set_bit(uint32_t *tab, int index) | ||
152 | +{ | ||
153 | + int i, mask; | ||
154 | + i = index >> 5; | ||
155 | + mask = 1 << (index & 0x1f); | ||
156 | + tab[i] |= mask; | ||
157 | +} | ||
158 | + | ||
159 | +static inline void reset_bit(uint32_t *tab, int index) | ||
160 | +{ | ||
161 | + int i, mask; | ||
162 | + i = index >> 5; | ||
163 | + mask = 1 << (index & 0x1f); | ||
164 | + tab[i] &= ~mask; | ||
165 | +} | ||
166 | + | ||
167 | +#define foreach_apic(apic, deliver_bitmask, code) \ | ||
168 | +{\ | ||
169 | + int __i, __j, __mask;\ | ||
170 | + for(__i = 0; __i < MAX_APIC_WORDS; __i++) {\ | ||
171 | + __mask = deliver_bitmask[__i];\ | ||
172 | + if (__mask) {\ | ||
173 | + for(__j = 0; __j < 32; __j++) {\ | ||
174 | + if (__mask & (1 << __j)) {\ | ||
175 | + apic = local_apics[__i * 32 + __j];\ | ||
176 | + if (apic) {\ | ||
177 | + code;\ | ||
178 | + }\ | ||
179 | + }\ | ||
180 | + }\ | ||
181 | + }\ | ||
182 | + }\ | ||
183 | +} | ||
184 | + | ||
185 | +static void apic_bus_deliver(const uint32_t *deliver_bitmask, | ||
186 | + uint8_t delivery_mode, | ||
105 | uint8_t vector_num, uint8_t polarity, | 187 | uint8_t vector_num, uint8_t polarity, |
106 | uint8_t trigger_mode) | 188 | uint8_t trigger_mode) |
107 | { | 189 | { |
@@ -110,13 +192,23 @@ static void apic_bus_deliver(uint32_t deliver_bitmask, uint8_t delivery_mode, | @@ -110,13 +192,23 @@ static void apic_bus_deliver(uint32_t deliver_bitmask, uint8_t delivery_mode, | ||
110 | switch (delivery_mode) { | 192 | switch (delivery_mode) { |
111 | case APIC_DM_LOWPRI: | 193 | case APIC_DM_LOWPRI: |
112 | /* XXX: search for focus processor, arbitration */ | 194 | /* XXX: search for focus processor, arbitration */ |
113 | - if (deliver_bitmask) { | ||
114 | - uint32_t m = 1; | ||
115 | - while ((deliver_bitmask & m) == 0) | ||
116 | - m <<= 1; | ||
117 | - deliver_bitmask = m; | 195 | + { |
196 | + int i, d; | ||
197 | + d = -1; | ||
198 | + for(i = 0; i < MAX_APIC_WORDS; i++) { | ||
199 | + if (deliver_bitmask[i]) { | ||
200 | + d = i * 32 + ffs_bit(deliver_bitmask[i]); | ||
201 | + break; | ||
202 | + } | ||
203 | + } | ||
204 | + if (d >= 0) { | ||
205 | + apic_iter = local_apics[d]; | ||
206 | + if (apic_iter) { | ||
207 | + apic_set_irq(apic_iter, vector_num, trigger_mode); | ||
208 | + } | ||
209 | + } | ||
118 | } | 210 | } |
119 | - break; | 211 | + return; |
120 | 212 | ||
121 | case APIC_DM_FIXED: | 213 | case APIC_DM_FIXED: |
122 | break; | 214 | break; |
@@ -127,11 +219,8 @@ static void apic_bus_deliver(uint32_t deliver_bitmask, uint8_t delivery_mode, | @@ -127,11 +219,8 @@ static void apic_bus_deliver(uint32_t deliver_bitmask, uint8_t delivery_mode, | ||
127 | 219 | ||
128 | case APIC_DM_INIT: | 220 | case APIC_DM_INIT: |
129 | /* normal INIT IPI sent to processors */ | 221 | /* normal INIT IPI sent to processors */ |
130 | - for (apic_iter = first_local_apic; apic_iter != NULL; | ||
131 | - apic_iter = apic_iter->next_apic) { | ||
132 | - if (deliver_bitmask & (1 << apic_iter->id)) | ||
133 | - apic_init_ipi(apic_iter); | ||
134 | - } | 222 | + foreach_apic(apic_iter, deliver_bitmask, |
223 | + apic_init_ipi(apic_iter) ); | ||
135 | return; | 224 | return; |
136 | 225 | ||
137 | case APIC_DM_EXTINT: | 226 | case APIC_DM_EXTINT: |
@@ -142,11 +231,8 @@ static void apic_bus_deliver(uint32_t deliver_bitmask, uint8_t delivery_mode, | @@ -142,11 +231,8 @@ static void apic_bus_deliver(uint32_t deliver_bitmask, uint8_t delivery_mode, | ||
142 | return; | 231 | return; |
143 | } | 232 | } |
144 | 233 | ||
145 | - for (apic_iter = first_local_apic; apic_iter != NULL; | ||
146 | - apic_iter = apic_iter->next_apic) { | ||
147 | - if (deliver_bitmask & (1 << apic_iter->id)) | ||
148 | - apic_set_irq(apic_iter, vector_num, trigger_mode); | ||
149 | - } | 234 | + foreach_apic(apic_iter, deliver_bitmask, |
235 | + apic_set_irq(apic_iter, vector_num, trigger_mode) ); | ||
150 | } | 236 | } |
151 | 237 | ||
152 | void cpu_set_apic_base(CPUState *env, uint64_t val) | 238 | void cpu_set_apic_base(CPUState *env, uint64_t val) |
@@ -187,42 +273,6 @@ uint8_t cpu_get_apic_tpr(CPUX86State *env) | @@ -187,42 +273,6 @@ uint8_t cpu_get_apic_tpr(CPUX86State *env) | ||
187 | return s->tpr >> 4; | 273 | return s->tpr >> 4; |
188 | } | 274 | } |
189 | 275 | ||
190 | -static int fls_bit(int value) | ||
191 | -{ | ||
192 | - unsigned int ret = 0; | ||
193 | - | ||
194 | -#ifdef HOST_I386 | ||
195 | - __asm__ __volatile__ ("bsr %1, %0\n" : "+r" (ret) : "rm" (value)); | ||
196 | - return ret; | ||
197 | -#else | ||
198 | - if (value > 0xffff) | ||
199 | - value >>= 16, ret = 16; | ||
200 | - if (value > 0xff) | ||
201 | - value >>= 8, ret += 8; | ||
202 | - if (value > 0xf) | ||
203 | - value >>= 4, ret += 4; | ||
204 | - if (value > 0x3) | ||
205 | - value >>= 2, ret += 2; | ||
206 | - return ret + (value >> 1); | ||
207 | -#endif | ||
208 | -} | ||
209 | - | ||
210 | -static inline void set_bit(uint32_t *tab, int index) | ||
211 | -{ | ||
212 | - int i, mask; | ||
213 | - i = index >> 5; | ||
214 | - mask = 1 << (index & 0x1f); | ||
215 | - tab[i] |= mask; | ||
216 | -} | ||
217 | - | ||
218 | -static inline void reset_bit(uint32_t *tab, int index) | ||
219 | -{ | ||
220 | - int i, mask; | ||
221 | - i = index >> 5; | ||
222 | - mask = 1 << (index & 0x1f); | ||
223 | - tab[i] &= ~mask; | ||
224 | -} | ||
225 | - | ||
226 | /* return -1 if no bit is set */ | 276 | /* return -1 if no bit is set */ |
227 | static int get_highest_priority_int(uint32_t *tab) | 277 | static int get_highest_priority_int(uint32_t *tab) |
228 | { | 278 | { |
@@ -294,26 +344,37 @@ static void apic_eoi(APICState *s) | @@ -294,26 +344,37 @@ static void apic_eoi(APICState *s) | ||
294 | apic_update_irq(s); | 344 | apic_update_irq(s); |
295 | } | 345 | } |
296 | 346 | ||
297 | -static uint32_t apic_get_delivery_bitmask(uint8_t dest, uint8_t dest_mode) | 347 | +static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, |
348 | + uint8_t dest, uint8_t dest_mode) | ||
298 | { | 349 | { |
299 | - uint32_t mask = 0; | ||
300 | APICState *apic_iter; | 350 | APICState *apic_iter; |
351 | + int i; | ||
301 | 352 | ||
302 | if (dest_mode == 0) { | 353 | if (dest_mode == 0) { |
303 | - if (dest == 0xff) | ||
304 | - mask = 0xff; | ||
305 | - else | ||
306 | - mask = 1 << dest; | 354 | + if (dest == 0xff) { |
355 | + memset(deliver_bitmask, 0xff, MAX_APIC_WORDS * sizeof(uint32_t)); | ||
356 | + } else { | ||
357 | + memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t)); | ||
358 | + set_bit(deliver_bitmask, dest); | ||
359 | + } | ||
307 | } else { | 360 | } else { |
308 | /* XXX: cluster mode */ | 361 | /* XXX: cluster mode */ |
309 | - for (apic_iter = first_local_apic; apic_iter != NULL; | ||
310 | - apic_iter = apic_iter->next_apic) { | ||
311 | - if (dest & apic_iter->log_dest) | ||
312 | - mask |= (1 << apic_iter->id); | 362 | + memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t)); |
363 | + for(i = 0; i < MAX_APICS; i++) { | ||
364 | + apic_iter = local_apics[i]; | ||
365 | + if (apic_iter) { | ||
366 | + if (apic_iter->dest_mode == 0xf) { | ||
367 | + if (dest & apic_iter->log_dest) | ||
368 | + set_bit(deliver_bitmask, i); | ||
369 | + } else if (apic_iter->dest_mode == 0x0) { | ||
370 | + if ((dest & 0xf0) == (apic_iter->log_dest & 0xf0) && | ||
371 | + (dest & apic_iter->log_dest & 0x0f)) { | ||
372 | + set_bit(deliver_bitmask, i); | ||
373 | + } | ||
374 | + } | ||
375 | + } | ||
313 | } | 376 | } |
314 | } | 377 | } |
315 | - | ||
316 | - return mask; | ||
317 | } | 378 | } |
318 | 379 | ||
319 | 380 | ||
@@ -356,23 +417,25 @@ static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode, | @@ -356,23 +417,25 @@ static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode, | ||
356 | uint8_t delivery_mode, uint8_t vector_num, | 417 | uint8_t delivery_mode, uint8_t vector_num, |
357 | uint8_t polarity, uint8_t trigger_mode) | 418 | uint8_t polarity, uint8_t trigger_mode) |
358 | { | 419 | { |
359 | - uint32_t deliver_bitmask = 0; | 420 | + uint32_t deliver_bitmask[MAX_APIC_WORDS]; |
360 | int dest_shorthand = (s->icr[0] >> 18) & 3; | 421 | int dest_shorthand = (s->icr[0] >> 18) & 3; |
361 | APICState *apic_iter; | 422 | APICState *apic_iter; |
362 | 423 | ||
363 | switch (dest_shorthand) { | 424 | switch (dest_shorthand) { |
364 | - case 0: | ||
365 | - deliver_bitmask = apic_get_delivery_bitmask(dest, dest_mode); | ||
366 | - break; | ||
367 | - case 1: | ||
368 | - deliver_bitmask = (1 << s->id); | ||
369 | - break; | ||
370 | - case 2: | ||
371 | - deliver_bitmask = 0xffffffff; | ||
372 | - break; | ||
373 | - case 3: | ||
374 | - deliver_bitmask = 0xffffffff & ~(1 << s->id); | ||
375 | - break; | 425 | + case 0: |
426 | + apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode); | ||
427 | + break; | ||
428 | + case 1: | ||
429 | + memset(deliver_bitmask, 0x00, sizeof(deliver_bitmask)); | ||
430 | + set_bit(deliver_bitmask, s->id); | ||
431 | + break; | ||
432 | + case 2: | ||
433 | + memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask)); | ||
434 | + break; | ||
435 | + case 3: | ||
436 | + memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask)); | ||
437 | + reset_bit(deliver_bitmask, s->id); | ||
438 | + break; | ||
376 | } | 439 | } |
377 | 440 | ||
378 | switch (delivery_mode) { | 441 | switch (delivery_mode) { |
@@ -381,24 +444,16 @@ static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode, | @@ -381,24 +444,16 @@ static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode, | ||
381 | int trig_mode = (s->icr[0] >> 15) & 1; | 444 | int trig_mode = (s->icr[0] >> 15) & 1; |
382 | int level = (s->icr[0] >> 14) & 1; | 445 | int level = (s->icr[0] >> 14) & 1; |
383 | if (level == 0 && trig_mode == 1) { | 446 | if (level == 0 && trig_mode == 1) { |
384 | - for (apic_iter = first_local_apic; apic_iter != NULL; | ||
385 | - apic_iter = apic_iter->next_apic) { | ||
386 | - if (deliver_bitmask & (1 << apic_iter->id)) { | ||
387 | - apic_iter->arb_id = apic_iter->id; | ||
388 | - } | ||
389 | - } | 447 | + foreach_apic(apic_iter, deliver_bitmask, |
448 | + apic_iter->arb_id = apic_iter->id ); | ||
390 | return; | 449 | return; |
391 | } | 450 | } |
392 | } | 451 | } |
393 | break; | 452 | break; |
394 | 453 | ||
395 | case APIC_DM_SIPI: | 454 | case APIC_DM_SIPI: |
396 | - for (apic_iter = first_local_apic; apic_iter != NULL; | ||
397 | - apic_iter = apic_iter->next_apic) { | ||
398 | - if (deliver_bitmask & (1 << apic_iter->id)) { | ||
399 | - apic_startup(apic_iter, vector_num); | ||
400 | - } | ||
401 | - } | 455 | + foreach_apic(apic_iter, deliver_bitmask, |
456 | + apic_startup(apic_iter, vector_num) ); | ||
402 | return; | 457 | return; |
403 | } | 458 | } |
404 | 459 | ||
@@ -749,6 +804,8 @@ int apic_init(CPUState *env) | @@ -749,6 +804,8 @@ int apic_init(CPUState *env) | ||
749 | { | 804 | { |
750 | APICState *s; | 805 | APICState *s; |
751 | 806 | ||
807 | + if (last_apic_id >= MAX_APICS) | ||
808 | + return -1; | ||
752 | s = qemu_mallocz(sizeof(APICState)); | 809 | s = qemu_mallocz(sizeof(APICState)); |
753 | if (!s) | 810 | if (!s) |
754 | return -1; | 811 | return -1; |
@@ -772,10 +829,8 @@ int apic_init(CPUState *env) | @@ -772,10 +829,8 @@ int apic_init(CPUState *env) | ||
772 | 829 | ||
773 | register_savevm("apic", 0, 1, apic_save, apic_load, s); | 830 | register_savevm("apic", 0, 1, apic_save, apic_load, s); |
774 | qemu_register_reset(apic_reset, s); | 831 | qemu_register_reset(apic_reset, s); |
775 | - | ||
776 | - s->next_apic = first_local_apic; | ||
777 | - first_local_apic = s; | ||
778 | 832 | ||
833 | + local_apics[s->id] = s; | ||
779 | return 0; | 834 | return 0; |
780 | } | 835 | } |
781 | 836 | ||
@@ -790,6 +845,7 @@ static void ioapic_service(IOAPICState *s) | @@ -790,6 +845,7 @@ static void ioapic_service(IOAPICState *s) | ||
790 | uint8_t dest; | 845 | uint8_t dest; |
791 | uint8_t dest_mode; | 846 | uint8_t dest_mode; |
792 | uint8_t polarity; | 847 | uint8_t polarity; |
848 | + uint32_t deliver_bitmask[MAX_APIC_WORDS]; | ||
793 | 849 | ||
794 | for (i = 0; i < IOAPIC_NUM_PINS; i++) { | 850 | for (i = 0; i < IOAPIC_NUM_PINS; i++) { |
795 | mask = 1 << i; | 851 | mask = 1 << i; |
@@ -807,8 +863,10 @@ static void ioapic_service(IOAPICState *s) | @@ -807,8 +863,10 @@ static void ioapic_service(IOAPICState *s) | ||
807 | vector = pic_read_irq(isa_pic); | 863 | vector = pic_read_irq(isa_pic); |
808 | else | 864 | else |
809 | vector = entry & 0xff; | 865 | vector = entry & 0xff; |
810 | - apic_bus_deliver(apic_get_delivery_bitmask(dest, dest_mode), | ||
811 | - delivery_mode, vector, polarity, trig_mode); | 866 | + |
867 | + apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode); | ||
868 | + apic_bus_deliver(deliver_bitmask, delivery_mode, | ||
869 | + vector, polarity, trig_mode); | ||
812 | } | 870 | } |
813 | } | 871 | } |
814 | } | 872 | } |
vl.c
@@ -153,10 +153,12 @@ USBPort *vm_usb_ports[MAX_VM_USB_PORTS]; | @@ -153,10 +153,12 @@ USBPort *vm_usb_ports[MAX_VM_USB_PORTS]; | ||
153 | USBDevice *vm_usb_hub; | 153 | USBDevice *vm_usb_hub; |
154 | static VLANState *first_vlan; | 154 | static VLANState *first_vlan; |
155 | int smp_cpus = 1; | 155 | int smp_cpus = 1; |
156 | -#ifdef TARGET_SPARC | 156 | +#if defined(TARGET_SPARC) |
157 | #define MAX_CPUS 16 | 157 | #define MAX_CPUS 16 |
158 | +#elif defined(TARGET_I386) | ||
159 | +#define MAX_CPUS 255 | ||
158 | #else | 160 | #else |
159 | -#define MAX_CPUS 8 | 161 | +#define MAX_CPUS 1 |
160 | #endif | 162 | #endif |
161 | 163 | ||
162 | /***********************************************************/ | 164 | /***********************************************************/ |