Message ID | 20200805175700.62775-48-maz@kernel.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [01/56] KVM: arm64: Enable Address Authentication at EL2 if available | expand |
Hi Marc, -----Original Message----- From: kvmarm-bounces@lists.cs.columbia.edu <kvmarm-bounces@lists.cs.columbia.edu> On Behalf Of Marc Zyngier Sent: Thursday, August 6, 2020 1:57 AM To: Paolo Bonzini <pbonzini@redhat.com> Cc: Peng Hao <richard.peng@oppo.com>; kernel-team@android.com; kvm@vger.kernel.org; Will Deacon <will@kernel.org>; Catalin Marinas <Catalin.Marinas@arm.com>; Alexander Graf <graf@amazon.com>; kvmarm@lists.cs.columbia.edu; linux-arm-kernel@lists.infradead.org Subject: [PATCH 47/56] KVM: arm64: timers: Move timer registers to the sys_regs file Move the timer gsisters to the sysreg file. This will further help when they are directly changed by a nesting hypervisor in the VNCR page. This requires moving the initialisation of the timer struct so that some of the helpers (such as arch_timer_ctx_index) can work correctly at an early stage. Signed-off-by: Marc Zyngier <maz@kernel.org> --- arch/arm64/include/asm/kvm_host.h | 6 ++ arch/arm64/kvm/arch_timer.c | 155 +++++++++++++++++++++++------- arch/arm64/kvm/trace_arm.h | 8 +- include/kvm/arm_arch_timer.h | 11 +-- 4 files changed, 136 insertions(+), 44 deletions(-) +static u64 timer_get_offset(struct arch_timer_context *ctxt) { + struct kvm_vcpu *vcpu = ctxt->vcpu; + + switch(arch_timer_ctx_index(ctxt)) { + case TIMER_VTIMER: + return __vcpu_sys_reg(vcpu, CNTVOFF_EL2); + default: + return 0; + } +} + Can I export this helper? As in my ptp_kvm implementation I need get VCNT offset value separately not just give me a result of VCNT. Thanks Jianyong
On 2020-08-19 10:24, Jianyong Wu wrote: > Hi Marc, > > -----Original Message----- > From: kvmarm-bounces@lists.cs.columbia.edu > <kvmarm-bounces@lists.cs.columbia.edu> On Behalf Of Marc Zyngier > Sent: Thursday, August 6, 2020 1:57 AM > To: Paolo Bonzini <pbonzini@redhat.com> > Cc: Peng Hao <richard.peng@oppo.com>; kernel-team@android.com; > kvm@vger.kernel.org; Will Deacon <will@kernel.org>; Catalin Marinas > <Catalin.Marinas@arm.com>; Alexander Graf <graf@amazon.com>; > kvmarm@lists.cs.columbia.edu; linux-arm-kernel@lists.infradead.org > Subject: [PATCH 47/56] KVM: arm64: timers: Move timer registers to the > sys_regs file > > Move the timer gsisters to the sysreg file. This will further help > when they are directly changed by a nesting hypervisor in the VNCR > page. > > This requires moving the initialisation of the timer struct so that > some of the helpers (such as arch_timer_ctx_index) can work correctly > at an early stage. > > Signed-off-by: Marc Zyngier <maz@kernel.org> > --- > arch/arm64/include/asm/kvm_host.h | 6 ++ > arch/arm64/kvm/arch_timer.c | 155 +++++++++++++++++++++++------- > arch/arm64/kvm/trace_arm.h | 8 +- > include/kvm/arm_arch_timer.h | 11 +-- > 4 files changed, 136 insertions(+), 44 deletions(-) > > +static u64 timer_get_offset(struct arch_timer_context *ctxt) { > + struct kvm_vcpu *vcpu = ctxt->vcpu; > + > + switch(arch_timer_ctx_index(ctxt)) { > + case TIMER_VTIMER: > + return __vcpu_sys_reg(vcpu, CNTVOFF_EL2); > + default: > + return 0; > + } > +} > + > Can I export this helper? As in my ptp_kvm implementation I need get > VCNT offset value separately not just give me a result of VCNT. Sorry, you need to give me a bit more context. What do you need the offset for exactly? M.
> -----Original Message----- > From: Marc Zyngier <maz@kernel.org> > Sent: Wednesday, August 19, 2020 6:00 PM > To: Jianyong Wu <Jianyong.Wu@arm.com> > Cc: Paolo Bonzini <pbonzini@redhat.com>; Peng Hao > <richard.peng@oppo.com>; kernel-team@android.com; > kvm@vger.kernel.org; Will Deacon <will@kernel.org>; Catalin Marinas > <Catalin.Marinas@arm.com>; Alexander Graf <graf@amazon.com>; > kvmarm@lists.cs.columbia.edu; linux-arm-kernel@lists.infradead.org > Subject: Re: [PATCH 47/56] KVM: arm64: timers: Move timer registers to the > sys_regs file > > On 2020-08-19 10:24, Jianyong Wu wrote: > > Hi Marc, > > > > -----Original Message----- > > From: kvmarm-bounces@lists.cs.columbia.edu > > <kvmarm-bounces@lists.cs.columbia.edu> On Behalf Of Marc Zyngier > > Sent: Thursday, August 6, 2020 1:57 AM > > To: Paolo Bonzini <pbonzini@redhat.com> > > Cc: Peng Hao <richard.peng@oppo.com>; kernel-team@android.com; > > kvm@vger.kernel.org; Will Deacon <will@kernel.org>; Catalin Marinas > > <Catalin.Marinas@arm.com>; Alexander Graf <graf@amazon.com>; > > kvmarm@lists.cs.columbia.edu; linux-arm-kernel@lists.infradead.org > > Subject: [PATCH 47/56] KVM: arm64: timers: Move timer registers to the > > sys_regs file > > > > Move the timer gsisters to the sysreg file. This will further help > > when they are directly changed by a nesting hypervisor in the VNCR > > page. > > > > This requires moving the initialisation of the timer struct so that > > some of the helpers (such as arch_timer_ctx_index) can work correctly > > at an early stage. > > > > Signed-off-by: Marc Zyngier <maz@kernel.org> > > --- > > arch/arm64/include/asm/kvm_host.h | 6 ++ > > arch/arm64/kvm/arch_timer.c | 155 +++++++++++++++++++++++------- > > arch/arm64/kvm/trace_arm.h | 8 +- > > include/kvm/arm_arch_timer.h | 11 +-- > > 4 files changed, 136 insertions(+), 44 deletions(-) > > > > +static u64 timer_get_offset(struct arch_timer_context *ctxt) { > > + struct kvm_vcpu *vcpu = ctxt->vcpu; > > + > > + switch(arch_timer_ctx_index(ctxt)) { > > + case TIMER_VTIMER: > > + return __vcpu_sys_reg(vcpu, CNTVOFF_EL2); > > + default: > > + return 0; > > + } > > +} > > + > > Can I export this helper? As in my ptp_kvm implementation I need get > > VCNT offset value separately not just give me a result of VCNT. > > Sorry, you need to give me a bit more context. What do you need the offset > for exactly? Yeah, In my ptp_kvm implementation, I need acquire wall time and counter cycle in the same time in host. After get host counter cycle, I need subtract it by VCNT offset to obtain VCNT. See https://lkml.org/lkml/2020/6/19/441 https://lkml.org/lkml/2020/6/19/441 But now I can't get the VCNT offset easily like before using " vcpu_vtimer(vcpu)->cntvoff" and I can't use the helper like "kvm_arm_timer_read" as I need acquire the counter cycle in the same time with the host wall time. Thanks Jianyong > > M. > -- > Jazz is not dead. It just smells funny...
On 2020-08-19 11:18, Jianyong Wu wrote: >> -----Original Message----- >> From: Marc Zyngier <maz@kernel.org> >> Sent: Wednesday, August 19, 2020 6:00 PM >> To: Jianyong Wu <Jianyong.Wu@arm.com> >> Cc: Paolo Bonzini <pbonzini@redhat.com>; Peng Hao >> <richard.peng@oppo.com>; kernel-team@android.com; >> kvm@vger.kernel.org; Will Deacon <will@kernel.org>; Catalin Marinas >> <Catalin.Marinas@arm.com>; Alexander Graf <graf@amazon.com>; >> kvmarm@lists.cs.columbia.edu; linux-arm-kernel@lists.infradead.org >> Subject: Re: [PATCH 47/56] KVM: arm64: timers: Move timer registers to >> the >> sys_regs file >> >> On 2020-08-19 10:24, Jianyong Wu wrote: >> > Hi Marc, >> > >> > -----Original Message----- >> > From: kvmarm-bounces@lists.cs.columbia.edu >> > <kvmarm-bounces@lists.cs.columbia.edu> On Behalf Of Marc Zyngier >> > Sent: Thursday, August 6, 2020 1:57 AM >> > To: Paolo Bonzini <pbonzini@redhat.com> >> > Cc: Peng Hao <richard.peng@oppo.com>; kernel-team@android.com; >> > kvm@vger.kernel.org; Will Deacon <will@kernel.org>; Catalin Marinas >> > <Catalin.Marinas@arm.com>; Alexander Graf <graf@amazon.com>; >> > kvmarm@lists.cs.columbia.edu; linux-arm-kernel@lists.infradead.org >> > Subject: [PATCH 47/56] KVM: arm64: timers: Move timer registers to the >> > sys_regs file >> > >> > Move the timer gsisters to the sysreg file. This will further help >> > when they are directly changed by a nesting hypervisor in the VNCR >> > page. >> > >> > This requires moving the initialisation of the timer struct so that >> > some of the helpers (such as arch_timer_ctx_index) can work correctly >> > at an early stage. >> > >> > Signed-off-by: Marc Zyngier <maz@kernel.org> >> > --- >> > arch/arm64/include/asm/kvm_host.h | 6 ++ >> > arch/arm64/kvm/arch_timer.c | 155 +++++++++++++++++++++++------- >> > arch/arm64/kvm/trace_arm.h | 8 +- >> > include/kvm/arm_arch_timer.h | 11 +-- >> > 4 files changed, 136 insertions(+), 44 deletions(-) >> > >> > +static u64 timer_get_offset(struct arch_timer_context *ctxt) { >> > + struct kvm_vcpu *vcpu = ctxt->vcpu; >> > + >> > + switch(arch_timer_ctx_index(ctxt)) { >> > + case TIMER_VTIMER: >> > + return __vcpu_sys_reg(vcpu, CNTVOFF_EL2); >> > + default: >> > + return 0; >> > + } >> > +} >> > + >> > Can I export this helper? As in my ptp_kvm implementation I need get >> > VCNT offset value separately not just give me a result of VCNT. >> >> Sorry, you need to give me a bit more context. What do you need the >> offset >> for exactly? > > Yeah, > In my ptp_kvm implementation, I need acquire wall time and counter > cycle in the same time in host. After get host counter cycle, I need > subtract it by VCNT offset to obtain VCNT. See > https://lkml.org/lkml/2020/6/19/441 > https://lkml.org/lkml/2020/6/19/441 > But now I can't get the VCNT offset easily like before using " > vcpu_vtimer(vcpu)->cntvoff" and I can't use the helper like > "kvm_arm_timer_read" as I need acquire the counter cycle in the same > time with the host wall time. I must be missing something. CNTVOFF_EL2 is now implemented as a standard system register, and has the same visibility as any other vcpu sysreg. Why doesn't vcpu_read_sys_reg(vcpu, CNTVOFF_EL2) work for you? M.
> -----Original Message----- > From: Marc Zyngier <maz@kernel.org> > Sent: Wednesday, August 19, 2020 6:39 PM > To: Jianyong Wu <Jianyong.Wu@arm.com> > Cc: Paolo Bonzini <pbonzini@redhat.com>; Peng Hao > <richard.peng@oppo.com>; kernel-team@android.com; kvm@vger.kernel.org; > Will Deacon <will@kernel.org>; Catalin Marinas <Catalin.Marinas@arm.com>; > Alexander Graf <graf@amazon.com>; kvmarm@lists.cs.columbia.edu; linux- > arm-kernel@lists.infradead.org > Subject: Re: [PATCH 47/56] KVM: arm64: timers: Move timer registers to the > sys_regs file > > On 2020-08-19 11:18, Jianyong Wu wrote: > >> -----Original Message----- > >> From: Marc Zyngier <maz@kernel.org> > >> Sent: Wednesday, August 19, 2020 6:00 PM > >> To: Jianyong Wu <Jianyong.Wu@arm.com> > >> Cc: Paolo Bonzini <pbonzini@redhat.com>; Peng Hao > >> <richard.peng@oppo.com>; kernel-team@android.com; > >> kvm@vger.kernel.org; Will Deacon <will@kernel.org>; Catalin Marinas > >> <Catalin.Marinas@arm.com>; Alexander Graf <graf@amazon.com>; > >> kvmarm@lists.cs.columbia.edu; linux-arm-kernel@lists.infradead.org > >> Subject: Re: [PATCH 47/56] KVM: arm64: timers: Move timer registers > >> to the sys_regs file > >> > >> On 2020-08-19 10:24, Jianyong Wu wrote: > >> > Hi Marc, > >> > > >> > -----Original Message----- > >> > From: kvmarm-bounces@lists.cs.columbia.edu > >> > <kvmarm-bounces@lists.cs.columbia.edu> On Behalf Of Marc Zyngier > >> > Sent: Thursday, August 6, 2020 1:57 AM > >> > To: Paolo Bonzini <pbonzini@redhat.com> > >> > Cc: Peng Hao <richard.peng@oppo.com>; kernel-team@android.com; > >> > kvm@vger.kernel.org; Will Deacon <will@kernel.org>; Catalin Marinas > >> > <Catalin.Marinas@arm.com>; Alexander Graf <graf@amazon.com>; > >> > kvmarm@lists.cs.columbia.edu; linux-arm-kernel@lists.infradead.org > >> > Subject: [PATCH 47/56] KVM: arm64: timers: Move timer registers to > >> > the sys_regs file > >> > > >> > Move the timer gsisters to the sysreg file. This will further help > >> > when they are directly changed by a nesting hypervisor in the VNCR > >> > page. > >> > > >> > This requires moving the initialisation of the timer struct so that > >> > some of the helpers (such as arch_timer_ctx_index) can work > >> > correctly at an early stage. > >> > > >> > Signed-off-by: Marc Zyngier <maz@kernel.org> > >> > --- > >> > arch/arm64/include/asm/kvm_host.h | 6 ++ > >> > arch/arm64/kvm/arch_timer.c | 155 +++++++++++++++++++++++------- > >> > arch/arm64/kvm/trace_arm.h | 8 +- > >> > include/kvm/arm_arch_timer.h | 11 +-- > >> > 4 files changed, 136 insertions(+), 44 deletions(-) > >> > > >> > +static u64 timer_get_offset(struct arch_timer_context *ctxt) { > >> > + struct kvm_vcpu *vcpu = ctxt->vcpu; > >> > + > >> > + switch(arch_timer_ctx_index(ctxt)) { > >> > + case TIMER_VTIMER: > >> > + return __vcpu_sys_reg(vcpu, CNTVOFF_EL2); > >> > + default: > >> > + return 0; > >> > + } > >> > +} > >> > + > >> > Can I export this helper? As in my ptp_kvm implementation I need > >> > get VCNT offset value separately not just give me a result of VCNT. > >> > >> Sorry, you need to give me a bit more context. What do you need the > >> offset for exactly? > > > > Yeah, > > In my ptp_kvm implementation, I need acquire wall time and counter > > cycle in the same time in host. After get host counter cycle, I need > > subtract it by VCNT offset to obtain VCNT. See > > https://lkml.org/lkml/2020/6/19/441 > > https://lkml.org/lkml/2020/6/19/441 > > But now I can't get the VCNT offset easily like before using " > > vcpu_vtimer(vcpu)->cntvoff" and I can't use the helper like > > "kvm_arm_timer_read" as I need acquire the counter cycle in the same > > time with the host wall time. > > I must be missing something. CNTVOFF_EL2 is now implemented as a standard > system register, and has the same visibility as any other vcpu sysreg. > > Why doesn't vcpu_read_sys_reg(vcpu, CNTVOFF_EL2) work for you? Maybe it serves me, let me try it, thanks. Thanks Jianyong > > M. > -- > Jazz is not dead. It just smells funny...
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 91b1adb6789c..e1a32c0707bb 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -189,6 +189,12 @@ enum vcpu_sysreg { SP_EL1, SPSR_EL1, + CNTVOFF_EL2, + CNTV_CVAL_EL0, + CNTV_CTL_EL0, + CNTP_CVAL_EL0, + CNTP_CTL_EL0, + /* 32bit specific registers. Keep them at the end of the range */ DACR32_EL2, /* Domain Access Control Register */ IFSR32_EL2, /* Instruction Fault Status Register */ diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c index 33d85a504720..32ba6fbc3814 100644 --- a/arch/arm64/kvm/arch_timer.c +++ b/arch/arm64/kvm/arch_timer.c @@ -51,6 +51,93 @@ static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu, struct arch_timer_context *timer, enum kvm_arch_timer_regs treg); +u32 timer_get_ctl(struct arch_timer_context *ctxt) +{ + struct kvm_vcpu *vcpu = ctxt->vcpu; + + switch(arch_timer_ctx_index(ctxt)) { + case TIMER_VTIMER: + return __vcpu_sys_reg(vcpu, CNTV_CTL_EL0); + case TIMER_PTIMER: + return __vcpu_sys_reg(vcpu, CNTP_CTL_EL0); + default: + WARN_ON(1); + return 0; + } +} + +u64 timer_get_cval(struct arch_timer_context *ctxt) +{ + struct kvm_vcpu *vcpu = ctxt->vcpu; + + switch(arch_timer_ctx_index(ctxt)) { + case TIMER_VTIMER: + return __vcpu_sys_reg(vcpu, CNTV_CVAL_EL0); + case TIMER_PTIMER: + return __vcpu_sys_reg(vcpu, CNTP_CVAL_EL0); + default: + WARN_ON(1); + return 0; + } +} + +static u64 timer_get_offset(struct arch_timer_context *ctxt) +{ + struct kvm_vcpu *vcpu = ctxt->vcpu; + + switch(arch_timer_ctx_index(ctxt)) { + case TIMER_VTIMER: + return __vcpu_sys_reg(vcpu, CNTVOFF_EL2); + default: + return 0; + } +} + +static void timer_set_ctl(struct arch_timer_context *ctxt, u32 ctl) +{ + struct kvm_vcpu *vcpu = ctxt->vcpu; + + switch(arch_timer_ctx_index(ctxt)) { + case TIMER_VTIMER: + __vcpu_sys_reg(vcpu, CNTV_CTL_EL0) = ctl; + break; + case TIMER_PTIMER: + __vcpu_sys_reg(vcpu, CNTP_CTL_EL0) = ctl; + break; + default: + WARN_ON(1); + } +} + +static void timer_set_cval(struct arch_timer_context *ctxt, u64 cval) +{ + struct kvm_vcpu *vcpu = ctxt->vcpu; + + switch(arch_timer_ctx_index(ctxt)) { + case TIMER_VTIMER: + __vcpu_sys_reg(vcpu, CNTV_CVAL_EL0) = cval; + break; + case TIMER_PTIMER: + __vcpu_sys_reg(vcpu, CNTP_CVAL_EL0) = cval; + break; + default: + WARN_ON(1); + } +} + +static void timer_set_offset(struct arch_timer_context *ctxt, u64 offset) +{ + struct kvm_vcpu *vcpu = ctxt->vcpu; + + switch(arch_timer_ctx_index(ctxt)) { + case TIMER_VTIMER: + __vcpu_sys_reg(vcpu, CNTVOFF_EL2) = offset; + break; + default: + WARN(offset, "timer %ld\n", arch_timer_ctx_index(ctxt)); + } +} + u64 kvm_phys_timer_read(void) { return timecounter->cc->read(timecounter->cc); @@ -124,8 +211,8 @@ static u64 kvm_timer_compute_delta(struct arch_timer_context *timer_ctx) { u64 cval, now; - cval = timer_ctx->cnt_cval; - now = kvm_phys_timer_read() - timer_ctx->cntvoff; + cval = timer_get_cval(timer_ctx); + now = kvm_phys_timer_read() - timer_get_offset(timer_ctx); if (now < cval) { u64 ns; @@ -144,8 +231,8 @@ static bool kvm_timer_irq_can_fire(struct arch_timer_context *timer_ctx) { WARN_ON(timer_ctx && timer_ctx->loaded); return timer_ctx && - !(timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_IT_MASK) && - (timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_ENABLE); + ((timer_get_ctl(timer_ctx) & + (ARCH_TIMER_CTRL_IT_MASK | ARCH_TIMER_CTRL_ENABLE)) == ARCH_TIMER_CTRL_ENABLE); } /* @@ -256,8 +343,8 @@ static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx) if (!kvm_timer_irq_can_fire(timer_ctx)) return false; - cval = timer_ctx->cnt_cval; - now = kvm_phys_timer_read() - timer_ctx->cntvoff; + cval = timer_get_cval(timer_ctx); + now = kvm_phys_timer_read() - timer_get_offset(timer_ctx); return cval <= now; } @@ -350,8 +437,8 @@ static void timer_save_state(struct arch_timer_context *ctx) switch (index) { case TIMER_VTIMER: - ctx->cnt_ctl = read_sysreg_el0(SYS_CNTV_CTL); - ctx->cnt_cval = read_sysreg_el0(SYS_CNTV_CVAL); + timer_set_ctl(ctx, read_sysreg_el0(SYS_CNTV_CTL)); + timer_set_cval(ctx, read_sysreg_el0(SYS_CNTV_CVAL)); /* Disable the timer */ write_sysreg_el0(0, SYS_CNTV_CTL); @@ -359,8 +446,8 @@ static void timer_save_state(struct arch_timer_context *ctx) break; case TIMER_PTIMER: - ctx->cnt_ctl = read_sysreg_el0(SYS_CNTP_CTL); - ctx->cnt_cval = read_sysreg_el0(SYS_CNTP_CVAL); + timer_set_ctl(ctx, read_sysreg_el0(SYS_CNTP_CTL)); + timer_set_cval(ctx, read_sysreg_el0(SYS_CNTP_CVAL)); /* Disable the timer */ write_sysreg_el0(0, SYS_CNTP_CTL); @@ -429,14 +516,14 @@ static void timer_restore_state(struct arch_timer_context *ctx) switch (index) { case TIMER_VTIMER: - write_sysreg_el0(ctx->cnt_cval, SYS_CNTV_CVAL); + write_sysreg_el0(timer_get_cval(ctx), SYS_CNTV_CVAL); isb(); - write_sysreg_el0(ctx->cnt_ctl, SYS_CNTV_CTL); + write_sysreg_el0(timer_get_ctl(ctx), SYS_CNTV_CTL); break; case TIMER_PTIMER: - write_sysreg_el0(ctx->cnt_cval, SYS_CNTP_CVAL); + write_sysreg_el0(timer_get_cval(ctx), SYS_CNTP_CVAL); isb(); - write_sysreg_el0(ctx->cnt_ctl, SYS_CNTP_CTL); + write_sysreg_el0(timer_get_ctl(ctx), SYS_CNTP_CTL); break; case NR_KVM_TIMERS: BUG(); @@ -528,7 +615,7 @@ void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu) kvm_timer_vcpu_load_nogic(vcpu); } - set_cntvoff(map.direct_vtimer->cntvoff); + set_cntvoff(timer_get_offset(map.direct_vtimer)); kvm_timer_unblocking(vcpu); @@ -639,8 +726,8 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu) * resets the timer to be disabled and unmasked and is compliant with * the ARMv7 architecture. */ - vcpu_vtimer(vcpu)->cnt_ctl = 0; - vcpu_ptimer(vcpu)->cnt_ctl = 0; + timer_set_ctl(vcpu_vtimer(vcpu), 0); + timer_set_ctl(vcpu_ptimer(vcpu), 0); if (timer->enabled) { kvm_timer_update_irq(vcpu, false, vcpu_vtimer(vcpu)); @@ -668,13 +755,13 @@ static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff) mutex_lock(&kvm->lock); kvm_for_each_vcpu(i, tmp, kvm) - vcpu_vtimer(tmp)->cntvoff = cntvoff; + timer_set_offset(vcpu_vtimer(tmp), cntvoff); /* * When called from the vcpu create path, the CPU being created is not * included in the loop above, so we just set it here as well. */ - vcpu_vtimer(vcpu)->cntvoff = cntvoff; + timer_set_offset(vcpu_vtimer(vcpu), cntvoff); mutex_unlock(&kvm->lock); } @@ -684,9 +771,12 @@ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); + vtimer->vcpu = vcpu; + ptimer->vcpu = vcpu; + /* Synchronize cntvoff across all vtimers of a VM. */ update_vtimer_cntvoff(vcpu, kvm_phys_timer_read()); - ptimer->cntvoff = 0; + timer_set_offset(ptimer, 0); hrtimer_init(&timer->bg_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_HARD); timer->bg_timer.function = kvm_bg_timer_expire; @@ -704,9 +794,6 @@ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) vtimer->host_timer_irq_flags = host_vtimer_irq_flags; ptimer->host_timer_irq_flags = host_ptimer_irq_flags; - - vtimer->vcpu = vcpu; - ptimer->vcpu = vcpu; } static void kvm_timer_init_interrupt(void *info) @@ -756,10 +843,12 @@ static u64 read_timer_ctl(struct arch_timer_context *timer) * UNKNOWN when ENABLE bit is 0, so we chose to set ISTATUS bit * regardless of ENABLE bit for our implementation convenience. */ + u32 ctl = timer_get_ctl(timer); + if (!kvm_timer_compute_delta(timer)) - return timer->cnt_ctl | ARCH_TIMER_CTRL_IT_STAT; - else - return timer->cnt_ctl; + ctl |= ARCH_TIMER_CTRL_IT_STAT; + + return ctl; } u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid) @@ -795,8 +884,8 @@ static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu, switch (treg) { case TIMER_REG_TVAL: - val = timer->cnt_cval - kvm_phys_timer_read() + timer->cntvoff; - val &= lower_32_bits(val); + val = timer_get_cval(timer) - kvm_phys_timer_read() + timer_get_offset(timer); + val = lower_32_bits(val); break; case TIMER_REG_CTL: @@ -804,11 +893,11 @@ static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu, break; case TIMER_REG_CVAL: - val = timer->cnt_cval; + val = timer_get_cval(timer); break; case TIMER_REG_CNT: - val = kvm_phys_timer_read() - timer->cntvoff; + val = kvm_phys_timer_read() - timer_get_offset(timer); break; default: @@ -842,15 +931,15 @@ static void kvm_arm_timer_write(struct kvm_vcpu *vcpu, { switch (treg) { case TIMER_REG_TVAL: - timer->cnt_cval = kvm_phys_timer_read() - timer->cntvoff + (s32)val; + timer_set_cval(timer, kvm_phys_timer_read() - timer_get_offset(timer) + (s32)val); break; case TIMER_REG_CTL: - timer->cnt_ctl = val & ~ARCH_TIMER_CTRL_IT_STAT; + timer_set_ctl(timer, val & ~ARCH_TIMER_CTRL_IT_STAT); break; case TIMER_REG_CVAL: - timer->cnt_cval = val; + timer_set_cval(timer, val); break; default: diff --git a/arch/arm64/kvm/trace_arm.h b/arch/arm64/kvm/trace_arm.h index 4c71270cc097..4691053c5ee4 100644 --- a/arch/arm64/kvm/trace_arm.h +++ b/arch/arm64/kvm/trace_arm.h @@ -301,8 +301,8 @@ TRACE_EVENT(kvm_timer_save_state, ), TP_fast_assign( - __entry->ctl = ctx->cnt_ctl; - __entry->cval = ctx->cnt_cval; + __entry->ctl = timer_get_ctl(ctx); + __entry->cval = timer_get_cval(ctx); __entry->timer_idx = arch_timer_ctx_index(ctx); ), @@ -323,8 +323,8 @@ TRACE_EVENT(kvm_timer_restore_state, ), TP_fast_assign( - __entry->ctl = ctx->cnt_ctl; - __entry->cval = ctx->cnt_cval; + __entry->ctl = timer_get_ctl(ctx); + __entry->cval = timer_get_cval(ctx); __entry->timer_idx = arch_timer_ctx_index(ctx); ), diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h index a821dd1df0cf..51c19381108c 100644 --- a/include/kvm/arm_arch_timer.h +++ b/include/kvm/arm_arch_timer.h @@ -26,16 +26,9 @@ enum kvm_arch_timer_regs { struct arch_timer_context { struct kvm_vcpu *vcpu; - /* Registers: control register, timer value */ - u32 cnt_ctl; - u64 cnt_cval; - /* Timer IRQ */ struct kvm_irq_level irq; - /* Virtual offset */ - u64 cntvoff; - /* Emulated Timer (may be unused) */ struct hrtimer hrtimer; @@ -109,4 +102,8 @@ void kvm_arm_timer_write_sysreg(struct kvm_vcpu *vcpu, enum kvm_arch_timer_regs treg, u64 val); +/* Needed for tracing */ +u32 timer_get_ctl(struct arch_timer_context *ctxt); +u64 timer_get_cval(struct arch_timer_context *ctxt); + #endif
Move the timer gsisters to the sysreg file. This will further help when they are directly changed by a nesting hypervisor in the VNCR page. This requires moving the initialisation of the timer struct so that some of the helpers (such as arch_timer_ctx_index) can work correctly at an early stage. Signed-off-by: Marc Zyngier <maz@kernel.org> --- arch/arm64/include/asm/kvm_host.h | 6 ++ arch/arm64/kvm/arch_timer.c | 155 +++++++++++++++++++++++------- arch/arm64/kvm/trace_arm.h | 8 +- include/kvm/arm_arch_timer.h | 11 +-- 4 files changed, 136 insertions(+), 44 deletions(-)