CR8 support
[qemu] / hw / apic.c
1 /*
2  *  APIC support
3  * 
4  *  Copyright (c) 2004-2005 Fabrice Bellard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include "vl.h"
21
22 //#define DEBUG_APIC
23
24 /* APIC Local Vector Table */
25 #define APIC_LVT_TIMER   0
26 #define APIC_LVT_THERMAL 1
27 #define APIC_LVT_PERFORM 2
28 #define APIC_LVT_LINT0   3
29 #define APIC_LVT_LINT1   4
30 #define APIC_LVT_ERROR   5
31 #define APIC_LVT_NB      6
32
33 /* APIC delivery modes */
34 #define APIC_DM_FIXED   0
35 #define APIC_DM_LOWPRI  1
36 #define APIC_DM_SMI     2
37 #define APIC_DM_NMI     4
38 #define APIC_DM_INIT    5
39 #define APIC_DM_SIPI    6
40 #define APIC_DM_EXTINT  7
41
42 #define APIC_TRIGGER_EDGE  0
43 #define APIC_TRIGGER_LEVEL 1
44
45 #define APIC_LVT_TIMER_PERIODIC         (1<<17)
46 #define APIC_LVT_MASKED                 (1<<16)
47 #define APIC_LVT_LEVEL_TRIGGER          (1<<15)
48 #define APIC_LVT_REMOTE_IRR             (1<<14)
49 #define APIC_INPUT_POLARITY             (1<<13)
50 #define APIC_SEND_PENDING               (1<<12)
51
52 #define ESR_ILLEGAL_ADDRESS (1 << 7)
53
54 #define APIC_SV_ENABLE (1 << 8)
55
56 typedef struct APICState {
57     CPUState *cpu_env;
58     uint32_t apicbase;
59     uint8_t id;
60     uint8_t tpr;
61     uint32_t spurious_vec;
62     uint32_t isr[8];  /* in service register */
63     uint32_t tmr[8];  /* trigger mode register */
64     uint32_t irr[8]; /* interrupt request register */
65     uint32_t lvt[APIC_LVT_NB];
66     uint32_t esr; /* error register */
67     uint32_t icr[2];
68
69     uint32_t divide_conf;
70     int count_shift;
71     uint32_t initial_count;
72     int64_t initial_count_load_time, next_time;
73     QEMUTimer *timer;
74 } APICState;
75
76 static int apic_io_memory;
77
78 void cpu_set_apic_base(CPUState *env, uint64_t val)
79 {
80     APICState *s = env->apic_state;
81 #ifdef DEBUG_APIC
82     printf("cpu_set_apic_base: %016llx\n", val);
83 #endif
84     s->apicbase = (val & 0xfffff000) | 
85         (s->apicbase & (MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE));
86     /* if disabled, cannot be enabled again */
87     if (!(val & MSR_IA32_APICBASE_ENABLE)) {
88         s->apicbase &= ~MSR_IA32_APICBASE_ENABLE;
89         env->cpuid_features &= ~CPUID_APIC;
90         s->spurious_vec &= ~APIC_SV_ENABLE;
91     }
92 }
93
94 uint64_t cpu_get_apic_base(CPUState *env)
95 {
96     APICState *s = env->apic_state;
97 #ifdef DEBUG_APIC
98     printf("cpu_get_apic_base: %016llx\n", (uint64_t)s->apicbase);
99 #endif
100     return s->apicbase;
101 }
102
103 void cpu_set_apic_tpr(CPUX86State *env, uint8_t val)
104 {
105     APICState *s = env->apic_state;
106     s->tpr = (val & 0x0f) << 4;
107 }
108
109 uint8_t cpu_get_apic_tpr(CPUX86State *env)
110 {
111     APICState *s = env->apic_state;
112     return s->tpr >> 4;
113 }
114
115 /* return -1 if no bit is set */
116 static int get_highest_priority_int(uint32_t *tab)
117 {
118     int i;
119     for(i = 0;i < 8; i++) {
120         if (tab[i] != 0) {
121             return i * 32 + ffs(tab[i]) - 1;
122         }
123     }
124     return -1;
125 }
126
127 static inline void set_bit(uint32_t *tab, int index)
128 {
129     int i, mask;
130     i = index >> 5;
131     mask = 1 << (index & 0x1f);
132     tab[i] |= mask;
133 }
134
135 static inline void reset_bit(uint32_t *tab, int index)
136 {
137     int i, mask;
138     i = index >> 5;
139     mask = 1 << (index & 0x1f);
140     tab[i] &= ~mask;
141 }
142
143 static int apic_get_ppr(APICState *s)
144 {
145     int tpr, isrv, ppr;
146
147     tpr = (s->tpr >> 4);
148     isrv = get_highest_priority_int(s->isr);
149     if (isrv < 0)
150         isrv = 0;
151     isrv >>= 4;
152     if (tpr >= isrv)
153         ppr = s->tpr;
154     else
155         ppr = isrv << 4;
156     return ppr;
157 }
158
159 /* signal the CPU if an irq is pending */
160 static void apic_update_irq(APICState *s)
161 {
162     int irrv, isrv;
163     irrv = get_highest_priority_int(s->irr);
164     if (irrv < 0)
165         return;
166     isrv = get_highest_priority_int(s->isr);
167     /* if the pending irq has less priority, we do not make a new request */
168     if (isrv >= 0 && irrv >= isrv)
169         return;
170     cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
171 }
172
173 static void apic_set_irq(APICState *s, int vector_num, int trigger_mode)
174 {
175     set_bit(s->irr, vector_num);
176     if (trigger_mode)
177         set_bit(s->tmr, vector_num);
178     else
179         reset_bit(s->tmr, vector_num);
180     apic_update_irq(s);
181 }
182
183 static void apic_eoi(APICState *s)
184 {
185     int isrv;
186     isrv = get_highest_priority_int(s->isr);
187     if (isrv < 0)
188         return;
189     reset_bit(s->isr, isrv);
190     apic_update_irq(s);
191 }
192
193 int apic_get_interrupt(CPUState *env)
194 {
195     APICState *s = env->apic_state;
196     int intno;
197
198     /* if the APIC is installed or enabled, we let the 8259 handle the
199        IRQs */
200     if (!s)
201         return -1;
202     if (!(s->spurious_vec & APIC_SV_ENABLE))
203         return -1;
204     
205     /* XXX: spurious IRQ handling */
206     intno = get_highest_priority_int(s->irr);
207     if (intno < 0)
208         return -1;
209     reset_bit(s->irr, intno);
210     set_bit(s->isr, intno);
211     apic_update_irq(s);
212     return intno;
213 }
214
215 static uint32_t apic_get_current_count(APICState *s)
216 {
217     int64_t d;
218     uint32_t val;
219     d = (qemu_get_clock(vm_clock) - s->initial_count_load_time) >> 
220         s->count_shift;
221     if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
222         /* periodic */
223         val = s->initial_count - (d % (s->initial_count + 1));
224     } else {
225         if (d >= s->initial_count)
226             val = 0;
227         else
228             val = s->initial_count - d;
229     }
230     return val;
231 }
232
233 static void apic_timer_update(APICState *s, int64_t current_time)
234 {
235     int64_t next_time, d;
236     
237     if (!(s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)) {
238         d = (current_time - s->initial_count_load_time) >> 
239             s->count_shift;
240         if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
241             d = ((d / (s->initial_count + 1)) + 1) * (s->initial_count + 1);
242         } else {
243             if (d >= s->initial_count)
244                 goto no_timer;
245             d = s->initial_count + 1;
246         }
247         next_time = s->initial_count_load_time + (d << s->count_shift);
248         qemu_mod_timer(s->timer, next_time);
249         s->next_time = next_time;
250     } else {
251     no_timer:
252         qemu_del_timer(s->timer);
253     }
254 }
255
256 static void apic_timer(void *opaque)
257 {
258     APICState *s = opaque;
259
260     if (!(s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)) {
261         apic_set_irq(s, s->lvt[APIC_LVT_TIMER] & 0xff, APIC_TRIGGER_EDGE);
262     }
263     apic_timer_update(s, s->next_time);
264 }
265
266 static uint32_t apic_mem_readb(void *opaque, target_phys_addr_t addr)
267 {
268     return 0;
269 }
270
271 static uint32_t apic_mem_readw(void *opaque, target_phys_addr_t addr)
272 {
273     return 0;
274 }
275
276 static void apic_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
277 {
278 }
279
280 static void apic_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
281 {
282 }
283
284 static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr)
285 {
286     CPUState *env;
287     APICState *s;
288     uint32_t val;
289     int index;
290
291     env = cpu_single_env;
292     if (!env)
293         return 0;
294     s = env->apic_state;
295
296     index = (addr >> 4) & 0xff;
297     switch(index) {
298     case 0x02: /* id */
299         val = s->id << 24;
300         break;
301     case 0x03: /* version */
302         val = 0x11 | ((APIC_LVT_NB - 1) << 16); /* version 0x11 */
303         break;
304     case 0x08:
305         val = s->tpr;
306         break;
307     case 0x0a:
308         /* ppr */
309         val = apic_get_ppr(s);
310         break;
311     case 0x0f:
312         val = s->spurious_vec;
313         break;
314     case 0x10 ... 0x17:
315         val = s->isr[index & 7];
316         break;
317     case 0x18 ... 0x1f:
318         val = s->tmr[index & 7];
319         break;
320     case 0x20 ... 0x27:
321         val = s->irr[index & 7];
322         break;
323     case 0x28:
324         val = s->esr;
325         break;
326     case 0x32 ... 0x37:
327         val = s->lvt[index - 0x32];
328         break;
329     case 0x30:
330     case 0x31:
331         val = s->icr[index & 1];
332         break;
333     case 0x38:
334         val = s->initial_count;
335         break;
336     case 0x39:
337         val = apic_get_current_count(s);
338         break;
339     case 0x3e:
340         val = s->divide_conf;
341         break;
342     default:
343         s->esr |= ESR_ILLEGAL_ADDRESS;
344         val = 0;
345         break;
346     }
347 #ifdef DEBUG_APIC
348     printf("APIC read: %08x = %08x\n", (uint32_t)addr, val);
349 #endif
350     return val;
351 }
352
353 static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
354 {
355     CPUState *env;
356     APICState *s;
357     int index;
358
359     env = cpu_single_env;
360     if (!env)
361         return;
362     s = env->apic_state;
363
364 #ifdef DEBUG_APIC
365     printf("APIC write: %08x = %08x\n", (uint32_t)addr, val);
366 #endif
367
368     index = (addr >> 4) & 0xff;
369     switch(index) {
370     case 0x02:
371         s->id = (val >> 24);
372         break;
373     case 0x08:
374         s->tpr = val;
375         break;
376     case 0x0b: /* EOI */
377         apic_eoi(s);
378         break;
379     case 0x0f:
380         s->spurious_vec = val & 0x1ff;
381         break;
382     case 0x30:
383     case 0x31:
384         s->icr[index & 1] = val;
385         break;
386     case 0x32 ... 0x37:
387         {
388             int n = index - 0x32;
389             s->lvt[n] = val;
390             if (n == APIC_LVT_TIMER)
391                 apic_timer_update(s, qemu_get_clock(vm_clock));
392         }
393         break;
394     case 0x38:
395         s->initial_count = val;
396         s->initial_count_load_time = qemu_get_clock(vm_clock);
397         apic_timer_update(s, s->initial_count_load_time);
398         break;
399     case 0x3e:
400         {
401             int v;
402             s->divide_conf = val & 0xb;
403             v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4);
404             s->count_shift = (v + 1) & 7;
405         }
406         break;
407     default:
408         s->esr |= ESR_ILLEGAL_ADDRESS;
409         break;
410     }
411 }
412
413
414
415 static CPUReadMemoryFunc *apic_mem_read[3] = {
416     apic_mem_readb,
417     apic_mem_readw,
418     apic_mem_readl,
419 };
420
421 static CPUWriteMemoryFunc *apic_mem_write[3] = {
422     apic_mem_writeb,
423     apic_mem_writew,
424     apic_mem_writel,
425 };
426
427 int apic_init(CPUState *env)
428 {
429     APICState *s;
430     int i;
431
432     s = malloc(sizeof(APICState));
433     if (!s)
434         return -1;
435     memset(s, 0, sizeof(*s));
436     env->apic_state = s;
437     s->cpu_env = env;
438     s->apicbase = 0xfee00000 | 
439         MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE;
440     for(i = 0; i < APIC_LVT_NB; i++)
441         s->lvt[i] = 1 << 16; /* mask LVT */
442     s->spurious_vec = 0xff;
443
444     if (apic_io_memory == 0) {
445         /* NOTE: the APIC is directly connected to the CPU - it is not
446            on the global memory bus. */
447         apic_io_memory = cpu_register_io_memory(0, apic_mem_read, 
448                                                 apic_mem_write, NULL);
449         cpu_register_physical_memory(s->apicbase & ~0xfff, 0x1000, apic_io_memory);
450     }
451     s->timer = qemu_new_timer(vm_clock, apic_timer, s);
452     return 0;
453 }