162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 362306a36Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 462306a36Sopenharmony_ci * for more details. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * KVM/MIPS: Interrupt delivery 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. 962306a36Sopenharmony_ci * Authors: Sanjay Lal <sanjayl@kymasys.com> 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/errno.h> 1362306a36Sopenharmony_ci#include <linux/err.h> 1462306a36Sopenharmony_ci#include <linux/vmalloc.h> 1562306a36Sopenharmony_ci#include <linux/fs.h> 1662306a36Sopenharmony_ci#include <linux/memblock.h> 1762306a36Sopenharmony_ci#include <asm/page.h> 1862306a36Sopenharmony_ci#include <asm/cacheflush.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include <linux/kvm_host.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include "interrupt.h" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_civoid kvm_mips_deliver_interrupts(struct kvm_vcpu *vcpu, u32 cause) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci unsigned long *pending = &vcpu->arch.pending_exceptions; 2762306a36Sopenharmony_ci unsigned long *pending_clr = &vcpu->arch.pending_exceptions_clr; 2862306a36Sopenharmony_ci unsigned int priority; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci if (!(*pending) && !(*pending_clr)) 3162306a36Sopenharmony_ci return; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci priority = __ffs(*pending_clr); 3462306a36Sopenharmony_ci while (priority <= MIPS_EXC_MAX) { 3562306a36Sopenharmony_ci kvm_mips_callbacks->irq_clear(vcpu, priority, cause); 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci priority = find_next_bit(pending_clr, 3862306a36Sopenharmony_ci BITS_PER_BYTE * sizeof(*pending_clr), 3962306a36Sopenharmony_ci priority + 1); 4062306a36Sopenharmony_ci } 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci priority = __ffs(*pending); 4362306a36Sopenharmony_ci while (priority <= MIPS_EXC_MAX) { 4462306a36Sopenharmony_ci kvm_mips_callbacks->irq_deliver(vcpu, priority, cause); 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci priority = find_next_bit(pending, 4762306a36Sopenharmony_ci BITS_PER_BYTE * sizeof(*pending), 4862306a36Sopenharmony_ci priority + 1); 4962306a36Sopenharmony_ci } 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci} 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ciint kvm_mips_pending_timer(struct kvm_vcpu *vcpu) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci return test_bit(MIPS_EXC_INT_TIMER, &vcpu->arch.pending_exceptions); 5662306a36Sopenharmony_ci} 57