Annotation of qemu/hw/kvm/apic.c, revision 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.