~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to xen/common/kernel.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/******************************************************************************
2
2
 * kernel.c
3
3
 * 
4
 
 * This file should contain architecture-independent bootstrap and low-level
5
 
 * help routines. It's a bit x86/PC specific right now!
6
 
 * 
7
 
 * Copyright (c) 2002-2003 K A Fraser
 
4
 * Copyright (c) 2002-2005 K A Fraser
8
5
 */
9
6
 
10
 
#include <stdarg.h>
11
 
#include <xeno/lib.h>
12
 
#include <xeno/errno.h>
13
 
#include <xeno/spinlock.h>
14
 
#include <xeno/multiboot.h>
15
 
#include <xeno/sched.h>
16
 
#include <xeno/mm.h>
17
 
#include <xeno/delay.h>
18
 
#include <xeno/skbuff.h>
19
 
#include <xeno/interrupt.h>
20
 
#include <xeno/compile.h>
21
 
#include <xeno/version.h>
22
 
#include <xeno/netdevice.h>
23
 
#include <asm/io.h>
24
 
#include <asm/msr.h>
25
 
#include <asm/uaccess.h>
26
 
#include <hypervisor-ifs/dom0_ops.h>
27
 
#include <asm/byteorder.h>
28
 
#include <linux/if_ether.h>
29
 
#include <asm/domain_page.h>
30
 
#include <xeno/console.h>
31
 
#include <xeno/net_headers.h>
32
 
 
33
 
kmem_cache_t *task_struct_cachep;
34
 
 
35
 
static int xpos, ypos;
36
 
static volatile unsigned char *video;
37
 
 
38
 
spinlock_t console_lock = SPIN_LOCK_UNLOCKED;
39
 
 
40
 
struct e820entry {
41
 
    unsigned long addr_lo, addr_hi;        /* start of memory segment */
42
 
    unsigned long size_lo, size_hi;        /* size of memory segment */
43
 
    unsigned long type;                    /* type of memory segment */
44
 
};
45
 
 
46
 
void init_vga(void);
47
 
void init_serial(void);
48
 
void start_of_day(void);
49
 
 
50
 
/* opt_console: If true, Xen sends logging to the VGA console. */
51
 
int opt_console = 1;
52
 
/* opt_ser_baud: Baud rate at which logging is sent to COM1. */
53
 
/* NB. Default (0) means that serial I/O is disabled. */
54
 
unsigned int opt_ser_baud = 0;
55
 
/* opt_dom0_mem: Kilobytes of memory allocated to domain 0. */
56
 
unsigned int opt_dom0_mem = 16000;
57
 
/* opt_ifname: Name of physical network interface to use. */
58
 
unsigned char opt_ifname[10] = "eth0";
59
 
/* opt_noht: If true, Hyperthreading is ignored. */
60
 
int opt_noht=0;
61
 
/* opt_noacpi: If true, ACPI tables are not parsed. */
62
 
int opt_noacpi=0;
63
 
/* opt_nosmp: If true, secondary processors are ignored. */
64
 
int opt_nosmp=0;
65
 
/* opt_noreboot: If true, machine will need manual reset on error. */
66
 
int opt_noreboot=0;
67
 
/* opt_ignorebiostables: If true, ACPI and MP tables are ignored. */
68
 
/* NB. This flag implies 'nosmp' and 'noacpi'. */
69
 
int opt_ignorebiostables=0;
70
 
/* opt_watchdog: If true, run a watchdog NMI on each processor. */
71
 
int opt_watchdog=0;
72
 
 
73
 
static struct {
74
 
    unsigned char *name;
75
 
    enum { OPT_IP, OPT_STR, OPT_UINT, OPT_BOOL } type;
76
 
    void *var;
77
 
} opts[] = {
78
 
    { "console",          OPT_UINT, &opt_console },
79
 
    { "ser_baud",         OPT_UINT, &opt_ser_baud },
80
 
    { "dom0_mem",         OPT_UINT, &opt_dom0_mem }, 
81
 
    { "ifname",           OPT_STR,  &opt_ifname },
82
 
    { "noht",             OPT_BOOL, &opt_noht },
83
 
    { "noacpi",           OPT_BOOL, &opt_noacpi },
84
 
    { "nosmp",            OPT_BOOL, &opt_nosmp },
85
 
    { "noreboot",         OPT_BOOL, &opt_noreboot },
86
 
    { "ignorebiostables", OPT_BOOL, &opt_ignorebiostables },
87
 
    { "watchdog",         OPT_BOOL, &opt_watchdog },
88
 
    { NULL,               0,        NULL     }
89
 
};
90
 
 
91
 
 
92
 
void cmain (unsigned long magic, multiboot_info_t *mbi)
 
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
 
22
 
 
23
#ifndef COMPAT
 
24
 
 
25
int tainted;
 
26
 
 
27
xen_commandline_t saved_cmdline;
 
