ia64/xen-unstable

view xen/common/kernel.c @ 17062:0769835cf50f

x86 shadow: Reduce scope of shadow lock.

emulate_map_dest doesn't require holding lock, since
only shadow related operation possibly involved is to
remove shadow which is less frequent and can acquire
lock inside. Rest are either guest table walk or
per-vcpu monitor table manipulation

Signed-off-by Kevin Tian <kevin.tian@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Feb 14 10:33:12 2008 +0000 (2008-02-14)
parents 847bc9b19c48
children 33d6ed9fd3c5
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 for ( ; ; )
38 {
39 /* Skip whitespace. */
40 while ( *p == ' ' )
41 p++;
42 if ( *p == '\0' )
43 break;
45 /* Grab the next whitespace-delimited option. */
46 q = optkey = opt;
47 while ( (*p != ' ') && (*p != '\0') )
48 {
49 if ( (q-opt) < (sizeof(opt)-1) ) /* avoid overflow */
50 *q++ = *p;
51 p++;
52 }
53 *q = '\0';
55 /* Search for value part of a key=value option. */
56 optval = strchr(opt, '=');
57 if ( optval != NULL )
58 *optval++ = '\0'; /* nul-terminate the option value */
59 else
60 optval = q; /* default option value is empty string */
62 /* Boolean parameters can be inverted with 'no-' prefix. */
63 bool_assert = !!strncmp("no-", optkey, 3);
64 if ( !bool_assert )
65 optkey += 3;
67 for ( param = &__setup_start; param <= &__setup_end; param++ )
68 {
69 if ( strcmp(param->name, optkey) )
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 case OPT_INVBOOL:
83 if ( !strcmp("no", optval) ||
84 !strcmp("off", optval) ||
85 !strcmp("false", optval) ||
86 !strcmp("0", optval) )
87 bool_assert = !bool_assert;
88 if ( param->type == OPT_INVBOOL )
89 bool_assert = !bool_assert;
90 *(int *)param->var = bool_assert;
91 break;
92 case OPT_CUSTOM:
93 ((void (*)(const char *))param->var)(optval);
94 break;
95 }
96 }
97 }
98 }
100 /**
101 * print_tainted - return a string to represent the kernel taint state.
102 *
103 * 'S' - SMP with CPUs not designed for SMP.
104 * 'M' - Machine had a machine check experience.
105 * 'B' - System has hit bad_page.
106 *
107 * The string is overwritten by the next call to print_taint().
108 */
109 char *print_tainted(char *str)
110 {
111 if ( tainted )
112 {
113 snprintf(str, TAINT_STRING_MAX_LEN, "Tainted: %c%c%c%c",
114 tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
115 tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
116 tainted & TAINT_BAD_PAGE ? 'B' : ' ',
117 tainted & TAINT_SYNC_CONSOLE ? 'C' : ' ');
118 }
119 else
120 {
121 snprintf(str, TAINT_STRING_MAX_LEN, "Not tainted");
122 }
124 return str;
125 }
127 void add_taint(unsigned flag)
128 {
129 tainted |= flag;
130 }
132 # define DO(fn) long do_##fn
134 #endif
136 /*
137 * Simple hypercalls.
138 */
140 DO(xen_version)(int cmd, XEN_GUEST_HANDLE(void) arg)
141 {
142 switch ( cmd )
143 {
144 case XENVER_version:
145 {
146 return (xen_major_version() << 16) | xen_minor_version();
147 }
149 case XENVER_extraversion:
150 {
151 xen_extraversion_t extraversion;
152 safe_strcpy(extraversion, xen_extra_version());
153 if ( copy_to_guest(arg, extraversion, ARRAY_SIZE(extraversion)) )
154 return -EFAULT;
155 return 0;
156 }
158 case XENVER_compile_info:
159 {
160 struct xen_compile_info info;
161 safe_strcpy(info.compiler, xen_compiler());
162 safe_strcpy(info.compile_by, xen_compile_by());
163 safe_strcpy(info.compile_domain, xen_compile_domain());
164 safe_strcpy(info.compile_date, xen_compile_date());
165 if ( copy_to_guest(arg, &info, 1) )
166 return -EFAULT;
167 return 0;
168 }
170 case XENVER_capabilities:
171 {
172 xen_capabilities_info_t info;
173 extern void arch_get_xen_caps(xen_capabilities_info_t *info);
175 memset(info, 0, sizeof(info));
176 arch_get_xen_caps(&info);
178 if ( copy_to_guest(arg, info, ARRAY_SIZE(info)) )
179 return -EFAULT;
180 return 0;
181 }
183 case XENVER_platform_parameters:
184 {
185 xen_platform_parameters_t params = {
186 .virt_start = HYPERVISOR_VIRT_START
187 };
188 if ( copy_to_guest(arg, &params, 1) )
189 return -EFAULT;
190 return 0;
192 }
194 case XENVER_changeset:
195 {
196 xen_changeset_info_t chgset;
197 safe_strcpy(chgset, xen_changeset());
198 if ( copy_to_guest(arg, chgset, ARRAY_SIZE(chgset)) )
199 return -EFAULT;
200 return 0;
201 }
203 case XENVER_get_features:
204 {
205 xen_feature_info_t fi;
206 struct domain *d = current->domain;
208 if ( copy_from_guest(&fi, arg, 1) )
209 return -EFAULT;
211 switch ( fi.submap_idx )
212 {
213 case 0:
214 fi.submap = 0;
215 if ( VM_ASSIST(d, VMASST_TYPE_pae_extended_cr3) )
216 fi.submap |= (1U << XENFEAT_pae_pgdir_above_4gb);
217 if ( paging_mode_translate(current->domain) )
218 fi.submap |=
219 (1U << XENFEAT_writable_page_tables) |
220 (1U << XENFEAT_auto_translated_physmap);
221 if ( supervisor_mode_kernel )
222 fi.submap |= 1U << XENFEAT_supervisor_mode_kernel;
223 #ifdef CONFIG_X86
224 if ( !is_hvm_vcpu(current) )
225 fi.submap |= 1U << XENFEAT_mmu_pt_update_preserve_ad;
226 #endif
227 break;
228 default:
229 return -EINVAL;
230 }
232 if ( copy_to_guest(arg, &fi, 1) )
233 return -EFAULT;
234 return 0;
235 }
237 case XENVER_pagesize:
238 {
239 return (!guest_handle_is_null(arg) ? -EINVAL : PAGE_SIZE);
240 }
242 case XENVER_guest_handle:
243 {
244 if ( copy_to_guest(arg, current->domain->handle,
245 ARRAY_SIZE(current->domain->handle)) )
246 return -EFAULT;
247 return 0;
248 }
249 }
251 return -ENOSYS;
252 }
254 DO(nmi_op)(unsigned int cmd, XEN_GUEST_HANDLE(void) arg)
255 {
256 struct xennmi_callback cb;
257 long rc = 0;
259 switch ( cmd )
260 {
261 case XENNMI_register_callback:
262 rc = -EFAULT;
263 if ( copy_from_guest(&cb, arg, 1) )
264 break;
265 rc = register_guest_nmi_callback(cb.handler_address);
266 break;
267 case XENNMI_unregister_callback:
268 rc = unregister_guest_nmi_callback();
269 break;
270 default:
271 rc = -ENOSYS;
272 break;
273 }
275 return rc;
276 }
278 DO(vm_assist)(unsigned int cmd, unsigned int type)
279 {
280 return vm_assist(current->domain, cmd, type);
281 }
283 DO(ni_hypercall)(void)
284 {
285 /* No-op hypercall. */
286 return -ENOSYS;
287 }
289 /*
290 * Local variables:
291 * mode: C
292 * c-set-style: "BSD"
293 * c-basic-offset: 4
294 * tab-width: 4
295 * indent-tabs-mode: nil
296 * End:
297 */