Revision e5ad936b hw/apic.c

b/hw/apic.c
35 35
#define MSI_ADDR_DEST_ID_SHIFT		12
36 36
#define	MSI_ADDR_DEST_ID_MASK		0x00ffff0
37 37

  
38
#define SYNC_FROM_VAPIC                 0x1
39
#define SYNC_TO_VAPIC                   0x2
40
#define SYNC_ISR_IRR_TO_VAPIC           0x4
41

  
38 42
static APICCommonState *local_apics[MAX_APICS + 1];
39 43

  
40 44
static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode);
......
78 82
    return !!(tab[i] & mask);
79 83
}
80 84

  
85
/* return -1 if no bit is set */
86
static int get_highest_priority_int(uint32_t *tab)
87
{
88
    int i;
89
    for (i = 7; i >= 0; i--) {
90
        if (tab[i] != 0) {
91
            return i * 32 + fls_bit(tab[i]);
92
        }
93
    }
94
    return -1;
95
}
96

  
97
static void apic_sync_vapic(APICCommonState *s, int sync_type)
98
{
99
    VAPICState vapic_state;
100
    size_t length;
101
    off_t start;
102
    int vector;
103

  
104
    if (!s->vapic_paddr) {
105
        return;
106
    }
107
    if (sync_type & SYNC_FROM_VAPIC) {
108
        cpu_physical_memory_rw(s->vapic_paddr, (void *)&vapic_state,
109
                               sizeof(vapic_state), 0);
110
        s->tpr = vapic_state.tpr;
111
    }
112
    if (sync_type & (SYNC_TO_VAPIC | SYNC_ISR_IRR_TO_VAPIC)) {
113
        start = offsetof(VAPICState, isr);
114
        length = offsetof(VAPICState, enabled) - offsetof(VAPICState, isr);
115

  
116
        if (sync_type & SYNC_TO_VAPIC) {
117
            assert(qemu_cpu_is_self(s->cpu_env));
118

  
119
            vapic_state.tpr = s->tpr;
120
            vapic_state.enabled = 1;
121
            start = 0;
122
            length = sizeof(VAPICState);
123
        }
124

  
125
        vector = get_highest_priority_int(s->isr);
126
        if (vector < 0) {
127
            vector = 0;
128
        }
129
        vapic_state.isr = vector & 0xf0;
130

  
131
        vapic_state.zero = 0;
132

  
133
        vector = get_highest_priority_int(s->irr);
134
        if (vector < 0) {
135
            vector = 0;
136
        }
137
        vapic_state.irr = vector & 0xff;
138

  
139
        cpu_physical_memory_write_rom(s->vapic_paddr + start,
140
                                      ((void *)&vapic_state) + start, length);
141
    }
142
}
143

  
144
static void apic_vapic_base_update(APICCommonState *s)
145
{
146
    apic_sync_vapic(s, SYNC_TO_VAPIC);
147
}
148

  
81 149
static void apic_local_deliver(APICCommonState *s, int vector)
82 150
{
83 151
    uint32_t lvt = s->lvt[vector];
......
239 307

  
240 308
static void apic_set_tpr(APICCommonState *s, uint8_t val)
241 309
{
242
    s->tpr = (val & 0x0f) << 4;
243
    apic_update_irq(s);
310
    /* Updates from cr8 are ignored while the VAPIC is active */
311
    if (!s->vapic_paddr) {
312
        s->tpr = val << 4;
313
        apic_update_irq(s);
314
    }
244 315
}
245 316

  
246
/* return -1 if no bit is set */
247
static int get_highest_priority_int(uint32_t *tab)
317
static uint8_t apic_get_tpr(APICCommonState *s)
248 318
{
249
    int i;
250
    for(i = 7; i >= 0; i--) {
251
        if (tab[i] != 0) {
252
            return i * 32 + fls_bit(tab[i]);
253
        }
254
    }
255
    return -1;
319
    apic_sync_vapic(s, SYNC_FROM_VAPIC);
320
    return s->tpr >> 4;
256 321
}
257 322

  
258 323
static int apic_get_ppr(APICCommonState *s)
......
312 377
    }
