~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/riscv/kvm/vcpu_timer.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /arch/riscv/kvm/vcpu_timer.c (Architecture ppc) and /arch/sparc64/kvm/vcpu_timer.c (Architecture sparc64)


  1 // SPDX-License-Identifier: GPL-2.0                 1 
  2 /*                                                
  3  * Copyright (C) 2019 Western Digital Corporat    
  4  *                                                
  5  * Authors:                                       
  6  *     Atish Patra <atish.patra@wdc.com>          
  7  */                                               
  8                                                   
  9 #include <linux/errno.h>                          
 10 #include <linux/err.h>                            
 11 #include <linux/kvm_host.h>                       
 12 #include <linux/uaccess.h>                        
 13 #include <clocksource/timer-riscv.h>              
 14 #include <asm/csr.h>                              
 15 #include <asm/delay.h>                            
 16 #include <asm/kvm_vcpu_timer.h>                   
 17                                                   
 18 static u64 kvm_riscv_current_cycles(struct kvm    
 19 {                                                 
 20         return get_cycles64() + gt->time_delta    
 21 }                                                 
 22                                                   
 23 static u64 kvm_riscv_delta_cycles2ns(u64 cycle    
 24                                      struct kv    
 25                                      struct kv    
 26 {                                                 
 27         unsigned long flags;                      
 28         u64 cycles_now, cycles_delta, delta_ns    
 29                                                   
 30         local_irq_save(flags);                    
 31         cycles_now = kvm_riscv_current_cycles(    
 32         if (cycles_now < cycles)                  
 33                 cycles_delta = cycles - cycles    
 34         else                                      
 35                 cycles_delta = 0;                 
 36         delta_ns = (cycles_delta * gt->nsec_mu    
 37         local_irq_restore(flags);                 
 38                                                   
 39         return delta_ns;                          
 40 }                                                 
 41                                                   
 42 static enum hrtimer_restart kvm_riscv_vcpu_hrt    
 43 {                                                 
 44         u64 delta_ns;                             
 45         struct kvm_vcpu_timer *t = container_o    
 46         struct kvm_vcpu *vcpu = container_of(t    
 47         struct kvm_guest_timer *gt = &vcpu->kv    
 48                                                   
 49         if (kvm_riscv_current_cycles(gt) < t->    
 50                 delta_ns = kvm_riscv_delta_cyc    
 51                 hrtimer_forward_now(&t->hrt, k    
 52                 return HRTIMER_RESTART;           
 53         }                                         
 54                                                   
 55         t->next_set = false;                      
 56         kvm_riscv_vcpu_set_interrupt(vcpu, IRQ    
 57                                                   
 58         return HRTIMER_NORESTART;                 
 59 }                                                 
 60                                                   
 61 static int kvm_riscv_vcpu_timer_cancel(struct     
 62 {                                                 
 63         if (!t->init_done || !t->next_set)        
 64                 return -EINVAL;                   
 65                                                   
 66         hrtimer_cancel(&t->hrt);                  
 67         t->next_set = false;                      
 68                                                   
 69         return 0;                                 
 70 }                                                 
 71                                                   
 72 static int kvm_riscv_vcpu_update_vstimecmp(str    
 73 {                                                 
 74 #if defined(CONFIG_32BIT)                         
 75                 csr_write(CSR_VSTIMECMP, ncycl    
 76                 csr_write(CSR_VSTIMECMPH, ncyc    
 77 #else                                             
 78                 csr_write(CSR_VSTIMECMP, ncycl    
 79 #endif                                            
 80                 return 0;                         
 81 }                                                 
 82                                                   
 83 static int kvm_riscv_vcpu_update_hrtimer(struc    
 84 {                                                 
 85         struct kvm_vcpu_timer *t = &vcpu->arch    
 86         struct kvm_guest_timer *gt = &vcpu->kv    
 87         u64 delta_ns;                             
 88                                                   
 89         if (!t->init_done)                        
 90                 return -EINVAL;                   
 91                                                   
 92         kvm_riscv_vcpu_unset_interrupt(vcpu, I    
 93                                                   
 94         delta_ns = kvm_riscv_delta_cycles2ns(n    
 95         t->next_cycles = ncycles;                 
 96         hrtimer_start(&t->hrt, ktime_set(0, de    
 97         t->next_set = true;                       
 98                                                   
 99         return 0;                                 
100 }                                                 
101                                                   
102 int kvm_riscv_vcpu_timer_next_event(struct kvm    
103 {                                                 
104         struct kvm_vcpu_timer *t = &vcpu->arch    
105                                                   
106         return t->timer_next_event(vcpu, ncycl    
107 }                                                 
108                                                   
109 static enum hrtimer_restart kvm_riscv_vcpu_vst    
110 {                                                 
111         u64 delta_ns;                             
112         struct kvm_vcpu_timer *t = container_o    
113         struct kvm_vcpu *vcpu = container_of(t    
114         struct kvm_guest_timer *gt = &vcpu->kv    
115                                                   
116         if (kvm_riscv_current_cycles(gt) < t->    
117                 delta_ns = kvm_riscv_delta_cyc    
118                 hrtimer_forward_now(&t->hrt, k    
119                 return HRTIMER_RESTART;           
120         }                                         
121                                                   
122         t->next_set = false;                      
123         kvm_vcpu_kick(vcpu);                      
124                                                   
125         return HRTIMER_NORESTART;                 
126 }                                                 
127                                                   
128 bool kvm_riscv_vcpu_timer_pending(struct kvm_v    
129 {                                                 
130         struct kvm_vcpu_timer *t = &vcpu->arch    
131         struct kvm_guest_timer *gt = &vcpu->kv    
132                                                   
133         if (!kvm_riscv_delta_cycles2ns(t->next    
134             kvm_riscv_vcpu_has_interrupts(vcpu    
135                 return true;                      
136         else                                      
137                 return false;                     
138 }                                                 
139                                                   
140 static void kvm_riscv_vcpu_timer_blocking(stru    
141 {                                                 
142         struct kvm_vcpu_timer *t = &vcpu->arch    
143         struct kvm_guest_timer *gt = &vcpu->kv    
144         u64 delta_ns;                             
145                                                   
146         if (!t->init_done)                        
147                 return;                           
148                                                   
149         delta_ns = kvm_riscv_delta_cycles2ns(t    
150         hrtimer_start(&t->hrt, ktime_set(0, de    
151         t->next_set = true;                       
152 }                                                 
153                                                   
154 static void kvm_riscv_vcpu_timer_unblocking(st    
155 {                                                 
156         kvm_riscv_vcpu_timer_cancel(&vcpu->arc    
157 }                                                 
158                                                   
159 int kvm_riscv_vcpu_get_reg_timer(struct kvm_vc    
160                                  const struct     
161 {                                                 
162         struct kvm_vcpu_timer *t = &vcpu->arch    
163         struct kvm_guest_timer *gt = &vcpu->kv    
164         u64 __user *uaddr = (u64 __user *)(uns    
165         unsigned long reg_num = reg->id & ~(KV    
166                                             KV    
167                                             KV    
168         u64 reg_val;                              
169                                                   
170         if (KVM_REG_SIZE(reg->id) != sizeof(u6    
171                 return -EINVAL;                   
172         if (reg_num >= sizeof(struct kvm_riscv    
173                 return -ENOENT;                   
174                                                   
175         switch (reg_num) {                        
176         case KVM_REG_RISCV_TIMER_REG(frequency    
177                 reg_val = riscv_timebase;         
178                 break;                            
179         case KVM_REG_RISCV_TIMER_REG(time):       
180                 reg_val = kvm_riscv_current_cy    
181                 break;                            
182         case KVM_REG_RISCV_TIMER_REG(compare):    
183                 reg_val = t->next_cycles;         
184                 break;                            
185         case KVM_REG_RISCV_TIMER_REG(state):      
186                 reg_val = (t->next_set) ? KVM_    
187                                           KVM_    
188                 break;                            
189         default:                                  
190                 return -ENOENT;                   
191         }                                         
192                                                   
193         if (copy_to_user(uaddr, &reg_val, KVM_    
194                 return -EFAULT;                   
195                                                   
196         return 0;                                 
197 }                                                 
198                                                   
199 int kvm_riscv_vcpu_set_reg_timer(struct kvm_vc    
200                                  const struct     
201 {                                                 
202         struct kvm_vcpu_timer *t = &vcpu->arch    
203         struct kvm_guest_timer *gt = &vcpu->kv    
204         u64 __user *uaddr = (u64 __user *)(uns    
205         unsigned long reg_num = reg->id & ~(KV    
206                                             KV    
207                                             KV    
208         u64 reg_val;                              
209         int ret = 0;                              
210                                                   
211         if (KVM_REG_SIZE(reg->id) != sizeof(u6    
212                 return -EINVAL;                   
213         if (reg_num >= sizeof(struct kvm_riscv    
214                 return -ENOENT;                   
215                                                   
216         if (copy_from_user(&reg_val, uaddr, KV    
217                 return -EFAULT;                   
218                                                   
219         switch (reg_num) {                        
220         case KVM_REG_RISCV_TIMER_REG(frequency    
221                 if (reg_val != riscv_timebase)    
222                         return -EINVAL;           
223                 break;                            
224         case KVM_REG_RISCV_TIMER_REG(time):       
225                 gt->time_delta = reg_val - get    
226                 break;                            
227         case KVM_REG_RISCV_TIMER_REG(compare):    
228                 t->next_cycles = reg_val;         
229                 break;                            
230         case KVM_REG_RISCV_TIMER_REG(state):      
231                 if (reg_val == KVM_RISCV_TIMER    
232                         ret = kvm_riscv_vcpu_t    
233                 else                              
234                         ret = kvm_riscv_vcpu_t    
235                 break;                            
236         default:                                  
237                 ret = -ENOENT;                    
238                 break;                            
239         }                                         
240                                                   
241         return ret;                               
242 }                                                 
243                                                   
244 int kvm_riscv_vcpu_timer_init(struct kvm_vcpu     
245 {                                                 
246         struct kvm_vcpu_timer *t = &vcpu->arch    
247                                                   
248         if (t->init_done)                         
249                 return -EINVAL;                   
250                                                   
251         hrtimer_init(&t->hrt, CLOCK_MONOTONIC,    
252         t->init_done = true;                      
253         t->next_set = false;                      
254                                                   
255         /* Enable sstc for every vcpu if avail    
256         if (riscv_isa_extension_available(NULL    
257                 t->sstc_enabled = true;           
258                 t->hrt.function = kvm_riscv_vc    
259                 t->timer_next_event = kvm_risc    
260         } else {                                  
261                 t->sstc_enabled = false;          
262                 t->hrt.function = kvm_riscv_vc    
263                 t->timer_next_event = kvm_risc    
264         }                                         
265                                                   
266         return 0;                                 
267 }                                                 
268                                                   
269 int kvm_riscv_vcpu_timer_deinit(struct kvm_vcp    
270 {                                                 
271         int ret;                                  
272                                                   
273         ret = kvm_riscv_vcpu_timer_cancel(&vcp    
274         vcpu->arch.timer.init_done = false;       
275                                                   
276         return ret;                               
277 }                                                 
278                                                   
279 int kvm_riscv_vcpu_timer_reset(struct kvm_vcpu    
280 {                                                 
281         struct kvm_vcpu_timer *t = &vcpu->arch    
282                                                   
283         t->next_cycles = -1ULL;                   
284         return kvm_riscv_vcpu_timer_cancel(&vc    
285 }                                                 
286                                                   
287 static void kvm_riscv_vcpu_update_timedelta(st    
288 {                                                 
289         struct kvm_guest_timer *gt = &vcpu->kv    
290                                                   
291 #if defined(CONFIG_32BIT)                         
292         csr_write(CSR_HTIMEDELTA, (u32)(gt->ti    
293         csr_write(CSR_HTIMEDELTAH, (u32)(gt->t    
294 #else                                             
295         csr_write(CSR_HTIMEDELTA, gt->time_del    
296 #endif                                            
297 }                                                 
298                                                   
299 void kvm_riscv_vcpu_timer_restore(struct kvm_v    
300 {                                                 
301         struct kvm_vcpu_timer *t = &vcpu->arch    
302                                                   
303         kvm_riscv_vcpu_update_timedelta(vcpu);    
304                                                   
305         if (!t->sstc_enabled)                     
306                 return;                           
307                                                   
308 #if defined(CONFIG_32BIT)                         
309         csr_write(CSR_VSTIMECMP, (u32)t->next_    
310         csr_write(CSR_VSTIMECMPH, (u32)(t->nex    
311 #else                                             
312         csr_write(CSR_VSTIMECMP, t->next_cycle    
313 #endif                                            
314                                                   
315         /* timer should be enabled for the rem    
316         if (unlikely(!t->init_done))              
317                 return;                           
318                                                   
319         kvm_riscv_vcpu_timer_unblocking(vcpu);    
320 }                                                 
321                                                   
322 void kvm_riscv_vcpu_timer_sync(struct kvm_vcpu    
323 {                                                 
324         struct kvm_vcpu_timer *t = &vcpu->arch    
325                                                   
326         if (!t->sstc_enabled)                     
327                 return;                           
328                                                   
329 #if defined(CONFIG_32BIT)                         
330         t->next_cycles = csr_read(CSR_VSTIMECM    
331         t->next_cycles |= (u64)csr_read(CSR_VS    
332 #else                                             
333         t->next_cycles = csr_read(CSR_VSTIMECM    
334 #endif                                            
335 }                                                 
336                                                   
337 void kvm_riscv_vcpu_timer_save(struct kvm_vcpu    
338 {                                                 
339         struct kvm_vcpu_timer *t = &vcpu->arch    
340                                                   
341         if (!t->sstc_enabled)                     
342                 return;                           
343                                                   
344         /*                                        
345          * The vstimecmp CSRs are saved by kvm    
346          * upon every VM exit so no need to sa    
347          */                                       
348                                                   
349         /* timer should be enabled for the rem    
350         if (unlikely(!t->init_done))              
351                 return;                           
352                                                   
353         if (kvm_vcpu_is_blocking(vcpu))           
354                 kvm_riscv_vcpu_timer_blocking(    
355 }                                                 
356                                                   
357 void kvm_riscv_guest_timer_init(struct kvm *kv    
358 {                                                 
359         struct kvm_guest_timer *gt = &kvm->arc    
360                                                   
361         riscv_cs_get_mult_shift(&gt->nsec_mult    
362         gt->time_delta = -get_cycles64();         
363 }                                                 
364                                                   

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php