static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) { struct kvm *kvm = vcpu->kvm; int ret; if (likely(vcpu->arch.has_run_once)) return 0; vcpu->arch.has_run_once = true; /* * Map the VGIC hardware resources before running a vcpu the first * time on this VM. */ if (unlikely(irqchip_in_kernel(kvm) && !vgic_ready(kvm))) { ret = kvm_vgic_map_resources(kvm); if (ret) return ret; } /* * Enable the arch timers only if we have an in-kernel VGIC * and it has been properly initialized, since we cannot handle * interrupts from the virtual timer with a userspace gic. */ if (irqchip_in_kernel(kvm) && vgic_initialized(kvm)) kvm_timer_enable(kvm); return 0; }
void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id) { int i; ASSERT(irq_source_id != KVM_USERSPACE_IRQ_SOURCE_ID); mutex_lock(&kvm->irq_lock); if (irq_source_id < 0 || irq_source_id >= BITS_PER_LONG) { printk(KERN_ERR "kvm: IRQ source ID out of range!\n"); goto unlock; } clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap); if (!irqchip_in_kernel(kvm)) goto unlock; for (i = 0; i < KVM_IOAPIC_NUM_PINS; i++) { clear_bit(irq_source_id, &kvm->arch.vioapic->irq_states[i]); if (i >= 16) continue; #ifdef CONFIG_X86 clear_bit(irq_source_id, &pic_irqchip(kvm)->irq_states[i]); #endif } unlock: mutex_unlock(&kvm->irq_lock); }
static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) { struct kvm *kvm = vcpu->kvm; int ret = 0; if (likely(vcpu->arch.has_run_once)) return 0; vcpu->arch.has_run_once = true; /* * Map the VGIC hardware resources before running a vcpu the first * time on this VM. */ if (unlikely(irqchip_in_kernel(kvm) && !vgic_ready(kvm))) { ret = kvm_vgic_map_resources(kvm); if (ret) return ret; } ret = kvm_timer_enable(vcpu); if (ret) return ret; ret = kvm_arm_pmu_v3_enable(vcpu); return ret; }
/* * check if there is pending interrupt without * intack. */ int kvm_cpu_has_interrupt(struct kvm_vcpu *v) { if (!irqchip_in_kernel(v->kvm)) return v->arch.interrupt.pending; if (kvm_cpu_has_extint(v)) return 1; return kvm_apic_has_interrupt(v) != -1; /* LAPIC */ }
int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_event, bool line_status) { if (!irqchip_in_kernel(kvm)) return -ENXIO; irq_event->status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, irq_event->irq, irq_event->level, line_status); return 0; }
void kvm_apic_set_version(struct kvm_vcpu *vcpu) { struct kvm_lapic *apic = vcpu->arch.apic; struct kvm_cpuid_entry2 *feat; u32 v = APIC_VERSION; if (!irqchip_in_kernel(vcpu->kvm)) return; feat = kvm_find_cpuid_entry(apic->vcpu, 0x1, 0); if (feat && (feat->ecx & (1 << (X86_FEATURE_X2APIC & 31)))) v |= APIC_LVR_DIRECTED_EOI; apic_set_reg(apic, APIC_LVR, v); }
/* * Read pending interrupt vector and intack. */ int kvm_cpu_get_interrupt(struct kvm_vcpu *v) { int vector; if (!irqchip_in_kernel(v->kvm)) return v->arch.interrupt.nr; vector = kvm_cpu_get_extint(v); if (kvm_apic_vid_enabled(v->kvm) || vector != -1) return vector; /* PIC */ return kvm_get_apic_interrupt(v); /* APIC */ }
/* * check if there is pending interrupt without * intack. */ int kvm_cpu_has_interrupt(struct kvm_vcpu *v) { struct kvm_pic *s; if (!irqchip_in_kernel(v->kvm)) return v->arch.interrupt.pending; if (kvm_apic_has_interrupt(v) == -1) { /* LAPIC */ if (kvm_apic_accept_pic_intr(v)) { s = pic_irqchip(v->kvm); /* PIC */ return s->output; } else return 0; } return 1; }
/** * Map the MMIO regions depending on the VGIC model exposed to the guest * called on the first VCPU run. * Also map the virtual CPU interface into the VM. * v2/v3 derivatives call vgic_init if not already done. * vgic_ready() returns true if this function has succeeded. * @kvm: kvm struct pointer */ int kvm_vgic_map_resources(struct kvm *kvm) { struct vgic_dist *dist = &kvm->arch.vgic; int ret = 0; mutex_lock(&kvm->lock); if (!irqchip_in_kernel(kvm)) goto out; if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) ret = vgic_v2_map_resources(kvm); else ret = vgic_v3_map_resources(kvm); out: mutex_unlock(&kvm->lock); return ret; }
/* * Read pending interrupt vector and intack. */ int kvm_cpu_get_interrupt(struct kvm_vcpu *v) { struct kvm_pic *s; int vector; if (!irqchip_in_kernel(v->kvm)) return v->arch.interrupt.nr; vector = kvm_get_apic_interrupt(v); /* APIC */ if (vector == -1) { if (kvm_apic_accept_pic_intr(v)) { s = pic_irqchip(v->kvm); s->output = 0; /* PIC */ vector = kvm_pic_read_irq(v->kvm); } } return vector; }
int kvm_emulate_halt(struct kvm_vcpu *vcpu) { ktime_t kt; long itc_diff; unsigned long vcpu_now_itc; unsigned long expires; struct hrtimer *p_ht = &vcpu->arch.hlt_timer; unsigned long cyc_per_usec = local_cpu_data->cyc_per_usec; struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd); vcpu_now_itc = ia64_getreg(_IA64_REG_AR_ITC) + vcpu->arch.itc_offset; if (time_after(vcpu_now_itc, vpd->itm)) { vcpu->arch.timer_check = 1; return 1; } itc_diff = vpd->itm - vcpu_now_itc; if (itc_diff < 0) itc_diff = -itc_diff; expires = div64_u64(itc_diff, cyc_per_usec); kt = ktime_set(0, 1000 * expires); vcpu->arch.ht_active = 1; hrtimer_start(p_ht, kt, HRTIMER_MODE_ABS); if (irqchip_in_kernel(vcpu->kvm)) { vcpu->arch.mp_state = KVM_MP_STATE_HALTED; kvm_vcpu_block(vcpu); hrtimer_cancel(p_ht); vcpu->arch.ht_active = 0; if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE) return -EINTR; return 1; } else { printk(KERN_ERR"kvm: Unsupported userspace halt!"); return 0; } }
struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) { int err; struct kvm_vcpu *vcpu; if (irqchip_in_kernel(kvm) && vgic_initialized(kvm)) { err = -EBUSY; goto out; } if (id >= kvm->arch.max_vcpus) { err = -EINVAL; goto out; } vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); if (!vcpu) { err = -ENOMEM; goto out; } err = kvm_vcpu_init(vcpu, kvm, id); if (err) goto free_vcpu; err = create_hyp_mappings(vcpu, vcpu + 1); if (err) goto vcpu_uninit; return vcpu; vcpu_uninit: kvm_vcpu_uninit(vcpu); free_vcpu: kmem_cache_free(kvm_vcpu_cache, vcpu); out: return ERR_PTR(err); }
void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id) { ASSERT(irq_source_id != KVM_USERSPACE_IRQ_SOURCE_ID); #ifdef CONFIG_X86 ASSERT(irq_source_id != KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID); #endif mutex_lock(&kvm->irq_lock); if (irq_source_id < 0 || irq_source_id >= BITS_PER_LONG) { printk(KERN_ERR "kvm: IRQ source ID out of range!\n"); goto unlock; } clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap); if (!irqchip_in_kernel(kvm)) goto unlock; kvm_ioapic_clear_all(kvm->arch.vioapic, irq_source_id); #ifdef CONFIG_X86 kvm_pic_clear_all(pic_irqchip(kvm), irq_source_id); #endif unlock: mutex_unlock(&kvm->irq_lock); }
/** * kvm_vgic_create: triggered by the instantiation of the VGIC device by * user space, either through the legacy KVM_CREATE_IRQCHIP ioctl (v2 only) * or through the generic KVM_CREATE_DEVICE API ioctl. * irqchip_in_kernel() tells you if this function succeeded or not. * @kvm: kvm struct pointer * @type: KVM_DEV_TYPE_ARM_VGIC_V[23] */ int kvm_vgic_create(struct kvm *kvm, u32 type) { int i, vcpu_lock_idx = -1, ret; struct kvm_vcpu *vcpu; if (irqchip_in_kernel(kvm)) return -EEXIST; /* * This function is also called by the KVM_CREATE_IRQCHIP handler, * which had no chance yet to check the availability of the GICv2 * emulation. So check this here again. KVM_CREATE_DEVICE does * the proper checks already. */ if (type == KVM_DEV_TYPE_ARM_VGIC_V2 && !kvm_vgic_global_state.can_emulate_gicv2) return -ENODEV; /* * Any time a vcpu is run, vcpu_load is called which tries to grab the * vcpu->mutex. By grabbing the vcpu->mutex of all VCPUs we ensure * that no other VCPUs are run while we create the vgic. */ ret = -EBUSY; kvm_for_each_vcpu(i, vcpu, kvm) { if (!mutex_trylock(&vcpu->mutex)) goto out_unlock; vcpu_lock_idx = i; } kvm_for_each_vcpu(i, vcpu, kvm) { if (vcpu->arch.has_run_once) goto out_unlock; } ret = 0; if (type == KVM_DEV_TYPE_ARM_VGIC_V2) kvm->arch.max_vcpus = VGIC_V2_MAX_CPUS; else kvm->arch.max_vcpus = VGIC_V3_MAX_CPUS; if (atomic_read(&kvm->online_vcpus) > kvm->arch.max_vcpus) { ret = -E2BIG; goto out_unlock; } kvm->arch.vgic.in_kernel = true; kvm->arch.vgic.vgic_model = type; /* * kvm_vgic_global_state.vctrl_base is set on vgic probe (kvm_arch_init) * it is stored in distributor struct for asm save/restore purpose */ kvm->arch.vgic.vctrl_base = kvm_vgic_global_state.vctrl_base; kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF; kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF; kvm->arch.vgic.vgic_redist_base = VGIC_ADDR_UNDEF; out_unlock: for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) { vcpu = kvm_get_vcpu(kvm, vcpu_lock_idx); mutex_unlock(&vcpu->mutex); } return ret; }