visorkmodutils.c revision fcd0157ece8a1bf36b877a9c8078ea721678a38b
1/* timskmodutils.c
2 *
3 * Copyright (C) 2010 - 2013 UNISYS CORPORATION
4 * All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or (at
9 * your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
14 * NON INFRINGEMENT.  See the GNU General Public License for more
15 * details.
16 */
17
18#include "uniklog.h"
19#include "timskmod.h"
20
21#define MYDRVNAME "timskmodutils"
22
23/* s-Par uses the Intel processor's VT-X features to separate groups of
24 * processors into partitions. The firmware sets the hypervisor bit and
25 * reports an ID in the HV capabilities leaf so that the partition's OS
26 * knows s-Par is present and managing the processors.
27 */
28
29#define UNISYS_SPAR_LEAF_ID 0x40000000
30
31/* The s-Par leaf ID returns "UnisysSpar64" encoded across ebx, ecx, edx */
32#define UNISYS_SPAR_ID_EBX 0x73696e55
33#define UNISYS_SPAR_ID_ECX 0x70537379
34#define UNISYS_SPAR_ID_EDX 0x34367261
35
36int unisys_spar_platform;
37EXPORT_SYMBOL_GPL(unisys_spar_platform);
38
39/** Callers to interfaces that set __GFP_NORETRY flag below
40 *  must check for a NULL (error) result as we are telling the
41 *  kernel interface that it is okay to fail.
42 */
43
44void *kmalloc_kernel(size_t siz)
45{
46	return kmalloc(siz, GFP_KERNEL | __GFP_NORETRY);
47}
48
49/*  Use these handy-dandy seq_file_xxx functions if you want to call some
50 *  functions that write stuff into a seq_file, but you actually just want
51 *  to dump that output into a buffer.  Use them as follows:
52 *  - call visor_seq_file_new_buffer to create the seq_file (you supply the buf)
53 *  - call whatever functions you want that take a seq_file as an argument
54 *    (the buf you supplied will get the output data)
55 *  - call visor_seq_file_done_buffer to dispose of your seq_file
56 */
57struct seq_file *visor_seq_file_new_buffer(void *buf, size_t buf_size)
58{
59	struct seq_file *rc = NULL;
60	struct seq_file *m = kmalloc_kernel(sizeof(struct seq_file));
61
62	if (m == NULL) {
63		rc = NULL;
64		goto Away;
65	}
66	memset(m, 0, sizeof(struct seq_file));
67	m->buf = buf;
68	m->size = buf_size;
69	rc = m;
70Away:
71	if (rc == NULL) {
72		visor_seq_file_done_buffer(m);
73		m = NULL;
74	}
75	return rc;
76}
77EXPORT_SYMBOL_GPL(visor_seq_file_new_buffer);
78
79
80
81void visor_seq_file_done_buffer(struct seq_file *m)
82{
83	if (!m)
84		return;
85	kfree(m);
86}
87EXPORT_SYMBOL_GPL(visor_seq_file_done_buffer);
88
89static __init uint32_t
90visorutil_spar_detect(void)
91{
92	unsigned int eax, ebx, ecx, edx;
93
94	if (cpu_has_hypervisor) {
95		/* check the ID */
96		cpuid(UNISYS_SPAR_LEAF_ID, &eax, &ebx, &ecx, &edx);
97		return  (ebx == UNISYS_SPAR_ID_EBX) &&
98			(ecx == UNISYS_SPAR_ID_ECX) &&
99			(edx == UNISYS_SPAR_ID_EDX);
100	} else
101		return 0;
102
103}
104
105
106
107
108static __init int
109visorutil_mod_init(void)
110{
111	if (visorutil_spar_detect()) {
112		unisys_spar_platform = TRUE;
113		return 0;
114	} else
115		return -ENODEV;
116}
117
118static __exit void
119visorutil_mod_exit(void)
120{
121}
122
123module_init(visorutil_mod_init);
124module_exit(visorutil_mod_exit);
125
126