28
 
 
29
void cmdline_parse(char *cmdline)
93
30
{
94
 
    struct task_struct *new_dom;
95
 
    dom0_createdomain_t dom0_params;
96
 
    unsigned long max_page;
97
 
    unsigned char *cmdline;
98
 
    module_t *mod;
99
 
    int i;
100
 
 
101
 
    /*
102
 
     * Note that serial output cannot be done properly until after 
103
 
     * command-line arguments have been parsed, and the required baud rate is 
104
 
     * known. Any messages before that will be output using the settings of 
105
 
     * the bootloader, for example.
106
 
     */
107
 
 
108
 
    if ( magic != MULTIBOOT_BOOTLOADER_MAGIC )
109
 
    {
110
 
        init_vga();
111
 
        cls();
112
 
        printk("Invalid magic number: 0x%x\n", (unsigned)magic);
113
 
        for ( ; ; ) ;
114
 
    }
115
 
 
116
 
    /* Parse the command line. */
117
 
    cmdline = (unsigned char *)(mbi->cmdline ? __va(mbi->cmdline) : NULL);
118
 
    if ( cmdline != NULL )
119
 
    {
120
 
        unsigned char *opt_end, *opt;
121
 
        while ( *cmdline == ' ' ) cmdline++;
122
 
        cmdline = strchr(cmdline, ' ');
123
 
        while ( cmdline != NULL )
124
 
        {
125
 
            while ( *cmdline == ' ' ) cmdline++;
126
 
            if ( *cmdline == '\0' ) break;
127
 
            opt_end = strchr(cmdline, ' ');
128
 
            if ( opt_end != NULL ) *opt_end++ = '\0';
129
 
            opt = strchr(cmdline, '=');
130
 
            if ( opt != NULL ) *opt++ = '\0';
131
 
            for ( i = 0; opts[i].name != NULL; i++ )
 
31
    char opt[100], *optval, *optkey, *q;
 
32
    const char *p = cmdline;
 
33
    struct kernel_param *param;
 
34
    int bool_assert;
 
35
 
 
36
    safe_strcpy(saved_cmdline, cmdline);
 
37
 
 
38
    if ( p == NULL )
 
39
        return;
 
40
 
 
41
    for ( ; ; )
 
42
    {
 
43
        /* Skip whitespace. */
 
44
        while ( *p == ' ' )
 
45
            p++;
 
46
        if ( *p == '\0' )
 
47
            break;
 
48
 
 
49
        /* Grab the next whitespace-delimited option. */
 
50
        q = optkey = opt;
 
51
        while ( (*p != ' ') && (*p != '\0') )
 
52
        {
 
53
            if ( (q-opt) < (sizeof(opt)-1) ) /* avoid overflow */
 
54
                *q++ = *p;
 
55
            p++;
 
56
        }
 
57
        *q = '\0';
 
58
 
 
59
        /* Search for value part of a key=value option. */
 
60
        optval = strchr(opt, '=');
 
61
        if ( optval != NULL )
 
62
            *optval++ = '\0'; /* nul-terminate the option value */
 
63
        else
 
64
            optval = q;       /* default option value is empty string */
 
65
 
 
66
        /* Boolean parameters can be inverted with 'no-' prefix. */
 
67
        bool_assert = !!strncmp("no-", optkey, 3);
 
68
        if ( !bool_assert )
 
69
            optkey += 3;
 
70
 
 
71
        for ( param = &__setup_start; param <= &__setup_end; param++ )
 
72
        {
 
73
            if ( strcmp(param->name, optkey) )
 
74
                continue;
 
75
 
 
76
            switch ( param->type )
132
77
            {
133
 
                if ( strcmp(opts[i].name, cmdline ) != 0 ) continue;
134
 
                switch ( opts[i].type )
 
78
            case OPT_STR:
 
79
                strlcpy(param->var, optval, param->len);
 
80
                break;
 
81
            case OPT_UINT:
 
82
                *(unsigned int *)param->var = simple_strtol(optval, NULL, 0);
 
83
                break;
 
84
            case OPT_BOOL:
 
85
            case OPT_INVBOOL:
 
86
                if ( !strcmp("no", optval) ||
 
87
                     !strcmp("off", optval) ||
 
88
                     !strcmp("false", optval) ||
 
89
                     !strcmp("0", 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_SIZE: {
 
96
                uint64_t sz = parse_size_and_unit(optval, NULL);
 
97
                switch ( param->len )
135
98
                {
136
 
                case OPT_IP:
137
 
                    if ( opt != NULL )
138
 
                        *(unsigned long *)opts[i].var = str_to_quad(opt);
139
 
                    break;
140
 
                case OPT_STR:
141
 
                    if ( opt != NULL )
142
 
                        strcpy(opts[i].var, opt);
143
 
                    break;
144
 
                case OPT_UINT:
145
 
                    if ( opt != NULL )
146
 
                        *(unsigned int *)opts[i].var =
147
 
                            simple_strtol(opt, (char **)&opt, 0);
148
 
                    break;
149
 
                case OPT_BOOL:
150
 
                    *(int *)opts[i].var = 1;
151
 
                    break;
 
99
                case sizeof(uint32_t):
 
100
                    *(uint32_t *)param->var = sz;
 
101
                    break;
 
102
                case sizeof(uint64_t):
 
103
                    *(uint64_t *)param->var = sz;
 
104
                    break;
 
105
                default:
 
106
                    BUG();
152
107
                }
153
 
            }
154
 
            cmdline = opt_end;
 
108
                break;
 
109
            }
 
110
            case OPT_CUSTOM:
 
111
                ((void (*)(const char *))param->var)(optval);
 
112
                break;
 
113
            }
155
114
        }
156
115
    }
157
 
 
158
 
    init_serial();
159
 
    init_vga();
160
 
    cls();
161
 
 
162
 
    printk(XEN_BANNER);
163
 
    printk(" http://www.cl.cam.ac.uk/netos/xen\n");
164
 
    printk(" University of Cambridge Computer Laboratory\n\n");
165
 
    printk(" Xen version %d.%d%s (%s@%s) (%s) %s\n\n",
166
 
           XEN_VERSION, XEN_SUBVERSION, XEN_EXTRAVERSION,
167
 
           XEN_COMPILE_BY, XEN_COMPILE_DOMAIN,
168
 
           XEN_COMPILER, XEN_COMPILE_DATE);
169
 
 
170
 
    /* We require memory and module information. */
171
 
    if ( (mbi->flags & 9) != 9 )
172
 
    {
173
 
        printk("FATAL ERROR: Bad flags passed by bootloader: 0x%x\n", 
174
 
               (unsigned)mbi->flags);
175
 
        for ( ; ; ) ;
176
 
    }
177
 
 
178
 
    if ( mbi->mods_count == 0 )
179
 
    {
180
 
        printk("Require at least one Multiboot module!\n");
181
 
        for ( ; ; ) ;
182
 
    }
183
 
 
184
 
    set_current(&idle0_task);
185
 
 
186
 
    max_page = (mbi->mem_upper+1024) >> (PAGE_SHIFT - 10);
187
 
    init_frametable(max_page);
188
 
    printk("Initialised all memory on a %luMB machine\n",
189
 
           max_page >> (20-PAGE_SHIFT));
190
 
 
191
 
    init_page_allocator(__pa(&_end), MAX_MONITOR_ADDRESS);
192
 
 
193
 
    /* These things will get done by do_createdomain() for all other tasks. */
194
 
    current->shared_info = (void *)get_free_page(GFP_KERNEL);
195
 
    memset(current->shared_info, 0, sizeof(shared_info_t));
196
 
    set_fs(USER_DS);
197
 
 
198
 
    /* Initialise the slab allocator. */
199
 
    kmem_cache_init();
200
 
    kmem_cache_sizes_init(max_page);
201
 
 
202
 
    task_struct_cachep = kmem_cache_create(
203
 
        "task_struct_cache", sizeof(struct task_struct),
204
 
        0, SLAB_HWCACHE_ALIGN, NULL, NULL);
205
 
    if ( task_struct_cachep == NULL )
206
 
        panic("No slab cache for task structs.");
207
 
 
208
 
    start_of_day();
209
 
 
210
 
    /* Create initial domain 0. */
211
 
    dom0_params.memory_kb = opt_dom0_mem;
212
 
    new_dom = do_createdomain(0, 0);
213
 
    if ( new_dom == NULL ) panic("Error creating domain 0\n");
214
 
 
215
 
    /*
216
 
     * We're going to setup domain0 using the module(s) that we stashed safely
217
 
     * above our MAX_DIRECTMAP_ADDRESS in boot/Boot.S The second module, if
218
 
     * present, is an initrd ramdisk
219
 
     */
220
 
    mod = (module_t *)__va(mbi->mods_addr);
221
 
    if ( setup_guestos(new_dom, 
222
 
                       &dom0_params, 1,
223
 
                       (char *)MAX_DIRECTMAP_ADDRESS, 
224
 
                       mod[mbi->mods_count-1].mod_end - mod[0].mod_start,
225
 
                       __va(mod[0].string),
226
 
                       (mbi->mods_count == 2) ?
227
 
                       (mod[1].mod_end - mod[1].mod_start):0)
228
 
         != 0 ) panic("Could not set up DOM0 guest OS\n");
229
 
 
230
 
    wake_up(new_dom);
231
 
 
232
 
    startup_cpu_idle_loop();
233
 
}
234
 
 
235
 
 
236
 
#define SERIAL_BASE 0x3f8
237
 
#define RX_BUF      0
238
 
#define TX_HOLD     0
239
 
#define INT_ENABLE  1
240
 
#define INT_IDENT   2
241
 
#define DATA_FORMAT 3
242
 
#define LINE_CTL    4
243
 
#define LINE_STATUS 5
244
 
#define LINE_IN     6
245
 
#define DIVISOR_LO  0
246
 
#define DIVISOR_HI  1
247
 
 
248
 
void init_serial(void)
249
 
{
250
 
    if ( !SERIAL_ENABLED )
251
 
        return;
252
 
 
253
 
    /* 'opt_ser_baud' baud, no parity, 1 stop bit, 8 data bits. */
254
 
    outb(0x83, SERIAL_BASE+DATA_FORMAT);
255
 
    outb(115200/opt_ser_baud, SERIAL_BASE+DIVISOR_LO);
256
 
    outb(0, SERIAL_BASE+DIVISOR_HI);
257
 
    outb(0x03, SERIAL_BASE+DATA_FORMAT);
258
 
    
259
 
    /* DTR and RTS should both be high, to keep other end happy. */
260
 
    outb(0x02, SERIAL_BASE+LINE_CTL);
261
 
 
262
 
    /* No interrupts. */
263
 
    outb(0x00, SERIAL_BASE+INT_ENABLE);
264
 
}
265
 
 
266
 
 
267
 
#ifdef CONFIG_OUTPUT_SERIAL
268
 
void putchar_serial(unsigned char c)
269
 
{
270
 
    if ( !SERIAL_ENABLED )
271
 
        return;
272
 
    if ( c == '\n' ) putchar_serial('\r');
273
 
    while ( !(inb(SERIAL_BASE+LINE_STATUS)&(1<<5)) ) barrier();
274
 
    outb(c, SERIAL_BASE+TX_HOLD);
275
 
}
276
 
#else
277
 
void putchar_serial(unsigned char c) {}
278
 
#endif
279
 
 
280
 
 
281
 
#ifdef CONFIG_OUTPUT_CONSOLE
282
 
 
283
 
/* VGA text (mode 3) definitions. */
284
 
#define COLUMNS     80
285
 
#define LINES       25
286
 
#define ATTRIBUTE    7
287
 
#define VIDEO       __va(0xB8000)
288
 
 
289
 
int detect_video(void *video_base)
290
 
{
291
 
    volatile u16 *p = (volatile u16 *)video_base;
292
 
    u16 saved1 = p[0], saved2 = p[1];
293
 
    int video_found = 1;
294
 
 
295
 
    p[0] = 0xAA55;
296
 
    p[1] = 0x55AA;
297
 
    if ( (p[0] != 0xAA55) || (p[1] != 0x55AA) )
298
 
        video_found = 0;
299
 
 
300
 
    p[0] = 0x55AA;
301
 
    p[1] = 0xAA55;
302
 
    if ( (p[0] != 0x55AA) || (p[1] != 0xAA55) )
303
 
        video_found = 0;
304
 
 
305
 
    p[0] = saved1;
306
 
    p[1] = saved2;
307
 
 
308
 
    return video_found;
309
 
}
310
 
 
311
 
int detect_vga(void)
312
 
{
313
 
    /*
314
 
     * Look at a number of well-known locations. Even if video is not at
315
 
     * 0xB8000 right now, it will appear there when we set up text mode 3.
316
 
     * 
317
 
     * We assume if there is any sign of a video adaptor then it is at least
318
 
     * VGA-compatible (surely noone runs CGA, EGA, .... these days?).
319
 
     * 
320
 
     * These checks are basically to detect headless server boxes.
321
 
     */
322
 
    return (detect_video(__va(0xA0000)) || 
323
 
            detect_video(__va(0xB0000)) || 
324
 
            detect_video(__va(0xB8000)));
325
 
}
326
 
 
327
 
/* This is actually code from vgaHWRestore in an old version of XFree86 :-) */
328
 
void init_vga(void)
329
 
{
330
 
    /* The following VGA state was saved from a chip in text mode 3. */
331
 
    static unsigned char regs[] = {
332
 
        /* Sequencer registers */
333
 
        0x03, 0x00, 0x03, 0x00, 0x02,
334
 
        /* CRTC registers */
335
 
        0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 0x00, 0x4f, 0x20,
336
 
        0x0e, 0x00, 0x00, 0x01, 0xe0, 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96,
337
 
        0xb9, 0xa3, 0xff,
338
 
        /* Graphic registers */
339
 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff,
340
 
        /* Attribute registers */
341
 
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3a,
342
 
        0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x0c, 0x00, 0x0f, 0x08, 0x00
343
 
    };
344
 
 
345
 
    int i, j = 0;
346
 
    volatile unsigned char tmp;
347
 
 
348
 
    if ( !opt_console )
349
 
        return;
350
 
 
351
 
    if ( !detect_vga() )
352
 
    {
353
 
        printk("No VGA adaptor detected!\n");
354
 
        opt_console = 0;
355
 
        return;
356
 
    }
357
 
 
358
 
    tmp = inb(0x3da);
359
 
    outb(0x00, 0x3c0);
360
 
    
361
 
    for ( i = 0; i < 5;  i++ )
362
 
        outw((regs[j++] << 8) | i, 0x3c4);
363
 
    
364
 
    /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17]. */
365
 
    outw(((regs[5+17] & 0x7F) << 8) | 17, 0x3d4);
366
 
    
367
 
    for ( i = 0; i < 25; i++ ) 
368
 
        outw((regs[j++] << 8) | i, 0x3d4);
369
 
    
370
 
    for ( i = 0; i < 9;  i++ )
371
 
        outw((regs[j++] << 8) | i, 0x3ce);
372
 
    
373
 
    for ( i = 0; i < 21; i++ )
374
 
    {
375
 
        tmp = inb(0x3da);
376
 
        outb(i, 0x3c0); 
377
 
        outb(regs[j++], 0x3c0);
378
 
    }
379
 
    
380
 
    tmp = inb(0x3da);
381
 
    outb(0x20, 0x3c0);
382
 
}
383
 
 
384
 
 
385
 
/* Clear the screen and initialize VIDEO, XPOS and YPOS.  */
386
 
void cls(void)
387
 
{
388
 
    int i;
389
 
 
390
 
    if ( !opt_console )
391
 
        return;
392
 
 
393
 
    video = (unsigned char *) VIDEO;
394
 
    
395
 
    for (i = 0; i < COLUMNS * LINES * 2; i++)
396
 
        *(video + i) = 0;
397
 
    
398
 
    xpos = 0;
399
 
    ypos = 0;
400
 
    
401
 
    outw(10+(1<<(5+8)), 0x3d4); /* cursor off */
402
 
}
403
 
 
404
 
 
405
 
static void put_newline(void)
406
 
{
407
 
    xpos = 0;
408
 
    ypos++;
409
 
 
410
 
    if (ypos >= LINES)
411
 
    {
412
 
        static char zeroarr[2*COLUMNS] = { 0 };
413
 
        ypos = LINES-1;
414
 
        memcpy((char*)video, 
415
 
               (char*)video + 2*COLUMNS, (LINES-1)*2*COLUMNS);
416
 
        memcpy((char*)video + (LINES-1)*2*COLUMNS, 
417
 
               zeroarr, 2*COLUMNS);
418
 
    }
419
 
}
420
 
 
421
 
 
422
 
void putchar_console(int c)
423
 
{
424
 
    if ( !opt_console )
425
 
        return;
426
 
 
427
 
    if ( c == '\n' )
428
 
    {
429
 
        put_newline();
 
116
}
 
117
 
 
118
/**
 
119
 *      print_tainted - return a string to represent the kernel taint state.
 
120
 *
 
121
 *  'S' - SMP with CPUs not designed for SMP.
 
122
 *  'M' - Machine had a machine check experience.
 
123
 *  'B' - System has hit bad_page.
 
124
 *
 
125
 *      The string is overwritten by the next call to print_taint().
 
126
 */
 
127
char *print_tainted(char *str)
 
128
{
 
129
    if ( tainted )
 
130
    {
 
131
        snprintf(str, TAINT_STRING_MAX_LEN, "Tainted: %c%c%c%c",
 
132
                 tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
 
133
                 tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
 
134
                 tainted & TAINT_BAD_PAGE ? 'B' : ' ',
 
135
                 tainted & TAINT_SYNC_CONSOLE ? 'C' : ' ');
430
136
    }
431
137
    else
432
138
    {
433
 
        *(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF;
434
 
        *(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE;
435
 
        
436
 
        xpos++;
437
 
        if (xpos >= COLUMNS)
438
 
            put_newline();
439
 
    }
440
 
}
441
 
 
442
 
#else
443
 
 
444
 
void init_vga(void) {}
445
 
void cls(void) {}
446
 
void putchar_console(int c) {}
447
 
 
448
 
#endif
449
 
 
450
 
#ifdef CONFIG_OUTPUT_CONSOLE_RING
451
 
 
452
 
void putchar_console_ring(int c)
453
 
{
454
 
    if (console_ring.len < CONSOLE_RING_SIZE)
455
 
        console_ring.buf[console_ring.len++] = (char)c;
456
 
}
457
 
 
458
 
#else
459
 
 
460
 
void putchar_console_ring(int c) {}
461
 
 
462
 
#endif
463
 
 
464
 
 
465
 
static void putchar(int c)
466
 
{
467
 
    if ( (c != '\n') && ((c < 32) || (c > 126)) ) return;
468
 
    putchar_serial(c);
469
 
    putchar_console(c);
470
 
    putchar_console_ring(c);
471
 
}
472
 
 
473
 
 
474
 
static inline void __putstr(const char *str)
475
 
{
476
 
    while ( *str ) putchar(*str++);
477
 
}
478
 
 
479
 
 
480
 
void printf (const char *fmt, ...)
481
 
{
482
 
    va_list args;
483
 
    char buf[128];
484
 
    const char *p = fmt;
485
 
    unsigned long flags;
486
 
 
487
 
    /*
488
 
     * If the format string contains '%' descriptors then we have to parse it 
489
 
     * before printing it. We parse it into a fixed-length buffer. Long 
490
 
     * strings should therefore _not_ contain '%' characters!
491
 
     */
492
 
    if ( strchr(fmt, '%') != NULL )
493
 
    {
494
 
        va_start(args, fmt);
495
 
        (void)vsnprintf(buf, sizeof(buf), fmt, args);
496
 
        va_end(args);        
497
 
        p = buf; 
498
 
    }
499
 
 
500
 
    spin_lock_irqsave(&console_lock, flags);
501
 
    while ( *p ) putchar(*p++);
502
 
    spin_unlock_irqrestore(&console_lock, flags);
503
 
}
504
 
 
505
 
 
506
 
void panic(const char *fmt, ...)
507
 
{
508
 
    va_list args;
509
 
    char buf[128];
510
 
    unsigned long flags;
511
 
    extern void machine_restart(char *);
512
 
    
513
 
    va_start(args, fmt);
514
 
    (void)vsnprintf(buf, sizeof(buf), fmt, args);
515
 
    va_end(args);
516
 
    
517
 
    /* Spit out multiline message in one go. */
518
 
    spin_lock_irqsave(&console_lock, flags);
519
 
    __putstr("\n****************************************\n");
520
 
    __putstr(buf);
521
 
    __putstr("Aieee! CPU");
522
 
    sprintf(buf, "%d", smp_processor_id());
523
 
    __putstr(buf);
524
 
    __putstr(" is toast...\n");
525
 
    __putstr("****************************************\n\n");
526
 
    __putstr("Reboot in five seconds...\n");
527
 
    spin_unlock_irqrestore(&console_lock, flags);
528
 
 
529
 
    mdelay(5000);
530
 
    machine_restart(0);
531
 
}
532
 
 
533
 
 
534
 
/* No-op syscall. */
535
 
asmlinkage long sys_ni_syscall(void)
536
 
{
537
 
    return -ENOSYS;
538
 
}
539
 
 
540
 
 
541
 
unsigned short compute_cksum(unsigned short *buf, int count)
542
 
{
543
 
    unsigned long sum = 0;
544
 
    while ( count-- )
545
 
        sum += *buf++;
546
 
    while ( sum >> 16 )
547
 
        sum = (sum & 0xffff) + (sum >> 16);
548
 
    return (unsigned short) ~sum;
549
 
}
550
 
 
551
 
 
552
 
/*
553
 
 * Function written by ek247. Exports console output from all domains upwards 
554
 
 * to domain0, by stuffing it into a fake network packet.
555
 
 */
556
 
int console_export(char *str, int len)
557
 
{
558
 
    struct sk_buff *skb;
559
 
    struct iphdr *iph = NULL;  
560
 
    struct udphdr *udph = NULL; 
561
 
    struct ethhdr *ethh = NULL; 
562
 
    int hdr_size = sizeof(struct iphdr) + sizeof(struct udphdr); 
563
 
    u8 *skb_data;
564
 
 
565
 
    skb = dev_alloc_skb(sizeof(struct ethhdr) + 
566
 
                                   hdr_size + len + 20);
567
 
    if ( skb == NULL ) return 0;
568
 
 
569
 
    skb->dev = the_dev;
570
 
    skb_data = (u8 *)map_domain_mem((skb->pf - frame_table) << PAGE_SHIFT);
571
 
    skb_reserve(skb, 2);
572
 
 
573
 
    /* Get a pointer to each header. */
574
 
    ethh = (struct ethhdr *) 
575
 
        (skb_data + (skb->data - skb->head));
576
 
    iph  = (struct iphdr *)(ethh + 1);
577
 
    udph = (struct udphdr *)(iph + 1); 
578
 
 
579
 
    skb_reserve(skb, sizeof(struct ethhdr)); 
580
 
    skb_put(skb, hdr_size +  len); 
581
 
 
582
 
    /* Build IP header. */
583
 
    iph->version = 4;
584
 
    iph->ihl     = 5;
585
 
    iph->tos     = 0;
586
 
    iph->tot_len = htons(hdr_size + len);
587
 
    iph->id      = 0xdead;
588
 
    iph->frag_off= 0;
589
 
    iph->ttl     = 255;
590
 
    iph->protocol= 17;
591
 
    iph->daddr   = htonl(0xa9fe0100);  /* 169.254.1.0 */
592
 
    iph->saddr   = htonl(0xa9fefeff);  /* 169.254.254.255 */
593
 
    iph->check   = 0;
594
 
    iph->check   = compute_cksum((__u16 *)iph, sizeof(struct iphdr)/2); 
595
 
 
596
 
    /* Build UDP header. */
597
 
    udph->source = htons(current->domain);
598
 
    udph->dest   = htons(666);
599
 
    udph->len    = htons(sizeof(struct udphdr) + len);
600
 
    udph->check  = 0;
601
 
 
602
 
    /* Build the UDP payload. */
603
 
    memcpy((char *)(udph + 1), str, len); 
604
 
 
605
 
    /* Fix Ethernet header. */
606
 
    memset(ethh->h_source, 0, ETH_ALEN);
607
 
    memset(ethh->h_dest,   0, ETH_ALEN);
608
 
    ethh->h_proto = htons(ETH_P_IP);
609
 
    skb->mac.ethernet= (struct ethhdr *)ethh;
610
 
 
611
 
    unmap_domain_mem(skb_data);
612
 
    
613
 
    skb->dst_vif = find_vif_by_id(0);
614
 
    (void)netif_rx(skb);
615
 
 
616
 
    return 1;
617
 
}
618
 
 
619
 
 
620
 
long do_console_write(char *str, unsigned int count)
621
 
{
622
 
#define SIZEOF_BUF 256
623
 
    unsigned char safe_str[SIZEOF_BUF+1];
624
 
    unsigned char exported_str[SIZEOF_BUF+2];
625
 
    unsigned char dom_id[5];
626
 
    unsigned char *p;
627
 
    unsigned long flags;
628
 
    int j;
629
 
    
630
 
    if ( count == 0 )
631
 
        return 0;
632
 
 
633
 
    if ( count > SIZEOF_BUF ) 
634
 
        count = SIZEOF_BUF;
635
 
    
636
 
    if ( copy_from_user(safe_str, str, count) )
637
 
        return -EFAULT;
638
 
    safe_str[count] = '\0';
639
 
    
640
 
    p = safe_str;
641
 
    while ( *p != '\0' )
642
 
    {
643
 
        j = 0;
644
 
 
645
 
        spin_lock_irqsave(&console_lock, flags);
646
 
        
647
 
        __putstr("DOM"); 
648
 
        sprintf(dom_id, "%d", current->domain);
649
 
        __putstr(dom_id);
650
 
        __putstr(": ");
651
 
        
652
 
        while ( (*p != '\0') && (*p != '\n') )
653
 
        {
654
 
            exported_str[j++] = *p;
655
 
            putchar(*p);
656
 
            p++;
657
 
        }
658
 
 
659
 
        if ( *p == '\n' )
660
 
            p++;
661
 
 
662
 
        putchar('\n');
663
 
        
664
 
        spin_unlock_irqrestore(&console_lock, flags);
665
 
 
666
 
        if ( current->domain != 0 )
667
 
        {
668
 
            exported_str[j++] = '\n';
669
 
            exported_str[j++] = '\0';
670
 
            console_export(exported_str, j);
671
 
        }
672
 
    }
673
 
 
674
 
    return 0;
675
 
}
676
 
 
677
 
 
678
 
void __out_of_line_bug(int line)
679
 
{
680
 
    printk("kernel BUG in header file at line %d\n", line);
681
 
    BUG();
682
 
    for ( ; ; ) continue;
683
 
}
684
 
 
685
 
 
686
 
/*
687
 
 * GRAVEYARD
688
 
 */
689
 
#if 0
690
 
    if ( (mbi->flags & (1<<6)) )
691
 
    {
692
 
        memory_map_t *mmap = (memory_map_t *)mbi->mmap_addr;
693
 
        struct e820entry *e820 = E820_MAP;
694
 
 
695
 
        while ( (unsigned long)mmap < (mbi->mmap_addr + mbi->mmap_length) )
696
 
        {
697
 
            e820->addr_lo = mmap->base_addr_low;
698
 
            e820->addr_hi = mmap->base_addr_high;
699
 
            e820->size_lo = mmap->length_low;
700
 
            e820->size_hi = mmap->length_high;
701
 
            e820->type    = mmap->type;
702
 
            e820++;
703
 
            mmap = (memory_map_t *) 
704
 
                ((unsigned long)mmap + mmap->size + sizeof (mmap->size));
705
 
        }
706
 
    }
707
 
#endif
708
 
 
 
139
        snprintf(str, TAINT_STRING_MAX_LEN, "Not tainted");
 
140
    }
 
141
 
 
142
    return str;
 
143
}
 
144
 
 
145
void add_taint(unsigned flag)
 
146
{
 
147
    tainted |= flag;
 
148
}
 
149
 
 
150
# define DO(fn) long do_##fn
 
151
 
 
152
#endif
 
153
 
 
154
/*
 
155
 * Simple hypercalls.
 
156
 */
 
157
 
 
158
DO(xen_version)(int cmd, XEN_GUEST_HANDLE(void) arg)
 
159
{
 
160
    switch ( cmd )
 
161
    {
 
162
    case XENVER_version:
 
163
    {
 
164
        return (xen_major_version() << 16) | xen_minor_version();
 
165
    }
 
166
 
 
167
    case XENVER_extraversion:
 
168
    {
 
169
        xen_extraversion_t extraversion;
 
170
        safe_strcpy(extraversion, xen_extra_version());
 
171
        if ( copy_to_guest(arg, extraversion, ARRAY_SIZE(extraversion)) )
 
172
            return -EFAULT;
 
173
        return 0;
 
174
    }
 
175
 
 
176
    case XENVER_compile_info:
 
177
    {
 
178
        struct xen_compile_info info;
 
179
        safe_strcpy(info.compiler,       xen_compiler());
 
180
        safe_strcpy(info.compile_by,     xen_compile_by());
 
181
        safe_strcpy(info.compile_domain, xen_compile_domain());
 
182
        safe_strcpy(info.compile_date,   xen_compile_date());
 
183
        if ( copy_to_guest(arg, &info, 1) )
 
184
            return -EFAULT;
 
185
        return 0;
 
186
    }
 
187
 
 
188
    case XENVER_capabilities:
 
189
    {
 
190
        xen_capabilities_info_t info;
 
191
        extern void arch_get_xen_caps(xen_capabilities_info_t *info);
 
192
 
 
193
        memset(info, 0, sizeof(info));
 
194
        arch_get_xen_caps(&info);
 
195
 
 
196
        if ( copy_to_guest(arg, info, ARRAY_SIZE(info)) )
 
197
            return -EFAULT;
 
198
        return 0;
 
199
    }
 
200
    
 
201
    case XENVER_platform_parameters:
 
202
    {
 
203
        xen_platform_parameters_t params = {
 
204
            .virt_start = HYPERVISOR_VIRT_START
 
205
        };
 
206
        if ( copy_to_guest(arg, &params, 1) )
 
207
            return -EFAULT;
 
208
        return 0;
 
209
        
 
210
    }
 
211
    
 
212
    case XENVER_changeset:
 
213
    {
 
214
        xen_changeset_info_t chgset;
 
215
        safe_strcpy(chgset, xen_changeset());
 
216
        if ( copy_to_guest(arg, chgset, ARRAY_SIZE(chgset)) )
 
217
            return -EFAULT;
 
218
        return 0;
 
219
    }
 
220
 
 
221
    case XENVER_get_features:
 
222
    {
 
223
        xen_feature_info_t fi;
 
224
        struct domain *d = current->domain;
 
225
 
 
226
        if ( copy_from_guest(&fi, arg, 1) )
 
227
            return -EFAULT;
 
228
 
 
229
        switch ( fi.submap_idx )
 
230
        {
 
231
        case 0:
 
232
            fi.submap = 0;
 
233
            if ( VM_ASSIST(d, VMASST_TYPE_pae_extended_cr3) )
 
234
                fi.submap |= (1U << XENFEAT_pae_pgdir_above_4gb);
 
235
            if ( paging_mode_translate(current->domain) )
 
236
                fi.submap |= 
 
237
                    (1U << XENFEAT_writable_page_tables) |
 
238
                    (1U << XENFEAT_auto_translated_physmap);
 
239
            if ( supervisor_mode_kernel )
 
240
                fi.submap |= 1U << XENFEAT_supervisor_mode_kernel;
 
241
#ifdef CONFIG_X86
 
242
            if ( !is_hvm_vcpu(current) )
 
243
                fi.submap |= (1U << XENFEAT_mmu_pt_update_preserve_ad) |
 
244
                             (1U << XENFEAT_highmem_assist) |
 
245
                             (1U << XENFEAT_gnttab_map_avail_bits);
 
246
#endif
 
247
            break;
 
248
        default:
 
249
            return -EINVAL;
 
250
        }
 
251
 
 
252
        if ( copy_to_guest(arg, &fi, 1) )
 
253
            return -EFAULT;
 
254
        return 0;
 
255
    }
 
256
 
 
257
    case XENVER_pagesize:
 
258
    {
 
259
        return (!guest_handle_is_null(arg) ? -EINVAL : PAGE_SIZE);
 
260
    }
 
261
 
 
262
    case XENVER_guest_handle:
 
263
    {
 
264
        if ( copy_to_guest(arg, current->domain->handle,
 
265
                           ARRAY_SIZE(current->domain->handle)) )
 
266
            return -EFAULT;
 
267
        return 0;
 
268
    }
 
269
 
 
270
    case XENVER_commandline:
 
271
    {
 
272
        if ( copy_to_guest(arg, saved_cmdline, ARRAY_SIZE(saved_cmdline)) )
 
273
            return -EFAULT;
 
274
        return 0;
 
275
    }
 
276
    }
 
277
 
 
278
    return -ENOSYS;
 
279
}
 
280
 
 
281
DO(nmi_op)(unsigned int cmd, XEN_GUEST_HANDLE(void) arg)
 
282
{
 
283
    struct xennmi_callback cb;
 
284
    long rc = 0;
 
285
 
 
286
    switch ( cmd )
 
287
    {
 
288
    case XENNMI_register_callback:
 
289
        rc = -EFAULT;
 
290
        if ( copy_from_guest(&cb, arg, 1) )
 
291
            break;
 
292
        rc = register_guest_nmi_callback(cb.handler_address);
 
293
        break;
 
294
    case XENNMI_unregister_callback:
 
295
        rc = unregister_guest_nmi_callback();
 
296
        break;
 
297
    default:
 
298
        rc = -ENOSYS;
 
299
        break;
 
300
    }
 
301
 
 
302
    return rc;
 
303
}
 
304
 
 
305
DO(vm_assist)(unsigned int cmd, unsigned int type)
 
306
{
 
307
    return vm_assist(current->domain, cmd, type);
 
308
}
 
309
 
 
310
DO(ni_hypercall)(void)
 
311
{
 
312
    /* No-op hypercall. */
 
313
    return -ENOSYS;
 
314
}
 
315
 
 
316
/*
 
317
 * Local variables:
 
318
 * mode: C
 
319
 * c-set-style: "BSD"
 
320
 * c-basic-offset: 4
 
321
 * tab-width: 4
 
322
 * indent-tabs-mode: nil
 
323
 * End:
 
324
 */