Statistics
| Branch: | Revision:

root / arch_init.c @ ad96090a

History | View | Annotate | Download (11.7 kB)

1
/*
2
 * QEMU System Emulator
3
 *
4
 * Copyright (c) 2003-2008 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include <stdint.h>
25
#include <stdarg.h>
26
#ifndef _WIN32
27
#include <sys/mman.h>
28
#endif
29
#include "config.h"
30
#include "monitor.h"
31
#include "sysemu.h"
32
#include "arch_init.h"
33
#include "audio/audio.h"
34
#include "hw/pc.h"
35
#include "hw/pci.h"
36
#include "hw/audiodev.h"
37
#include "kvm.h"
38
#include "migration.h"
39
#include "net.h"
40
#include "gdbstub.h"
41
#include "hw/smbios.h"
42

    
43
#ifdef TARGET_SPARC
44
int graphic_width = 1024;
45
int graphic_height = 768;
46
int graphic_depth = 8;
47
#else
48
int graphic_width = 800;
49
int graphic_height = 600;
50
int graphic_depth = 15;
51
#endif
52

    
53
const char arch_config_name[] = CONFIG_QEMU_CONFDIR "/target-" TARGET_ARCH ".conf";
54

    
55
#if defined(TARGET_ALPHA)
56
#define QEMU_ARCH QEMU_ARCH_ALPHA
57
#elif defined(TARGET_ARM)
58
#define QEMU_ARCH QEMU_ARCH_ARM
59
#elif defined(TARGET_CRIS)
60
#define QEMU_ARCH QEMU_ARCH_CRIS
61
#elif defined(TARGET_I386)
62
#define QEMU_ARCH QEMU_ARCH_I386
63
#elif defined(TARGET_M68K)
64
#define QEMU_ARCH QEMU_ARCH_M68K
65
#elif defined(TARGET_MICROBLAZE)
66
#define QEMU_ARCH QEMU_ARCH_MICROBLAZE
67
#elif defined(TARGET_MIPS)
68
#define QEMU_ARCH QEMU_ARCH_MIPS
69
#elif defined(TARGET_PPC)
70
#define QEMU_ARCH QEMU_ARCH_PPC
71
#elif defined(TARGET_S390X)
72
#define QEMU_ARCH QEMU_ARCH_S390X
73
#elif defined(TARGET_SH4)
74
#define QEMU_ARCH QEMU_ARCH_SH4
75
#elif defined(TARGET_SPARC)
76
#define QEMU_ARCH QEMU_ARCH_SPARC
77
#endif
78

    
79
const uint32_t arch_type = QEMU_ARCH;
80

    
81
/***********************************************************/
82
/* ram save/restore */
83

    
84
#define RAM_SAVE_FLAG_FULL        0x01 /* Obsolete, not used anymore */
85
#define RAM_SAVE_FLAG_COMPRESS        0x02
86
#define RAM_SAVE_FLAG_MEM_SIZE        0x04
87
#define RAM_SAVE_FLAG_PAGE        0x08
88
#define RAM_SAVE_FLAG_EOS        0x10
89

    
90
static int is_dup_page(uint8_t *page, uint8_t ch)
91
{
92
    uint32_t val = ch << 24 | ch << 16 | ch << 8 | ch;
93
    uint32_t *array = (uint32_t *)page;
94
    int i;
95

    
96
    for (i = 0; i < (TARGET_PAGE_SIZE / 4); i++) {
97
        if (array[i] != val) {
98
            return 0;
99
        }
100
    }
101

    
102
    return 1;
103
}
104

    
105
static int ram_save_block(QEMUFile *f)
106
{
107
    static ram_addr_t current_addr = 0;
108
    ram_addr_t saved_addr = current_addr;
109
    ram_addr_t addr = 0;
110
    int found = 0;
111

    
112
    while (addr < last_ram_offset) {
113
        if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
114
            uint8_t *p;
115

    
116
            cpu_physical_memory_reset_dirty(current_addr,
117
                                            current_addr + TARGET_PAGE_SIZE,
118
                                            MIGRATION_DIRTY_FLAG);
119

    
120
            p = qemu_get_ram_ptr(current_addr);
121

    
122
            if (is_dup_page(p, *p)) {
123
                qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_COMPRESS);
124
                qemu_put_byte(f, *p);
125
            } else {
126
                qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_PAGE);
127
                qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
128
            }
