aboutsummaryrefslogtreecommitdiffstats
path: root/virt/kvm
diff options
context:
space:
mode:
authorAndre Przywara <andre.przywara@arm.com>2018-07-05 11:48:23 -0400
committerMarc Zyngier <marc.zyngier@arm.com>2019-02-19 16:05:40 -0500
commit84135d3d18da2ff17d3ad1a609b2818cc3049552 (patch)
treec72a908ddb0d63d73e186273e3b12c0f180ea9c2 /virt/kvm
parent09838de943d4c0ee75a99cd7665940705ab8dcea (diff)
KVM: arm/arm64: consolidate arch timer trap handlers
At the moment we have separate system register emulation handlers for each timer register. Actually they are quite similar, and we rely on kvm_arm_timer_[gs]et_reg() for the actual emulation anyways, so let's just merge all of those handlers into one function, which just marshalls the arguments and then hands off to a set of common accessors. This makes extending the emulation to include EL2 timers much easier. Signed-off-by: Andre Przywara <andre.przywara@arm.com> [Fixed 32-bit VM breakage and reduced to reworking existing code] Signed-off-by: Christoffer Dall <christoffer.dall@arm.com> [Fixed 32bit host, general cleanup] Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'virt/kvm')
-rw-r--r--virt/kvm/arm/arch_timer.c130
1 files changed, 113 insertions, 17 deletions
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 4986028d9829..f7d377448438 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -25,6 +25,7 @@
25 25
26#include <clocksource/arm_arch_timer.h> 26#include <clocksource/arm_arch_timer.h>
27#include <asm/arch_timer.h> 27#include <asm/arch_timer.h>
28#include <asm/kvm_emulate.h>
28#include <asm/kvm_hyp.h> 29#include <asm/kvm_hyp.h>
29 30
30#include <kvm/arm_vgic.h> 31#include <kvm/arm_vgic.h>
@@ -52,6 +53,13 @@ static bool kvm_timer_irq_can_fire(struct arch_timer_context *timer_ctx);
52static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level, 53static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
53 struct arch_timer_context *timer_ctx); 54 struct arch_timer_context *timer_ctx);
54static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx); 55static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx);
56static void kvm_arm_timer_write(struct kvm_vcpu *vcpu,
57 struct arch_timer_context *timer,
58 enum kvm_arch_timer_regs treg,
59 u64 val);
60static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu,
61 struct arch_timer_context *timer,
62 enum kvm_arch_timer_regs treg);
55 63
56u64 kvm_phys_timer_read(void) 64u64 kvm_phys_timer_read(void)
57{ 65{
@@ -628,24 +636,25 @@ static void kvm_timer_init_interrupt(void *info)
628 636
629int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value) 637int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
630{ 638{
631 struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
632 struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
633
634 switch (regid) { 639 switch (regid) {
635 case KVM_REG_ARM_TIMER_CTL: 640 case KVM_REG_ARM_TIMER_CTL:
636 vtimer->cnt_ctl = value & ~ARCH_TIMER_CTRL_IT_STAT; 641 kvm_arm_timer_write(vcpu,
642 vcpu_vtimer(vcpu), TIMER_REG_CTL, value);
637 break; 643 break;
638 case KVM_REG_ARM_TIMER_CNT: 644 case KVM_REG_ARM_TIMER_CNT:
639 update_vtimer_cntvoff(vcpu, kvm_phys_timer_read() - value); 645 update_vtimer_cntvoff(vcpu, kvm_phys_timer_read() - value);
640 break; 646 break;
641 case KVM_REG_ARM_TIMER_CVAL: 647 case KVM_REG_ARM_TIMER_CVAL:
642 vtimer->cnt_cval = value; 648 kvm_arm_timer_write(vcpu,
649 vcpu_vtimer(vcpu), TIMER_REG_CVAL, value);
643 break; 650 break;
644 case KVM_REG_ARM_PTIMER_CTL: 651 case KVM_REG_ARM_PTIMER_CTL:
645 ptimer->cnt_ctl = value & ~ARCH_TIMER_CTRL_IT_STAT; 652 kvm_arm_timer_write(vcpu,
653 vcpu_ptimer(vcpu), TIMER_REG_CTL, value);
646 break; 654 break;
647 case KVM_REG_ARM_PTIMER_CVAL: 655 case KVM_REG_ARM_PTIMER_CVAL:
648 ptimer->cnt_cval = value; 656 kvm_arm_timer_write(vcpu,
657 vcpu_ptimer(vcpu), TIMER_REG_CVAL, value);
649 break; 658 break;
650 659
651 default: 660 default:
@@ -672,26 +681,113 @@ static u64 read_timer_ctl(struct arch_timer_context *timer)
672 681
673u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid) 682u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid)
674{ 683{
675 struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
676 struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
677
678 switch (regid) { 684 switch (regid) {
679 case KVM_REG_ARM_TIMER_CTL: 685 case KVM_REG_ARM_TIMER_CTL:
680 return read_timer_ctl(vtimer); 686 return kvm_arm_timer_read(vcpu,
687 vcpu_vtimer(vcpu), TIMER_REG_CTL);
681 case KVM_REG_ARM_TIMER_CNT: 688 case KVM_REG_ARM_TIMER_CNT:
682 return kvm_phys_timer_read() - vtimer->cntvoff; 689 return kvm_arm_timer_read(vcpu,
690 vcpu_vtimer(vcpu), TIMER_REG_CNT);
683 case KVM_REG_ARM_TIMER_CVAL: 691 case KVM_REG_ARM_TIMER_CVAL:
684 return vtimer->cnt_cval; 692 return kvm_arm_timer_read(vcpu,
693 vcpu_vtimer(vcpu), TIMER_REG_CVAL);
685 case KVM_REG_ARM_PTIMER_CTL: 694 case KVM_REG_ARM_PTIMER_CTL:
686 return read_timer_ctl(ptimer); 695 return kvm_arm_timer_read(vcpu,
687 case KVM_REG_ARM_PTIMER_CVAL: 696 vcpu_ptimer(vcpu), TIMER_REG_CTL);
688 return ptimer->cnt_cval;
689 case KVM_REG_ARM_PTIMER_CNT: 697 case KVM_REG_ARM_PTIMER_CNT:
690 return kvm_phys_timer_read(); 698 return kvm_arm_timer_read(vcpu,
699 vcpu_vtimer(vcpu), TIMER_REG_CNT);
700 case KVM_REG_ARM_PTIMER_CVAL:
701 return kvm_arm_timer_read(vcpu,
702 vcpu_ptimer(vcpu), TIMER_REG_CVAL);
691 } 703 }
692 return (u64)-1; 704 return (u64)-1;
693} 705}
694 706
707static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu,
708 struct arch_timer_context *timer,
709 enum kvm_arch_timer_regs treg)
710{
711 u64 val;
712
713 switch (treg) {
714 case TIMER_REG_TVAL:
715 val = kvm_phys_timer_read() - timer->cntvoff - timer->cnt_cval;
716 break;
717
718 case TIMER_REG_CTL:
719 val = read_timer_ctl(timer);
720 break;
721
722 case TIMER_REG_CVAL:
723 val = timer->cnt_cval;
724 break;
725
726 case TIMER_REG_CNT:
727 val = kvm_phys_timer_read() - timer->cntvoff;
728 break;
729
730 default:
731 BUG();
732 }
733
734 return val;
735}
736
737u64 kvm_arm_timer_read_sysreg(struct kvm_vcpu *vcpu,
738 enum kvm_arch_timers tmr,
739 enum kvm_arch_timer_regs treg)
740{
741 u64 val;
742
743 preempt_disable();
744 kvm_timer_vcpu_put(vcpu);
745
746 val = kvm_arm_timer_read(vcpu, vcpu_get_timer(vcpu, tmr), treg);
747
748 kvm_timer_vcpu_load(vcpu);
749 preempt_enable();
750
751 return val;
752}
753
754static void kvm_arm_timer_write(struct kvm_vcpu *vcpu,
755 struct arch_timer_context *timer,
756 enum kvm_arch_timer_regs treg,
757 u64 val)
758{
759 switch (treg) {
760 case TIMER_REG_TVAL:
761 timer->cnt_cval = val - kvm_phys_timer_read() - timer->cntvoff;
762 break;
763
764 case TIMER_REG_CTL:
765 timer->cnt_ctl = val & ~ARCH_TIMER_CTRL_IT_STAT;
766 break;
767
768 case TIMER_REG_CVAL:
769 timer->cnt_cval = val;
770 break;
771
772 default:
773 BUG();
774 }
775}
776
777void kvm_arm_timer_write_sysreg(struct kvm_vcpu *vcpu,
778 enum kvm_arch_timers tmr,
779 enum kvm_arch_timer_regs treg,
780 u64 val)
781{
782 preempt_disable();
783 kvm_timer_vcpu_put(vcpu);
784
785 kvm_arm_timer_write(vcpu, vcpu_get_timer(vcpu, tmr), treg, val);
786
787 kvm_timer_vcpu_load(vcpu);
788 preempt_enable();
789}
790
695static int kvm_timer_starting_cpu(unsigned int cpu) 791static int kvm_timer_starting_cpu(unsigned int cpu)
696{ 792{
697 kvm_timer_init_interrupt(NULL); 793 kvm_timer_init_interrupt(NULL);