Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932488AbcLZRsb (ORCPT ); Mon, 26 Dec 2016 12:48:31 -0500 Received: from outprodmail01.cc.columbia.edu ([128.59.72.39]:52028 "EHLO outprodmail01.cc.columbia.edu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755768AbcLZRs2 (ORCPT ); Mon, 26 Dec 2016 12:48:28 -0500 X-Greylist: delayed 1323 seconds by postgrey-1.27 at vger.kernel.org; Mon, 26 Dec 2016 12:46:20 EST From: Jintack Lim To: kvmarm@lists.cs.columbia.edu, christoffer.dall@linaro.org, marc.zyngier@arm.com Cc: pbonzini@redhat.com, rkrcmar@redhat.com, linux@armlinux.org.uk, catalin.marinas@arm.com, will.deacon@arm.com, andre.przywara@arm.com, linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Jintack Lim Subject: [RFC 8/8] KVM: arm/arm64: Emulate the EL1 phys timer register access Date: Mon, 26 Dec 2016 12:12:06 -0500 Message-Id: <1482772326-29110-9-git-send-email-jintack@cs.columbia.edu> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1482772326-29110-1-git-send-email-jintack@cs.columbia.edu> References: <1482772326-29110-1-git-send-email-jintack@cs.columbia.edu> X-No-Spam-Score: Local Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3376 Lines: 109 Emulate read and write operations to CNTP_TVAL, CNTP_CVAL and CNTP_CTL. Now the VM is able to use the EL1 physical timer. Signed-off-by: Jintack Lim --- arch/arm64/kvm/sys_regs.c | 35 ++++++++++++++++++++++++++++++++--- include/kvm/arm_arch_timer.h | 3 +++ virt/kvm/arm/arch_timer.c | 4 ++-- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index fd9e747..7cef94f 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -824,7 +824,15 @@ static bool access_cntp_tval(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) { - kvm_inject_undefined(vcpu); + struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); + cycle_t now = kvm_phys_timer_read(); + + if (p->is_write) { + ptimer->cnt_cval = p->regval + now; + kvm_timer_emulate(vcpu, ptimer); + } else + p->regval = ptimer->cnt_cval - now; + return true; } @@ -832,7 +840,21 @@ static bool access_cntp_ctl(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) { - kvm_inject_undefined(vcpu); + struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); + + if (p->is_write) { + /* ISTATUS bit is read-only */ + ptimer->cnt_ctl = p->regval & ~ARCH_TIMER_CTRL_IT_STAT; + kvm_timer_emulate(vcpu, ptimer); + } else { + cycle_t now = kvm_phys_timer_read(); + + p->regval = ptimer->cnt_ctl; + /* Set ISTATUS bit if it's expired */ + if (ptimer->cnt_cval <= now) + p->regval |= ARCH_TIMER_CTRL_IT_STAT; + } + return true; } @@ -840,7 +862,14 @@ static bool access_cntp_cval(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) { - kvm_inject_undefined(vcpu); + struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); + + if (p->is_write) { + ptimer->cnt_cval = p->regval; + kvm_timer_emulate(vcpu, ptimer); + } else + p->regval = ptimer->cnt_cval; + return true; } diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h index 04ed9c1..776579b 100644 --- a/include/kvm/arm_arch_timer.h +++ b/include/kvm/arm_arch_timer.h @@ -75,6 +75,9 @@ bool kvm_timer_should_fire(struct kvm_vcpu *vcpu, struct arch_timer_context *timer_ctx); void kvm_timer_schedule(struct kvm_vcpu *vcpu); void kvm_timer_unschedule(struct kvm_vcpu *vcpu); +void kvm_timer_emulate(struct kvm_vcpu *vcpu, struct arch_timer_context *timer); + +cycle_t kvm_phys_timer_read(void); void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu); diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index be8d953..7a161f8 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c @@ -39,7 +39,7 @@ void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu) vcpu_vtimer(vcpu)->active_cleared_last = false; } -static cycle_t kvm_phys_timer_read(void) +cycle_t kvm_phys_timer_read(void) { return timecounter->cc->read(timecounter->cc); } @@ -258,7 +258,7 @@ static int kvm_timer_update_state(struct kvm_vcpu *vcpu) * Schedule the background timer for the emulated timer. The background timer * runs whenever vcpu is runnable and the timer is not expired. */ -static void kvm_timer_emulate(struct kvm_vcpu *vcpu, +void kvm_timer_emulate(struct kvm_vcpu *vcpu, struct arch_timer_context *timer_ctx) { struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; -- 1.9.1