source: trunk/packages/xen-3.1/xen-3.1/xen/common/kernel.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 7.3 KB
Line 
1/******************************************************************************
2 * kernel.c
3 *
4 * Copyright (c) 2002-2005 K A Fraser
5 */
6
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
22
23#ifndef COMPAT
24
25int tainted;
26
27void cmdline_parse(char *cmdline)
28{
29    char opt[100], *optval, *q;
30    const char *p = cmdline;
31    struct kernel_param *param;
32   
33    if ( p == NULL )
34        return;
35
36    /* Skip whitespace and the image name. */
37    while ( *p == ' ' )
38        p++;
39    if ( (p = strchr(p, ' ')) == NULL )
40        return;
41
42    for ( ; ; )
43    {
44        /* Skip whitespace. */
45        while ( *p == ' ' )
46            p++;
47        if ( *p == '\0' )
48            break;
49
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';
59
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 */
66
67        for ( param = &__setup_start; param <= &__setup_end; param++ )
68        {
69            if ( strcmp(param->name, opt ) != 0 )
70                continue;
71
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}
91
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 */
101char *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    }
115
116    return str;
117}
118
119void add_taint(unsigned flag)
120{
121    tainted |= flag;
122}
123
124# define DO(fn) long do_##fn
125
126#endif
127
128/*
129 * Simple hypercalls.
130 */
131
132DO(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    }
140
141    case XENVER_extraversion:
142    {
143        xen_extraversion_t extraversion;
144        safe_strcpy(extraversion, xen_extra_version());
145        if ( copy_to_guest(arg, (char *)extraversion, sizeof(extraversion)) )
146            return -EFAULT;
147        return 0;
148    }
149
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    }
161
162    case XENVER_capabilities:
163    {
164        xen_capabilities_info_t info;
165        extern void arch_get_xen_caps(xen_capabilities_info_t *info);
166
167        memset(info, 0, sizeof(info));
168        arch_get_xen_caps(&info);
169
170        if ( copy_to_guest(arg, (char *)info, sizeof(info)) )
171            return -EFAULT;
172        return 0;
173    }
174   
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;
183       
184    }
185   
186    case XENVER_changeset:
187    {
188        xen_changeset_info_t chgset;
189        safe_strcpy(chgset, xen_changeset());
190        if ( copy_to_guest(arg, (char *)chgset, sizeof(chgset)) )
191            return -EFAULT;
192        return 0;
193    }
194
195    case XENVER_get_features:
196    {
197        xen_feature_info_t fi;
198        struct domain *d = current->domain;
199
200        if ( copy_from_guest(&fi, arg, 1) )
201            return -EFAULT;
202
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        }
219
220        if ( copy_to_guest(arg, &fi, 1) )
221            return -EFAULT;
222        return 0;
223    }
224
225    case XENVER_pagesize:
226    {
227        return (!guest_handle_is_null(arg) ? -EINVAL : PAGE_SIZE);
228    }
229
230    case XENVER_guest_handle:
231    {
232        if ( copy_to_guest(arg, (char *)current->domain->handle,
233                           sizeof(current->domain->handle)) )
234            return -EFAULT;
235        return 0;
236    }   
237    }
238
239    return -ENOSYS;
240}
241
242#ifndef COMPAT
243
244long register_guest_nmi_callback(unsigned long address)
245{
246    struct vcpu *v = current;
247    struct domain *d = current->domain;
248
249    if ( (d->domain_id != 0) || (v->vcpu_id != 0) )
250        return -EINVAL;
251
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
261
262    return 0;
263}
264
265long unregister_guest_nmi_callback(void)
266{
267    struct vcpu *v = current;
268
269    v->nmi_addr = 0;
270
271    return 0;
272}
273
274#endif
275
276DO(nmi_op)(unsigned int cmd, XEN_GUEST_HANDLE(void) arg)
277{
278    struct xennmi_callback cb;
279    long rc = 0;
280
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    }
296
297    return rc;
298}
299
300DO(vm_assist)(unsigned int cmd, unsigned int type)
301{
302    return vm_assist(current->domain, cmd, type);
303}
304
305DO(ni_hypercall)(void)
306{
307    /* No-op hypercall. */
308    return -ENOSYS;
309}
310
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 */
Note: See TracBrowser for help on using the repository browser.