Updated `README.md` with instructions for building/using the kernel module.
[xeon-phi-kernel-module] / ras / micras_common.c
CommitLineData
800f879a
AT
1/*
2 * Copyright 2010-2017 Intel Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * Disclaimer: The codes contained in these modules may be specific to
14 * the Intel Software Development Platform codenamed Knights Ferry,
15 * and the Intel product codenamed Knights Corner, and are not backward
16 * compatible with other Intel products. Additionally, Intel will NOT
17 * support the codes or instruction set in future products.
18 *
19 * Intel offers no warranty of any kind regarding the code. This code is
20 * licensed on an "AS IS" basis and Intel is not obligated to provide
21 * any support, assistance, installation, training, or other services
22 * of any kind. Intel is also not obligated to provide any updates,
23 * enhancements or extensions. Intel specifically disclaims any warranty
24 * of merchantability, non-infringement, fitness for any particular
25 * purpose, and any other warranty.
26 *
27 * Further, Intel disclaims all liability of any kind, including but
28 * not limited to liability for infringement of any proprietary rights,
29 * relating to the use of the code, even if Intel is notified of the
30 * possibility of such liability. Except as expressly stated in an Intel
31 * license agreement provided with this code and agreed upon with Intel,
32 * no license, express or implied, by estoppel or otherwise, to any
33 * intellectual property rights is granted herein.
34 */
35
36/*
37 * RAS MT module, common code
38 *
39 * Code and data structures to handle get/set tasks for KnC and KnF.
40 * Parties accessing the data structures are supposed to use the
41 * micras_mt_tsk() routines to ensure integrity and consistency.
42 * Particularly important when handling sysfs nodes and actions
43 * requested from SCIF connections must use that method in order
44 * to guarantee serialized access.
45 *
46 * Even if read-only access to latest valid data is required,
47 * it should go through micras_mt_tsk() using dedicated handlers
48 * in this module.
49 */
50
51#include <linux/types.h>
52#include <linux/errno.h>
53#include <linux/kernel.h>
54#include <linux/mm.h>
55#include <linux/mm_types.h>
56#include <linux/io.h>
57#include <linux/utsname.h>
58#include <linux/sched.h>
59#include <linux/time.h>
60#include <linux/jiffies.h>
61#include <linux/tick.h>
62#include <linux/kernel_stat.h>
63#include <linux/bitmap.h>
64#include <generated/compile.h>
65#include <generated/utsrelease.h>
66#include <asm/mic/mic_knc/autobaseaddress.h>
67#include <asm/mic/mic_knc/micsboxdefine.h>
68#include "micras.h"
69
70
71/*
72 * Persistent data accessible through the CP api.
73 * Some functions just read/modify hardware CSRs
74 * and thus need no storage between invocations.
75 */
76
77 struct mr_rsp_hwinf hwinf; /* Card specific */
78 struct mr_rsp_vers vers; /* Card specific */
79static struct mr_rsp_pver pver;
80 struct mr_rsp_freq freq; /* Card specific */
81 struct mr_rsp_volt volt; /* Card specific */
82 struct mr_rsp_power power; /* Card specific */
83 struct mr_rsp_plim plim; /* Card specific */
84static struct mr_rsp_clst clst;
85 struct mr_rsp_gddr gddr;
86 struct mr_rsp_gfreq gfreq; /* Card Specific */
87 struct mr_rsp_gvolt gvolt; /* Card specific */
88 struct mr_rsp_temp temp; /* Card specific */
89 struct mr_rsp_ecc ecc; /* Card specific */
90static struct mr_rsp_trc trc;
91 struct mr_rsp_trbo trbo; /* Card specific */
92 struct mr_rsp_pmcfg pmcfg; /* Card specific */
93
94
95/*
96 * Map of SKUs for KnX cards (currently known, will change)
97 * The SKU is identified solely from the PCIe ID and sub-ID.
98 * A zero sub-ID is a don't care.
99 *
100 *TBD: core counts in KnF needs update, not all have 32.
101 *
102 * Notes:
103 * - Unless the PCIe subID differs, there are two 2250 cards
104 * that can't be distinguished from each other, one has 8 TXs
105 * and the other has none. PO cards -> impact only internal.
106 * - Not sure exactly what 2254 is, suspect MPI prototype.
107 */
108
109#define VD(v, d) (PUT_BITS(15,0,(v)) | PUT_BITS(31,16,(d)))
110
111static struct sku {
112 uint32_t devID; /* PCIe Vendor and device ID */
113 uint32_t subID; /* PCIe Sub- Vendor and device ID */
114 uint8_t revNo; /* PCIe Revision number */
115 uint8_t cr; /* Core count */
116 uint8_t ch; /* Memory channels */
117 uint8_t tx; /* TX samplers (only in KnC) */
118 char * name; /* SKU name */
119} skuList[] = {
120 { VD(0x8086, 0x2240), 0, 0x00, 32, 8, 0, "E1" }, /* KnF */
121 { VD(0x8086, 0x2241), 0, 0x00, 32, 8, 0, "E2" }, /* KnF */
122 { VD(0x8086, 0x2242), 0, 0x00, 32, 8, 0, "E3" }, /* KnF */
123 { VD(0x8086, 0x2243), 0, 0x00, 32, 8, 0, "E3" }, /* KnF */
124 { VD(0x8086, 0x2249), VD(0x8086, 0xed08), 0, 32, 4, 0, "Ed" }, /* KnF */
125 { VD(0x8086, 0x2249), VD(0x8086, 0xed0a), 0, 32, 4, 0, "Eb" }, /* KnF */
126 { VD(0x8086, 0x224a), 0, 0x00, 32, 8, 0, "Eb" }, /* KnF */
127
128 { VD(0x8086, 0x2250), 0, 0x00, 60, 16, 0, "SKU1/SKU2" }, /* KnC: ES1, ES1B */
129 { VD(0x8086, 0x2250), 0, 0x10, 60, 16, 0, "SKU2" }, /* KnC: ES2 */
130 { VD(0x8086, 0x2250), 0, 0x11, 60, 16, 0, "SKU2" }, /* KnC: Mkt2 */
131 { VD(0x8086, 0x2250), 0, 0x20, 60, 16, 0, "SKU2" },
132 { VD(0x8086, 0x2251), 0, 0x00, 48, 16, 8, "SKU2" },
133 { VD(0x8086, 0x2252), 0, 0x00, 48, 16, 0, "SKU3" },
134 { VD(0x8086, 0x2253), 0, 0x00, 40, 8, 0, "SKU4/SKU5" }, /* KnC: ES0, ES1 */
135 { VD(0x8086, 0x2253), 0, 0x10, 40, 8, 0, "SKU5" },
136 { VD(0x8086, 0x2254), 0, 0x00, 62, 16, 0, "??" }, /* KnC: ?? */
137 { VD(0x8086, 0x2255), 0, 0x00, 62, 16, 8, "SKUX" }, /* KnC: A0-PO */
138 { VD(0x8086, 0x2256), 0, 0x00, 48, 12, 7, "SKU5" }, /* KnC: A0-PO */
139 { VD(0x8086, 0x2257), 0, 0x00, 4, 16, 0, "SKUZ" },
140 { VD(0x8086, 0x2258), 0, 0x00, 62, 16, 0, "SKU1" }, /* KnC: ES1, ES1B */
141 { VD(0x8086, 0x2258), 0, 0x10, 62, 16, 0, "SKU1" },
142 { VD(0x8086, 0x2259), 0, 0x00, 52, 16, 0, "SKU3" }, /* KnC: ES1 */
143 { VD(0x8086, 0x225a), 0, 0x00, 48, 12, 0, "SKU4" }, /* KnC: ES1, ES1B */
144 { VD(0x8086, 0x225a), 0, 0x10, 48, 12, 0, "SKU4" }, /* KnC: ES2 */
145 { VD(0x8086, 0x225a), 0, 0x11, 48, 12, 0, "SKU4" }, /* KnC: Int5 */
146 { VD(0x8086, 0x225b), 0, 0x00, 52, 12, 0, "SKU3" },
147 { VD(0x8086, 0x225b), 0, 0x10, 52, 12, 0, "SKU3" },
148 { VD(0x8086, 0x225c), 0, 0x10, 61, 16, 0, "SKU1" }, /* KnC: Mkt1 */
149 { VD(0x8086, 0x225c), 0, 0x11, 61, 16, 0, "SKU1" }, /* KnC: Mkt1 */
150 { VD(0x8086, 0x225c), 0, 0x20, 61, 16, 0, "SKU1" }, /* KnC: Mkt1 */
151 { VD(0x8086, 0x225d), 0, 0x10, 57, 12, 0, "SKU4" }, /* KnC: Mkt4 */
152 { VD(0x8086, 0x225d), 0, 0x11, 57, 12, 0, "SKU4" }, /* KnC: Mkt3, Mkt4 */
153 { VD(0x8086, 0x225d), 0, 0x20, 57, 12, 0, "SKU4" },
154 { VD(0x8086, 0x225e), 0, 0x11, 57, 16, 0, "GZ" },
155 { VD(0x8086, 0x225e), 0, 0x20, 57, 16, 0, "GZ" },
156};
157
158
159/*
160 * Map of GDDR vendor ID vs company names
161 */
162
163static struct {
164 int id;
165 char * vendor;
166} GddrVendors[] = {
167 { 1, "Samsung" },
168 { 2, "Quimonda" },
169 { 3, "Elpida" },
170 { 6, "Hynix" },
171};
172
173
174
175/*
176**
177** Initializations
178**
179** This has two intended purposes:
180** - Do a on-time effort to collect info on properties that
181** are not going to change after the initial setup by
182** either bootstrap or kernel initialization.
183** - Collect initial values on things we can modify.
184** Intent is that unloading the ras module should reset
185** all state to that of the time the module was loaded.
186**
187*/
188
189void __init
190mr_mt_init(void)
191{
192 static int only_once = 1;
193 uint32_t scr4, scr9, scr13;
194 uint32_t eax, ebx, ecx, edx;
195 uint32_t thr, hwt;
196 uint32_t id;
197 int i;
198
199 if (! only_once)
200 return;
201 only_once = 0;
202
203 /*
204 * HWINF:
205 * Scratch register 13 has more info than the hwinf record
206 * currently can contain, may revisit.
207 * 3:0 Substepping
208 * 7:4 Stepping (0 A, 2&3 B, 4 C, 6 D)
209 * 11:8 Model
210 * 15:12 Family (11 KnF)
211 * 17:16 Processor
212 * 19:18 Platform (0 Silicon, 1 FSIM, 2 MCEMU)
213 * 23:20 Extended model
214 * 31:24 Extended family
215 *
216 * Valid KnF steppings (Step + Substep):
217 * "A0" (0 + 0), "A1" (0 + 1), "A2" (0 + 2),
218 * "B0" (2 + 0), "B1" (3 + 1), "C0" (4 + 0),
219 * "D0" (6 + 0)
220 * Valid KnC steppings (Step + Substep):
221 * TBD:
222 */
223 scr13 = mr_sbox_rl(0, SBOX_SCRATCH13);
224 hwinf.rev = GET_BITS(11, 8, scr13);
225 hwinf.step = GET_BITS( 7, 4, scr13);
226 hwinf.substep = GET_BITS( 3, 0, scr13);
227
228 /*
229 * VERS:
230 * Add OS version
231 */
232 vers.uos[0] = scnprintf(vers.uos + 1, MR_VERS_LEN -2,
233 "Linux version: %s (build %s)",
234 init_uts_ns.name.release,
235 init_uts_ns.name.version);
236
237 /*
238 * PVERS:
239 * Make MicRas version available
240 */
241 pver.api[0] = scnprintf(pver.api + 1, MR_PVER_LEN -2,
242 "%s", RAS_VER);
243
244 /*
245 * CLST:
246 * On regular CPU's this is read from CPUID 2 (htt cores)
247 * and CPUID 4 (die cores), threads per cores is htt/die.
248 * This does not work the same way in MIC, cores & threads
249 * per core on various SKUs is not reflected by the CPUIDs.
250 * All we have is the number of registered APIC IDs, which
251 * happens to be the same as logical CPUs (htt cores).
252 * The threads per core (die cores) is given by bootstrap in
253 * scratch register #4 as a bit field.
254 * 3:0 Threads per core (mask)
255 * 5:4 Cache size (0,1,2: 512K, 3: 256K)
256 * 9:6 GBOX channel count (0 based)
257 * 29:25 ICC divider for MCLK
258 * 30 Soft reset boot
259 * 31 Internal flash build
260 */
261 cpuid(1, &eax, &ebx, &ecx, &edx);
262 hwt = GET_BITS(23, 16, ebx);
263 if (hwt > nr_cpu_ids)
264 hwt = nr_cpu_ids;
265 scr4 = mr_sbox_rl(0, SBOX_SCRATCH4);
266 thr = GET_BITS(3, 0, scr4);
267 thr = bitmap_weight((const unsigned long *) &thr, 4);
268 if (thr) {
269 if (hwt % thr)
270 printk("mr_mt_init: cpu/thr mismatch: hwt %d, thr %d, cor %d, (%d)\n",
271 hwt, thr, hwt / thr, hwt % thr);
272 clst.thr = thr;
273 }
274 else {
275 printk("Who trashed scratch #4? Val 0x%08x => 0 threads/core?\n", scr4);
276 clst.thr = 4; /* Best guess */
277 }
278 clst.count = hwt / 4;
279
280 /*
281 * GDDR:
282 * Bootstrap leaves information in scratch register #9
283 * about the GDDR devices. The layout is:
284 * 3:0 Vendor ID, see table GddrVendors above
285 * 7:4 Revision
286 * 9:8 Density (00 = 512, 01 = 1024, 02 = 2048)
287 * 11:10 FIFO depth
288 * 15:12 DRAM info ??
289 * 29 ECC enable
290 */
291 scr9 = mr_sbox_rl(0, SBOX_SCRATCH9);
292 id = GET_BITS(3, 0, scr9);
293 for(i = 0; i < ARRAY_SIZE(GddrVendors); i++)
294 if (GddrVendors[i].id == id) {
295 gddr.dev[0] = scnprintf(gddr.dev +1, MR_GVND_LEN -2,
296 "%s", GddrVendors[i].vendor);
297 break;
298 }
299 if (i == ARRAY_SIZE(GddrVendors))
300 gddr.dev[0] = scnprintf(gddr.dev +1, MR_GVND_LEN -2, "Vendor %d", id);
301 gddr.rev = GET_BITS(7, 4, scr9);
302 gddr.size = 512 * (1 << GET_BITS(9, 8, scr9));
303
304 /*
305 * Card specific initialization
306 */
307 mr_mt_card_init();
308
309 /*
310 *TBD: Save commmon registers this module may change
311 */
312}
313
314void __exit
315mr_mt_exit(void)
316{
317 /*
318 * Card specific clean-up
319 */
320 mr_mt_card_exit();
321
322 /*
323 *TBD: Restore commmon registers this module may change
324 */
325}
326
327
328/*
329 * Return SKU properties for this card (as string)
330 * Processor can be identified on it's own easily,
331 * but the SKU reflects the impact of fuse changes
332 * which don't alter the CPU id.
333 *
334 * SKU properties:
335 * - name Name of sku (if known)
336 * - mch Number of memory channels
337 * - txs Number of texture samplers
338 */
339
340/*
341 * Why are these not defined in the includes?
342 */
343
344#ifndef SBOX_PCIE_VENDOR_ID_DEVICE_ID
345#define SBOX_PCIE_VENDOR_ID_DEVICE_ID 0x00005800
346#endif
347#ifndef SBOX_PCIE_PCI_SUBSYSTEM
348#define SBOX_PCIE_PCI_SUBSYSTEM 0x0000582c
349#endif
350#ifndef SBOX_PCIE_PCI_REVISION_ID_AND_C_0X8
351#define SBOX_PCIE_PCI_REVISION_ID_AND_C_0X8 0x00005808
352#endif
353
354static struct sku *
355get_sku(void)
356{
357 static struct sku * sku;
358 uint32_t dev, sub, rev, fuse;
359 char * grp;
360 int i;
361
362 if (sku)
363 return sku;
364
365 dev = mr_sbox_rl(0, SBOX_PCIE_VENDOR_ID_DEVICE_ID);
366 rev = mr_sbox_rl(0, SBOX_PCIE_PCI_REVISION_ID_AND_C_0X8);
367 sub = mr_sbox_rl(0, SBOX_PCIE_PCI_SUBSYSTEM);
368 fuse = mr_sbox_rl(0, SBOX_SCRATCH7);
369 rev = GET_BITS(7, 0, rev);
370 fuse = GET_BITS(15, 0, fuse);
371
372 /*
373 * Usually the fuse revision define a group of SKUs.
374 * Once that's determined we'll use the other details
375 * to identify the SKU within that group.
376 */
377 if (fuse >= 0 && fuse <= 1)
378 grp = "A0 PO";
379 else if (fuse >= 2 && fuse <= 3)
380 grp = "A0 ES1";
381 else if (fuse >= 4 && fuse <= 50)
382 grp = "A0 ES1B";
383 else if (fuse >= 51 && fuse <= 100)
384 grp = "B0 PO";
385 else if (fuse >= 101 && fuse <= 150)
386 grp = "B0 ES2";
387 else if (fuse >= 151 && fuse <= 152)
388 grp = "B1 PO";
389 else if (fuse >= 153 && fuse <= 154)
390 grp = "B1 PO";
391 else if (fuse == 155)
392 grp = "B1 QS";
393 else if (fuse == 156)
394 grp = "B1 PRQ";
395 else if (fuse == 157)
396 grp = "B1 PRQ/GZ";
397 else if (fuse >= 158 && fuse <= 159)
398 grp = "B1 PRQ";
399 else if (fuse >= 201 && fuse <= 203)
400 grp = "B2 PRQ/QS";
401 else if (fuse == 253)
402 grp = "C0 PO";
403 else if (fuse == 254)
404 grp = "C0 QS";
405 else
406 grp = "???";
407
408 /*
409 * Now determine which member of the group.
410 * Take hints from PCIe device ID and revision.
411 * Device ID mappings is a mess, see table above.
412 * Revision has a simple mapping (follows fuses):
413 * 0x00 => A0 cards
414 * 0x10 => B0 cards
415 * 0x11 => B1 cards
416 * 0x20 => C0 cards
417 * 0x21 => C1 cards (if ever to be made)
418 */
419 for(i = 0; i < ARRAY_SIZE(skuList); i++) {
420 if (dev == skuList[i].devID) {
421 if (skuList[i].subID && sub != skuList[i].subID)
422 continue;
423 if (rev != skuList[i].revNo)
424 continue;
425
426 /*
427 * Found one, this is the place to cross reference it
428 * - memory channels should match SCR4 bits 9:6
429 */
430 break;
431 }
432 }
433
434 if (i < ARRAY_SIZE(skuList)) {
435 sku = skuList + i;
436 printk("RAS: card %x:%x:%x is a \"%s %s\" (%d cores, %d memch, %d txs)\n",
437 dev, sub, rev, grp, sku->name, sku->cr, sku->ch, sku->tx);
438 }
439
440 return sku;
441}
442
443#if NOT_YET
444char *
445mr_sku(void)
446{
447 struct sku * sku;
448
449 sku = get_sku();
450 return sku ? sku->name : 0;
451}
452#endif
453
454int
455mr_mch(void)
456{
457 struct sku * sku;
458
459 sku = get_sku();
460 return sku ? sku->ch : 0;
461}
462
463int
464mr_txs(void)
465{
466 struct sku * sku;
467
468 sku = get_sku();
469 return sku ? sku->tx : 0;
470}
471
472
473/*
474**
475** MT Get functions
476**
477** All works the same way; they get an opague pointer to
478** a place where the return structure can be placed. The
479** return value is either the amount (bytes) to be shipped
480** back in response or one of the MR_* error codes.
481**
482*/
483
484int
485mr_get_hwinf(void * p)
486{
487 struct mr_rsp_hwinf * r;
488
489 r = (struct mr_rsp_hwinf *) p;
490 *r = hwinf;
491 return sizeof(*r);
492}
493
494
495int
496mr_get_vers(void * p)
497{
498 struct mr_rsp_vers * r;
499
500 r = (struct mr_rsp_vers *) p;
501 *r = vers;
502 return sizeof(*r);
503}
504
505
506int
507mr_get_pver(void * p)
508{
509 struct mr_rsp_pver * r;
510
511 r = (struct mr_rsp_pver *) p;
512 *r = pver;
513 return sizeof(*r);
514}
515
516
517int
518mr_get_clst(void * p)
519{
520 struct mr_rsp_clst * r;
521
522 r = (struct mr_rsp_clst *) p;
523 *r = clst;
524 return sizeof(*r);
525}
526
527
528int
529mr_get_gddr(void * p)
530{
531 struct mr_rsp_gddr * r;
532
533 r = (struct mr_rsp_gddr *) p;
534 *r = gddr;
535 return sizeof(*r);
536}
537
538
539int
540mr_get_trc(void * p)
541{
542 struct mr_rsp_trc * r;
543
544 r = (struct mr_rsp_trc *) p;
545 *r = trc;
546 return sizeof(*r);
547}
548
549
550int
551mr_get_cutl(void * p)
552{
553 struct mr_rsp_cutl * r;
554 struct timespec tp;
555 struct cpu_usage_stat * u;
556 uint64_t user, nice, sys, idle;
557 int i, n;
558
559 r = (struct mr_rsp_cutl *) p;
560 memset(r, '\0', sizeof(*r));
561 r->tck = ACTHZ;
562 r->core = clst.count;
563 r->thr = clst.thr;
564 ktime_get_ts(&tp);
565 monotonic_to_bootbased(&tp);
566 r->jif = timespec_to_jiffies(&tp);
567
568 for_each_possible_cpu(i) {
569 u = & kstat_cpu(i).cpustat;
570
571 user = u->user;
572 nice = u->nice;
573 sys = u->system + u->irq + u->softirq;
574 idle = u->idle + u->iowait;
575
576 r->sum.user += user;
577 r->sum.nice += nice;
578 r->sum.sys += sys;
579 r->sum.idle += idle;
580
581 /*
582 * Currently the boot processor is thread 0 of the last
583 * enabled core. Thus, on a 32 core machine, we get:
584 *
585 * cpu # 0 1 2 3 4 5 .. 124 125 126 127
586 * core # 31 0 0 0 0 1 .. 30 31 31 31
587 * apic ID 124 0 1 2 3 4 .. 123 125 126 127
588 *
589 * The core is included in the per-cpu CpuInfo struct,
590 * and it should be safe to get it from there.
591 */
592 n = cpu_data(i).cpu_core_id;
593 if (n < r->core) {
594 r->cpu[n].user += user;
595 r->cpu[n].nice += nice;
596 r->cpu[n].sys += sys;
597 r->cpu[n].idle += idle;
598 }
599 }
600
601 return sizeof(*r);
602}
603
604
605int
606mr_get_mem(void * p)
607{
608 struct mr_rsp_mem * r;
609 struct sysinfo si;
610
611 si_meminfo(&si);
612
613 r = (struct mr_rsp_mem *) p;
614 memset(r, '\0', sizeof(*r));
615 r->total = si.totalram << (PAGE_SHIFT - 10);
616 r->free = si.freeram << (PAGE_SHIFT - 10);
617 r->bufs = si.bufferram << (PAGE_SHIFT - 10);
618
619 return sizeof(*r);
620}
621
622
623int
624mr_get_os(void * p)
625{
626 struct mr_rsp_os * r;
627 uint16_t i;
628 struct timespec tp;
629 struct task_struct * t;
630
631 ktime_get_ts(&tp);
632 monotonic_to_bootbased(&tp);
633
634 r = (struct mr_rsp_os *) p;
635 memset(r, '\0', sizeof(*r));
636 r->uptime = tp.tv_sec + (tp.tv_nsec ? 1 : 0);
637 r->loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
638 r->loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);
639 r->loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT);
640
641 /*
642 * Walk process list and indentify processes that
643 * are associated with user programs. For now we
644 * exclude kernel threads and non-stable processes.
645 *
646 *TBD: Really just wanted to take the task_lock, but
647 * it is not exported to modules. It seems to be
648 * tied into the RCU logic, so locking the whole
649 * RCU should do the trick as long as it's just
650 * for a very short time.
651 */
652 i = 0;
653 rcu_read_lock();
654 for_each_process(t) {
655 if ((t->flags & (PF_KTHREAD | PF_STARTING | PF_EXITING)) ||
656 (t->group_leader && t->group_leader != t))
657 continue;
658
659 if (i < ARRAY_SIZE(r->apid))
660 r->apid[i] = t->pid;
661 i++;
662 }
663 rcu_read_unlock();
664 r->alen = i;
665
666 return sizeof(*r);
667}
668
669
670int
671mr_get_proc(void * p)
672{
673 struct mr_rsp_proc * r;
674 struct task_struct * t, * s;
675 struct mm_struct * mm;
676 struct timespec uptime, start, ts;
677 cputime_t utime, stime;
678 pid_t pid;
679 int err, i;
680
681 err = -MR_ERR_NOVAL;
682 pid = * (uint32_t *) p;
683 if (! pid)
684 return err;
685
686 r = (struct mr_rsp_proc *) p;
687 memset(r, '\0', sizeof(*r));
688 do_posix_clock_monotonic_gettime(&uptime);
689
690 rcu_read_lock();
691 t = pid_task(find_pid_ns(pid, &init_pid_ns), PIDTYPE_PID);
692 if (t) {
693 /*
694 * Found process, get base stats
695 */
696 r->pid = pid;
697 strncpy(r->name +1, t->comm, sizeof(r->name) -1);
698 start = t->start_time;
699 utime = t->utime;
700 stime = t->stime;
701 mm = get_task_mm(t);
702 if (mm) {
703#ifdef SPLIT_RSS_COUNTING
704 r->rss = atomic_long_read(& mm->rss_stat.count[MM_FILEPAGES]) +
705 atomic_long_read(& mm->rss_stat.count[MM_ANONPAGES]);
706#else
707 r->rss = mm->rss_stat.count[MM_FILEPAGES] +
708 mm->rss_stat.count[MM_ANONPAGES];
709#endif
710 r->vm = mm->total_vm;
711 mmput(mm);
712 }
713
714 /*
715 * Next try get list of threads (if any)
716 */
717 i = 0;
718 if (!t->group_leader || t->group_leader == t) {
719 s = t;
720 do {
721 if (s->pid != pid) {
722 if (i < ARRAY_SIZE(r->tpid))
723 r->tpid[i++] = s->pid;
724 }
725 } while_each_thread(t, s);
726 }
727 r->tlen = i;
728 err = sizeof(*r);
729 }
730 rcu_read_unlock();
731
732 /*
733 * Convert values into API formats (uSec, kB).
734 */
735 if (err > 0) {
736 r->name[0] = strlen(r->name +1);
737 ts = timespec_sub(uptime, start);
738 r->etime = timespec_to_ns(&ts) / NSEC_PER_USEC;
739 r->utime = jiffies_to_usecs(utime);
740 r->stime = jiffies_to_usecs(stime);
741 r->vm = r->vm << (PAGE_SHIFT - 10);
742 r->rss = r->rss << (PAGE_SHIFT - 10);
743 }
744
745 return err;
746}
747
748
749
750/*
751**
752** MT Set functions
753**
754** All works the same way; they get an opague pointer to
755** a location where the 'set' parameter from the request is
756** placed. Return code is one of the MR_* error codes.
757**
758** Input screening takes place here (to the extent possible).
759**
760*/
761
762
763#if NOT_YET
764int
765mr_set_gvolt(void * p)
766{
767 /*
768 * Cannot be set from uOS, pretend success
769 */
770 return 0;
771}
772
773
774int
775mr_set_gfreq(void * p)
776{
777 /*
778 * Cannot be set from uOS, pretend success
779 */
780 return 0;
781}
782#endif
783
784
785int
786mr_set_trc(void * p)
787{
788 /*
789 * No idea on what to do with this
790 */
791 trc.lvl = *(uint32_t *) p;
792 return 0;
793}
794
795
796
797/*
798**
799** MT Process controls
800**
801*/
802
803int
804mr_cmd_pkill(void * p)
805{
806 struct task_struct * t;
807 const struct cred * cred;
808 pid_t pid;
809 uint32_t val;
810 int sig, ret;
811
812 val = *(uint32_t *) p;
813 pid = GET_BITS(23, 0, val);
814 sig = GET_BITS(31, 24, val);
815
816 ret = -MR_ERR_INVAUX;
817 rcu_read_lock();
818 t = pid_task(find_pid_ns(pid, &init_pid_ns), PIDTYPE_PID);
819 if (t) {
820 if (!(t->flags & (PF_KTHREAD | PF_STARTING | PF_EXITING)) &&
821 !(t->group_leader && t->group_leader != t)) {
822
823 cred = __task_cred(t);
824 if (cred->euid >= 500) {
825 if (!send_sig(sig, t, 1))
826 ret = 0;
827 }
828 else
829 ret = -MR_ERR_PERM;
830 }
831 }
832 rcu_read_unlock();
833
834 return ret;
835}
836
837
838int
839mr_cmd_ukill(void * p)
840{
841 struct task_struct * t;
842 const struct cred * cred;
843 uid_t uid;
844 uint32_t val;
845 int sig, ret;
846
847 val = *(uint32_t *) p;
848 uid = GET_BITS(23, 0, val);
849 sig = GET_BITS(31, 24, val);
850
851 if (uid < 500)
852 return -MR_ERR_PERM;
853
854 ret = 0;
855 rcu_read_lock();
856 for_each_process(t) {
857 if ((t->flags & (PF_KTHREAD | PF_STARTING | PF_EXITING)) ||
858 (t->group_leader && t->group_leader != t))
859 continue;
860
861 cred = __task_cred(t);
862 if (cred->euid == uid) {
863 ret = send_sig(sig, t, 1);
864 if (ret)
865 break;
866 }
867 }
868 rcu_read_unlock();
869
870 return ret ? -MR_ERR_INVAUX : 0;
871}
872
873
874/*
875**
876** Debug utilities.
877** Remove or comment out when development complete!
878**
879*/
880
881#if EE_VERIFY
882/*
883 * Hex dumper
884 */
885
886#include <linux/ctype.h>
887
888#define ALEN 9 /* Digits of address shown */
889
890void
891dmp_hex(void *ptr, int len, const char *msg, ...)
892{
893 unsigned char * d;
894 unsigned char * prev;
895 int n, m;
896 int star;
897 char asc[16 + 1];
898
899 star = 0;
900 prev = 0;
901
902 /*
903 * Print message (if any).
904 * It is treated as a 'printf' format strings with arguments.
905 */
906 if (msg) {
907 va_list ap;
908
909 va_start(ap, msg);
910 vprintk(msg, ap);
911 va_end(ap);
912 printk("\n");
913 }
914
915 /*
916 * Loop trying to dump 16 bytes at a time
917 */
918 for(d = (unsigned char *) ptr;; d += 16) {
919
920 /*
921 * Locate dump area from input buffer;
922 */
923 n = (len > 16) ? 16 : len;
924 len -= n;
925
926 /*
927 * Skip repeated lines.
928 * I want the last line shown on the output.
929 */
930 if (d != ptr && n == 16 && !memcmp(d, prev, 16)) {
931 if (len) {
932 if (!star) {
933 star = 1;
934 printk("%*s\n", ALEN + 3, "*");
935 }
936 continue;
937 }
938 }
939
940 /*
941 * Print one line of hex dump.
942 */
943 if (n) {
944 printk("%*lx ", ALEN, ((long) d) & ((1L << 4 * ALEN) - 1));
945 for(m = 0; m < n; m++) {
946 printk("%02x ", d[m]);
947 if (m == 7)
948 printk(" ");
949 asc[m] = (isascii(d[m]) && isprint(d[m])) ? d[m] : '.';
950 }
951 asc[m] = '\0';
952 printk("%*s %s\n", 3 * (16 - m) + (m < 8), "", asc);
953 }
954
955 /*
956 * We are done when end of buffer reached
957 */
958 if (!len)
959 break;
960
961 /*
962 * Reset repeat line suppression
963 */
964 star = 0;
965 prev = d;
966 }
967}
968#endif