diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2012-12-07 12:52:03 -0500 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2013-06-12 11:40:32 -0400 |
commit | 003300de6c3e51934fb52eb2677f6f4fb4996cbd (patch) | |
tree | 1d214ebdd5cdcc9f86a0a44c6670a55c4da7f53f /arch/arm64/kvm | |
parent | f61701e0a24a09aa4a44baf24e57dcc5e706afa8 (diff) |
arm64: KVM: Plug the arch timer
Add support for the in-kernel timer emulation.
Reviewed-by: Christopher Covington <cov@codeaurora.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'arch/arm64/kvm')
-rw-r--r-- | arch/arm64/kvm/hyp.S | 56 | ||||
-rw-r--r-- | arch/arm64/kvm/reset.c | 12 |
2 files changed, 68 insertions, 0 deletions
diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S index 8dc27a367d77..8b510835b440 100644 --- a/arch/arm64/kvm/hyp.S +++ b/arch/arm64/kvm/hyp.S | |||
@@ -390,6 +390,60 @@ __kvm_hyp_code_start: | |||
390 | 2: | 390 | 2: |
391 | .endm | 391 | .endm |
392 | 392 | ||
393 | .macro save_timer_state | ||
394 | // x0: vcpu pointer | ||
395 | ldr x2, [x0, #VCPU_KVM] | ||
396 | kern_hyp_va x2 | ||
397 | ldr w3, [x2, #KVM_TIMER_ENABLED] | ||
398 | cbz w3, 1f | ||
399 | |||
400 | mrs x3, cntv_ctl_el0 | ||
401 | and x3, x3, #3 | ||
402 | str w3, [x0, #VCPU_TIMER_CNTV_CTL] | ||
403 | bic x3, x3, #1 // Clear Enable | ||
404 | msr cntv_ctl_el0, x3 | ||
405 | |||
406 | isb | ||
407 | |||
408 | mrs x3, cntv_cval_el0 | ||
409 | str x3, [x0, #VCPU_TIMER_CNTV_CVAL] | ||
410 | |||
411 | 1: | ||
412 | // Allow physical timer/counter access for the host | ||
413 | mrs x2, cnthctl_el2 | ||
414 | orr x2, x2, #3 | ||
415 | msr cnthctl_el2, x2 | ||
416 | |||
417 | // Clear cntvoff for the host | ||
418 | msr cntvoff_el2, xzr | ||
419 | .endm | ||
420 | |||
421 | .macro restore_timer_state | ||
422 | // x0: vcpu pointer | ||
423 | // Disallow physical timer access for the guest | ||
424 | // Physical counter access is allowed | ||
425 | mrs x2, cnthctl_el2 | ||
426 | orr x2, x2, #1 | ||
427 | bic x2, x2, #2 | ||
428 | msr cnthctl_el2, x2 | ||
429 | |||
430 | ldr x2, [x0, #VCPU_KVM] | ||
431 | kern_hyp_va x2 | ||
432 | ldr w3, [x2, #KVM_TIMER_ENABLED] | ||
433 | cbz w3, 1f | ||
434 | |||
435 | ldr x3, [x2, #KVM_TIMER_CNTVOFF] | ||
436 | msr cntvoff_el2, x3 | ||
437 | ldr x2, [x0, #VCPU_TIMER_CNTV_CVAL] | ||
438 | msr cntv_cval_el0, x2 | ||
439 | isb | ||
440 | |||
441 | ldr w2, [x0, #VCPU_TIMER_CNTV_CTL] | ||
442 | and x2, x2, #3 | ||
443 | msr cntv_ctl_el0, x2 | ||
444 | 1: | ||
445 | .endm | ||
446 | |||
393 | __save_sysregs: | 447 | __save_sysregs: |
394 | save_sysregs | 448 | save_sysregs |
395 | ret | 449 | ret |
@@ -433,6 +487,7 @@ ENTRY(__kvm_vcpu_run) | |||
433 | activate_vm | 487 | activate_vm |
434 | 488 | ||
435 | restore_vgic_state | 489 | restore_vgic_state |
490 | restore_timer_state | ||
436 | 491 | ||
437 | // Guest context | 492 | // Guest context |
438 | add x2, x0, #VCPU_CONTEXT | 493 | add x2, x0, #VCPU_CONTEXT |
@@ -455,6 +510,7 @@ __kvm_vcpu_return: | |||
455 | bl __save_fpsimd | 510 | bl __save_fpsimd |
456 | bl __save_sysregs | 511 | bl __save_sysregs |
457 | 512 | ||
513 | save_timer_state | ||
458 | save_vgic_state | 514 | save_vgic_state |
459 | 515 | ||
460 | deactivate_traps | 516 | deactivate_traps |
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index f6536a06231a..766150ac76ed 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/kvm_host.h> | 23 | #include <linux/kvm_host.h> |
24 | #include <linux/kvm.h> | 24 | #include <linux/kvm.h> |
25 | 25 | ||
26 | #include <kvm/arm_arch_timer.h> | ||
27 | |||
26 | #include <asm/cputype.h> | 28 | #include <asm/cputype.h> |
27 | #include <asm/ptrace.h> | 29 | #include <asm/ptrace.h> |
28 | #include <asm/kvm_arm.h> | 30 | #include <asm/kvm_arm.h> |
@@ -36,6 +38,11 @@ static const struct kvm_regs default_regs_reset = { | |||
36 | PSR_F_BIT | PSR_D_BIT), | 38 | PSR_F_BIT | PSR_D_BIT), |
37 | }; | 39 | }; |
38 | 40 | ||
41 | static const struct kvm_irq_level default_vtimer_irq = { | ||
42 | .irq = 27, | ||
43 | .level = 1, | ||
44 | }; | ||
45 | |||
39 | int kvm_arch_dev_ioctl_check_extension(long ext) | 46 | int kvm_arch_dev_ioctl_check_extension(long ext) |
40 | { | 47 | { |
41 | int r; | 48 | int r; |
@@ -58,11 +65,13 @@ int kvm_arch_dev_ioctl_check_extension(long ext) | |||
58 | */ | 65 | */ |
59 | int kvm_reset_vcpu(struct kvm_vcpu *vcpu) | 66 | int kvm_reset_vcpu(struct kvm_vcpu *vcpu) |
60 | { | 67 | { |
68 | const struct kvm_irq_level *cpu_vtimer_irq; | ||
61 | const struct kvm_regs *cpu_reset; | 69 | const struct kvm_regs *cpu_reset; |
62 | 70 | ||
63 | switch (vcpu->arch.target) { | 71 | switch (vcpu->arch.target) { |
64 | default: | 72 | default: |
65 | cpu_reset = &default_regs_reset; | 73 | cpu_reset = &default_regs_reset; |
74 | cpu_vtimer_irq = &default_vtimer_irq; | ||
66 | break; | 75 | break; |
67 | } | 76 | } |
68 | 77 | ||
@@ -72,5 +81,8 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) | |||
72 | /* Reset system registers */ | 81 | /* Reset system registers */ |
73 | kvm_reset_sys_regs(vcpu); | 82 | kvm_reset_sys_regs(vcpu); |
74 | 83 | ||
84 | /* Reset timer */ | ||
85 | kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq); | ||
86 | |||
75 | return 0; | 87 | return 0; |
76 | } | 88 | } |