129

    
130
            found = 1;
131
            break;
132
        }
133
        addr += TARGET_PAGE_SIZE;
134
        current_addr = (saved_addr + addr) % last_ram_offset;
135
    }
136

    
137
    return found;
138
}
139

    
140
static uint64_t bytes_transferred;
141

    
142
static ram_addr_t ram_save_remaining(void)
143
{
144
    ram_addr_t addr;
145
    ram_addr_t count = 0;
146

    
147
    for (addr = 0; addr < last_ram_offset; addr += TARGET_PAGE_SIZE) {
148
        if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
149
            count++;
150
        }
151
    }
152

    
153
    return count;
154
}
155

    
156
uint64_t ram_bytes_remaining(void)
157
{
158
    return ram_save_remaining() * TARGET_PAGE_SIZE;
159
}
160

    
161
uint64_t ram_bytes_transferred(void)
162
{
163
    return bytes_transferred;
164
}
165

    
166
uint64_t ram_bytes_total(void)
167
{
168
    return last_ram_offset;
169
}
170

    
171
int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
172
{
173
    ram_addr_t addr;
174
    uint64_t bytes_transferred_last;
175
    double bwidth = 0;
176
    uint64_t expected_time = 0;
177

    
178
    if (stage < 0) {
179
        cpu_physical_memory_set_dirty_tracking(0);
180
        return 0;
181
    }
182

    
183
    if (cpu_physical_sync_dirty_bitmap(0, TARGET_PHYS_ADDR_MAX) != 0) {
184
        qemu_file_set_error(f);
185
        return 0;
186
    }
187

    
188
    if (stage == 1) {
189
        bytes_transferred = 0;
190

    
191
        /* Make sure all dirty bits are set */
192
        for (addr = 0; addr < last_ram_offset; addr += TARGET_PAGE_SIZE) {
193
            if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
194
                cpu_physical_memory_set_dirty(addr);
195
            }
196
        }
197

    
198
        /* Enable dirty memory tracking */
199
        cpu_physical_memory_set_dirty_tracking(1);
200

    
201
        qemu_put_be64(f, last_ram_offset | RAM_SAVE_FLAG_MEM_SIZE);
202
    }
203

    
204
    bytes_transferred_last = bytes_transferred;
205
    bwidth = qemu_get_clock_ns(rt_clock);
206

    
207
    while (!qemu_file_rate_limit(f)) {
208
        int ret;
209

    
210
        ret = ram_save_block(f);
211
        bytes_transferred += ret * TARGET_PAGE_SIZE;
212
        if (ret == 0) { /* no more blocks */
213
            break;
214
        }
215
    }
216

    
217
    bwidth = qemu_get_clock_ns(rt_clock) - bwidth;
218
    bwidth = (bytes_transferred - bytes_transferred_last) / bwidth;
219

    
220
    /* if we haven't transferred anything this round, force expected_time to a
221
     * a very high value, but without crashing */
222
    if (bwidth == 0) {
223
        bwidth = 0.000001;
224
    }
225

    
226
    /* try transferring iterative blocks of memory */
227
    if (stage == 3) {
228
        /* flush all remaining blocks regardless of rate limiting */
229
        while (ram_save_block(f) != 0) {
230
            bytes_transferred += TARGET_PAGE_SIZE;
231
        }
232
        cpu_physical_memory_set_dirty_tracking(0);
233
    }
234

    
235
    qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
236

    
237
    expected_time = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth;
