ia64/xen-unstable

view xen/common/kernel.c @ 15647:cc48264ed647

Merge
author Tim Deegan <Tim.Deegan@xensource.com>
date Tue Jul 24 14:53:06 2007 +0100 (2007-07-24)
parents 3c28bc13a3f8
children 2eb38cefdcd9
line source
1 /******************************************************************************
2 * kernel.c
3 *
4 * Copyright (c) 2002-2005 K A Fraser
5 */
7 #include <xen/config.h>
8 #include <xen/init.h>
9 #include <xen/lib.h>
10 #include <xen/errno.h>
11 #include <xen/version.h>
12 #include <xen/sched.h>
13 #include <xen/paging.h>
14 #include <xen/nmi.h>
15 #include <xen/guest_access.h>
16 #include <asm/current.h>
17 #include <public/nmi.h>
18 #include <public/version.h>
19 #ifdef CONFIG_X86
20 #include <asm/shared.h>
21 #endif
23 #ifndef COMPAT
25 int tainted;
27 void cmdline_parse(char *cmdline)
28 {
29 char opt[100], *optval, *optkey, *q;
30 const char *p = cmdline;
31 struct kernel_param *param;
32 int bool_assert;
34 if ( p == NULL )
35 return;
37 /* Skip whitespace and the image name. */
38 while ( *p == ' ' )
39 p++;
40 if ( (p = strchr(p, ' ')) == NULL )
41 return;
43 for ( ; ; )
44 {
45 /* Skip whitespace. */
46 while ( *p == ' ' )
47 p++;
48 if ( *p == '\0' )
49 break;
51 /* Grab the next whitespace-delimited option. */
52 q = optkey = opt;
53 while ( (*p != ' ') && (*p != '\0') )
54 {
55 if ( (q-opt) < (sizeof(opt)-1) ) /* avoid overflow */
56 *q++ = *p;
57 p++;
58 }
59 *q = '\0';
61 /* Search for value part of a key=value option. */
62 optval = strchr(opt, '=');
63 if ( optval != NULL )
64 *optval++ = '\0'; /* nul-terminate the option value */
65 else
66 optval = q; /* default option value is empty string */
68 /* Boolean parameters can be inverted with 'no-' prefix. */
69 bool_assert = !!strncmp("no-", optkey, 3);
70 if ( !bool_assert )
71 optkey += 3;
73 for ( param = &__setup_start; param <= &__setup_end; param++ )
74 {
75 if ( strcmp(param->name, optkey) )
76 continue;
78 switch ( param->type )
79 {
80 case OPT_STR:
81 strlcpy(param->var, optval, param->len);
82 break;
83 case OPT_UINT:
84 *(unsigned int *)param->var =
85 simple_strtol(optval, (const char **)&optval, 0);
86 break;
87 case OPT_BOOL:
88 case OPT_INVBOOL:
89 if ( !strcmp("no", optval) || !strcmp("off", optval) )
90 bool_assert = !bool_assert;
91 if ( param->type == OPT_INVBOOL )
92 bool_assert = !bool_assert;
93 *(int *)param->var = bool_assert;
94 break;
95 case OPT_CUSTOM:
96 ((void (*)(const char *))param->var)(optval);
97 break;
98 }
99 }
100 }
101 }
103 /**
104 * print_tainted - return a string to represent the kernel taint state.
105 *
106 * 'S' - SMP with CPUs not designed for SMP.
107 * 'M' - Machine had a machine check experience.
108 * 'B' - System has hit bad_page.
109 *
110 * The string is overwritten by the next call to print_taint().
111 */
112 char *print_tainted(char *str)
113 {
114 if ( tainted )
115 {
116 snprintf(str, TAINT_STRING_MAX_LEN, "Tainted: %c%c%c%c",
117 tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
118 tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
119 tainted & TAINT_BAD_PAGE ? 'B' : ' ',
120 tainted & TAINT_SYNC_CONSOLE ? 'C' : ' ');
121 }
122 else
123 {
124 snprintf(str, TAINT_STRING_MAX_LEN, "Not tainted");
125 }
127 return str;
128 }
130 void add_taint(unsigned flag)
131 {
132 tainted |= flag;
133 }
135 # define DO(fn) long do_##fn
137 #endif
139 /*
140 * Simple hypercalls.
141 */
143 DO(xen_version)(int cmd, XEN_GUEST_HANDLE(void) arg)
144 {
145 switch ( cmd )
146 {
147 case XENVER_version:
148 {
149 return (xen_major_version() << 16) | xen_minor_version();
150 }
152 case XENVER_extraversion:
153 {
154 xen_extraversion_t extraversion;
155 safe_strcpy(extraversion, xen_extra_version());
156 if ( copy_to_guest(arg, extraversion, ARRAY_SIZE(extraversion)) )
157 return -EFAULT;
158 return 0;
159 }
161 case XENVER_compile_info:
162 {
163 struct xen_compile_info info;
164 safe_strcpy(info.compiler, xen_compiler());
165 safe_strcpy(info.compile_by, xen_compile_by());
166 safe_strcpy(info.compile_domain, xen_compile_domain());
167 safe_strcpy(info.compile_date, xen_compile_date());
168 if ( copy_to_guest(arg, &info, 1) )
169 return -EFAULT;
170 return 0;
171 }
173 case XENVER_capabilities:
174 {
175 xen_capabilities_info_t info;
176 extern void arch_get_xen_caps(xen_capabilities_info_t *info);
178 memset(info, 0, sizeof(info));
179 arch_get_xen_caps(&info);
181 if ( copy_to_guest(arg, info, ARRAY_SIZE(info)) )
182 return -EFAULT;
183 return 0;
184 }
186 case XENVER_platform_parameters:
187 {
188 xen_platform_parameters_t params = {
189 .virt_start = HYPERVISOR_VIRT_START
190 };
191 if ( copy_to_guest(arg, &params, 1) )
192 return -EFAULT;
193 return 0;
195 }
197 case XENVER_changeset:
198 {
199 xen_changeset_info_t chgset;
200 safe_strcpy(chgset, xen_changeset());
201 if ( copy_to_guest(arg, chgset, ARRAY_SIZE(chgset)) )
202 return -EFAULT;
203 return 0;
204 }
206 case XENVER_get_features:
207 {
208 xen_feature_info_t fi;
209 struct domain *d = current->domain;
211 if ( copy_from_guest(&fi, arg, 1) )
212 return -EFAULT;
214 switch ( fi.submap_idx )
215 {
216 case 0:
217 fi.submap = 0;
218 if ( VM_ASSIST(d, VMASST_TYPE_pae_extended_cr3) )
219 fi.submap |= (1U << XENFEAT_pae_pgdir_above_4gb);
220 if ( paging_mode_translate(current->domain) )
221 fi.submap |=
222 (1U << XENFEAT_writable_page_tables) |
223 (1U << XENFEAT_auto_translated_physmap);
224 if ( supervisor_mode_kernel )
225 fi.submap |= 1U << XENFEAT_supervisor_mode_kernel;
226 break;
227 default:
228 return -EINVAL;
229 }
231 if ( copy_to_guest(arg, &fi, 1) )
232 return -EFAULT;
233 return 0;
234 }
236 case XENVER_pagesize:
237 {
238 return (!guest_handle_is_null(arg) ? -EINVAL : PAGE_SIZE);
239 }
241 case XENVER_guest_handle:
242 {
243 if ( copy_to_guest(arg, current->domain->handle,
244 ARRAY_SIZE(current->domain->handle)) )
245 return -EFAULT;
246 return 0;
247 }
248 }
250 return -ENOSYS;
251 }
253 #ifndef COMPAT
255 long register_guest_nmi_callback(unsigned long address)
256 {
257 struct vcpu *v = current;
258 struct domain *d = current->domain;
260 if ( (d->domain_id != 0) || (v->vcpu_id != 0) )
261 return -EINVAL;
263 v->nmi_addr = address;
264 #ifdef CONFIG_X86
265 /*
266 * If no handler was registered we can 'lose the NMI edge'. Re-assert it
267 * now.
268 */
269 if ( arch_get_nmi_reason(d) != 0 )
270 v->nmi_pending = 1;
271 #endif
273 return 0;
274 }
276 long unregister_guest_nmi_callback(void)
277 {
278 struct vcpu *v = current;
280 v->nmi_addr = 0;
282 return 0;
283 }
285 #endif
287 DO(nmi_op)(unsigned int cmd, XEN_GUEST_HANDLE(void) arg)
288 {
289 struct xennmi_callback cb;
290 long rc = 0;
292 switch ( cmd )
293 {
294 case XENNMI_register_callback:
295 rc = -EFAULT;
296 if ( copy_from_guest(&cb, arg, 1) )
297 break;
298 rc = register_guest_nmi_callback(cb.handler_address);
299 break;
300 case XENNMI_unregister_callback:
301 rc = unregister_guest_nmi_callback();
302 break;
303 default:
304 rc = -ENOSYS;
305 break;
306 }
308 return rc;
309 }
311 DO(vm_assist)(unsigned int cmd, unsigned int type)
312 {
313 return vm_assist(current->domain, cmd, type);
314 }
316 DO(ni_hypercall)(void)
317 {
318 /* No-op hypercall. */
319 return -ENOSYS;
320 }
322 /*
323 * Local variables:
324 * mode: C
325 * c-set-style: "BSD"
326 * c-basic-offset: 4
327 * tab-width: 4
328 * indent-tabs-mode: nil
329 * End:
330 */