diff options
Diffstat (limited to 'arch/powerpc/kvm/emulate.c')
-rw-r--r-- | arch/powerpc/kvm/emulate.c | 61 |
1 files changed, 32 insertions, 29 deletions
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c index 141dce3c6810..968f40101883 100644 --- a/arch/powerpc/kvm/emulate.c +++ b/arch/powerpc/kvm/emulate.c | |||
@@ -13,6 +13,7 @@ | |||
13 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 13 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
14 | * | 14 | * |
15 | * Copyright IBM Corp. 2007 | 15 | * Copyright IBM Corp. 2007 |
16 | * Copyright 2011 Freescale Semiconductor, Inc. | ||
16 | * | 17 | * |
17 | * Authors: Hollis Blanchard <hollisb@us.ibm.com> | 18 | * Authors: Hollis Blanchard <hollisb@us.ibm.com> |
18 | */ | 19 | */ |
@@ -69,54 +70,55 @@ | |||
69 | #define OP_STH 44 | 70 | #define OP_STH 44 |
70 | #define OP_STHU 45 | 71 | #define OP_STHU 45 |
71 | 72 | ||
72 | #ifdef CONFIG_PPC_BOOK3S | ||
73 | static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu) | ||
74 | { | ||
75 | return 1; | ||
76 | } | ||
77 | #else | ||
78 | static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu) | ||
79 | { | ||
80 | return vcpu->arch.tcr & TCR_DIE; | ||
81 | } | ||
82 | #endif | ||
83 | |||
84 | void kvmppc_emulate_dec(struct kvm_vcpu *vcpu) | 73 | void kvmppc_emulate_dec(struct kvm_vcpu *vcpu) |
85 | { | 74 | { |
86 | unsigned long dec_nsec; | 75 | unsigned long dec_nsec; |
76 | unsigned long long dec_time; | ||
87 | 77 | ||
88 | pr_debug("mtDEC: %x\n", vcpu->arch.dec); | 78 | pr_debug("mtDEC: %x\n", vcpu->arch.dec); |
79 | hrtimer_try_to_cancel(&vcpu->arch.dec_timer); | ||
80 | |||
89 | #ifdef CONFIG_PPC_BOOK3S | 81 | #ifdef CONFIG_PPC_BOOK3S |
90 | /* mtdec lowers the interrupt line when positive. */ | 82 | /* mtdec lowers the interrupt line when positive. */ |
91 | kvmppc_core_dequeue_dec(vcpu); | 83 | kvmppc_core_dequeue_dec(vcpu); |
92 | 84 | ||
93 | /* POWER4+ triggers a dec interrupt if the value is < 0 */ | 85 | /* POWER4+ triggers a dec interrupt if the value is < 0 */ |
94 | if (vcpu->arch.dec & 0x80000000) { | 86 | if (vcpu->arch.dec & 0x80000000) { |
95 | hrtimer_try_to_cancel(&vcpu->arch.dec_timer); | ||
96 | kvmppc_core_queue_dec(vcpu); | 87 | kvmppc_core_queue_dec(vcpu); |
97 | return; | 88 | return; |
98 | } | 89 | } |
99 | #endif | 90 | #endif |
100 | if (kvmppc_dec_enabled(vcpu)) { | 91 | |
101 | /* The decrementer ticks at the same rate as the timebase, so | 92 | #ifdef CONFIG_BOOKE |
102 | * that's how we convert the guest DEC value to the number of | 93 | /* On BOOKE, DEC = 0 is as good as decrementer not enabled */ |
103 | * host ticks. */ | 94 | if (vcpu->arch.dec == 0) |
104 | 95 | return; | |
105 | hrtimer_try_to_cancel(&vcpu->arch.dec_timer); | 96 | #endif |
106 | dec_nsec = vcpu->arch.dec; | 97 | |
107 | dec_nsec *= 1000; | 98 | /* |
108 | dec_nsec /= tb_ticks_per_usec; | 99 | * The decrementer ticks at the same rate as the timebase, so |
109 | hrtimer_start(&vcpu->arch.dec_timer, ktime_set(0, dec_nsec), | 100 | * that's how we convert the guest DEC value to the number of |
110 | HRTIMER_MODE_REL); | 101 | * host ticks. |
111 | vcpu->arch.dec_jiffies = get_tb(); | 102 | */ |
112 | } else { | 103 | |
113 | hrtimer_try_to_cancel(&vcpu->arch.dec_timer); | 104 | dec_time = vcpu->arch.dec; |
114 | } | 105 | dec_time *= 1000; |
106 | do_div(dec_time, tb_ticks_per_usec); | ||
107 | dec_nsec = do_div(dec_time, NSEC_PER_SEC); | ||
108 | hrtimer_start(&vcpu->arch.dec_timer, | ||
109 | ktime_set(dec_time, dec_nsec), HRTIMER_MODE_REL); | ||
110 | vcpu->arch.dec_jiffies = get_tb(); | ||
115 | } | 111 | } |
116 | 112 | ||
117 | u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb) | 113 | u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb) |
118 | { | 114 | { |
119 | u64 jd = tb - vcpu->arch.dec_jiffies; | 115 | u64 jd = tb - vcpu->arch.dec_jiffies; |
116 | |||
117 | #ifdef CONFIG_BOOKE | ||
118 | if (vcpu->arch.dec < jd) | ||
119 | return 0; | ||
120 | #endif | ||
121 | |||
120 | return vcpu->arch.dec - jd; | 122 | return vcpu->arch.dec - jd; |
121 | } | 123 | } |
122 | 124 | ||
@@ -159,7 +161,8 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
159 | case OP_TRAP_64: | 161 | case OP_TRAP_64: |
160 | kvmppc_core_queue_program(vcpu, SRR1_PROGTRAP); | 162 | kvmppc_core_queue_program(vcpu, SRR1_PROGTRAP); |
161 | #else | 163 | #else |
162 | kvmppc_core_queue_program(vcpu, vcpu->arch.esr | ESR_PTR); | 164 | kvmppc_core_queue_program(vcpu, |
165 | vcpu->arch.shared->esr | ESR_PTR); | ||
163 | #endif | 166 | #endif |
164 | advance = 0; | 167 | advance = 0; |
165 | break; | 168 | break; |