Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


P-State control interface - Linux implementation
[palacios.git] / linux_module / iface-pstate-ctrl.c
1 /*
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2014, the V3VEE Project <http://www.v3vee.org>
11  * all rights reserved.
12  *
13  * Author: Kyle C. Hale <kh@u.northwestern.edu>
14  *         Shiva Rao <shiva.rao.717@gmail.com>
15  *         Peter Dinda <pdinda@northwestern.edu>
16  *
17  * This is free software.  you are permitted to use,
18  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
19  */
20
21 #include <linux/uaccess.h>
22 #include <linux/seq_file.h>
23 #include <linux/proc_fs.h>
24 #include <linux/cpufreq.h>
25 #include <asm/processor.h>
26 #include <asm/msr.h>
27 #include <asm/msr-index.h>
28
29 #include <interfaces/vmm_pstate_ctrl.h>
30
31 #include "palacios.h"
32 #include "iface-pstate-ctrl.h"
33
34 #include "linux-exts.h"
35
36 /*
37   This P-STATE control implementation includes:
38
39   - Direct control of Intel and AMD processor pstates
40   - External control of processor states via Linux (unimplemented)
41   - Internal control of processor states in Palacios (handoff from Linux)
42
43   Additionally, it provides a user-space interface for manipulating
44   p-state regardless of the host's functionality.  This includes
45   an ioctl for commanding the implementation and a /proc file for 
46   showing current status and capabilities.
47
48 */
49
50
51
52
53 struct pstate_core_info {
54     // Here we have the notion of host control
55 #define V3_PSTATE_HOST_CONTROL 0
56     // and all the modes from the Palacios interface:
57     // V3_PSTATE_EXTERNAL_CONTROL
58     // V3_PSTATE_DIRECT_CONTROL
59     // V3_PSTATE_INTERNAL_CONTROL
60     uint32_t mode;
61     
62     // Apply if we are under the DIRECT state
63     uint8_t cur_pstate;
64     uint8_t max_pstate;
65     uint8_t min_pstate;
66
67     uint8_t cur_hw_pstate;
68
69     // Apply if we are under the EXTERNAL state
70     uint64_t cur_freq_khz;
71     uint64_t max_freq_khz;
72     uint64_t min_freq_khz;
73    
74     // Intel-specific for DIRECT state
75     uint8_t turbo_disabled;
76     uint8_t no_turbo;
77     
78     int have_cpufreq;
79     
80 };
81
82
83 static DEFINE_PER_CPU(struct pstate_core_info, core_state);
84
85
86 // These are used to assert DIRECT control over the core pstates
87 struct pstate_core_funcs {
88     void    (*arch_init)(void);
89     void    (*arch_deinit)(void);
90     uint8_t (*get_min_pstate)(void);
91     uint8_t (*get_max_pstate)(void);
92     uint8_t (*get_pstate)(void);
93     void    (*set_pstate)(uint8_t pstate);
94 };
95
96 struct pstate_machine_info {
97     enum {INTEL, AMD, OTHER } arch;
98     int supports_pstates;
99     // used for DIRECT control
100     struct pstate_core_funcs *funcs;
101 };
102
103 static struct pstate_machine_info machine_state;
104
105
106 /****************************************************
107    AMD  DIRECT CONTROL
108 ***************************************************/
109
110 /* AMD Programmer's Manual Vol 2 (Rev 3, 2013), Sec. 17.1, pp.557 */
111 #define MSR_PSTATE_LIMIT_REG_AMD 0xc0010061
112 #define MSR_PSTATE_CTL_REG_AMD   0xc0010062
113 #define MSR_PSTATE_STAT_REG_AMD  0xc0010063
114
115 struct p_state_limit_reg_amd {
116     union {
117         uint64_t val;
118         struct {
119             uint8_t  pstate_limit : 4; /* lowest P-state value (highest perf.) supported currently (this can change at runtime) */
120             uint8_t  pstate_max   : 4; /* highest P-state value supported  (lowest perf) */
121             uint64_t rsvd         : 56;
122         } reg;
123     } __attribute__((packed));
124 } __attribute__((packed));
125
126
127 struct p_state_stat_reg_amd {
128     union {
129         uint64_t val;
130         struct {
131             uint8_t  pstate  : 4;
132             uint64_t rsvd    : 60;
133         } reg;
134     } __attribute__((packed));
135 } __attribute__((packed));
136
137
138 struct p_state_ctl_reg_amd {
139     union {
140         uint64_t val;
141         struct {
142             uint8_t  cmd  : 4;
143             uint64_t rsvd : 60;
144         } reg;
145     } __attribute__((packed));
146 } __attribute__((packed));
147
148
149 /* CPUID Fn8000_0007_EDX[HwPstate(7)] = 1 */
150 static uint8_t supports_pstates_amd (void)
151 {
152     uint32_t eax, ebx, ecx, edx;
153     cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
154     return !!(edx & (1 << 7));
155 }
156
157 static void init_arch_amd(void)
158 {
159     /* KCH: nothing to do here */
160 }
161
162 static void deinit_arch_amd(void)
163 {
164     /* KCH: nothing to do here */
165 }
166
167 static uint8_t get_pstate_amd(void) 
168 {
169     struct p_state_stat_reg_amd pstat;
170
171     rdmsrl(MSR_PSTATE_STAT_REG_AMD, pstat.val);
172
173     get_cpu_var(core_state).cur_pstate=pstat.reg.pstate;
174     put_cpu_var(core_state);
175
176     return pstat.reg.pstate;
177 }
178
179 static void set_pstate_amd(uint8_t p)
180 {
181     struct p_state_ctl_reg_amd pctl;
182     pctl.val = 0;
183     pctl.reg.cmd = p;
184
185     wrmsrl(MSR_PSTATE_CTL_REG_AMD, pctl.val);
186
187     get_cpu_var(core_state).cur_pstate=p;
188     put_cpu_var(core_state);
189 }
190
191 /*
192  * NOTE: HW may change this value at runtime
193  */
194 static uint8_t get_max_pstate_amd(void)
195 {
196     struct p_state_limit_reg_amd plimits;
197
198     rdmsrl(MSR_PSTATE_LIMIT_REG_AMD, plimits.val);
199
200     return plimits.reg.pstate_max;
201 }
202
203
204 static uint8_t get_min_pstate_amd(void)
205 {
206     struct p_state_limit_reg_amd plimits;
207
208     rdmsrl(MSR_PSTATE_LIMIT_REG_AMD, plimits.val);
209
210     return plimits.reg.pstate_limit;
211 }
212
213
214 static struct pstate_core_funcs amd_funcs =
215 {
216     .arch_init        = init_arch_amd,
217     .arch_deinit      = deinit_arch_amd,
218     .get_pstate       = get_pstate_amd,
219     .set_pstate       = set_pstate_amd,
220     .get_max_pstate   = get_max_pstate_amd,
221     .get_min_pstate   = get_min_pstate_amd,
222 };
223
224
225
226 /***********************************************************
227   INTEL DIRECT CONTROL
228 **********************************************************/
229
230
231 /* Intel System Programmer's Manual Vol. 3B, 14-2 */
232 #define MSR_MPERF_IA32         0x000000e7
233 #define MSR_APERF_IA32         0x000000e8
234 #define MSR_MISC_ENABLE_IA32   0x000001a0
235 #define MSR_NHM_TURBO_RATIO_LIMIT   0x000001ad
236 #define MSR_PLATFORM_INFO_IA32 0x000000ce
237 #define MSR_PERF_CTL_IA32      0x00000199
238
239
240
241 struct turbo_mode_info_reg_intel {
242     union {
243         uint64_t val;
244         struct {
245             uint8_t  rsvd0;
246             uint8_t  max_noturbo_ratio;
247             uint16_t rsvd1                  : 12;
248             uint8_t  ratio_limit            : 1;
249             uint8_t  tdc_tdp_limit          : 1;
250             uint16_t rsvd2                  : 10;
251             uint8_t  min_ratio;
252             uint16_t rsvd3;
253         } reg;
254     } __attribute__((packed));
255 } __attribute__((packed));
256             
257
258 /* CPUID.01:ECX.AES(7) */
259 static uint8_t supports_pstates_intel(void)
260 {
261     /* NOTE: CPUID.06H:ECX.SETBH[bit 3] is set and it also implies the presence of a new architectural MSR called IA32_ENERGY_PERF_BIAS (1B0H).
262      */
263     uint32_t eax, ebx, ecx, edx;
264     cpuid(0x1, &eax, &ebx, &ecx, &edx);
265     return !!(ecx & (1 << 7));
266 }
267
268
269 static void init_arch_intel(void)
270 {
271     uint64_t val;
272
273     rdmsrl(MSR_MISC_ENABLE_IA32, val);
274
275     val |= 1 << 16;
276
277     wrmsrl(MSR_MISC_ENABLE_IA32, val);
278
279 }
280
281 static void deinit_arch_intel(void)
282 {
283     // ??
284 }
285
286 /* TODO: Intel P-states require sampling at intervals... */
287 static uint8_t get_pstate_intel(void)
288 {
289     uint8_t pstate;
290
291     // This should read the HW... 
292     pstate=get_cpu_var(core_state).cur_pstate;
293     put_cpu_var(core_state);
294     return pstate;
295 }
296     
297 static void set_pstate_intel(uint8_t p)
298 {
299     uint64_t val = ((uint64_t)p) << 8;
300
301     /* ...Intel IDA (dynamic acceleration)
302     if (c->no_turbo && !c->turbo_disabled) {
303         val |= 1 << 32;
304     }
305     */
306
307     wrmsrl(MSR_PERF_CTL_IA32, val);
308
309     get_cpu_var(core_state).cur_pstate = p;
310     put_cpu_var(core_state);
311 }
312
313
314 static uint8_t get_min_pstate_intel(void)
315 {
316     struct turbo_mode_info_reg_intel t;
317
318     rdmsrl(MSR_PLATFORM_INFO_IA32, t.val);
319
320     return t.reg.min_ratio;
321 }
322
323
324
325 static uint8_t get_max_pstate_intel (void)
326 {
327     struct turbo_mode_info_reg_intel t;
328     
329     rdmsrl(MSR_PLATFORM_INFO_IA32, t.val);
330
331     return t.reg.max_noturbo_ratio;
332 }
333
334 static struct pstate_core_funcs intel_funcs =
335 {
336     .arch_init        = init_arch_intel,
337     .arch_deinit      = deinit_arch_intel,
338     .get_pstate       = get_pstate_intel,
339     .set_pstate       = set_pstate_intel,
340     .get_max_pstate   = get_max_pstate_intel,
341     .get_min_pstate   = get_min_pstate_intel,
342 };
343
344
345
346 /***********************************************
347   Arch determination and setup
348 ***********************************************/
349  
350 static inline void cpuid_string (uint32_t id, uint32_t dest[4]) 
351 {
352     asm volatile("cpuid"
353                  :"=a"(*dest),"=b"(*(dest+1)),"=c"(*(dest+2)),"=d"(*(dest+3))
354                  :"a"(id));
355 }
356     
357
358 static int get_cpu_vendor (char name[13])
359 {
360     uint32_t dest[4];
361     uint32_t maxid;
362     
363     cpuid_string(0,dest);
364     maxid=dest[0];
365     ((uint32_t*)name)[0]=dest[1];
366     ((uint32_t*)name)[1]=dest[3];
367     ((uint32_t*)name)[2]=dest[2];
368     name[12]=0;
369     
370     return maxid;
371 }
372
373
374 static int is_intel (void)
375 {
376   char name[13];
377   get_cpu_vendor(name);
378   return !strcmp(name,"GenuineIntel");
379 }
380
381
382 static int is_amd (void)
383 {
384   char name[13];
385   get_cpu_vendor(name);
386   return !strcmp(name,"AuthenticAMD");
387 }
388
389 static int pstate_arch_setup(void)
390 {
391     
392     if (is_amd()) {
393         machine_state.arch = AMD;
394         machine_state.funcs = &amd_funcs;
395         machine_state.supports_pstates = supports_pstates_amd();
396         INFO("PSTATE: P-State initialized for AMD\n");
397     } else if (is_intel()) {
398         machine_state.arch  = INTEL;
399         machine_state.funcs = &intel_funcs;
400         machine_state.supports_pstates = supports_pstates_intel();
401         INFO("PSTATE: P-State initialized for INTEL (Work in progress...)\n");
402         return 0;
403         
404     } else {
405         machine_state.arch = OTHER;
406         machine_state.funcs = NULL;
407         machine_state.supports_pstates = 0;
408         INFO("PSTATE: P-state control: No support for direct control on this architecture\n");
409         return 0;
410     }
411     
412     return 0;
413 }
414
415
416
417 /******************************************************************
418   Linux Interface
419 *****************************************************************/
420
421 #if 0
422 // The purpose of the stub governor is the pretend to keep
423 // the processor at the maximum frequency, while we manipulate he
424 // processor ccre directly
425 static int governor_run(struct cpufreq_policy *policy, unsigned int event)
426 {
427     switch (event) {
428         case CPUFREQ_GOV_START:
429         case CPUFREQ_GOV_STOP:
430             cpu_freq_driver_target(policy, policy->max_freq);
431
432         case CPUFREQ_GOV_LIMITS:
433     }                           
434 }
435
436 static struct cpufreq_governor stub_governor = 
437 {
438     .name="PALACIOS_STUB",
439     .governor=governor_run,
440     .owner=.THIS_MODULE,
441 }
442
443 static void linux_init(void)
444 {
445     // get_policy
446     //
447     // change to userspace governor - or change to our do nothing governor? (call set_speed)
448     // stash the old governor
449     // tell governor to do max freq
450
451 }
452
453 static void linux_deinit(void)
454 {
455 }
456
457 static uint8_t linux_get_pstate(void)
458 {
459     return 0;
460 }
461
462 static void linux_set_pstate(uint8_t p)
463 {
464 }
465
466 static void linux_restore_defaults(void)
467 {
468 }
469
470 #endif
471
472
473 /******************************************************************
474   Generic Interface as provided to Palacios and to the rest of the
475   module
476 ******************************************************************/
477
478 static void init_core(void)
479 {
480     unsigned cpu;
481     struct cpufreq_policy *p;
482
483
484     DEBUG("P-State Core Init\n");
485
486     get_cpu_var(core_state).mode = V3_PSTATE_HOST_CONTROL;
487     get_cpu_var(core_state).cur_pstate = 0;
488     
489     if (machine_state.funcs) {
490         get_cpu_var(core_state).min_pstate = machine_state.funcs->get_min_pstate();
491         get_cpu_var(core_state).max_pstate = machine_state.funcs->get_max_pstate();
492     } else {
493         get_cpu_var(core_state).min_pstate = 0;
494         get_cpu_var(core_state).max_pstate = 0;
495     }
496
497
498     cpu = get_cpu(); put_cpu();
499
500     p = cpufreq_cpu_get(cpu);
501
502     if (!p) { 
503         get_cpu_var(core_state).have_cpufreq = 0;
504         get_cpu_var(core_state).min_freq_khz=0;
505         get_cpu_var(core_state).max_freq_khz=0;
506         get_cpu_var(core_state).cur_freq_khz=0;
507     } else {
508         get_cpu_var(core_state).have_cpufreq = 1;
509         get_cpu_var(core_state).min_freq_khz=p->min;
510         get_cpu_var(core_state).max_freq_khz=p->max;
511         get_cpu_var(core_state).cur_freq_khz=p->cur;
512         cpufreq_cpu_put(p);
513     }
514
515     put_cpu_var(core_state);
516         
517 }
518
519
520 void palacios_pstate_ctrl_release(void);
521
522
523 static void deinit_core(void)
524 {
525     DEBUG("P-State Core Deinit\n");
526     palacios_pstate_ctrl_release();
527 }
528
529
530
531 void palacios_pstate_ctrl_get_chars(struct v3_cpu_pstate_chars *c) 
532 {
533     memset(c,0,sizeof(struct v3_cpu_pstate_chars));
534    
535
536     c->features = V3_PSTATE_INTERNAL_CONTROL;
537
538     if (get_cpu_var(core_state).have_cpufreq) {
539         c->features |= V3_PSTATE_EXTERNAL_CONTROL;
540     }
541
542     if (machine_state.arch==AMD || machine_state.arch==INTEL) { 
543         c->features |= V3_PSTATE_DIRECT_CONTROL;
544     }
545     c->cur_mode = get_cpu_var(core_state).mode;
546     c->min_pstate = get_cpu_var(core_state).min_pstate;
547     c->max_pstate = get_cpu_var(core_state).max_pstate;
548     c->cur_pstate = get_cpu_var(core_state).cur_pstate;
549     c->min_freq_khz = get_cpu_var(core_state).min_freq_khz;
550     c->max_freq_khz = get_cpu_var(core_state).max_freq_khz;
551     c->cur_freq_khz = get_cpu_var(core_state).cur_freq_khz;
552
553     put_cpu_var(core_state);
554
555     
556     
557 }
558
559
560 uint8_t palacios_pstate_ctrl_get_pstate(void)
561 {
562     if (get_cpu_var(core_state).mode==V3_PSTATE_DIRECT_CONTROL) { 
563         put_cpu_var(core_state);
564         return machine_state.funcs->get_pstate();
565     } else {
566         put_cpu_var(core_state);
567         return 0;
568     }
569 }
570
571 void palacios_pstate_ctrl_set_pstate(uint8_t p)
572 {
573     if (get_cpu_var(core_state).mode==V3_PSTATE_DIRECT_CONTROL) { 
574         put_cpu_var(core_state);
575         machine_state.funcs->set_pstate(p);
576     } 
577 }
578
579
580 void palacios_pstate_ctrl_set_pstate_wrapper(void *p)
581 {
582     palacios_pstate_ctrl_set_pstate((uint8_t)(uint64_t)p);
583 }
584
585 uint64_t palacios_pstate_ctrl_get_freq(void)
586 {
587     if (get_cpu_var(core_state).mode==V3_PSTATE_EXTERNAL_CONTROL) { 
588         put_cpu_var(core_state);
589         ERROR("Unimplemented get freq\n");
590         return 0;
591     } else {
592         put_cpu_var(core_state);
593         return 0;
594     }
595 }
596
597 void palacios_pstate_ctrl_set_freq(uint64_t p)
598 {
599     if (get_cpu_var(core_state).mode==V3_PSTATE_EXTERNAL_CONTROL) { 
600         put_cpu_var(core_state);
601         ERROR("Unimplemented set freq\n");
602     } 
603     put_cpu_var(core_state);
604
605 }
606
607
608 static void switch_to_external(void)
609 {
610     if (!(get_cpu_var(core_state).have_cpufreq)) {
611         put_cpu_var(core_state);
612         ERROR("No cpufreq  - cannot switch to external...\n");
613         return;
614     }
615     put_cpu_var(core_state);
616
617     ERROR("Unimplemented switch to external...\n");
618 }
619  
620 static void switch_to_direct(void)
621 {
622     if (get_cpu_var(core_state).have_cpufreq) { 
623         put_cpu_var(core_state);
624         ERROR("Unimplemented: switch to direct on machine with cpu freq\n");
625         // The implementation would set the policy and governor to peg cpu
626         // regardless of load
627     }
628
629     if (machine_state.funcs && machine_state.funcs->arch_init) {
630        get_cpu_var(core_state).mode=V3_PSTATE_DIRECT_CONTROL;
631     
632        machine_state.funcs->arch_init();
633
634        put_cpu_var(core_state);
635     }
636
637 }
638     
639
640 static void switch_to_internal(void)
641 {
642     if (get_cpu_var(core_state).have_cpufreq) { 
643         put_cpu_var(core_state);
644         ERROR("Unimplemented: switch to internal on machine with cpu freq\n");
645         return;
646         // The implementation would set the policy and governor to peg cpu
647         // regardless of load - exactly like direct
648     }
649
650     get_cpu_var(core_state).mode=V3_PSTATE_INTERNAL_CONTROL;
651     
652     put_cpu_var(core_state);
653
654     return;
655 }
656
657
658 static void switch_from_external(void)
659 {
660     if (!(get_cpu_var(core_state).have_cpufreq)) {
661         put_cpu_var(core_state);
662         ERROR("No cpufreq  - how did we get here... external...\n");
663         return;
664     }
665
666     ERROR("Unimplemented switch from external...\n");
667     
668     get_cpu_var(core_state).mode = V3_PSTATE_HOST_CONTROL;
669
670     put_cpu_var(core_state);
671
672 }
673  
674 static void switch_from_direct(void)
675 {
676      
677     if (get_cpu_var(core_state).have_cpufreq) { 
678         put_cpu_var(core_state);
679         ERROR("Unimplemented: switch from direct on machine with cpu freq - will just pretend to do so\n");
680         // The implementation would switch back to default policy and governor
681     }
682
683     get_cpu_var(core_state).mode=V3_PSTATE_HOST_CONTROL;
684
685
686     machine_state.funcs->set_pstate(get_cpu_var(core_state).min_pstate);
687
688     machine_state.funcs->arch_deinit();
689
690     put_cpu_var(core_state);
691 }
692     
693
694 static void switch_from_internal(void)
695 {
696     if (get_cpu_var(core_state).have_cpufreq) { 
697         put_cpu_var(core_state);
698         ERROR("Unimplemented: switch from internal on machine with cpu freq - will just pretend to do so\n");
699         // The implementation would switch back to default policy and governor
700     }
701
702     get_cpu_var(core_state).mode=V3_PSTATE_HOST_CONTROL;
703
704     put_cpu_var(core_state);
705     
706     return;
707 }
708
709
710
711 void palacios_pstate_ctrl_acquire(uint32_t type)
712 {
713     if (get_cpu_var(core_state).mode != V3_PSTATE_HOST_CONTROL) { 
714         palacios_pstate_ctrl_release();
715     }
716
717     put_cpu_var(core_state);
718
719     switch (type) { 
720         case V3_PSTATE_EXTERNAL_CONTROL:
721             switch_to_external();
722             break;
723         case V3_PSTATE_DIRECT_CONTROL:
724             switch_to_direct();
725             break;
726         case V3_PSTATE_INTERNAL_CONTROL:
727             switch_to_internal();
728             break;
729         default:
730             ERROR("Unknown pstate control type %u\n",type);
731             break;
732     }
733
734 }
735
736 // Wrappers for xcalls
737 static void palacios_pstate_ctrl_acquire_external(void)
738 {
739     palacios_pstate_ctrl_acquire(V3_PSTATE_EXTERNAL_CONTROL);
740 }
741
742 static void palacios_pstate_ctrl_acquire_direct(void)
743 {
744     palacios_pstate_ctrl_acquire(V3_PSTATE_DIRECT_CONTROL);
745 }
746
747
748 void palacios_pstate_ctrl_release(void)
749 {
750
751     if (get_cpu_var(core_state).mode == V3_PSTATE_HOST_CONTROL) { 
752         put_cpu_var(core_state);
753         return;
754     }
755
756     switch (get_cpu_var(core_state).mode) { 
757         case V3_PSTATE_EXTERNAL_CONTROL:
758             switch_from_external();
759             break;
760         case V3_PSTATE_DIRECT_CONTROL:
761             switch_from_direct();
762             break;
763         case V3_PSTATE_INTERNAL_CONTROL:
764             switch_from_internal();
765             break;
766         default:
767             ERROR("Unknown pstate control type %u\n",core_state.mode);
768             break;
769     }
770
771     put_cpu_var(core_state);
772     
773 }
774
775
776 static void update_hw_pstate(void *arg)
777 {
778     if (machine_state.funcs && machine_state.funcs->get_pstate) {
779         get_cpu_var(core_state).cur_hw_pstate = machine_state.funcs->get_pstate();
780         put_cpu_var(core_state);
781     } else {
782         get_cpu_var(core_state).cur_hw_pstate = 0;
783         put_cpu_var(core_state);
784     }
785 }
786
787
788 /***************************************************************************
789   PROC Interface to expose state
790 ***************************************************************************/
791
792 static int pstate_show(struct seq_file * file, void * v)
793 {
794     unsigned int cpu;
795     unsigned int numcpus = num_online_cpus();
796
797     seq_printf(file, "V3VEE DVFS Status\n\n");
798
799     for (cpu=0;cpu<numcpus;cpu++) { 
800         palacios_xcall(cpu,update_hw_pstate,0);
801     }
802     
803     seq_printf(file, "Arch:\t%s\nPStates:\t%s\n\n",
804                machine_state.arch==INTEL ? "Intel" : 
805                machine_state.arch==AMD ? "AMD" : "Other",
806                machine_state.supports_pstates ? "Yes" : "No");
807                
808     for (cpu=0;cpu<numcpus;cpu++) { 
809         struct pstate_core_info *s = &per_cpu(core_state,cpu);
810         seq_printf(file,"pcore %u: hw pstate %u mode %s of [ host ",cpu,
811                    s->cur_hw_pstate,
812                    s->mode==V3_PSTATE_HOST_CONTROL ? "host" :
813                    s->mode==V3_PSTATE_EXTERNAL_CONTROL ? "external" :
814                    s->mode==V3_PSTATE_DIRECT_CONTROL ? "direct" : 
815                    s->mode==V3_PSTATE_INTERNAL_CONTROL ? "internal" : "UNKNOWN");
816         if (s->have_cpufreq) { 
817             seq_printf(file," external ");
818         }
819         if (machine_state.arch==AMD || machine_state.arch==INTEL) { 
820             seq_printf(file,"direct ");
821         }
822         seq_printf(file,"internal ] ");
823         if (s->mode==V3_PSTATE_EXTERNAL_CONTROL) { 
824             seq_printf(file,"(min=%llu max=%llu cur=%llu) ", s->min_freq_khz, s->max_freq_khz, s->cur_freq_khz);
825         } 
826         if (s->mode==V3_PSTATE_DIRECT_CONTROL) { 
827             seq_printf(file,"(min=%u max=%u cur=%u) ", (uint32_t)s->min_pstate, (uint32_t)s->max_pstate, (uint32_t)s->cur_pstate);
828         }
829         seq_printf(file,"\n");
830     }
831     return 0;
832 }
833
834 static int pstate_open(struct inode * inode, struct file * file) 
835 {
836     return single_open(file, pstate_show, NULL);
837 }
838
839
840 static struct file_operations pstate_fops = {
841     .owner = THIS_MODULE,
842     .open = pstate_open, 
843     .read = seq_read,
844     .llseek = seq_lseek,
845     .release = seq_release
846 };
847
848 int pstate_proc_setup(void)
849 {
850     struct proc_dir_entry *proc;
851     
852     proc = create_proc_entry("v3-dvfs",0444, palacios_get_procdir());
853
854     if (!proc) { 
855         ERROR("Failed to create proc entry for p-state control\n");
856         return -1;
857     }
858     
859     proc->proc_fops = &pstate_fops;
860     
861     return 0;
862 }
863   
864 void pstate_proc_teardown(void)
865 {
866     remove_proc_entry("v3-dvfs",palacios_get_procdir());
867 }
868
869 /********************************************************************
870   User interface (ioctls)
871 ********************************************************************/
872
873 static int dvfs_ctrl(unsigned int cmd, unsigned long arg) 
874 {
875     struct v3_dvfs_ctrl_request r;
876
877     if (copy_from_user(&r,(void __user*)arg,sizeof(struct v3_dvfs_ctrl_request))) {
878         ERROR("Failed to copy DVFS request from user\n");
879         return -EFAULT;
880     }
881
882     if (r.pcore >= num_online_cpus()) {
883         ERROR("Cannot apply DVFS request to pcore %u\n",r.pcore);
884         return -EFAULT;
885     }
886
887     switch (r.cmd) {
888         case V3_DVFS_ACQUIRE: {
889             switch (r.acq_type) { 
890                 case V3_DVFS_EXTERNAL:
891                     palacios_xcall(r.pcore,(void (*)(void*))palacios_pstate_ctrl_acquire_external,0);
892                     return 0;
893                     break;
894                 case V3_DVFS_DIRECT:
895                     palacios_xcall(r.pcore,(void (*)(void*))palacios_pstate_ctrl_acquire_direct,0);
896                     return 0;
897                     break;
898                 default:
899                     ERROR("Unknown DVFS acquire type %u\n",r.acq_type);
900                     return -EFAULT;
901             }
902         }
903             break;
904         case V3_DVFS_RELEASE: {
905             palacios_xcall(r.pcore,(void (*)(void*))palacios_pstate_ctrl_release,0);
906             return 0;
907         }
908             break;
909         case V3_DVFS_SETFREQ: {
910             palacios_xcall(r.pcore,(void (*)(void*))palacios_pstate_ctrl_set_freq,(void*)r.freq_khz);
911             return 0;
912         }
913             break;
914         case V3_DVFS_SETPSTATE: {
915             palacios_xcall(r.pcore,(void (*)(void*))palacios_pstate_ctrl_set_pstate_wrapper,(void*)(uint64_t)r.pstate);
916             return 0;
917         }
918         default: {
919             ERROR("Unknown DVFS command %u\n",r.cmd);
920             return -EFAULT;
921         }
922             break;
923     }
924 }
925
926
927 void pstate_user_setup(void)
928 {
929     add_global_ctrl(V3_DVFS_CTRL, dvfs_ctrl);
930 }
931
932
933 void pstate_user_teardown(void)
934 {
935     remove_global_ctrl(V3_DVFS_CTRL);
936 }
937
938 static struct v3_host_pstate_ctrl_iface hooks = {
939     .get_chars = palacios_pstate_ctrl_get_chars,
940     .acquire = palacios_pstate_ctrl_acquire,
941     .release = palacios_pstate_ctrl_release,
942     .set_pstate = palacios_pstate_ctrl_set_pstate,
943     .get_pstate = palacios_pstate_ctrl_get_pstate,
944     .set_freq = palacios_pstate_ctrl_set_freq,
945     .get_freq = palacios_pstate_ctrl_get_freq,
946 };
947
948
949     
950 static int pstate_ctrl_init(void) 
951 {
952     unsigned int cpu;
953     unsigned int numcpus = num_online_cpus();
954
955     pstate_arch_setup();
956
957     for (cpu=0;cpu<numcpus;cpu++) { 
958         palacios_xcall(cpu,(void ((*)(void*)))init_core,0);
959     }
960
961     V3_Init_Pstate_Ctrl(&hooks);  
962
963     if (pstate_proc_setup()) { 
964         ERROR("Unable to initialize P-State Control\n");
965         return -1;
966     }
967
968     pstate_user_setup();
969
970     INFO("P-State Control Initialized\n");
971
972     return 0;
973 }
974
975 static int pstate_ctrl_deinit(void)
976 {
977     unsigned int cpu;
978     unsigned int numcpus=num_online_cpus();
979
980
981     pstate_user_teardown();
982
983     pstate_proc_teardown();
984
985     // release pstate control if we have it, and we need to do this on each processor
986     for (cpu=0;cpu<numcpus;cpu++) { 
987         palacios_xcall(cpu,(void (*)(void *))deinit_core,0);
988     }
989
990     return 0;
991 }
992         
993
994 static struct linux_ext pstate_ext = {
995     .name = "PSTATE_CTRL",
996     .init = pstate_ctrl_init,
997     .deinit = pstate_ctrl_deinit,
998     .guest_init = NULL,
999     .guest_deinit = NULL,
1000 };
1001
1002
1003 register_extension(&pstate_ext);
1004
1005
1006