~ubuntu-branches/ubuntu/trusty/powertop-1.13/trusty

« back to all changes in this revision

Viewing changes to intelcstates.c

  • Committer: Package Import Robot
  • Author(s): Jamie Strandboge
  • Date: 2011-11-11 13:36:57 UTC
  • Revision ID: package-import@ubuntu.com-20111111133657-dumpedggvnmcjb2e
Tags: upstream-1.13
ImportĀ upstreamĀ versionĀ 1.13

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2008, Intel Corporation
 
3
 *
 
4
 * This file is part of PowerTOP
 
5
 *
 
6
 * This program file is free software; you can redistribute it and/or modify it
 
7
 * under the terms of the GNU General Public License as published by the
 
8
 * Free Software Foundation; version 2 of the License.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful, but WITHOUT
 
11
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
12
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 
13
 * for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program in a file named COPYING; if not, write to the
 
17
 * Free Software Foundation, Inc.,
 
18
 * 51 Franklin Street, Fifth Floor,
 
19
 * Boston, MA 02110-1301 USA
 
20
 *
 
21
 * Authors:
 
22
 *      Arjan van de Ven <arjan@linux.intel.com>
 
23
 */
 
24
 
 
25
#include <unistd.h>
 
26
#include <stdio.h>
 
27
#include <stdlib.h>
 
28
#include <string.h>
 
29
#include <stdint.h>
 
30
#include <sys/types.h>
 
31
#include <dirent.h>
 
32
#include <ctype.h>
 
33
 
 
34
#include "powertop.h"
 
35
 
 
36
#ifdef __i386
 
37
 
 
38
 
 
39
/*
 
40
 * Perform a CPU ID operation; with various registers set
 
41
 */
 
42
static void cpuid(      unsigned int *eax,
 
43
                        unsigned int *ebx,
 
44
                        unsigned int *ecx,
 
45
                        unsigned int *edx)
 
46
{
 
47
        /* call the cpuid instruction with the registers as input and output
 
48
         * modification by Dwokfur based on Sam Hocevar's discussion on
 
49
         * how to make Assemly code PIC compatible:
 
50
         * http://sam.zoy.org/blog/2007-04-13-shlib-with-non-pic-code-have-inline-assembly-and-pic-mix-well
 
51
         */
 
52
        __asm__("pushl %%ebx    \n\t" /* save %ebx */
 
53
                "cpuid          \n\t"
 
54
                "movl %%ebx, %1 \n\t" /* save what cpuid just put in %ebx */
 
55
                "popl %%ebx     \n\t" /* restore the old %ebx */
 
56
                : "=a" (*eax),
 
57
                  "=r" (*ebx),
 
58
                  "=c" (*ecx),
 
59
                  "=d" (*edx)
 
60
                : "0" (*eax),
 
61
                  "1" (*ebx),
 
62
                  "2" (*ecx),
 
63
                  "3" (*edx)
 
64
                );
 
65
}
 
66
 
 
67
#endif
 
68
 
 
69
 
 
70
void print_intel_cstates(void)
 
71
{
 
72
#ifdef __i386__
 
73
 
 
74
        int bios_table[8];
 
75
        int bioscount = 0;
 
76
        DIR *cpudir;
 
77
        DIR *dir;
 
78
        struct dirent *entry;
 
79
        FILE *file = NULL;
 
80
        char line[4096];
 
81
        char filename[128], *f;
 
82
        int len, i;
 
83
        unsigned int eax, ebx, ecx, edx;
 
84
 
 
85
        memset(bios_table, 0, sizeof(bios_table));
 
86
 
 
87
 
 
88
        cpudir = opendir("/sys/devices/system/cpu");
 
89
        if (!cpudir)
 
90
                return;
 
91
 
 
92
        /* Loop over cpuN entries */
 
93
        while ((entry = readdir(cpudir))) {
 
94
                if (strlen(entry->d_name) < 3)
 
95
                        continue;
 
96
 
 
97
                if (!isdigit(entry->d_name[3]))
 
98
                        continue;
 
99
 
 
100
                len = sprintf(filename, "/sys/devices/system/cpu/%s/cpuidle",
 
101
                              entry->d_name);
 
102
 
 
103
                dir = opendir(filename);
 
104
                if (!dir)
 
105
                        return;
 
106
 
 
107
                /* For each C-state, there is a stateX directory which
 
108
                 * contains a 'usage' and a 'time' (duration) file */
 
109
                while ((entry = readdir(dir))) {
 
110
                        if (strlen(entry->d_name) < 3)
 
111
                                continue;
 
112
                        sprintf(filename + len, "/%s/desc", entry->d_name);
 
113
                        file = fopen(filename, "r");
 
114
                        if (file) {
 
115
 
 
116
                                memset(line, 0, 4096);
 
117
                                f = fgets(line, 4096, file);
 
118
                                fclose(file);
 
119
                                if (f == NULL)
 
120
                                        break;
 
121
 
 
122
                                f = strstr(line, "MWAIT ");
 
123
                                if (f) {
 
124
                                        f += 6;
 
125
                                        bios_table[(strtoull(f, NULL, 16)>>4) + 1]++;
 
126
                                        bioscount++;
 
127
                                }
 
128
                        }
 
129
                }
 
130
                closedir(dir);
 
131
 
 
132
        }
 
133
        closedir(cpudir);
 
134
        if (!bioscount)
 
135
                return;
 
136
 
 
137
        eax = 5;
 
138
        ebx = 0; ecx = 0; edx = 0;
 
139
        cpuid(&eax, &ebx, &ecx, &edx);
 
140
        if (!edx || ((ecx&1) == 0))
 
141
                return;
 
142
 
 
143
        printf(_("Your CPU supports the following C-states : "));
 
144
        i = 0;
 
145
        while (edx) {
 
146
                if (edx&7)
 
147
                        printf("C%i ", i);
 
148
                edx = edx >> 4;
 
149
                i++;
 
150
        }
 
151
        printf("\n");
 
152
        printf(_("Your BIOS reports the following C-states : "));
 
153
        for (i = 0; i < 8; i++)
 
154
                if (bios_table[i])
 
155
                        printf("C%i ", i);
 
156
        printf("\n");
 
157
#endif
 
158
}