Annotation of qemu/hw/kvm/apic.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * KVM in-kernel APIC support
                      3:  *
                      4:  * Copyright (c) 2011 Siemens AG
                      5:  *
                      6:  * Authors:
                      7:  *  Jan Kiszka          <[email protected]>
                      8:  *
                      9:  * This work is licensed under the terms of the GNU GPL version 2.
                     10:  * See the COPYING file in the top-level directory.
                     11:  */
                     12: #include "hw/apic_internal.h"
                     13: #include "kvm.h"
                     14: 
                     15: static inline void kvm_apic_set_reg(struct kvm_lapic_state *kapic,
                     16:                                     int reg_id, uint32_t val)
                     17: {
                     18:     *((uint32_t *)(kapic->regs + (reg_id << 4))) = val;
                     19: }
                     20: 
                     21: static inline uint32_t kvm_apic_get_reg(struct kvm_lapic_state *kapic,
                     22:                                         int reg_id)
                     23: {
                     24:     return *((uint32_t *)(kapic->regs + (reg_id << 4)));
                     25: }
                     26: 
                     27: void kvm_put_apic_state(DeviceState *d, struct kvm_lapic_state *kapic)
                     28: {
                     29:     APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
                     30:     int i;
                     31: 
                     32:     memset(kapic, 0, sizeof(*kapic));
                     33:     kvm_apic_set_reg(kapic, 0x2, s->id << 24);
                     34:     kvm_apic_set_reg(kapic, 0x8, s->tpr);
                     35:     kvm_apic_set_reg(kapic, 0xd, s->log_dest << 24);
                     36:     kvm_apic_set_reg(kapic, 0xe, s->dest_mode << 28 | 0x0fffffff);
                     37:     kvm_apic_set_reg(kapic, 0xf, s->spurious_vec);
                     38:     for (i = 0; i < 8; i++) {
                     39:         kvm_apic_set_reg(kapic, 0x10 + i, s->isr[i]);
                     40:         kvm_apic_set_reg(kapic, 0x18 + i, s->tmr[i]);
                     41:         kvm_apic_set_reg(kapic, 0x20 + i, s->irr[i]);
                     42:     }
                     43:     kvm_apic_set_reg(kapic, 0x28, s->esr);
                     44:     kvm_apic_set_reg(kapic, 0x30, s->icr[0]);
                     45:     kvm_apic_set_reg(kapic, 0x31, s->icr[1]);
                     46:     for (i = 0; i < APIC_LVT_NB; i++) {
                     47:         kvm_apic_set_reg(kapic, 0x32 + i, s->lvt[i]);
                     48:     }
                     49:     kvm_apic_set_reg(kapic, 0x38, s->initial_count);
                     50:     kvm_apic_set_reg(kapic, 0x3e, s->divide_conf);
                     51: }
                     52: 
                     53: void kvm_get_apic_state(DeviceState *d, struct kvm_lapic_state *kapic)
                     54: {
                     55:     APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
                     56:     int i, v;
                     57: 
                     58:     s->id = kvm_apic_get_reg(kapic, 0x2) >> 24;
                     59:     s->tpr = kvm_apic_get_reg(kapic, 0x8);
                     60:     s->arb_id = kvm_apic_get_reg(kapic, 0x9);
                     61:     s->log_dest = kvm_apic_get_reg(kapic, 0xd) >> 24;
                     62:     s->dest_mode = kvm_apic_get_reg(kapic, 0xe) >> 28;
                     63:     s->spurious_vec = kvm_apic_get_reg(kapic, 0xf);
                     64:     for (i = 0; i < 8; i++) {
                     65:         s->isr[i] = kvm_apic_get_reg(kapic, 0x10 + i);
                     66:         s->tmr[i] = kvm_apic_get_reg(kapic, 0x18 + i);
                     67:         s->irr[i] = kvm_apic_get_reg(kapic, 0x20 + i);
                     68:     }
                     69:     s->esr = kvm_apic_get_reg(kapic, 0x28);
                     70:     s->icr[0] = kvm_apic_get_reg(kapic, 0x30);
                     71:     s->icr[1] = kvm_apic_get_reg(kapic, 0x31);
                     72:     for (i = 0; i < APIC_LVT_NB; i++) {
                     73:         s->lvt[i] = kvm_apic_get_reg(kapic, 0x32 + i);
                     74:     }
                     75:     s->initial_count = kvm_apic_get_reg(kapic, 0x38);
                     76:     s->divide_conf = kvm_apic_get_reg(kapic, 0x3e);
                     77: 
                     78:     v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4);
                     79:     s->count_shift = (v + 1) & 7;
                     80: 
                     81:     s->initial_count_load_time = qemu_get_clock_ns(vm_clock);
                     82:     apic_next_timer(s, s->initial_count_load_time);
                     83: }
                     84: 
                     85: static void kvm_apic_set_base(APICCommonState *s, uint64_t val)
                     86: {
                     87:     s->apicbase = val;
                     88: }
                     89: 
                     90: static void kvm_apic_set_tpr(APICCommonState *s, uint8_t val)
                     91: {
                     92:     s->tpr = (val & 0x0f) << 4;
                     93: }
                     94: 
                     95: static uint8_t kvm_apic_get_tpr(APICCommonState *s)
                     96: {
                     97:     return s->tpr >> 4;
                     98: }
                     99: 
                    100: static void kvm_apic_enable_tpr_reporting(APICCommonState *s, bool enable)
                    101: {
                    102:     struct kvm_tpr_access_ctl ctl = {
                    103:         .enabled = enable
                    104:     };
                    105: 
                    106:     kvm_vcpu_ioctl(s->cpu_env, KVM_TPR_ACCESS_REPORTING, &ctl);
                    107: }
                    108: 
                    109: static void kvm_apic_vapic_base_update(APICCommonState *s)
                    110: {
                    111:     struct kvm_vapic_addr vapid_addr = {
                    112:         .vapic_addr = s->vapic_paddr,
                    113:     };
                    114:     int ret;
                    115: 
                    116:     ret = kvm_vcpu_ioctl(s->cpu_env, KVM_SET_VAPIC_ADDR, &vapid_addr);
                    117:     if (ret < 0) {
                    118:         fprintf(stderr, "KVM: setting VAPIC address failed (%s)\n",
                    119:                 strerror(-ret));
                    120:         abort();
                    121:     }
                    122: }
                    123: 
                    124: static void do_inject_external_nmi(void *data)
                    125: {
                    126:     APICCommonState *s = data;
                    127:     CPUX86State *env = s->cpu_env;
                    128:     uint32_t lvt;
                    129:     int ret;
                    130: 
                    131:     cpu_synchronize_state(env);
                    132: 
                    133:     lvt = s->lvt[APIC_LVT_LINT1];
                    134:     if (!(lvt & APIC_LVT_MASKED) && ((lvt >> 8) & 7) == APIC_DM_NMI) {
                    135:         ret = kvm_vcpu_ioctl(env, KVM_NMI);
                    136:         if (ret < 0) {
                    137:             fprintf(stderr, "KVM: injection failed, NMI lost (%s)\n",
                    138:                     strerror(-ret));
                    139:         }
                    140:     }
                    141: }
                    142: 
                    143: static void kvm_apic_external_nmi(APICCommonState *s)
                    144: {
                    145:     run_on_cpu(s->cpu_env, do_inject_external_nmi, s);
                    146: }
                    147: 
                    148: static void kvm_apic_init(APICCommonState *s)
                    149: {
                    150:     memory_region_init_reservation(&s->io_memory, "kvm-apic-msi",
                    151:                                    MSI_SPACE_SIZE);
                    152: }
                    153: 
                    154: static void kvm_apic_class_init(ObjectClass *klass, void *data)
                    155: {
                    156:     APICCommonClass *k = APIC_COMMON_CLASS(klass);
                    157: 
                    158:     k->init = kvm_apic_init;
                    159:     k->set_base = kvm_apic_set_base;
                    160:     k->set_tpr = kvm_apic_set_tpr;
                    161:     k->get_tpr = kvm_apic_get_tpr;
                    162:     k->enable_tpr_reporting = kvm_apic_enable_tpr_reporting;
                    163:     k->vapic_base_update = kvm_apic_vapic_base_update;
                    164:     k->external_nmi = kvm_apic_external_nmi;
                    165: }
                    166: 
                    167: static TypeInfo kvm_apic_info = {
                    168:     .name = "kvm-apic",
                    169:     .parent = TYPE_APIC_COMMON,
                    170:     .instance_size = sizeof(APICCommonState),
                    171:     .class_init = kvm_apic_class_init,
                    172: };
                    173: 
                    174: static void kvm_apic_register_types(void)
                    175: {
                    176:     type_register_static(&kvm_apic_info);
                    177: }
                    178: 
                    179: type_init(kvm_apic_register_types)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.