238

    
239
    return (stage == 2) && (expected_time <= migrate_max_downtime());
240
}
241

    
242
int ram_load(QEMUFile *f, void *opaque, int version_id)
243
{
244
    ram_addr_t addr;
245
    int flags;
246

    
247
    if (version_id != 3) {
248
        return -EINVAL;
249
    }
250

    
251
    do {
252
        addr = qemu_get_be64(f);
253

    
254
        flags = addr & ~TARGET_PAGE_MASK;
255
        addr &= TARGET_PAGE_MASK;
256

    
257
        if (flags & RAM_SAVE_FLAG_MEM_SIZE) {
258
            if (addr != last_ram_offset) {
259
                return -EINVAL;
260
            }
261
        }
262

    
263
        if (flags & RAM_SAVE_FLAG_COMPRESS) {
264
            uint8_t ch = qemu_get_byte(f);
265
            memset(qemu_get_ram_ptr(addr), ch, TARGET_PAGE_SIZE);
266
#ifndef _WIN32
267
            if (ch == 0 &&
268
                (!kvm_enabled() || kvm_has_sync_mmu())) {
269
                madvise(qemu_get_ram_ptr(addr), TARGET_PAGE_SIZE,
270
                        MADV_DONTNEED);
271
            }
272
#endif
273
        } else if (flags & RAM_SAVE_FLAG_PAGE) {
274
            qemu_get_buffer(f, qemu_get_ram_ptr(addr), TARGET_PAGE_SIZE);
275
        }
276
        if (qemu_file_has_error(f)) {
277
            return -EIO;
278
        }
279
    } while (!(flags & RAM_SAVE_FLAG_EOS));
280

    
281
    return 0;
282
}
283

    
284
void qemu_service_io(void)
285
{
286
    qemu_notify_event();
287
}
288

    
289
#ifdef HAS_AUDIO
290
struct soundhw soundhw[] = {
291
#ifdef HAS_AUDIO_CHOICE
292
#if defined(TARGET_I386) || defined(TARGET_MIPS)
293
    {
294
        "pcspk",
295
        "PC speaker",
296
        0,
297
        1,
298
        { .init_isa = pcspk_audio_init }
299
    },
300
#endif
301

    
302
#ifdef CONFIG_SB16
303
    {
304
        "sb16",
305
        "Creative Sound Blaster 16",
306
        0,
307
        1,
308
        { .init_isa = SB16_init }
309
    },
310
#endif
311

    
312
#ifdef CONFIG_CS4231A
313
    {
314
        "cs4231a",
315
        "CS4231A",
316
        0,
317
        1,
318
        { .init_isa = cs4231a_init }
319
    },
320
#endif
321

    
322
#ifdef CONFIG_ADLIB
323
    {
324
        "adlib",
325
#ifdef HAS_YMF262
326
        "Yamaha YMF262 (OPL3)",
327
#else
328
        "Yamaha YM3812 (OPL2)",
329
#endif
330
        0,
331
        1,
332
        { .init_isa = Adlib_init }
333
    },
334
#endif
335

    
336
#ifdef CONFIG_GUS
337
    {
338
        "gus",
339
        "Gravis Ultrasound GF1",
340
        0,
341
        1,
342
        { .init_isa = GUS_init }
343
    },
344
#endif
345

    
346
#ifdef CONFIG_AC97
347
    {
348
        "ac97",
349
        "Intel 82801AA AC97 Audio",
350
        0,
351
        0,
352
        { .init_pci = ac97_init }
353
    },
354
#endif
355

    
356
#ifdef CONFIG_ES1370
357
    {
358
        "es1370",
359
        "ENSONIQ AudioPCI ES1370",
360
        0,
361
        0,
362
        { .init_pci = es1370_init }
363
    },
364
#endif
365

    
366
#endif /* HAS_AUDIO_CHOICE */
367

    
368
    { NULL, NULL, 0, 0, { NULL } }
369
};
370

    
371
void select_soundhw(const char *optarg)
372
{
373
    struct soundhw *c;
374

    
375
    if (*optarg == '?') {
376
    show_valid_cards:
377

    
378
        printf("Valid sound card names (comma separated):\n");
379
        for (c = soundhw; c->name; ++c) {
380
            printf ("%-11s %s\n", c->name, c->descr);
381
        }
382
        printf("\n-soundhw all will enable all of the above\n");
383
        exit(*optarg != '?');
384
    }
385
    else {
386
        size_t l;
387
        const char *p;
388
        char *e;
389
        int bad_card = 0;
390

    
391
        if (!strcmp(optarg, "all")) {
392
            for (c = soundhw; c->name; ++c) {
393
                c->enabled = 1;
394
            }
395
            return;
396
        }
397

    
398
        p = optarg;
399
        while (*p) {
400
            e = strchr(p, ',');
401
            l = !e ? strlen(p) : (size_t) (e - p);
402

    
403
            for (c = soundhw; c->name; ++c) {
404
                if (!strncmp(c->name, p, l) && !c->name[l]) {
405
                    c->enabled = 1;
406
                    break;
407
                }
408
            }
409

    
410
            if (!c->name) {
411
                if (l > 80) {
412
                    fprintf(stderr,
413
                            "Unknown sound card name (too big to show)\n");
414
                }
415
                else {
416
                    fprintf(stderr, "Unknown sound card name `%.*s'\n",
417
                            (int) l, p);
418
                }
419
                bad_card = 1;
420
            }
421
            p += l + (e != NULL);
422
        }
423

    
424
        if (bad_card) {
425
            goto show_valid_cards;
426
        }
427
    }
428
}
429
#else
430
void select_soundhw(const char *optarg)
431
{
432
}
433
#endif
434

    
435
int qemu_uuid_parse(const char *str, uint8_t *uuid)
436
{
437
    int ret;
438

    
439
    if (strlen(str) != 36) {
440
        return -1;
441
    }
442

    
443
    ret = sscanf(str, UUID_FMT, &uuid[0], &uuid[1], &uuid[2], &uuid[3],
444
                 &uuid[4], &uuid[5], &uuid[6], &uuid[7], &uuid[8], &uuid[9],
445
                 &uuid[10], &uuid[11], &uuid[12], &uuid[13], &uuid[14],
446
                 &uuid[15]);
447

    
448
    if (ret != 16) {
449
        return -1;
450
    }
451
#ifdef TARGET_I386
452
    smbios_add_field(1, offsetof(struct smbios_type_1, uuid), 16, uuid);
453
#endif
454
    return 0;
455
}
456

    
457
void do_acpitable_option(const char *optarg)
458
{
459
#ifdef TARGET_I386
460
    if (acpi_table_add(optarg) < 0) {
461
        fprintf(stderr, "Wrong acpi table provided\n");
462
        exit(1);
463
    }
464
#endif
465
}
466

    
467
void do_smbios_option(const char *optarg)
468
{
469
#ifdef TARGET_I386
470
    if (smbios_entry_add(optarg) < 0) {
471
        fprintf(stderr, "Wrong smbios provided\n");
472
        exit(1);
473
    }
474
#endif
475
}
476

    
477
void cpudef_init(void)
478
{
479
#if defined(cpudef_setup)
480
    cpudef_setup(); /* parse cpu definitions in target config file */
481
#endif
482
}
483

    
484
int audio_available(void)
485
{
486
#ifdef HAS_AUDIO
487
    return 1;
488
#else
489
    return 0;
490
#endif
491
}
492

    
493
int kvm_available(void)
494
{
495
#ifdef CONFIG_KVM
496
    return 1;
497
#else
498
    return 0;
499
#endif
500
}
501

    
502
int xen_available(void)
503
{
504
#ifdef CONFIG_XEN
505
    return 1;
506
#else
507
    return 0;
508
#endif
509
}