direct-io.hg

view xen/common/kernel.c @ 15399:45a44a9cbe8d

Enhance guest memory accessor macros so that source operands can be
pointers to const or arrays.

Only build-tested on ia64, and untested for powerpc (which, however,
is almost identical to ia64, except for an apparent bug in the original
version of __copy_field_{from,to}_guest in that the field offset was
multiplied by the field size).

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author kfraser@localhost.localdomain
date Wed Jun 20 15:29:53 2007 +0100 (2007-06-20)
parents f830c5719e74
children 646ec1f2b41f
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/shadow.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, *q;
30 const char *p = cmdline;
31 struct kernel_param *param;
33 if ( p == NULL )
34 return;
36 /* Skip whitespace and the image name. */
37 while ( *p == ' ' )
38 p++;
39 if ( (p = strchr(p, ' ')) == NULL )
40 return;
42 for ( ; ; )
43 {
44 /* Skip whitespace. */
45 while ( *p == ' ' )
46 p++;
47 if ( *p == '\0' )
48 break;
50 /* Grab the next whitespace-delimited option. */
51 q = opt;
52 while ( (*p != ' ') && (*p != '\0') )
53 {
54 if ( (q-opt) < (sizeof(opt)-1) ) /* avoid overflow */
55 *q++ = *p;
56 p++;
57 }
58 *q = '\0';
60 /* Search for value part of a key=value option. */
61 optval = strchr(opt, '=');
62 if ( optval != NULL )
63 *optval++ = '\0'; /* nul-terminate the option value */
64 else
65 optval = q; /* default option value is empty string */
67 for ( param = &__setup_start; param <= &__setup_end; param++ )
68 {
69 if ( strcmp(param->name, opt ) != 0 )
70 continue;
72 switch ( param->type )
73 {
74 case OPT_STR:
75 strlcpy(param->var, optval, param->len);
76 break;
77 case OPT_UINT:
78 *(unsigned int *)param->var =
79 simple_strtol(optval, (const char **)&optval, 0);
80 break;
81 case OPT_BOOL:
82 *(int *)param->var = 1;
83 break;
84 case OPT_CUSTOM:
85 ((void (*)(const char *))param->var)(optval);
86 break;
87 }
88 }
89 }
90 }
92 /**
93 * print_tainted - return a string to represent the kernel taint state.
94 *
95 * 'S' - SMP with CPUs not designed for SMP.
96 * 'M' - Machine had a machine check experience.
97 * 'B' - System has hit bad_page.
98 *
99 * The string is overwritten by the next call to print_taint().
100 */
101 char *print_tainted(char *str)
102 {
103 if ( tainted )
104 {
105 snprintf(str, TAINT_STRING_MAX_LEN, "Tainted: %c%c%c%c",
106 tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
107 tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
108 tainted & TAINT_BAD_PAGE ? 'B' : ' ',
109 tainted & TAINT_SYNC_CONSOLE ? 'C' : ' ');
110 }
111 else
112 {
113 snprintf(str, TAINT_STRING_MAX_LEN, "Not tainted");
114 }
116 return str;
117 }
119 void add_taint(unsigned flag)
120 {
121 tainted |= flag;
122 }
124 # define DO(fn) long do_##fn
126 #endif
128 /*
129 * Simple hypercalls.
130 */
132 DO(xen_version)(int cmd, XEN_GUEST_HANDLE(void) arg)
133 {
134 switch ( cmd )
135 {
136 case XENVER_version:
137 {
138 return (xen_major_version() << 16) | xen_minor_version();
139 }
141 case XENVER_extraversion:
142 {
143 xen_extraversion_t extraversion;
144 safe_strcpy(extraversion, xen_extra_version());
145 if ( copy_to_guest(arg, extraversion, ARRAY_SIZE(extraversion)) )
146 return -EFAULT;
147 return 0;
148 }
150 case XENVER_compile_info:
151 {
152 struct xen_compile_info info;
153 safe_strcpy(info.compiler, xen_compiler());
154 safe_strcpy(info.compile_by, xen_compile_by());
155 safe_strcpy(info.compile_domain, xen_compile_domain());
156 safe_strcpy(info.compile_date, xen_compile_date());
157 if ( copy_to_guest(arg, &info, 1) )
158 return -EFAULT;
159 return 0;
160 }
162 case XENVER_capabilities:
163 {
164 xen_capabilities_info_t info;
165 extern void arch_get_xen_caps(xen_capabilities_info_t *info);
167 memset(info, 0, sizeof(info));
168 arch_get_xen_caps(&info);
170 if ( copy_to_guest(arg, info, ARRAY_SIZE(info)) )
171 return -EFAULT;
172 return 0;
173 }
175 case XENVER_platform_parameters:
176 {
177 xen_platform_parameters_t params = {
178 .virt_start = HYPERVISOR_VIRT_START
179 };
180 if ( copy_to_guest(arg, &params, 1) )
181 return -EFAULT;
182 return 0;
184 }
186 case XENVER_changeset:
187 {
188 xen_changeset_info_t chgset;
189 safe_strcpy(chgset, xen_changeset());
190 if ( copy_to_guest(arg, chgset, ARRAY_SIZE(chgset)) )
191 return -EFAULT;
192 return 0;
193 }
195 case XENVER_get_features:
196 {
197 xen_feature_info_t fi;
198 struct domain *d = current->domain;
200 if ( copy_from_guest(&fi, arg, 1) )
201 return -EFAULT;
203 switch ( fi.submap_idx )
204 {
205 case 0:
206 fi.submap = 0;
207 if ( VM_ASSIST(d, VMASST_TYPE_pae_extended_cr3) )
208 fi.submap |= (1U << XENFEAT_pae_pgdir_above_4gb);
209 if ( shadow_mode_translate(current->domain) )
210 fi.submap |=
211 (1U << XENFEAT_writable_page_tables) |
212 (1U << XENFEAT_auto_translated_physmap);
213 if ( supervisor_mode_kernel )
214 fi.submap |= 1U << XENFEAT_supervisor_mode_kernel;
215 break;
216 default:
217 return -EINVAL;
218 }
220 if ( copy_to_guest(arg, &fi, 1) )
221 return -EFAULT;
222 return 0;
223 }
225 case XENVER_pagesize:
226 {
227 return (!guest_handle_is_null(arg) ? -EINVAL : PAGE_SIZE);
228 }
230 case XENVER_guest_handle:
231 {
232 if ( copy_to_guest(arg, current->domain->handle,
233 ARRAY_SIZE(current->domain->handle)) )
234 return -EFAULT;
235 return 0;
236 }
237 }
239 return -ENOSYS;
240 }
242 #ifndef COMPAT
244 long register_guest_nmi_callback(unsigned long address)
245 {
246 struct vcpu *v = current;
247 struct domain *d = current->domain;
249 if ( (d->domain_id != 0) || (v->vcpu_id != 0) )
250 return -EINVAL;
252 v->nmi_addr = address;
253 #ifdef CONFIG_X86
254 /*
255 * If no handler was registered we can 'lose the NMI edge'. Re-assert it
256 * now.
257 */
258 if ( arch_get_nmi_reason(d) != 0 )
259 v->nmi_pending = 1;
260 #endif
262 return 0;
263 }
265 long unregister_guest_nmi_callback(void)
266 {
267 struct vcpu *v = current;
269 v->nmi_addr = 0;
271 return 0;
272 }
274 #endif
276 DO(nmi_op)(unsigned int cmd, XEN_GUEST_HANDLE(void) arg)
277 {
278 struct xennmi_callback cb;
279 long rc = 0;
281 switch ( cmd )
282 {
283 case XENNMI_register_callback:
284 rc = -EFAULT;
285 if ( copy_from_guest(&cb, arg, 1) )
286 break;
287 rc = register_guest_nmi_callback(cb.handler_address);
288 break;
289 case XENNMI_unregister_callback:
290 rc = unregister_guest_nmi_callback();
291 break;
292 default:
293 rc = -ENOSYS;
294 break;
295 }
297 return rc;
298 }
300 DO(vm_assist)(unsigned int cmd, unsigned int type)
301 {
302 return vm_assist(current->domain, cmd, type);
303 }
305 DO(ni_hypercall)(void)
306 {
307 /* No-op hypercall. */
308 return -ENOSYS;
309 }
311 /*
312 * Local variables:
313 * mode: C
314 * c-set-style: "BSD"
315 * c-basic-offset: 4
316 * tab-width: 4
317 * indent-tabs-mode: nil
318 * End:
319 */