313 378
}
314 379

  
380
void apic_poll_irq(DeviceState *d)
381
{
382
    APICCommonState *s = APIC_COMMON(d);
383

  
384
    apic_sync_vapic(s, SYNC_FROM_VAPIC);
385
    apic_update_irq(s);
386
}
387

  
315 388
static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode)
316 389
{
317 390
    apic_report_irq_delivered(!get_bit(s->irr, vector_num));
......
321 394
        set_bit(s->tmr, vector_num);
322 395
    else
323 396
        reset_bit(s->tmr, vector_num);
397
    if (s->vapic_paddr) {
398
        apic_sync_vapic(s, SYNC_ISR_IRR_TO_VAPIC);
399
        /*
400
         * The vcpu thread needs to see the new IRR before we pull its current
401
         * TPR value. That way, if we miss a lowering of the TRP, the guest
402
         * has the chance to notice the new IRR and poll for IRQs on its own.
403
         */
404
        smp_wmb();
405
        apic_sync_vapic(s, SYNC_FROM_VAPIC);
406
    }
324 407
    apic_update_irq(s);
325 408
}
326 409

  
......
334 417
    if (!(s->spurious_vec & APIC_SV_DIRECTED_IO) && get_bit(s->tmr, isrv)) {
335 418
        ioapic_eoi_broadcast(isrv);
336 419
    }
420
    apic_sync_vapic(s, SYNC_FROM_VAPIC | SYNC_TO_VAPIC);
337 421
    apic_update_irq(s);
338 422
}
339 423

  
......
471 555
    if (!(s->spurious_vec & APIC_SV_ENABLE))
472 556
        return -1;
473 557

  
558
    apic_sync_vapic(s, SYNC_FROM_VAPIC);
474 559
    intno = apic_irq_pending(s);
475 560

  
476 561
    if (intno == 0) {
562
        apic_sync_vapic(s, SYNC_TO_VAPIC);
477 563
        return -1;
478 564
    } else if (intno < 0) {
565
        apic_sync_vapic(s, SYNC_TO_VAPIC);
479 566
        return s->spurious_vec & 0xff;
480 567
    }
481 568
    reset_bit(s->irr, intno);
482 569
    set_bit(s->isr, intno);
570
    apic_sync_vapic(s, SYNC_TO_VAPIC);
483 571
    apic_update_irq(s);
484 572
    return intno;
485 573
}
......
576 664
        val = 0x11 | ((APIC_LVT_NB - 1) << 16); /* version 0x11 */
577 665
        break;
578 666
    case 0x08:
667
        apic_sync_vapic(s, SYNC_FROM_VAPIC);
668
        if (apic_report_tpr_access) {
669
            cpu_report_tpr_access(s->cpu_env, TPR_ACCESS_READ);
670
        }
579 671
        val = s->tpr;
580 672
        break;
581 673
    case 0x09:
......
675 767
    case 0x03:
676 768
        break;
677 769
    case 0x08:
770
        if (apic_report_tpr_access) {
771
            cpu_report_tpr_access(s->cpu_env, TPR_ACCESS_WRITE);
772
        }
678 773
        s->tpr = val;
774
        apic_sync_vapic(s, SYNC_TO_VAPIC);
679 775
        apic_update_irq(s);
680 776
        break;
681 777
    case 0x09:
......
737 833
    }
738 834
}
739 835

  
836
static void apic_pre_save(APICCommonState *s)
837
{
838
    apic_sync_vapic(s, SYNC_FROM_VAPIC);
839
}
840

  
740 841
static void apic_post_load(APICCommonState *s)
741 842
{
742 843
    if (s->timer_expiry != -1) {
......
770 871
    k->init = apic_init;
771 872
    k->set_base = apic_set_base;
772 873
    k->set_tpr = apic_set_tpr;
874
    k->get_tpr = apic_get_tpr;
875
    k->vapic_base_update = apic_vapic_base_update;
773 876
    k->external_nmi = apic_external_nmi;
877
    k->pre_save = apic_pre_save;
774 878
    k->post_load = apic_post_load;
775 879
}
776 880

  

Also available in: Unified diff