-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathest.diff
280 lines (272 loc) · 7.65 KB
/
est.diff
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
# Apply this patch to the original usr/src/sys/arch/x86/x86/est.c C
# source file found in the NetBSD kernel source tree, version 5.0.2.
--- a/est.c 2010-06-14 00:31:36.797834314 +0200
+++ b/est.c 2010-06-14 00:32:07.018834503 +0200
@@ -86,6 +86,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
+#include <sys/kmem.h>
#include <sys/sysctl.h>
#include <sys/once.h>
@@ -1005,6 +1006,137 @@
static int est_init_once(void);
static void est_init_main(int);
+#define PHC_ID16(FID, VID) ( ((FID) << 8) | (VID) )
+#define PHC_MAXLEN 30
+static uint16_t* phc_origin_table; /* PHC: keep orignal settings */
+static char *phc_string_vids;
+static int phc_est_sysctl_helper(SYSCTLFN_PROTO);
+
+/* atoi clone:
+ * parse a string, discarding no-digit character
+ * and returning the first int found.
+ *
+ * (*remain) points to the remaining string.
+ *
+ * return -1 on error / end of string
+ */
+static int
+phc_atoi(char *string, char **remain)
+{
+ char *pc = string;
+ int result = 0;
+
+ while ( (*pc != '\0') && ! isdigit(*pc) )
+ pc++;
+
+ if (*pc == '\0')
+ return -1;
+
+ while (isdigit(*pc)) {
+ result = *pc - '0' + 10 * (result);
+ pc++;
+ }
+
+ return *remain = pc, result;
+}
+
+static int
+phc_est_sysctl_helper(SYSCTLFN_ARGS)
+{
+ struct sysctlnode node;
+ int error;
+ char input_string[PHC_MAXLEN];
+ struct msr_cpu_broadcast mcb;
+ int i,fq,*vids;
+ char *string,*remain;
+
+ if (est_fqlist == NULL)
+ return EOPNOTSUPP;
+
+ strlcpy( input_string, phc_string_vids, sizeof(input_string));
+
+ node = *rnode;
+ node.sysctl_data = input_string;
+ node.sysctl_size = sizeof(input_string);
+
+ error = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (error
+ || newp == NULL
+ || strncmp(input_string, phc_string_vids, PHC_MAXLEN) == 0 )
+ return error;
+
+ /* () input_string is different, process it () */
+
+ /* Parse input string one Voltage ID at a time */
+ remain = string = input_string;
+
+ vids = kmem_alloc(est_fqlist->n * sizeof(int), KM_SLEEP);
+ if (vids == NULL)
+ return ENOMEM;
+
+ /* First round: check input values */
+ for( i = 0; i< est_fqlist->n; i++) {
+ int ref_vid = MSR2VOLTINC(phc_origin_table[i]);
+ int vid = phc_atoi( string, &remain);
+
+ if (vid == -1) {
+ printf("%s: require at least %d values\n",
+ __func__, est_fqlist->n);
+ kmem_free( vids, est_fqlist->n * sizeof(int));
+ return EINVAL;
+ }
+
+ if ( vid < 0 || vid > ref_vid ) {
+ printf("%s: %d VID out of bounds\n",
+ __func__, vid);
+ kmem_free( vids, est_fqlist->n * sizeof(int));
+ return EINVAL;
+ }
+
+ vids[i] = vid;
+
+ /* iteration */
+ string = remain;
+ }
+
+ /* ignoring rest of string
+ * in case where input_string is too long */
+ *remain = '\0';
+
+ /* Save new VIDs */
+ for( i = 0; i< est_fqlist->n; i++) {
+ int ref_fid = MSR2FREQINC(phc_origin_table[i]);
+ fake_table[i] = PHC_ID16( ref_fid, vids[i]);
+#ifdef EST_DEBUG
+ printf("PHC: using new VID %d for FID %d\n"
+ , vids[i], ref_fid);
+#endif /* EST_DEBUG */
+ }
+
+ /* clean memory <!> */
+ kmem_free( vids, est_fqlist->n * sizeof(int));
+
+ /* save string for futur display */
+ strncpy ( phc_string_vids, input_string, PHC_MAXLEN);
+
+ /* reset MSR */
+ fq = MSR2MHZ(rdmsr(MSR_PERF_STATUS), bus_clock);
+ for (i = est_fqlist->n - 1; i > 0; i--)
+ if (MSR2MHZ(est_fqlist->table[i], bus_clock) >= fq)
+ break;
+ fq = MSR2MHZ(est_fqlist->table[i], bus_clock);
+ mcb.msr_read = true;
+ mcb.msr_type = MSR_PERF_CTL;
+ mcb.msr_mask = 0xffffULL;
+ mcb.msr_value = est_fqlist->table[i];
+ msr_cpu_broadcast(&mcb);
+
+ /* Display raw VID voltages */
+ /*rnode->sysctl_data = &phc_string_vids;*/
+
+ return 0;
+}
+
static int
est_sysctl_helper(SYSCTLFN_ARGS)
{
@@ -1082,7 +1214,10 @@
size_t len, freq_len;
char *freq_names;
const char *cpuname;
-
+ const struct sysctlnode *voltnode;
+ size_t vids_len,fids_len;
+ char *phc_original_vids,*phc_fids;
+
cpuname = device_xname(curcpu()->ci_dev);
if (CPUID2FAMILY(curcpu()->ci_signature) == 15)
@@ -1232,6 +1367,29 @@
fake_fqlist.table = fake_table;
est_fqlist = &fake_fqlist;
}
+ else {
+ /* PHC: Create a non-const fake table
+ * in order to modify volt values later */
+ int tablesize = est_fqlist->n * sizeof(uint16_t);
+
+#ifdef EST_DEBUG
+ printf("PHC: replacing static const table\n");
+#endif /* EST_DEBUG */
+
+ printf("%s: bus_clock = %d\n", __func__, bus_clock);
+ fake_table = malloc( tablesize, M_DEVBUF, M_WAITOK);
+ memcpy( fake_table, est_fqlist->table, tablesize);
+ fake_fqlist.table = fake_table;
+
+ fake_fqlist.n = est_fqlist->n;
+ fake_fqlist.vendor = est_fqlist->vendor;
+ fake_fqlist.bus_clk = est_fqlist->bus_clk;
+
+ est_fqlist = &fake_fqlist;
+ }
+
+ /* PHC: keep original setting in memory */
+ memcpy( &phc_origin_table, &fake_table, sizeof(fake_table));
/*
* OK, tell the user the available frequencies.
@@ -1241,8 +1399,8 @@
freq_names[0] = '\0';
len = 0;
for (i = 0; i < est_fqlist->n; i++) {
- len += snprintf(freq_names + len, freq_len - len, "%d%s",
- MSR2MHZ(est_fqlist->table[i], bus_clock),
+ len += snprintf(freq_names + len, freq_len - len,
+ "%d%s", MSR2MHZ(est_fqlist->table[i], bus_clock),
i < est_fqlist->n - 1 ? " " : "");
}
@@ -1251,6 +1409,36 @@
aprint_normal("%s: %s frequencies available (MHz): %s\n",
cpuname, est_desc, freq_names);
+ /* PHC: create initial string representation of FIDs */
+ fids_len = est_fqlist->n * 3 + 1;
+ phc_fids = kmem_alloc(fids_len, KM_SLEEP);
+ phc_fids[0] = '\0';
+ len = 0;
+ for (i = 0; i < est_fqlist->n && len < PHC_MAXLEN; i++) {
+ len += snprintf(phc_fids + len, fids_len - len, "%d%s",
+ MSR2FREQINC(est_fqlist->table[i]),
+ i < est_fqlist->n - 1 ? " " : "");
+ }
+ aprint_normal("%s: %s frequences id used: %s\n",
+ cpuname, est_desc, phc_fids);
+
+ /* PHC: create initial string representation of VIDs */
+ vids_len = est_fqlist->n * 3 + 1;
+ phc_original_vids = kmem_alloc(vids_len, KM_SLEEP);
+ phc_original_vids[0] = '\0';
+ len = 0;
+ for (i = 0; i < est_fqlist->n && len < PHC_MAXLEN; i++) {
+ len += snprintf(phc_original_vids + len, vids_len - len, "%d%s",
+ MSR2VOLTINC(est_fqlist->table[i]),
+ i < est_fqlist->n - 1 ? " " : "");
+ }
+ aprint_normal("%s: %s voltages id used: %s\n",
+ cpuname, est_desc, phc_original_vids);
+
+ /* PHC: create initial VIDs by copying original ones */
+ phc_string_vids = kmem_alloc( PHC_MAXLEN, KM_SLEEP);
+ strlcpy( phc_string_vids, phc_original_vids, vids_len);
+
/*
* Setup the sysctl sub-tree machdep.est.*
*/
@@ -1286,9 +1474,39 @@
NULL, 0, freq_names, freq_len, CTL_CREATE, CTL_EOL)) != 0)
goto err;
+ /* PHC: Adding a voltage subtree */
+ if ((rc = sysctl_createv(NULL, 0, &estnode, &voltnode,
+ 0, CTLTYPE_NODE, "phc", NULL,
+ NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
+ goto err;
+
+ if ((rc = sysctl_createv(NULL, 0, &voltnode, NULL,
+ 0, CTLTYPE_STRING, "fids",
+ SYSCTL_DESCR("Frequence ID list"),
+ NULL, 0, phc_fids, fids_len,
+ CTL_CREATE, CTL_EOL)) != 0)
+ goto err;
+
+ if ((rc = sysctl_createv(NULL, 0, &voltnode, NULL,
+ 0, CTLTYPE_STRING, "vids_original",
+ SYSCTL_DESCR("Original voltage ID list"),
+ NULL, 0, phc_original_vids, vids_len,
+ CTL_CREATE, CTL_EOL)) != 0)
+ goto err;
+
+ if ((rc = sysctl_createv(NULL, 0, &voltnode, NULL,
+ CTLFLAG_READWRITE, CTLTYPE_STRING, "vids",
+ SYSCTL_DESCR("Custom voltage ID list"),
+ phc_est_sysctl_helper, 0, NULL, PHC_MAXLEN,
+ CTL_CREATE, CTL_EOL)) != 0)
+ goto err;
+
return;
err:
free(freq_names, M_SYSCTLDATA);
+ /*free(fake_table, M_SYSCTLDATA); (! shoud we ??? !) */
+ kmem_free(phc_fids, fids_len);
+ kmem_free(phc_original_vids, vids_len);
aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
}