Compare commits
146 Commits
pull-ui-20
...
v0.10.6
Author | SHA1 | Date | |
---|---|---|---|
|
9eab386edb | ||
|
0def14568c | ||
|
ca888361bb | ||
|
df97ff696b | ||
|
cc15f92832 | ||
|
2670257db0 | ||
|
aae9547639 | ||
|
2872b8a445 | ||
|
51224c6f78 | ||
|
ed8f8da7a6 | ||
|
960b646371 | ||
|
fc78bd4503 | ||
|
259cf68eb1 | ||
|
41de90f32c | ||
|
3e6b53eb32 | ||
|
80de8ace66 | ||
|
ea0c91a0af | ||
|
71080d96fd | ||
|
a5617318fe | ||
|
73cf22cb60 | ||
|
04f4e710a0 | ||
|
accceed914 | ||
|
f29602ca0e | ||
|
17489dd7e9 | ||
|
936d7bf944 | ||
|
d13317e197 | ||
|
75204ffc5b | ||
|
9fb2ec9a1e | ||
|
a8bc8570fa | ||
|
700ece804f | ||
|
71c55593c0 | ||
|
5982abd9ca | ||
|
738208b656 | ||
|
61348b076b | ||
|
9e3a7df77c | ||
|
0926c7a4e5 | ||
|
a02ba54eed | ||
|
578485d835 | ||
|
a675d9b8b5 | ||
|
ce60db1da2 | ||
|
428009b4aa | ||
|
c87a097b4a | ||
|
2fbc3b4c81 | ||
|
8765893e9e | ||
|
822624e5d6 | ||
|
fe54857a13 | ||
|
ee60269c23 | ||
|
3978d7b4c8 | ||
|
dc0be040c2 | ||
|
1570841432 | ||
|
a59cc95e23 | ||
|
2058679372 | ||
|
f1cfb26c5a | ||
|
662524f5dc | ||
|
5f6521c78e | ||
|
abe73c324e | ||
|
ed16937820 | ||
|
faf8a63492 | ||
|
34aee2552f | ||
|
9fd0e57dc9 | ||
|
2fd0f93286 | ||
|
8bd8199f70 | ||
|
2da1e39864 | ||
|
b468f27acd | ||
|
8bc2ad6a6a | ||
|
f24f1e2a85 | ||
|
5d00b89b12 | ||
|
a2b8ec7d7d | ||
|
a95ad7bcbb | ||
|
3d2d1e3960 | ||
|
3382d425bc | ||
|
2031cfc4ea | ||
|
260437cba3 | ||
|
233e01e475 | ||
|
544995e22e | ||
|
57ba0792ca | ||
|
a2daabc49a | ||
|
530a491fc3 | ||
|
2fcc1d5b69 | ||
|
cb2768eb3c | ||
|
202e9d440e | ||
|
3c398c0f86 | ||
|
4df8f71ee5 | ||
|
84eba9b8f1 | ||
|
a34b6eb776 | ||
|
1ed3d07a22 | ||
|
00f56b3dcf | ||
|
71dc1b6fcb | ||
|
eb5951f333 | ||
|
8cacc9ad14 | ||
|
76dcd4921c | ||
|
0ee50993ce | ||
|
7020c09209 | ||
|
8bb66d8601 | ||
|
bcb8c5535d | ||
|
da95f49a9d | ||
|
06b393452f | ||
|
b7d11af2e0 | ||
|
8d47bb6162 | ||
|
80acab6c50 | ||
|
da0ac2bc13 | ||
|
d3c2632047 | ||
|
7cc73776e7 | ||
|
937e9a1c83 | ||
|
4498819404 | ||
|
c61ad61830 | ||
|
65297bc408 | ||
|
02d400ead7 | ||
|
20a9c6ac7f | ||
|
bd0b264c21 | ||
|
0f31aac44f | ||
|
30b15843b2 | ||
|
04ffdd7f94 | ||
|
7648bb760d | ||
|
ebb7184720 | ||
|
3f546bd0b1 | ||
|
00614a4cb4 | ||
|
7c14db42cb | ||
|
e58843d0f1 | ||
|
0e39d3f89b | ||
|
5389a9df53 | ||
|
21fd832512 | ||
|
15d4afd55b | ||
|
3df962a30d | ||
|
4827c90cef | ||
|
0f56231dce | ||
|
523faf1b92 | ||
|
414c078104 | ||
|
9cecf0f570 | ||
|
4ca9f3dd71 | ||
|
f902c4192e | ||
|
b96a313d3d | ||
|
d9aa1fce5a | ||
|
8a11f5ff08 | ||
|
b786b7ccbd | ||
|
d3be2b2f71 | ||
|
e36fb2a3a2 | ||
|
4978045781 | ||
|
cb5745c529 | ||
|
295b492cfa | ||
|
af8222c0f8 | ||
|
249139f4e6 | ||
|
8ae0978ed5 | ||
|
c0024a8257 | ||
|
e9af78a859 | ||
|
25c4fde177 |
111
Changelog
111
Changelog
@@ -1,3 +1,114 @@
|
||||
version 0.10.6:
|
||||
- e1000: ignore reset command (Kevin Wolf)
|
||||
- fix VNC memory allocation (Stefan Weil)
|
||||
- fix raw_pread_aligned return value (Christoph Hellwig)
|
||||
- allow monitor interaction when using -incoming exec: (Chris Lalancette)
|
||||
- fix -net socket,listen (Jan Kiszka)
|
||||
- live migration: don't send gratuitous packets all at once (Gleb Natapov)
|
||||
- serial: fix lost characters after sysrq (Jason Wessel)
|
||||
- Fix prototype of zfree (Stefan Weil)
|
||||
- Handle EINTR with exec: migration (Uri Lublin)
|
||||
- Delete io-handler before closing fd after migration (Uri Lublin)
|
||||
- Fix qemu_aio_flush (Andrea Arcangeli)
|
||||
- lsi53c895a: Implement additional registers (Sebastian Herbszt)
|
||||
- virtio-blk: fix warning (Gerd Hoffman)
|
||||
- i386: fix cpu reset (Nitin Kamble)
|
||||
- kvm: fix irq injection into full queue (Jan Kiszka)
|
||||
- Prevent CD-ROM eject while device is locked (Mark McLoughlin)
|
||||
- Fix screen dump with blank screen (Eduardo Habkost)
|
||||
- Fix memory leak with cpu_unregister_map_client (Isaku Yamahata)
|
||||
- Fix memory leak in SDL (Jan Kiszka)
|
||||
- Fix build on OS X 10.4 (John Arbuckle)
|
||||
- Fix leak of vlan clients after hot remove (Mark McLoughlin)
|
||||
- Fix migration after hot remove with eepro100 (Mark McLoughlin)
|
||||
- Don't start a VM after failed migration if stopped (Anthony Liguori)
|
||||
- Fix live migration under heavy IO load (Glauber Costa)
|
||||
- Honor -S on incoming migration (Paolo Bonzini)
|
||||
- Reset HPET config register on reset (Beth Kon)
|
||||
- Reset PS2 keyboard/mouse on reset (Dinesh Subraveti)
|
||||
|
||||
version 0.10.5:
|
||||
- kvm: trim unsupported cpu features from cpuid (Avi Kivity)
|
||||
- kvm: provide a better error message for -smp > 1 (Mark McLoughlin)
|
||||
- Remove initrd printfs (Richard Jones)
|
||||
- Initial variables found by valgrind (Jean-Christophe Dubois)
|
||||
- Fix -initrd with > 4GB guests (Glauber Costa)
|
||||
- Fix busy loop on live migration for certain platforms (Uri Lublin)
|
||||
- Remove GCC 3.x requirements from docs (Hollis Blanchard)
|
||||
- ETRAX: fixes for kernel command line, ethernet address, bmi (Edgar Iglesias)
|
||||
- CRIS: Fix bmi (Edgar Iglesias)
|
||||
- Fix bounce buffer errors (Avi Kivity)
|
||||
- Fix regression in -kernel (Anthony Liguori)
|
||||
|
||||
version 0.10.4:
|
||||
- Improve block range checks to remove integer overflow (Kevin Wolf)
|
||||
- e1000: do not re-init PCI config space 0 (Amit Shah)
|
||||
- fix AIO deletion race (Alex Graf)
|
||||
- reset option roms on reboot (Glauber Costa)
|
||||
- fix qcow2 corruption in cluster freeing (Gleb Natapov)
|
||||
- Enable power button event generation (Gleb Natapov)
|
||||
|
||||
version 0.10.3:
|
||||
- fix AIO cancellations (Avi Kivity)
|
||||
- fix live migration error path on incoming
|
||||
- avoid SEGV on pci hotplug failure (Chris Wright)
|
||||
- fix serial option in -drive
|
||||
- support DDIM for option roms (Glauber Costa)
|
||||
- avoid fork/exec on pre-2.6.27 kernels with KVM (Jan Kiszka)
|
||||
- block-vpc: don't silently create smaller images than requested (Kevin Wolf)
|
||||
- Fix non-ACPI timer interrupt routing (Beth Kon)
|
||||
- hpet: fix emulation of HPET_TN_SETVAL (Jan Kiszka)
|
||||
- kvm: fix cpuid initialization (Jan Kiszka)
|
||||
- qcow2: fix corruption on little endian hosts (Kevin Wolf)
|
||||
- avoid leaing memory on hot unplug (Mark McLoughlin)
|
||||
- fix savevm/migration after hot unplug (Mark McLoughlin)
|
||||
- Fix keyboard mapping on newer Xords with non-default keymaps (balrog)
|
||||
- Make PCI config status register read-only (Anthony Liguori)
|
||||
- Fix crash on resolution change -> screen dump -> vga redraw (Avi Kivity)
|
||||
|
||||
version 0.10.2:
|
||||
|
||||
- fix savevm/loadvm (Anthony Liguori)
|
||||
- live migration: fix dirty tracking windows (Glauber Costa)
|
||||
- live migration: improve error propogation (Glauber Costa)
|
||||
- qcow2: fix image creation for > ~2TB images (Chris Wright)
|
||||
- hotplug: fix error handling for if= parameter (Eduardo Habkost)
|
||||
- qcow2: fix data corruption (Nolan Leake)
|
||||
- virtio: fix guest oops with 2.6.25 kernels (Rusty Russell)
|
||||
- SH4: add support for -kernel (Takashi Yoshii, Aurelien Jarno)
|
||||
- hotplug: fix closing of char devices (Jan Kiszka)
|
||||
- hotplug: remove incorrect check for device name (Eduardo Habkost)
|
||||
- enable -k on win32 (Herve Poussineau)
|
||||
- configure: use LANG=C for grep (Andreas Faerber)
|
||||
- fix VGA regression (malc)
|
||||
|
||||
version 0.10.1:
|
||||
|
||||
- virtio-net: allow masking of notifications on empty queue (Alex Williamson)
|
||||
- e1000: fix rx descriptor low threshold logic (Alex Willaimson)
|
||||
- x86 tcg: add NULL checks to lsl instruction (Jan Kiszka)
|
||||
- kvm vga: fix screen corruption with -std-vga and Windows (Avi Kivity)
|
||||
- kvm vga: fix screen corruption with Ubuntu installations (Glauber Costa)
|
||||
- virtio-net: check right return size on sg list (Alex Williamson)
|
||||
- Make qemu_announce_self handle holes (live migration after hotplug)
|
||||
(Marcelo Tosatti)
|
||||
- Revert r6804-r6808 (qcow2 allocation info). This series of changes added
|
||||
a high cost to startup for large qcow2 images (Anthony Liguori)
|
||||
- qemu-img: fix help message (Aurelien Jarno)
|
||||
- Fix build for non-default installs of SDL (Anthony Liguori)
|
||||
- Fix race condition in env->interrupt_request. When using TCG and a dynticks
|
||||
host timer, this condition could cause TCG to get stuck in an infinite
|
||||
loop (Aurelien Jarno)
|
||||
- Fix reading encrypted hard disk passwords during early startup (Jan Kiszka)
|
||||
- Fix encrypted disk reporting in 'info block' (Jan Kiszka)
|
||||
- Fix console size with tiny displays (MusicPal) (Jan Kiszka)
|
||||
- Improve error handling in bdrv_open2 (Jan Kiszka)
|
||||
- Avoid leaking data in mux'ed character devices (Jan Kiszka)
|
||||
- Fix initial character device reset (no banner in monitor) (Jan Kiszka)
|
||||
- Fix cpuid KVM crash on i386 host (Lubomir Rintel)
|
||||
- Fix SLES10sp2 installation by adding ISTAT1 register to LSI SCSI emulation
|
||||
(Ryan Harper)
|
||||
|
||||
version 0.10.0:
|
||||
|
||||
- TCG support (No longer requires GCC 3.x)
|
||||
|
11
aio.c
11
aio.c
@@ -44,7 +44,8 @@ static AioHandler *find_aio_handler(int fd)
|
||||
|
||||
LIST_FOREACH(node, &aio_handlers, node) {
|
||||
if (node->fd == fd)
|
||||
return node;
|
||||
if (!node->deleted)
|
||||
return node;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -102,11 +103,15 @@ void qemu_aio_flush(void)
|
||||
do {
|
||||
ret = 0;
|
||||
|
||||
/*
|
||||
* If there are pending emulated aio start them now so flush
|
||||
* will be able to return 1.
|
||||
*/
|
||||
qemu_aio_wait();
|
||||
|
||||
LIST_FOREACH(node, &aio_handlers, node) {
|
||||
ret |= node->io_flush(node->opaque);
|
||||
}
|
||||
|
||||
qemu_aio_wait();
|
||||
} while (ret > 0);
|
||||
}
|
||||
|
||||
|
115
block-qcow2.c
115
block-qcow2.c
@@ -143,10 +143,6 @@ typedef struct BDRVQcowState {
|
||||
uint32_t crypt_method_header;
|
||||
AES_KEY aes_encrypt_key;
|
||||
AES_KEY aes_decrypt_key;
|
||||
|
||||
int64_t highest_alloc; /* highest cluester allocated (in clusters) */
|
||||
int64_t nc_free; /* num of free clusters below highest_alloc */
|
||||
|
||||
uint64_t snapshots_offset;
|
||||
int snapshots_size;
|
||||
int nb_snapshots;
|
||||
@@ -174,8 +170,6 @@ static void free_clusters(BlockDriverState *bs,
|
||||
#ifdef DEBUG_ALLOC
|
||||
static void check_refcounts(BlockDriverState *bs);
|
||||
#endif
|
||||
static void scan_refcount(BlockDriverState *bs, int64_t *high, int64_t *free);
|
||||
|
||||
|
||||
static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
|
||||
{
|
||||
@@ -276,8 +270,6 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
|
||||
if (refcount_init(bs) < 0)
|
||||
goto fail;
|
||||
|
||||
scan_refcount(bs, &s->highest_alloc, &s->nc_free);
|
||||
|
||||
/* read the backing file name */
|
||||
if (header.backing_file_offset != 0) {
|
||||
len = header.backing_file_size;
|
||||
@@ -678,6 +670,10 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
|
||||
|
||||
nb_available = (nb_available >> 9) + index_in_cluster;
|
||||
|
||||
if (nb_needed > nb_available) {
|
||||
nb_needed = nb_available;
|
||||
}
|
||||
|
||||
cluster_offset = 0;
|
||||
|
||||
/* seek the the l2 offset in the l1 table */
|
||||
@@ -907,6 +903,12 @@ static int alloc_cluster_link_l2(BlockDriverState *bs, uint64_t cluster_offset,
|
||||
goto err;
|
||||
|
||||
for (i = 0; i < m->nb_clusters; i++) {
|
||||
/* if two concurrent writes happen to the same unallocated cluster
|
||||
* each write allocates separate cluster and writes data concurrently.
|
||||
* The first one to complete updates l2 table with pointer to its
|
||||
* cluster the second one has to do RMW (which is done above by
|
||||
* copy_sectors()), update l2 table with its cluster pointer and free
|
||||
* old cluster. This is what this loop does */
|
||||
if(l2_table[l2_index + i] != 0)
|
||||
old_cluster[j++] = l2_table[l2_index + i];
|
||||
|
||||
@@ -920,7 +922,8 @@ static int alloc_cluster_link_l2(BlockDriverState *bs, uint64_t cluster_offset,
|
||||
goto err;
|
||||
|
||||
for (i = 0; i < j; i++)
|
||||
free_any_clusters(bs, old_cluster[i], 1);
|
||||
free_any_clusters(bs, be64_to_cpu(old_cluster[i]) & ~QCOW_OFLAG_COPIED,
|
||||
1);
|
||||
|
||||
ret = 0;
|
||||
err:
|
||||
@@ -1466,6 +1469,7 @@ static int qcow_create(const char *filename, int64_t total_size,
|
||||
const char *backing_file, int flags)
|
||||
{
|
||||
int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits;
|
||||
int ref_clusters;
|
||||
QCowHeader header;
|
||||
uint64_t tmp, offset;
|
||||
QCowCreateState s1, *s = &s1;
|
||||
@@ -1506,22 +1510,28 @@ static int qcow_create(const char *filename, int64_t total_size,
|
||||
offset += align_offset(l1_size * sizeof(uint64_t), s->cluster_size);
|
||||
|
||||
s->refcount_table = qemu_mallocz(s->cluster_size);
|
||||
s->refcount_block = qemu_mallocz(s->cluster_size);
|
||||
|
||||
s->refcount_table_offset = offset;
|
||||
header.refcount_table_offset = cpu_to_be64(offset);
|
||||
header.refcount_table_clusters = cpu_to_be32(1);
|
||||
offset += s->cluster_size;
|
||||
|
||||
s->refcount_table[0] = cpu_to_be64(offset);
|
||||
s->refcount_block_offset = offset;
|
||||
offset += s->cluster_size;
|
||||
|
||||
/* count how many refcount blocks needed */
|
||||
tmp = offset >> s->cluster_bits;
|
||||
ref_clusters = (tmp >> (s->cluster_bits - REFCOUNT_SHIFT)) + 1;
|
||||
for (i=0; i < ref_clusters; i++) {
|
||||
s->refcount_table[i] = cpu_to_be64(offset);
|
||||
offset += s->cluster_size;
|
||||
}
|
||||
|
||||
s->refcount_block = qemu_mallocz(ref_clusters * s->cluster_size);
|
||||
|
||||
/* update refcounts */
|
||||
create_refcount_update(s, 0, header_size);
|
||||
create_refcount_update(s, s->l1_table_offset, l1_size * sizeof(uint64_t));
|
||||
create_refcount_update(s, s->refcount_table_offset, s->cluster_size);
|
||||
create_refcount_update(s, s->refcount_block_offset, s->cluster_size);
|
||||
create_refcount_update(s, s->refcount_block_offset, ref_clusters * s->cluster_size);
|
||||
|
||||
/* write all the data */
|
||||
write(fd, &header, sizeof(header));
|
||||
@@ -1537,7 +1547,7 @@ static int qcow_create(const char *filename, int64_t total_size,
|
||||
write(fd, s->refcount_table, s->cluster_size);
|
||||
|
||||
lseek(fd, s->refcount_block_offset, SEEK_SET);
|
||||
write(fd, s->refcount_block, s->cluster_size);
|
||||
write(fd, s->refcount_block, ref_clusters * s->cluster_size);
|
||||
|
||||
qemu_free(s->refcount_table);
|
||||
qemu_free(s->refcount_block);
|
||||
@@ -1646,8 +1656,6 @@ static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
||||
bdi->cluster_size = s->cluster_size;
|
||||
bdi->vm_state_offset = (int64_t)s->l1_vm_state_index <<
|
||||
(s->cluster_bits + s->l2_bits);
|
||||
bdi->highest_alloc = s->highest_alloc << s->cluster_bits;
|
||||
bdi->num_free_bytes = s->nc_free << s->cluster_bits;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2166,39 +2174,6 @@ static int load_refcount_block(BlockDriverState *bs,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void scan_refcount(BlockDriverState *bs, int64_t *high, int64_t *free)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
int64_t refcnt_index, cluster_index, cluster_end, h = 0, f = 0;
|
||||
int64_t tail = 0; /* do not count last consecutive free entries */
|
||||
|
||||
for (refcnt_index=0; refcnt_index < s->refcount_table_size; refcnt_index++){
|
||||
if (s->refcount_table[refcnt_index] == 0) {
|
||||
f += 1 << (s->cluster_bits - REFCOUNT_SHIFT);
|
||||
tail += 1 << (s->cluster_bits - REFCOUNT_SHIFT);
|
||||
continue;
|
||||
}
|
||||
cluster_index = refcnt_index << (s->cluster_bits - REFCOUNT_SHIFT);
|
||||
cluster_end = (refcnt_index + 1) << (s->cluster_bits - REFCOUNT_SHIFT);
|
||||
for ( ; cluster_index < cluster_end; cluster_index++) {
|
||||
if (get_refcount(bs, cluster_index) == 0) {
|
||||
f++;
|
||||
tail++;
|
||||
}
|
||||
else {
|
||||
h = cluster_index;
|
||||
tail = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
f -= tail;
|
||||
if (free)
|
||||
*free = f;
|
||||
if (high)
|
||||
*high = (h+1);
|
||||
}
|
||||
|
||||
static int get_refcount(BlockDriverState *bs, int64_t cluster_index)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
@@ -2239,12 +2214,6 @@ retry:
|
||||
size,
|
||||
(s->free_cluster_index - nb_clusters) << s->cluster_bits);
|
||||
#endif
|
||||
|
||||
if (s->highest_alloc < s->free_cluster_index) {
|
||||
s->nc_free += (s->free_cluster_index - s->highest_alloc);
|
||||
s->highest_alloc = s->free_cluster_index;
|
||||
}
|
||||
|
||||
return (s->free_cluster_index - nb_clusters) << s->cluster_bits;
|
||||
}
|
||||
|
||||
@@ -2418,12 +2387,6 @@ static int update_cluster_refcount(BlockDriverState *bs,
|
||||
block_index = cluster_index &
|
||||
((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);
|
||||
refcount = be16_to_cpu(s->refcount_block_cache[block_index]);
|
||||
|
||||
if (refcount == 1 && addend == -1)
|
||||
s->nc_free += 1;
|
||||
else if (refcount == 0 && addend == 1)
|
||||
s->nc_free -= 1;
|
||||
|
||||
refcount += addend;
|
||||
if (refcount < 0 || refcount > 0xffff)
|
||||
return -EINVAL;
|
||||
@@ -2645,6 +2608,31 @@ static void dump_refcounts(BlockDriverState *bs)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int qcow_put_buffer(BlockDriverState *bs, const uint8_t *buf,
|
||||
int64_t pos, int size)
|
||||
{
|
||||
int growable = bs->growable;
|
||||
|
||||
bs->growable = 1;
|
||||
bdrv_pwrite(bs, pos, buf, size);
|
||||
bs->growable = growable;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static int qcow_get_buffer(BlockDriverState *bs, uint8_t *buf,
|
||||
int64_t pos, int size)
|
||||
{
|
||||
int growable = bs->growable;
|
||||
int ret;
|
||||
|
||||
bs->growable = 1;
|
||||
ret = bdrv_pread(bs, pos, buf, size);
|
||||
bs->growable = growable;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BlockDriver bdrv_qcow2 = {
|
||||
"qcow2",
|
||||
sizeof(BDRVQcowState),
|
||||
@@ -2670,4 +2658,7 @@ BlockDriver bdrv_qcow2 = {
|
||||
.bdrv_snapshot_delete = qcow_snapshot_delete,
|
||||
.bdrv_snapshot_list = qcow_snapshot_list,
|
||||
.bdrv_get_info = qcow_get_info,
|
||||
|
||||
.bdrv_put_buffer = qcow_put_buffer,
|
||||
.bdrv_get_buffer = qcow_get_buffer,
|
||||
};
|
||||
|
@@ -75,7 +75,11 @@
|
||||
|
||||
/* OS X does not have O_DSYNC */
|
||||
#ifndef O_DSYNC
|
||||
#ifdef O_SYNC
|
||||
#define O_DSYNC O_SYNC
|
||||
#elif defined(O_FSYNC)
|
||||
#define O_DSYNC O_FSYNC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Approximate O_DIRECT with O_DSYNC if O_DIRECT isn't available */
|
||||
@@ -234,7 +238,7 @@ static int raw_pread_aligned(BlockDriverState *bs, int64_t offset,
|
||||
|
||||
label__raw_read__success:
|
||||
|
||||
return ret;
|
||||
return (ret < 0) ? -errno : ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -399,10 +399,15 @@ static int find_device_type(BlockDriverState *bs, const char *filename)
|
||||
return FTYPE_HARDDISK;
|
||||
snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", p[0]);
|
||||
type = GetDriveType(s->drive_path);
|
||||
if (type == DRIVE_CDROM)
|
||||
switch (type) {
|
||||
case DRIVE_REMOVABLE:
|
||||
case DRIVE_FIXED:
|
||||
return FTYPE_HARDDISK;
|
||||
case DRIVE_CDROM:
|
||||
return FTYPE_CD;
|
||||
else
|
||||
default:
|
||||
return FTYPE_FILE;
|
||||
}
|
||||
} else {
|
||||
return FTYPE_FILE;
|
||||
}
|
||||
|
11
block-vpc.c
11
block-vpc.c
@@ -433,14 +433,16 @@ static int vpc_write(BlockDriverState *bs, int64_t sector_num,
|
||||
*
|
||||
* Note that the geometry doesn't always exactly match total_sectors but
|
||||
* may round it down.
|
||||
*
|
||||
* Returns 0 on success, -EFBIG if the size is larger than 127 GB
|
||||
*/
|
||||
static void calculate_geometry(int64_t total_sectors, uint16_t* cyls,
|
||||
static int calculate_geometry(int64_t total_sectors, uint16_t* cyls,
|
||||
uint8_t* heads, uint8_t* secs_per_cyl)
|
||||
{
|
||||
uint32_t cyls_times_heads;
|
||||
|
||||
if (total_sectors > 65535 * 16 * 255)
|
||||
total_sectors = 65535 * 16 * 255;
|
||||
return -EFBIG;
|
||||
|
||||
if (total_sectors > 65535 * 16 * 63) {
|
||||
*secs_per_cyl = 255;
|
||||
@@ -470,6 +472,8 @@ static void calculate_geometry(int64_t total_sectors, uint16_t* cyls,
|
||||
// Note: Rounding up deviates from the Virtual PC behaviour
|
||||
// However, we need this to avoid truncating images in qemu-img convert
|
||||
*cyls = (cyls_times_heads + *heads - 1) / *heads;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vpc_create(const char *filename, int64_t total_sectors,
|
||||
@@ -493,7 +497,8 @@ static int vpc_create(const char *filename, int64_t total_sectors,
|
||||
return -EIO;
|
||||
|
||||
// Calculate matching total_size and geometry
|
||||
calculate_geometry(total_sectors, &cyls, &heads, &secs_per_cyl);
|
||||
if (calculate_geometry(total_sectors, &cyls, &heads, &secs_per_cyl))
|
||||
return -EFBIG;
|
||||
total_sectors = (int64_t) cyls * heads * secs_per_cyl;
|
||||
|
||||
// Prepare the Hard Disk Footer
|
||||
|
205
block.c
205
block.c
@@ -41,6 +41,8 @@
|
||||
#define SECTOR_BITS 9
|
||||
#define SECTOR_SIZE (1 << SECTOR_BITS)
|
||||
|
||||
static AIOPool vectored_aio_pool;
|
||||
|
||||
typedef struct BlockDriverAIOCBSync {
|
||||
BlockDriverAIOCB common;
|
||||
QEMUBH *bh;
|
||||
@@ -141,6 +143,7 @@ static void bdrv_register(BlockDriver *bdrv)
|
||||
bdrv->bdrv_read = bdrv_read_em;
|
||||
bdrv->bdrv_write = bdrv_write_em;
|
||||
}
|
||||
aio_pool_init(&bdrv->aio_pool, bdrv->aiocb_size, bdrv->bdrv_aio_cancel);
|
||||
bdrv->next = first_drv;
|
||||
first_drv = bdrv;
|
||||
}
|
||||
@@ -311,8 +314,6 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
|
||||
int ret;
|
||||
|
||||
bs = bdrv_new("");
|
||||
if (!bs)
|
||||
return -ENOMEM;
|
||||
ret = bdrv_open2(bs, filename, flags | BDRV_O_FILE, NULL);
|
||||
if (ret < 0) {
|
||||
bdrv_delete(bs);
|
||||
@@ -338,6 +339,7 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
|
||||
bs->read_only = 0;
|
||||
bs->is_temporary = 0;
|
||||
bs->encrypted = 0;
|
||||
bs->valid_key = 0;
|
||||
|
||||
if (flags & BDRV_O_SNAPSHOT) {
|
||||
BlockDriverState *bs1;
|
||||
@@ -349,12 +351,10 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
|
||||
|
||||
/* if there is a backing file, use it */
|
||||
bs1 = bdrv_new("");
|
||||
if (!bs1) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (bdrv_open(bs1, filename, 0) < 0) {
|
||||
ret = bdrv_open(bs1, filename, 0);
|
||||
if (ret < 0) {
|
||||
bdrv_delete(bs1);
|
||||
return -1;
|
||||
return ret;
|
||||
}
|
||||
total_size = bdrv_getlength(bs1) >> SECTOR_BITS;
|
||||
|
||||
@@ -372,9 +372,10 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
|
||||
else
|
||||
realpath(filename, backing_filename);
|
||||
|
||||
if (bdrv_create(&bdrv_qcow2, tmp_filename,
|
||||
total_size, backing_filename, 0) < 0) {
|
||||
return -1;
|
||||
ret = bdrv_create(&bdrv_qcow2, tmp_filename,
|
||||
total_size, backing_filename, 0);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
filename = tmp_filename;
|
||||
bs->is_temporary = 1;
|
||||
@@ -383,14 +384,12 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
|
||||
pstrcpy(bs->filename, sizeof(bs->filename), filename);
|
||||
if (flags & BDRV_O_FILE) {
|
||||
drv = find_protocol(filename);
|
||||
if (!drv)
|
||||
return -ENOENT;
|
||||
} else {
|
||||
if (!drv) {
|
||||
drv = find_image_format(filename);
|
||||
if (!drv)
|
||||
return -1;
|
||||
}
|
||||
} else if (!drv) {
|
||||
drv = find_image_format(filename);
|
||||
}
|
||||
if (!drv) {
|
||||
ret = -ENOENT;
|
||||
goto unlink_and_fail;
|
||||
}
|
||||
bs->drv = drv;
|
||||
bs->opaque = qemu_mallocz(drv->instance_size);
|
||||
@@ -409,6 +408,9 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
|
||||
qemu_free(bs->opaque);
|
||||
bs->opaque = NULL;
|
||||
bs->drv = NULL;
|
||||
unlink_and_fail:
|
||||
if (bs->is_temporary)
|
||||
unlink(filename);
|
||||
return ret;
|
||||
}
|
||||
if (drv->bdrv_getlength) {
|
||||
@@ -422,15 +424,13 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
|
||||
if (bs->backing_file[0] != '\0') {
|
||||
/* if there is a backing file, use it */
|
||||
bs->backing_hd = bdrv_new("");
|
||||
if (!bs->backing_hd) {
|
||||
fail:
|
||||
bdrv_close(bs);
|
||||
return -ENOMEM;
|
||||
}
|
||||
path_combine(backing_filename, sizeof(backing_filename),
|
||||
filename, bs->backing_file);
|
||||
if (bdrv_open(bs->backing_hd, backing_filename, open_flags) < 0)
|
||||
goto fail;
|
||||
ret = bdrv_open(bs->backing_hd, backing_filename, open_flags);
|
||||
if (ret < 0) {
|
||||
bdrv_close(bs);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* call the change callback */
|
||||
@@ -533,7 +533,10 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
|
||||
|
||||
len = bdrv_getlength(bs);
|
||||
|
||||
if ((offset + size) > len)
|
||||
if (offset < 0)
|
||||
return -EIO;
|
||||
|
||||
if ((offset > len) || (len - offset < size))
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
@@ -970,6 +973,15 @@ int bdrv_is_encrypted(BlockDriverState *bs)
|
||||
return bs->encrypted;
|
||||
}
|
||||
|
||||
int bdrv_key_required(BlockDriverState *bs)
|
||||
{
|
||||
BlockDriverState *backing_hd = bs->backing_hd;
|
||||
|
||||
if (backing_hd && backing_hd->encrypted && !backing_hd->valid_key)
|
||||
return 1;
|
||||
return (bs->encrypted && !bs->valid_key);
|
||||
}
|
||||
|
||||
int bdrv_set_key(BlockDriverState *bs, const char *key)
|
||||
{
|
||||
int ret;
|
||||
@@ -982,7 +994,9 @@ int bdrv_set_key(BlockDriverState *bs, const char *key)
|
||||
}
|
||||
if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
|
||||
return -1;
|
||||
return bs->drv->bdrv_set_key(bs, key);
|
||||
ret = bs->drv->bdrv_set_key(bs, key);
|
||||
bs->valid_key = (ret == 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
|
||||
@@ -1015,12 +1029,12 @@ BlockDriverState *bdrv_find(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque)
|
||||
void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs), void *opaque)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
|
||||
for (bs = bdrv_first; bs != NULL; bs = bs->next) {
|
||||
it(opaque, bs->device_name);
|
||||
it(opaque, bs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1105,8 +1119,7 @@ void bdrv_info(void)
|
||||
}
|
||||
term_printf(" ro=%d", bs->read_only);
|
||||
term_printf(" drv=%s", bs->drv->format_name);
|
||||
if (bs->encrypted)
|
||||
term_printf(" encrypted");
|
||||
term_printf(" encrypted=%d", bdrv_is_encrypted(bs));
|
||||
} else {
|
||||
term_printf(" [not inserted]");
|
||||
}
|
||||
@@ -1118,7 +1131,6 @@ void bdrv_info(void)
|
||||
void bdrv_info_stats (void)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
BlockDriverInfo bdi;
|
||||
|
||||
for (bs = bdrv_first; bs != NULL; bs = bs->next) {
|
||||
term_printf ("%s:"
|
||||
@@ -1126,18 +1138,23 @@ void bdrv_info_stats (void)
|
||||
" wr_bytes=%" PRIu64
|
||||
" rd_operations=%" PRIu64
|
||||
" wr_operations=%" PRIu64
|
||||
,
|
||||
"\n",
|
||||
bs->device_name,
|
||||
bs->rd_bytes, bs->wr_bytes,
|
||||
bs->rd_ops, bs->wr_ops);
|
||||
if (bdrv_get_info(bs, &bdi) == 0)
|
||||
term_printf(" high=%" PRId64
|
||||
" bytes_free=%" PRId64,
|
||||
bdi.highest_alloc, bdi.num_free_bytes);
|
||||
term_printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
const char *bdrv_get_encrypted_filename(BlockDriverState *bs)
|
||||
{
|
||||
if (bs->backing_hd && bs->backing_hd->encrypted)
|
||||
return bs->backing_file;
|
||||
else if (bs->encrypted)
|
||||
return bs->filename;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bdrv_get_backing_filename(BlockDriverState *bs,
|
||||
char *filename, int filename_size)
|
||||
{
|
||||
@@ -1156,6 +1173,8 @@ int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_write_compressed)
|
||||
return -ENOTSUP;
|
||||
if (bdrv_check_request(bs, sector_num, nb_sectors))
|
||||
return -EIO;
|
||||
return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
|
||||
}
|
||||
|
||||
@@ -1170,6 +1189,26 @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
||||
return drv->bdrv_get_info(bs, bdi);
|
||||
}
|
||||
|
||||
int bdrv_put_buffer(BlockDriverState *bs, const uint8_t *buf, int64_t pos, int size)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
if (!drv)
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_put_buffer)
|
||||
return -ENOTSUP;
|
||||
return drv->bdrv_put_buffer(bs, buf, pos, size);
|
||||
}
|
||||
|
||||
int bdrv_get_buffer(BlockDriverState *bs, uint8_t *buf, int64_t pos, int size)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
if (!drv)
|
||||
return -ENOMEDIUM;
|
||||
if (!drv->bdrv_get_buffer)
|
||||
return -ENOTSUP;
|
||||
return drv->bdrv_get_buffer(bs, buf, pos, size);
|
||||
}
|
||||
|
||||
/**************************************************************/
|
||||
/* handling of snapshots */
|
||||
|
||||
@@ -1293,24 +1332,32 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
|
||||
/**************************************************************/
|
||||
/* async I/Os */
|
||||
|
||||
typedef struct VectorTranslationState {
|
||||
typedef struct VectorTranslationAIOCB {
|
||||
BlockDriverAIOCB common;
|
||||
QEMUIOVector *iov;
|
||||
uint8_t *bounce;
|
||||
int is_write;
|
||||
BlockDriverAIOCB *aiocb;
|
||||
BlockDriverAIOCB *this_aiocb;
|
||||
} VectorTranslationState;
|
||||
} VectorTranslationAIOCB;
|
||||
|
||||
static void bdrv_aio_cancel_vector(BlockDriverAIOCB *_acb)
|
||||
{
|
||||
VectorTranslationAIOCB *acb
|
||||
= container_of(_acb, VectorTranslationAIOCB, common);
|
||||
|
||||
bdrv_aio_cancel(acb->aiocb);
|
||||
}
|
||||
|
||||
static void bdrv_aio_rw_vector_cb(void *opaque, int ret)
|
||||
{
|
||||
VectorTranslationState *s = opaque;
|
||||
VectorTranslationAIOCB *s = (VectorTranslationAIOCB *)opaque;
|
||||
|
||||
if (!s->is_write) {
|
||||
qemu_iovec_from_buffer(s->iov, s->bounce, s->iov->size);
|
||||
}
|
||||
qemu_vfree(s->bounce);
|
||||
s->this_aiocb->cb(s->this_aiocb->opaque, ret);
|
||||
qemu_aio_release(s->this_aiocb);
|
||||
s->common.cb(s->common.opaque, ret);
|
||||
qemu_aio_release(s);
|
||||
}
|
||||
|
||||
static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
|
||||
@@ -1322,10 +1369,9 @@ static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
|
||||
int is_write)
|
||||
|
||||
{
|
||||
VectorTranslationState *s = qemu_mallocz(sizeof(*s));
|
||||
BlockDriverAIOCB *aiocb = qemu_aio_get(bs, cb, opaque);
|
||||
VectorTranslationAIOCB *s = qemu_aio_get_pool(&vectored_aio_pool, bs,
|
||||
cb, opaque);
|
||||
|
||||
s->this_aiocb = aiocb;
|
||||
s->iov = iov;
|
||||
s->bounce = qemu_memalign(512, nb_sectors * 512);
|
||||
s->is_write = is_write;
|
||||
@@ -1337,7 +1383,12 @@ static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
|
||||
s->aiocb = bdrv_aio_read(bs, sector_num, s->bounce, nb_sectors,
|
||||
bdrv_aio_rw_vector_cb, s);
|
||||
}
|
||||
return aiocb;
|
||||
if (!s->aiocb) {
|
||||
qemu_vfree(s->bounce);
|
||||
qemu_aio_release(s);
|
||||
return NULL;
|
||||
}
|
||||
return &s->common;
|
||||
}
|
||||
|
||||
BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
|
||||
@@ -1412,14 +1463,7 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
|
||||
|
||||
void bdrv_aio_cancel(BlockDriverAIOCB *acb)
|
||||
{
|
||||
BlockDriver *drv = acb->bs->drv;
|
||||
|
||||
if (acb->cb == bdrv_aio_rw_vector_cb) {
|
||||
VectorTranslationState *s = acb->opaque;
|
||||
acb = s->aiocb;
|
||||
}
|
||||
|
||||
drv->bdrv_aio_cancel(acb);
|
||||
acb->pool->cancel(acb);
|
||||
}
|
||||
|
||||
|
||||
@@ -1520,6 +1564,9 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
|
||||
|
||||
void bdrv_init(void)
|
||||
{
|
||||
aio_pool_init(&vectored_aio_pool, sizeof(VectorTranslationAIOCB),
|
||||
bdrv_aio_cancel_vector);
|
||||
|
||||
bdrv_register(&bdrv_raw);
|
||||
bdrv_register(&bdrv_host_device);
|
||||
#ifndef _WIN32
|
||||
@@ -1537,18 +1584,25 @@ void bdrv_init(void)
|
||||
bdrv_register(&bdrv_nbd);
|
||||
}
|
||||
|
||||
void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
|
||||
void *opaque)
|
||||
void aio_pool_init(AIOPool *pool, int aiocb_size,
|
||||
void (*cancel)(BlockDriverAIOCB *acb))
|
||||
{
|
||||
pool->aiocb_size = aiocb_size;
|
||||
pool->cancel = cancel;
|
||||
pool->free_aiocb = NULL;
|
||||
}
|
||||
|
||||
void *qemu_aio_get_pool(AIOPool *pool, BlockDriverState *bs,
|
||||
BlockDriverCompletionFunc *cb, void *opaque)
|
||||
{
|
||||
BlockDriver *drv;
|
||||
BlockDriverAIOCB *acb;
|
||||
|
||||
drv = bs->drv;
|
||||
if (drv->free_aiocb) {
|
||||
acb = drv->free_aiocb;
|
||||
drv->free_aiocb = acb->next;
|
||||
if (pool->free_aiocb) {
|
||||
acb = pool->free_aiocb;
|
||||
pool->free_aiocb = acb->next;
|
||||
} else {
|
||||
acb = qemu_mallocz(drv->aiocb_size);
|
||||
acb = qemu_mallocz(pool->aiocb_size);
|
||||
acb->pool = pool;
|
||||
}
|
||||
acb->bs = bs;
|
||||
acb->cb = cb;
|
||||
@@ -1556,12 +1610,18 @@ void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
|
||||
return acb;
|
||||
}
|
||||
|
||||
void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
|
||||
void *opaque)
|
||||
{
|
||||
return qemu_aio_get_pool(&bs->drv->aio_pool, bs, cb, opaque);
|
||||
}
|
||||
|
||||
void qemu_aio_release(void *p)
|
||||
{
|
||||
BlockDriverAIOCB *acb = p;
|
||||
BlockDriver *drv = acb->bs->drv;
|
||||
acb->next = drv->free_aiocb;
|
||||
drv->free_aiocb = acb;
|
||||
BlockDriverAIOCB *acb = (BlockDriverAIOCB *)p;
|
||||
AIOPool *pool = acb->pool;
|
||||
acb->next = pool->free_aiocb;
|
||||
pool->free_aiocb = acb;
|
||||
}
|
||||
|
||||
/**************************************************************/
|
||||
@@ -1604,11 +1664,15 @@ int bdrv_media_changed(BlockDriverState *bs)
|
||||
/**
|
||||
* If eject_flag is TRUE, eject the media. Otherwise, close the tray
|
||||
*/
|
||||
void bdrv_eject(BlockDriverState *bs, int eject_flag)
|
||||
int bdrv_eject(BlockDriverState *bs, int eject_flag)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
int ret;
|
||||
|
||||
if (bs->locked) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (!drv || !drv->bdrv_eject) {
|
||||
ret = -ENOTSUP;
|
||||
} else {
|
||||
@@ -1617,7 +1681,10 @@ void bdrv_eject(BlockDriverState *bs, int eject_flag)
|
||||
if (ret == -ENOTSUP) {
|
||||
if (eject_flag)
|
||||
bdrv_close(bs);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bdrv_is_locked(BlockDriverState *bs)
|
||||
|
17
block.h
17
block.h
@@ -26,8 +26,6 @@ typedef struct BlockDriverInfo {
|
||||
int cluster_size;
|
||||
/* offset at which the VM state can be saved (0 if not possible) */
|
||||
int64_t vm_state_offset;
|
||||
int64_t highest_alloc; /* highest allocated block offset (in bytes) */
|
||||
int64_t num_free_bytes; /* below highest_alloc */
|
||||
} BlockDriverInfo;
|
||||
|
||||
typedef struct QEMUSnapshotInfo {
|
||||
@@ -103,8 +101,6 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
|
||||
BlockDriverCompletionFunc *cb, void *opaque);
|
||||
void bdrv_aio_cancel(BlockDriverAIOCB *acb);
|
||||
|
||||
int qemu_key_check(BlockDriverState *bs, const char *name);
|
||||
|
||||
/* Ensure contents are flushed to disk. */
|
||||
void bdrv_flush(BlockDriverState *bs);
|
||||
void bdrv_flush_all(void);
|
||||
@@ -136,14 +132,17 @@ int bdrv_is_inserted(BlockDriverState *bs);
|
||||
int bdrv_media_changed(BlockDriverState *bs);
|
||||
int bdrv_is_locked(BlockDriverState *bs);
|
||||
void bdrv_set_locked(BlockDriverState *bs, int locked);
|
||||
void bdrv_eject(BlockDriverState *bs, int eject_flag);
|
||||
int bdrv_eject(BlockDriverState *bs, int eject_flag);
|
||||
void bdrv_set_change_cb(BlockDriverState *bs,
|
||||
void (*change_cb)(void *opaque), void *opaque);
|
||||
void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size);
|
||||
BlockDriverState *bdrv_find(const char *name);
|
||||
void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque);
|
||||
void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs),
|
||||
void *opaque);
|
||||
int bdrv_is_encrypted(BlockDriverState *bs);
|
||||
int bdrv_key_required(BlockDriverState *bs);
|
||||
int bdrv_set_key(BlockDriverState *bs, const char *key);
|
||||
int bdrv_query_missing_keys(void);
|
||||
void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
|
||||
void *opaque);
|
||||
const char *bdrv_get_device_name(BlockDriverState *bs);
|
||||
@@ -151,6 +150,7 @@ int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
|
||||
const uint8_t *buf, int nb_sectors);
|
||||
int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
|
||||
|
||||
const char *bdrv_get_encrypted_filename(BlockDriverState *bs);
|
||||
void bdrv_get_backing_filename(BlockDriverState *bs,
|
||||
char *filename, int filename_size);
|
||||
int bdrv_snapshot_create(BlockDriverState *bs,
|
||||
@@ -169,4 +169,9 @@ void path_combine(char *dest, int dest_size,
|
||||
const char *base_path,
|
||||
const char *filename);
|
||||
|
||||
int bdrv_put_buffer(BlockDriverState *bs, const uint8_t *buf,
|
||||
int64_t pos, int size);
|
||||
|
||||
int bdrv_get_buffer(BlockDriverState *bs, uint8_t *buf, int64_t pos, int size);
|
||||
|
||||
#endif
|
||||
|
20
block_int.h
20
block_int.h
@@ -30,6 +30,12 @@
|
||||
#define BLOCK_FLAG_COMPRESS 2
|
||||
#define BLOCK_FLAG_COMPAT6 4
|
||||
|
||||
typedef struct AIOPool {
|
||||
void (*cancel)(BlockDriverAIOCB *acb);
|
||||
int aiocb_size;
|
||||
BlockDriverAIOCB *free_aiocb;
|
||||
} AIOPool;
|
||||
|
||||
struct BlockDriver {
|
||||
const char *format_name;
|
||||
int instance_size;
|
||||
@@ -76,6 +82,11 @@ struct BlockDriver {
|
||||
QEMUSnapshotInfo **psn_info);
|
||||
int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
|
||||
|
||||
int (*bdrv_put_buffer)(BlockDriverState *bs, const uint8_t *buf,
|
||||
int64_t pos, int size);
|
||||
int (*bdrv_get_buffer)(BlockDriverState *bs, uint8_t *buf,
|
||||
int64_t pos, int size);
|
||||
|
||||
/* removable device specific */
|
||||
int (*bdrv_is_inserted)(BlockDriverState *bs);
|
||||
int (*bdrv_media_changed)(BlockDriverState *bs);
|
||||
@@ -85,7 +96,7 @@ struct BlockDriver {
|
||||
/* to control generic scsi devices */
|
||||
int (*bdrv_ioctl)(BlockDriverState *bs, unsigned long int req, void *buf);
|
||||
|
||||
BlockDriverAIOCB *free_aiocb;
|
||||
AIOPool aio_pool;
|
||||
struct BlockDriver *next;
|
||||
};
|
||||
|
||||
@@ -96,6 +107,7 @@ struct BlockDriverState {
|
||||
int removable; /* if true, the media can be removed */
|
||||
int locked; /* if true, the media cannot temporarily be ejected */
|
||||
int encrypted; /* if true, the media is encrypted */
|
||||
int valid_key; /* if true, a valid encryption key has been set */
|
||||
int sg; /* if true, the device is a /dev/sg* */
|
||||
/* event callback when inserting/removing */
|
||||
void (*change_cb)(void *opaque);
|
||||
@@ -134,6 +146,7 @@ struct BlockDriverState {
|
||||
};
|
||||
|
||||
struct BlockDriverAIOCB {
|
||||
AIOPool *pool;
|
||||
BlockDriverState *bs;
|
||||
BlockDriverCompletionFunc *cb;
|
||||
void *opaque;
|
||||
@@ -142,8 +155,13 @@ struct BlockDriverAIOCB {
|
||||
|
||||
void get_tmp_filename(char *filename, int size);
|
||||
|
||||
void aio_pool_init(AIOPool *pool, int aiocb_size,
|
||||
void (*cancel)(BlockDriverAIOCB *acb));
|
||||
|
||||
void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
|
||||
void *opaque);
|
||||
void *qemu_aio_get_pool(AIOPool *pool, BlockDriverState *bs,
|
||||
BlockDriverCompletionFunc *cb, void *opaque);
|
||||
void qemu_aio_release(void *p);
|
||||
|
||||
extern BlockDriverState *bdrv_first;
|
||||
|
2
configure
vendored
2
configure
vendored
@@ -1013,7 +1013,7 @@ EOF
|
||||
kvm="no";
|
||||
if [ -x "`which awk 2>/dev/null`" ] && \
|
||||
[ -x "`which grep 2>/dev/null`" ]; then
|
||||
kvmerr=`$cc $ARCH_CFLAGS -o $TMPE ${OS_CFLAGS} $kvm_cflags $TMPC 2>&1 \
|
||||
kvmerr=`LANG=C $cc $ARCH_CFLAGS -o $TMPE ${OS_CFLAGS} $kvm_cflags $TMPC 2>&1 \
|
||||
| grep "error: " \
|
||||
| awk -F "error: " '{if (NR>1) printf(", "); printf("%s",$2);}'`
|
||||
if test "$kvmerr" != "" ; then
|
||||
|
@@ -302,10 +302,9 @@ void term_printf(const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1
|
||||
void term_print_filename(const char *filename);
|
||||
void term_flush(void);
|
||||
void term_print_help(void);
|
||||
void monitor_readline(const char *prompt, int is_password,
|
||||
char *buf, int buf_size);
|
||||
void monitor_suspend(void);
|
||||
void monitor_resume(void);
|
||||
int monitor_read_bdrv_key(BlockDriverState *bs);
|
||||
|
||||
/* readline.c */
|
||||
typedef void ReadLineFunc(void *opaque, const char *str);
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include "config.h"
|
||||
#include <setjmp.h>
|
||||
#include <inttypes.h>
|
||||
#include <signal.h>
|
||||
#include "osdep.h"
|
||||
#include "sys-queue.h"
|
||||
|
||||
@@ -170,6 +171,7 @@ typedef struct CPUWatchpoint {
|
||||
memory was accessed */ \
|
||||
uint32_t halted; /* Nonzero if the CPU is in suspend state */ \
|
||||
uint32_t interrupt_request; \
|
||||
volatile sig_atomic_t exit_request; \
|
||||
/* The meaning of the MMU modes is defined in the target code. */ \
|
||||
CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \
|
||||
target_phys_addr_t iotlb[NB_MMU_MODES][CPU_TLB_SIZE]; \
|
||||
|
16
cpu-exec.c
16
cpu-exec.c
@@ -311,7 +311,7 @@ int cpu_exec(CPUState *env1)
|
||||
env->exception_index = -1;
|
||||
}
|
||||
#ifdef USE_KQEMU
|
||||
if (kqemu_is_ok(env) && env->interrupt_request == 0) {
|
||||
if (kqemu_is_ok(env) && env->interrupt_request == 0 && env->exit_request == 0) {
|
||||
int ret;
|
||||
env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
|
||||
ret = kqemu_cpu_exec(env);
|
||||
@@ -326,7 +326,7 @@ int cpu_exec(CPUState *env1)
|
||||
} else if (ret == 2) {
|
||||
/* softmmu execution needed */
|
||||
} else {
|
||||
if (env->interrupt_request != 0) {
|
||||
if (env->interrupt_request != 0 || env->exit_request != 0) {
|
||||
/* hardware interrupt will be executed just after */
|
||||
} else {
|
||||
/* otherwise, we restart */
|
||||
@@ -525,11 +525,11 @@ int cpu_exec(CPUState *env1)
|
||||
the program flow was changed */
|
||||
next_tb = 0;
|
||||
}
|
||||
if (interrupt_request & CPU_INTERRUPT_EXIT) {
|
||||
env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
|
||||
env->exception_index = EXCP_INTERRUPT;
|
||||
cpu_loop_exit();
|
||||
}
|
||||
}
|
||||
if (unlikely(env->exit_request)) {
|
||||
env->exit_request = 0;
|
||||
env->exception_index = EXCP_INTERRUPT;
|
||||
cpu_loop_exit();
|
||||
}
|
||||
#ifdef DEBUG_EXEC
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
|
||||
@@ -599,7 +599,7 @@ int cpu_exec(CPUState *env1)
|
||||
TB, but before it is linked into a potentially
|
||||
infinite loop and becomes env->current_tb. Avoid
|
||||
starting execution if there is a pending interrupt. */
|
||||
if (unlikely (env->interrupt_request & CPU_INTERRUPT_EXIT))
|
||||
if (unlikely (env->exit_request))
|
||||
env->current_tb = NULL;
|
||||
|
||||
while (env->current_tb) {
|
||||
|
@@ -10,6 +10,8 @@
|
||||
#include "dma.h"
|
||||
#include "block_int.h"
|
||||
|
||||
static AIOPool dma_aio_pool;
|
||||
|
||||
void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint)
|
||||
{
|
||||
qsg->sg = qemu_malloc(alloc_hint * sizeof(ScatterGatherEntry));
|
||||
@@ -37,6 +39,7 @@ void qemu_sglist_destroy(QEMUSGList *qsg)
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
BlockDriverAIOCB common;
|
||||
BlockDriverState *bs;
|
||||
BlockDriverAIOCB *acb;
|
||||
QEMUSGList *sg;
|
||||
@@ -46,13 +49,13 @@ typedef struct {
|
||||
target_phys_addr_t sg_cur_byte;
|
||||
QEMUIOVector iov;
|
||||
QEMUBH *bh;
|
||||
} DMABlockState;
|
||||
} DMAAIOCB;
|
||||
|
||||
static void dma_bdrv_cb(void *opaque, int ret);
|
||||
|
||||
static void reschedule_dma(void *opaque)
|
||||
{
|
||||
DMABlockState *dbs = (DMABlockState *)opaque;
|
||||
DMAAIOCB *dbs = (DMAAIOCB *)opaque;
|
||||
|
||||
qemu_bh_delete(dbs->bh);
|
||||
dbs->bh = NULL;
|
||||
@@ -61,32 +64,38 @@ static void reschedule_dma(void *opaque)
|
||||
|
||||
static void continue_after_map_failure(void *opaque)
|
||||
{
|
||||
DMABlockState *dbs = (DMABlockState *)opaque;
|
||||
DMAAIOCB *dbs = (DMAAIOCB *)opaque;
|
||||
|
||||
dbs->bh = qemu_bh_new(reschedule_dma, dbs);
|
||||
qemu_bh_schedule(dbs->bh);
|
||||
}
|
||||
|
||||
static void dma_bdrv_cb(void *opaque, int ret)
|
||||
static void dma_bdrv_unmap(DMAAIOCB *dbs)
|
||||
{
|
||||
DMABlockState *dbs = (DMABlockState *)opaque;
|
||||
target_phys_addr_t cur_addr, cur_len;
|
||||
void *mem;
|
||||
int i;
|
||||
|
||||
dbs->sector_num += dbs->iov.size / 512;
|
||||
for (i = 0; i < dbs->iov.niov; ++i) {
|
||||
cpu_physical_memory_unmap(dbs->iov.iov[i].iov_base,
|
||||
dbs->iov.iov[i].iov_len, !dbs->is_write,
|
||||
dbs->iov.iov[i].iov_len);
|
||||
}
|
||||
}
|
||||
|
||||
void dma_bdrv_cb(void *opaque, int ret)
|
||||
{
|
||||
DMAAIOCB *dbs = (DMAAIOCB *)opaque;
|
||||
target_phys_addr_t cur_addr, cur_len;
|
||||
void *mem;
|
||||
|
||||
dbs->acb = NULL;
|
||||
dbs->sector_num += dbs->iov.size / 512;
|
||||
dma_bdrv_unmap(dbs);
|
||||
qemu_iovec_reset(&dbs->iov);
|
||||
|
||||
if (dbs->sg_cur_index == dbs->sg->nsg || ret < 0) {
|
||||
dbs->acb->cb(dbs->acb->opaque, ret);
|
||||
dbs->common.cb(dbs->common.opaque, ret);
|
||||
qemu_iovec_destroy(&dbs->iov);
|
||||
qemu_aio_release(dbs->acb);
|
||||
qemu_free(dbs);
|
||||
qemu_aio_release(dbs);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -110,11 +119,16 @@ static void dma_bdrv_cb(void *opaque, int ret)
|
||||
}
|
||||
|
||||
if (dbs->is_write) {
|
||||
bdrv_aio_writev(dbs->bs, dbs->sector_num, &dbs->iov,
|
||||
dbs->iov.size / 512, dma_bdrv_cb, dbs);
|
||||
dbs->acb = bdrv_aio_writev(dbs->bs, dbs->sector_num, &dbs->iov,
|
||||
dbs->iov.size / 512, dma_bdrv_cb, dbs);
|
||||
} else {
|
||||
bdrv_aio_readv(dbs->bs, dbs->sector_num, &dbs->iov,
|
||||
dbs->iov.size / 512, dma_bdrv_cb, dbs);
|
||||
dbs->acb = bdrv_aio_readv(dbs->bs, dbs->sector_num, &dbs->iov,
|
||||
dbs->iov.size / 512, dma_bdrv_cb, dbs);
|
||||
}
|
||||
if (!dbs->acb) {
|
||||
dma_bdrv_unmap(dbs);
|
||||
qemu_iovec_destroy(&dbs->iov);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,10 +137,10 @@ static BlockDriverAIOCB *dma_bdrv_io(
|
||||
BlockDriverCompletionFunc *cb, void *opaque,
|
||||
int is_write)
|
||||
{
|
||||
DMABlockState *dbs = qemu_malloc(sizeof(*dbs));
|
||||
DMAAIOCB *dbs = qemu_aio_get_pool(&dma_aio_pool, bs, cb, opaque);
|
||||
|
||||
dbs->acb = NULL;
|
||||
dbs->bs = bs;
|
||||
dbs->acb = qemu_aio_get(bs, cb, opaque);
|
||||
dbs->sg = sg;
|
||||
dbs->sector_num = sector_num;
|
||||
dbs->sg_cur_index = 0;
|
||||
@@ -135,7 +149,11 @@ static BlockDriverAIOCB *dma_bdrv_io(
|
||||
dbs->bh = NULL;
|
||||
qemu_iovec_init(&dbs->iov, sg->nsg);
|
||||
dma_bdrv_cb(dbs, 0);
|
||||
return dbs->acb;
|
||||
if (!dbs->acb) {
|
||||
qemu_aio_release(dbs);
|
||||
return NULL;
|
||||
}
|
||||
return &dbs->common;
|
||||
}
|
||||
|
||||
|
||||
@@ -153,3 +171,16 @@ BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs,
|
||||
return dma_bdrv_io(bs, sg, sector, cb, opaque, 1);
|
||||
}
|
||||
|
||||
static void dma_aio_cancel(BlockDriverAIOCB *acb)
|
||||
{
|
||||
DMAAIOCB *dbs = container_of(acb, DMAAIOCB, common);
|
||||
|
||||
if (dbs->acb) {
|
||||
bdrv_aio_cancel(dbs->acb);
|
||||
}
|
||||
}
|
||||
|
||||
void dma_helper_init(void)
|
||||
{
|
||||
aio_pool_init(&dma_aio_pool, sizeof(DMAAIOCB), dma_aio_cancel);
|
||||
}
|
||||
|
1
dma.h
1
dma.h
@@ -37,5 +37,6 @@ BlockDriverAIOCB *dma_bdrv_read(BlockDriverState *bs,
|
||||
BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs,
|
||||
QEMUSGList *sg, uint64_t sector,
|
||||
BlockDriverCompletionFunc *cb, void *opaque);
|
||||
void dma_helper_init(void);
|
||||
|
||||
#endif
|
||||
|
19
exec.c
19
exec.c
@@ -523,6 +523,7 @@ static int cpu_common_load(QEMUFile *f, void *opaque, int version_id)
|
||||
|
||||
qemu_get_be32s(f, &env->halted);
|
||||
qemu_get_be32s(f, &env->interrupt_request);
|
||||
env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
|
||||
tlb_flush(env, 1);
|
||||
|
||||
return 0;
|
||||
@@ -1501,9 +1502,12 @@ void cpu_interrupt(CPUState *env, int mask)
|
||||
#endif
|
||||
int old_mask;
|
||||
|
||||
if (mask & CPU_INTERRUPT_EXIT) {
|
||||
env->exit_request = 1;
|
||||
mask &= ~CPU_INTERRUPT_EXIT;
|
||||
}
|
||||
|
||||
old_mask = env->interrupt_request;
|
||||
/* FIXME: This is probably not threadsafe. A different thread could
|
||||
be in the middle of a read-modify-write operation. */
|
||||
env->interrupt_request |= mask;
|
||||
#if defined(USE_NPTL)
|
||||
/* FIXME: TB unchaining isn't SMP safe. For now just ignore the
|
||||
@@ -1514,10 +1518,8 @@ void cpu_interrupt(CPUState *env, int mask)
|
||||
if (use_icount) {
|
||||
env->icount_decr.u16.high = 0xffff;
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* CPU_INTERRUPT_EXIT isn't a real interrupt. It just means
|
||||
an async event happened and we need to process it. */
|
||||
if (!can_do_io(env)
|
||||
&& (mask & ~(old_mask | CPU_INTERRUPT_EXIT)) != 0) {
|
||||
&& (mask & ~old_mask) != 0) {
|
||||
cpu_abort(env, "Raised interrupt while not in I/O function");
|
||||
}
|
||||
#endif
|
||||
@@ -2384,6 +2386,10 @@ ram_addr_t qemu_ram_alloc(ram_addr_t size)
|
||||
}
|
||||
addr = phys_ram_alloc_offset;
|
||||
phys_ram_alloc_offset = TARGET_PAGE_ALIGN(phys_ram_alloc_offset + size);
|
||||
|
||||
if (kvm_enabled())
|
||||
kvm_setup_guest_memory(phys_ram_base + addr, size);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -3104,6 +3110,7 @@ void cpu_unregister_map_client(void *_client)
|
||||
MapClient *client = (MapClient *)_client;
|
||||
|
||||
LIST_REMOVE(client, link);
|
||||
qemu_free(client);
|
||||
}
|
||||
|
||||
static void cpu_notify_map_clients(void)
|
||||
@@ -3113,7 +3120,7 @@ static void cpu_notify_map_clients(void)
|
||||
while (!LIST_EMPTY(&map_client_list)) {
|
||||
client = LIST_FIRST(&map_client_list);
|
||||
client->callback(client->opaque);
|
||||
LIST_REMOVE(client, link);
|
||||
cpu_unregister_map_client(client);
|
||||
}
|
||||
}
|
||||
|
||||
|
12
hw/acpi.c
12
hw/acpi.c
@@ -604,7 +604,7 @@ static uint32_t gpe_readb(void *opaque, uint32_t addr)
|
||||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
printf("gpe read %lx == %lx\n", addr, val);
|
||||
printf("gpe read %x == %x\n", addr, val);
|
||||
#endif
|
||||
return val;
|
||||
}
|
||||
@@ -646,7 +646,7 @@ static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
|
||||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
printf("gpe write %lx <== %d\n", addr, val);
|
||||
printf("gpe write %x <== %d\n", addr, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -666,7 +666,7 @@ static uint32_t pcihotplug_read(void *opaque, uint32_t addr)
|
||||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
printf("pcihotplug read %lx == %lx\n", addr, val);
|
||||
printf("pcihotplug read %x == %x\n", addr, val);
|
||||
#endif
|
||||
return val;
|
||||
}
|
||||
@@ -684,14 +684,14 @@ static void pcihotplug_write(void *opaque, uint32_t addr, uint32_t val)
|
||||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
printf("pcihotplug write %lx <== %d\n", addr, val);
|
||||
printf("pcihotplug write %x <== %d\n", addr, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t pciej_read(void *opaque, uint32_t addr)
|
||||
{
|
||||
#if defined(DEBUG)
|
||||
printf("pciej read %lx == %lx\n", addr, val);
|
||||
printf("pciej read %x\n", addr);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -705,7 +705,7 @@ static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG)
|
||||
printf("pciej write %lx <== %d\n", addr, val);
|
||||
printf("pciej write %x <== %d\n", addr, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -349,10 +349,10 @@ void axisdev88_init (ram_addr_t ram_size, int vga_ram_size,
|
||||
fprintf(stderr, "Too long CRIS kernel cmdline (max 256)\n");
|
||||
exit(1);
|
||||
}
|
||||
pstrcpy_targphys(high, 256, kernel_cmdline);
|
||||
/* Let the kernel know we are modifying the cmdline. */
|
||||
env->regs[10] = 0x87109563;
|
||||
env->regs[11] = high;
|
||||
env->regs[11] = 0x40000000;
|
||||
pstrcpy_targphys(env->regs[11], 256, kernel_cmdline);
|
||||
}
|
||||
}
|
||||
env->pc = bootstrap_pc;
|
||||
|
@@ -2637,11 +2637,16 @@ static void map_linear_vram(CirrusVGAState *s)
|
||||
|
||||
s->lfb_vram_mapped = 0;
|
||||
|
||||
cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x8000,
|
||||
(s->vram_offset + s->cirrus_bank_base[0]) | IO_MEM_UNASSIGNED);
|
||||
cpu_register_physical_memory(isa_mem_base + 0xa8000, 0x8000,
|
||||
(s->vram_offset + s->cirrus_bank_base[1]) | IO_MEM_UNASSIGNED);
|
||||
if (!(s->cirrus_srcptr != s->cirrus_srcptr_end)
|
||||
&& !((s->sr[0x07] & 0x01) == 0)
|
||||
&& !((s->gr[0x0B] & 0x14) == 0x14)
|
||||
&& !(s->gr[0x0B] & 0x02)) {
|
||||
|
||||
vga_dirty_log_stop((VGAState *)s);
|
||||
cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x8000,
|
||||
(s->vram_offset + s->cirrus_bank_base[0]) | IO_MEM_RAM);
|
||||
cpu_register_physical_memory(isa_mem_base + 0xa8000, 0x8000,
|
||||
|
@@ -55,12 +55,7 @@ void destroy_nic(dev_match_fn *match_fn, void *arg)
|
||||
nic = &nd_table[i];
|
||||
if (nic->used) {
|
||||
if (nic->private && match_fn(nic->private, arg)) {
|
||||
if (nic->vlan) {
|
||||
VLANClientState *vc;
|
||||
vc = qemu_find_vlan_client(nic->vlan, nic->private);
|
||||
if (vc)
|
||||
qemu_del_vlan_client(vc);
|
||||
}
|
||||
qemu_del_vlan_client(nic->vc);
|
||||
net_client_uninit(nic);
|
||||
}
|
||||
}
|
||||
|
34
hw/e1000.c
34
hw/e1000.c
@@ -75,7 +75,6 @@ enum {
|
||||
typedef struct E1000State_st {
|
||||
PCIDevice dev;
|
||||
VLANClientState *vc;
|
||||
NICInfo *nd;
|
||||
int mmio_index;
|
||||
|
||||
uint32_t mac_reg[0x8000];
|
||||
@@ -190,6 +189,13 @@ rxbufsize(uint32_t v)
|
||||
return 2048;
|
||||
}
|
||||
|
||||
static void
|
||||
set_ctrl(E1000State *s, int index, uint32_t val)
|
||||
{
|
||||
/* RST is self clearing */
|
||||
s->mac_reg[CTRL] = val & ~E1000_CTRL_RST;
|
||||
}
|
||||
|
||||
static void
|
||||
set_rx_control(E1000State *s, int index, uint32_t val)
|
||||
{
|
||||
@@ -666,8 +672,8 @@ e1000_receive(void *opaque, const uint8_t *buf, int size)
|
||||
n = E1000_ICS_RXT0;
|
||||
if ((rdt = s->mac_reg[RDT]) < s->mac_reg[RDH])
|
||||
rdt += s->mac_reg[RDLEN] / sizeof(desc);
|
||||
if (((rdt - s->mac_reg[RDH]) * sizeof(desc)) << s->rxbuf_min_shift >=
|
||||
s->mac_reg[RDLEN])
|
||||
if (((rdt - s->mac_reg[RDH]) * sizeof(desc)) <= s->mac_reg[RDLEN] >>
|
||||
s->rxbuf_min_shift)
|
||||
n |= E1000_ICS_RXDMT0;
|
||||
|
||||
set_ics(s, 0, n);
|
||||
@@ -784,12 +790,12 @@ enum { NREADOPS = ARRAY_SIZE(macreg_readops) };
|
||||
static void (*macreg_writeops[])(E1000State *, int, uint32_t) = {
|
||||
putreg(PBA), putreg(EERD), putreg(SWSM), putreg(WUFC),
|
||||
putreg(TDBAL), putreg(TDBAH), putreg(TXDCTL), putreg(RDBAH),
|
||||
putreg(RDBAL), putreg(LEDCTL), putreg(CTRL), putreg(VET),
|
||||
putreg(RDBAL), putreg(LEDCTL), putreg(VET),
|
||||
[TDLEN] = set_dlen, [RDLEN] = set_dlen, [TCTL] = set_tctl,
|
||||
[TDT] = set_tctl, [MDIC] = set_mdic, [ICS] = set_ics,
|
||||
[TDH] = set_16bit, [RDH] = set_16bit, [RDT] = set_rdt,
|
||||
[IMC] = set_imc, [IMS] = set_ims, [ICR] = set_icr,
|
||||
[EECD] = set_eecd, [RCTL] = set_rx_control,
|
||||
[EECD] = set_eecd, [RCTL] = set_rx_control, [CTRL] = set_ctrl,
|
||||
[RA ... RA+31] = &mac_writereg,
|
||||
[MTA ... MTA+127] = &mac_writereg,
|
||||
[VFTA ... VFTA+127] = &mac_writereg,
|
||||
@@ -1034,6 +1040,14 @@ e1000_mmio_map(PCIDevice *pci_dev, int region_num,
|
||||
excluded_regs[i] - 4);
|
||||
}
|
||||
|
||||
static void
|
||||
e1000_cleanup(VLANClientState *vc)
|
||||
{
|
||||
E1000State *d = vc->opaque;
|
||||
|
||||
unregister_savevm("e1000", d);
|
||||
}
|
||||
|
||||
static int
|
||||
pci_e1000_uninit(PCIDevice *dev)
|
||||
{
|
||||
@@ -1056,8 +1070,10 @@ pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn)
|
||||
d = (E1000State *)pci_register_device(bus, "e1000",
|
||||
sizeof(E1000State), devfn, NULL, NULL);
|
||||
|
||||
if (!d)
|
||||
return NULL;
|
||||
|
||||
pci_conf = d->dev.config;
|
||||
memset(pci_conf, 0, 256);
|
||||
|
||||
pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
|
||||
pci_config_set_device_id(pci_conf, E1000_DEVID);
|
||||
@@ -1078,7 +1094,6 @@ pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn)
|
||||
pci_register_io_region((PCIDevice *)d, 1, IOPORT_SIZE,
|
||||
PCI_ADDRESS_SPACE_IO, ioport_map);
|
||||
|
||||
d->nd = nd;
|
||||
memmove(d->eeprom_data, e1000_eeprom_template,
|
||||
sizeof e1000_eeprom_template);
|
||||
for (i = 0; i < 3; i++)
|
||||
@@ -1096,10 +1111,11 @@ pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn)
|
||||
memset(&d->tx, 0, sizeof d->tx);
|
||||
|
||||
d->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
e1000_receive, e1000_can_receive, d);
|
||||
e1000_receive, e1000_can_receive,
|
||||
e1000_cleanup, d);
|
||||
d->vc->link_status_changed = e1000_set_link_status;
|
||||
|
||||
qemu_format_nic_info_str(d->vc, d->nd->macaddr);
|
||||
qemu_format_nic_info_str(d->vc, nd->macaddr);
|
||||
|
||||
register_savevm(info_str, -1, 2, nic_save, nic_load, d);
|
||||
d->dev.unregister = pci_e1000_uninit;
|
||||
|
@@ -1735,17 +1735,39 @@ static void nic_save(QEMUFile * f, void *opaque)
|
||||
qemu_put_buffer(f, s->configuration, sizeof(s->configuration));
|
||||
}
|
||||
|
||||
static PCIDevice *nic_init(PCIBus * bus, NICInfo * nd,
|
||||
const char *name, uint32_t device)
|
||||
static void nic_cleanup(VLANClientState *vc)
|
||||
{
|
||||
EEPRO100State *s = vc->opaque;
|
||||
|
||||
unregister_savevm(vc->model, s);
|
||||
|
||||
eeprom93xx_free(s->eeprom);
|
||||
}
|
||||
|
||||
static int pci_nic_uninit(PCIDevice *dev)
|
||||
{
|
||||
PCIEEPRO100State *d = (PCIEEPRO100State *) dev;
|
||||
EEPRO100State *s = &d->eepro100;
|
||||
|
||||
cpu_unregister_io_memory(s->mmio_index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PCIDevice *nic_init(PCIBus * bus, NICInfo * nd, uint32_t device)
|
||||
{
|
||||
PCIEEPRO100State *d;
|
||||
EEPRO100State *s;
|
||||
|
||||
logout("\n");
|
||||
|
||||
d = (PCIEEPRO100State *) pci_register_device(bus, name,
|
||||
d = (PCIEEPRO100State *) pci_register_device(bus, nd->model,
|
||||
sizeof(PCIEEPRO100State), -1,
|
||||
NULL, NULL);
|
||||
if (!d)
|
||||
return NULL;
|
||||
|
||||
d->dev.unregister = pci_nic_uninit;
|
||||
|
||||
s = &d->eepro100;
|
||||
s->device = device;
|
||||
@@ -1776,30 +1798,30 @@ static PCIDevice *nic_init(PCIBus * bus, NICInfo * nd,
|
||||
nic_reset(s);
|
||||
|
||||
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
nic_receive, nic_can_receive, s);
|
||||
nic_receive, nic_can_receive,
|
||||
nic_cleanup, s);
|
||||
|
||||
qemu_format_nic_info_str(s->vc, s->macaddr);
|
||||
|
||||
qemu_register_reset(nic_reset, s);
|
||||
|
||||
register_savevm(name, -1, 3, nic_save, nic_load, s);
|
||||
register_savevm(s->vc->model, -1, 3, nic_save, nic_load, s);
|
||||
return (PCIDevice *)d;
|
||||
}
|
||||
|
||||
PCIDevice *pci_i82551_init(PCIBus * bus, NICInfo * nd, int devfn)
|
||||
{
|
||||
return nic_init(bus, nd, "i82551", i82551);
|
||||
//~ uint8_t *pci_conf = d->dev.config;
|
||||
return nic_init(bus, nd, i82551);
|
||||
}
|
||||
|
||||
PCIDevice *pci_i82557b_init(PCIBus * bus, NICInfo * nd, int devfn)
|
||||
{
|
||||
return nic_init(bus, nd, "i82557b", i82557B);
|
||||
return nic_init(bus, nd, i82557B);
|
||||
}
|
||||
|
||||
PCIDevice *pci_i82559er_init(PCIBus * bus, NICInfo * nd, int devfn)
|
||||
{
|
||||
return nic_init(bus, nd, "i82559er", i82559ER);
|
||||
return nic_init(bus, nd, i82559ER);
|
||||
}
|
||||
|
||||
/* eof */
|
||||
|
@@ -301,6 +301,7 @@ void eeprom93xx_free(eeprom_t *eeprom)
|
||||
{
|
||||
/* Destroy EEPROM. */
|
||||
logout("eeprom = 0x%p\n", eeprom);
|
||||
unregister_savevm("eeprom", eeprom);
|
||||
qemu_free(eeprom);
|
||||
}
|
||||
|
||||
|
@@ -140,10 +140,10 @@ void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size,
|
||||
fprintf(stderr, "Too long CRIS kernel cmdline (max 256)\n");
|
||||
exit(1);
|
||||
}
|
||||
pstrcpy_targphys(high, 256, kernel_cmdline);
|
||||
/* Let the kernel know we are modifying the cmdline. */
|
||||
env->regs[10] = 0x87109563;
|
||||
env->regs[11] = high;
|
||||
env->regs[11] = 0x40000000;
|
||||
pstrcpy_targphys(env->regs[11], 256, kernel_cmdline);
|
||||
}
|
||||
}
|
||||
env->pc = bootstrap_pc;
|
||||
|
@@ -401,8 +401,8 @@ static void eth_update_ma(struct fs_eth *eth, int ma)
|
||||
eth->macaddr[ma][i++] = eth->regs[reg] >> 8;
|
||||
eth->macaddr[ma][i++] = eth->regs[reg] >> 16;
|
||||
eth->macaddr[ma][i++] = eth->regs[reg] >> 24;
|
||||
eth->macaddr[ma][i++] = eth->regs[reg + 4];
|
||||
eth->macaddr[ma][i++] = eth->regs[reg + 4] >> 8;
|
||||
eth->macaddr[ma][i++] = eth->regs[reg + 1];
|
||||
eth->macaddr[ma][i++] = eth->regs[reg + 1] >> 8;
|
||||
|
||||
D(printf("set mac%d=%x.%x.%x.%x.%x.%x\n", ma,
|
||||
eth->macaddr[ma][0], eth->macaddr[ma][1],
|
||||
@@ -554,6 +554,16 @@ static CPUWriteMemoryFunc *eth_write[] = {
|
||||
ð_writel,
|
||||
};
|
||||
|
||||
static void eth_cleanup(VLANClientState *vc)
|
||||
{
|
||||
struct fs_eth *eth = vc->opaque;
|
||||
|
||||
cpu_unregister_io_memory(eth->ethregs);
|
||||
|
||||
qemu_free(eth->dma_out);
|
||||
qemu_free(eth);
|
||||
}
|
||||
|
||||
void *etraxfs_eth_init(NICInfo *nd, CPUState *env,
|
||||
qemu_irq *irq, target_phys_addr_t base, int phyaddr)
|
||||
{
|
||||
@@ -584,8 +594,9 @@ void *etraxfs_eth_init(NICInfo *nd, CPUState *env,
|
||||
eth->ethregs = cpu_register_io_memory(0, eth_read, eth_write, eth);
|
||||
cpu_register_physical_memory (base, 0x5c, eth->ethregs);
|
||||
|
||||
eth->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
eth_receive, eth_can_receive, eth);
|
||||
eth->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
eth_receive, eth_can_receive,
|
||||
eth_cleanup, eth);
|
||||
eth->vc->opaque = eth;
|
||||
eth->vc->link_status_changed = eth_set_link;
|
||||
|
||||
|
@@ -411,7 +411,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
|
||||
(timer->config & HPET_TN_SETVAL))
|
||||
timer->cmp = (timer->cmp & 0xffffffff00000000ULL)
|
||||
| new_val;
|
||||
else {
|
||||
if (timer_is_periodic(timer)) {
|
||||
/*
|
||||
* FIXME: Clamp period to reasonable min value?
|
||||
* Clamp period to reasonable max value
|
||||
@@ -554,6 +554,7 @@ static void hpet_reset(void *opaque) {
|
||||
/* 64-bit main counter; 3 timers supported; LegacyReplacementRoute. */
|
||||
s->capability = 0x8086a201ULL;
|
||||
s->capability |= ((HPET_CLK_PERIOD) << 32);
|
||||
s->config = 0ULL;
|
||||
if (count > 0)
|
||||
/* we don't enable pit when hpet_reset is first called (by hpet_init)
|
||||
* because hpet is taking over for pit here. On subsequent invocations,
|
||||
|
4
hw/hw.h
4
hw/hw.h
@@ -37,6 +37,7 @@ QEMUFile *qemu_fopen(const char *filename, const char *mode);
|
||||
QEMUFile *qemu_fopen_socket(int fd);
|
||||
QEMUFile *qemu_popen(FILE *popen_file, const char *mode);
|
||||
QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
|
||||
int qemu_popen_fd(QEMUFile *f);
|
||||
void qemu_fflush(QEMUFile *f);
|
||||
int qemu_fclose(QEMUFile *f);
|
||||
void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size);
|
||||
@@ -67,6 +68,7 @@ unsigned int qemu_get_be32(QEMUFile *f);
|
||||
uint64_t qemu_get_be64(QEMUFile *f);
|
||||
int qemu_file_rate_limit(QEMUFile *f);
|
||||
int qemu_file_has_error(QEMUFile *f);
|
||||
void qemu_file_set_error(QEMUFile *f);
|
||||
|
||||
/* Try to send any outstanding data. This function is useful when output is
|
||||
* halted due to rate limiting or EAGAIN errors occur as it can be used to
|
||||
@@ -238,6 +240,8 @@ int register_savevm_live(const char *idstr,
|
||||
LoadStateHandler *load_state,
|
||||
void *opaque);
|
||||
|
||||
void unregister_savevm(const char *idstr, void *opaque);
|
||||
|
||||
typedef void QEMUResetHandler(void *opaque);
|
||||
|
||||
void qemu_register_reset(QEMUResetHandler *func, void *opaque);
|
||||
|
26
hw/ide.c
26
hw/ide.c
@@ -359,6 +359,7 @@
|
||||
#define ASC_INCOMPATIBLE_FORMAT 0x30
|
||||
#define ASC_MEDIUM_NOT_PRESENT 0x3a
|
||||
#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39
|
||||
#define ASC_MEDIA_REMOVAL_PREVENTED 0x53
|
||||
|
||||
#define CFA_NO_ERROR 0x00
|
||||
#define CFA_MISC_ERROR 0x09
|
||||
@@ -1818,18 +1819,27 @@ static void ide_atapi_cmd(IDEState *s)
|
||||
break;
|
||||
case GPCMD_START_STOP_UNIT:
|
||||
{
|
||||
int start, eject;
|
||||
int start, eject, err = 0;
|
||||
start = packet[4] & 1;
|
||||
eject = (packet[4] >> 1) & 1;
|
||||
|
||||
if (eject && !start) {
|
||||
/* eject the disk */
|
||||
bdrv_eject(s->bs, 1);
|
||||
} else if (eject && start) {
|
||||
/* close the tray */
|
||||
bdrv_eject(s->bs, 0);
|
||||
if (eject) {
|
||||
err = bdrv_eject(s->bs, !start);
|
||||
}
|
||||
|
||||
switch (err) {
|
||||
case 0:
|
||||
ide_atapi_cmd_ok(s);
|
||||
break;
|
||||
case -EBUSY:
|
||||
ide_atapi_cmd_error(s, SENSE_NOT_READY,
|
||||
ASC_MEDIA_REMOVAL_PREVENTED);
|
||||
break;
|
||||
default:
|
||||
ide_atapi_cmd_error(s, SENSE_NOT_READY,
|
||||
ASC_MEDIUM_NOT_PRESENT);
|
||||
break;
|
||||
}
|
||||
ide_atapi_cmd_ok(s);
|
||||
}
|
||||
break;
|
||||
case GPCMD_MECHANISM_STATUS:
|
||||
|
@@ -262,6 +262,7 @@ typedef struct {
|
||||
uint32_t sbc;
|
||||
uint32_t csbc;
|
||||
uint32_t scratch[18]; /* SCRATCHA-SCRATCHR */
|
||||
uint8_t sbr;
|
||||
|
||||
/* Script ram is stored as 32-bit words in host byteorder. */
|
||||
uint32_t script_ram[2048];
|
||||
@@ -330,6 +331,7 @@ static void lsi_soft_reset(LSIState *s)
|
||||
s->ia = 0;
|
||||
s->sbc = 0;
|
||||
s->csbc = 0;
|
||||
s->sbr = 0;
|
||||
}
|
||||
|
||||
static int lsi_dma_40bit(LSIState *s)
|
||||
@@ -1369,6 +1371,8 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
|
||||
CASE_GET_REG32(dsa, 0x10)
|
||||
case 0x14: /* ISTAT0 */
|
||||
return s->istat0;
|
||||
case 0x15: /* ISTAT1 */
|
||||
return s->istat1;
|
||||
case 0x16: /* MBOX0 */
|
||||
return s->mbox0;
|
||||
case 0x17: /* MBOX1 */
|
||||
@@ -1398,6 +1402,7 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
|
||||
CASE_GET_REG24(dbc, 0x24)
|
||||
case 0x27: /* DCMD */
|
||||
return s->dcmd;
|
||||
CASE_GET_REG32(dnad, 0x28)
|
||||
CASE_GET_REG32(dsp, 0x2c)
|
||||
CASE_GET_REG32(dsps, 0x30)
|
||||
CASE_GET_REG32(scratch[0], 0x34)
|
||||
@@ -1405,6 +1410,8 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
|
||||
return s->dmode;
|
||||
case 0x39: /* DIEN */
|
||||
return s->dien;
|
||||
case 0x3a: /* SBR */
|
||||
return s->sbr;
|
||||
case 0x3b: /* DCNTL */
|
||||
return s->dcntl;
|
||||
case 0x40: /* SIEN0 */
|
||||
@@ -1484,6 +1491,11 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
|
||||
|
||||
static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
|
||||
{
|
||||
#define CASE_SET_REG24(name, addr) \
|
||||
case addr : s->name &= 0xffffff00; s->name |= val; break; \
|
||||
case addr + 1: s->name &= 0xffff00ff; s->name |= val << 8; break; \
|
||||
case addr + 2: s->name &= 0xff00ffff; s->name |= val << 16; break;
|
||||
|
||||
#define CASE_SET_REG32(name, addr) \
|
||||
case addr : s->name &= 0xffffff00; s->name |= val; break; \
|
||||
case addr + 1: s->name &= 0xffff00ff; s->name |= val << 8; break; \
|
||||
@@ -1588,6 +1600,8 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
|
||||
}
|
||||
s->ctest5 = val;
|
||||
break;
|
||||
CASE_SET_REG24(dbc, 0x24)
|
||||
CASE_SET_REG32(dnad, 0x28)
|
||||
case 0x2c: /* DSP[0:7] */
|
||||
s->dsp &= 0xffffff00;
|
||||
s->dsp |= val;
|
||||
@@ -1619,6 +1633,9 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
|
||||
s->dien = val;
|
||||
lsi_update_irq(s);
|
||||
break;
|
||||
case 0x3a: /* SBR */
|
||||
s->sbr = val;
|
||||
break;
|
||||
case 0x3b: /* DCNTL */
|
||||
s->dcntl = val & ~(LSI_DCNTL_PFF | LSI_DCNTL_STD);
|
||||
if ((val & LSI_DCNTL_STD) && (s->istat1 & LSI_ISTAT1_SRUN) == 0)
|
||||
@@ -1698,6 +1715,7 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
|
||||
BADF("Unhandled writeb 0x%x = 0x%x\n", offset, val);
|
||||
}
|
||||
}
|
||||
#undef CASE_SET_REG24
|
||||
#undef CASE_SET_REG32
|
||||
}
|
||||
|
||||
|
22
hw/mcf_fec.c
22
hw/mcf_fec.c
@@ -24,6 +24,7 @@ do { printf("mcf_fec: " fmt , ##args); } while (0)
|
||||
|
||||
typedef struct {
|
||||
qemu_irq *irq;
|
||||
int mmio_index;
|
||||
VLANClientState *vc;
|
||||
uint32_t irq_state;
|
||||
uint32_t eir;
|
||||
@@ -441,21 +442,30 @@ static CPUWriteMemoryFunc *mcf_fec_writefn[] = {
|
||||
mcf_fec_write
|
||||
};
|
||||
|
||||
static void mcf_fec_cleanup(VLANClientState *vc)
|
||||
{
|
||||
mcf_fec_state *s = vc->opaque;
|
||||
|
||||
cpu_unregister_io_memory(s->mmio_index);
|
||||
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq)
|
||||
{
|
||||
mcf_fec_state *s;
|
||||
int iomemtype;
|
||||
|
||||
qemu_check_nic_model(nd, "mcf_fec");
|
||||
|
||||
s = (mcf_fec_state *)qemu_mallocz(sizeof(mcf_fec_state));
|
||||
s->irq = irq;
|
||||
iomemtype = cpu_register_io_memory(0, mcf_fec_readfn,
|
||||
mcf_fec_writefn, s);
|
||||
cpu_register_physical_memory(base, 0x400, iomemtype);
|
||||
s->mmio_index = cpu_register_io_memory(0, mcf_fec_readfn,
|
||||
mcf_fec_writefn, s);
|
||||
cpu_register_physical_memory(base, 0x400, s->mmio_index);
|
||||
|
||||
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
mcf_fec_receive, mcf_fec_can_receive, s);
|
||||
s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
mcf_fec_receive, mcf_fec_can_receive,
|
||||
mcf_fec_cleanup, s);
|
||||
memcpy(s->macaddr, nd->macaddr, 6);
|
||||
qemu_format_nic_info_str(s->vc, s->macaddr);
|
||||
}
|
||||
|
23
hw/mipsnet.c
23
hw/mipsnet.c
@@ -33,9 +33,9 @@ typedef struct MIPSnetState {
|
||||
uint32_t intctl;
|
||||
uint8_t rx_buffer[MAX_ETH_FRAME_SIZE];
|
||||
uint8_t tx_buffer[MAX_ETH_FRAME_SIZE];
|
||||
int io_base;
|
||||
qemu_irq irq;
|
||||
VLANClientState *vc;
|
||||
NICInfo *nd;
|
||||
} MIPSnetState;
|
||||
|
||||
static void mipsnet_reset(MIPSnetState *s)
|
||||
@@ -232,6 +232,17 @@ static int mipsnet_load(QEMUFile *f, void *opaque, int version_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mipsnet_cleanup(VLANClientState *vc)
|
||||
{
|
||||
MIPSnetState *s = vc->opaque;
|
||||
|
||||
unregister_savevm("mipsnet", s);
|
||||
|
||||
isa_unassign_ioport(s->io_base, 36);
|
||||
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
|
||||
{
|
||||
MIPSnetState *s;
|
||||
@@ -247,16 +258,18 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
|
||||
register_ioport_write(base, 36, 4, mipsnet_ioport_write, s);
|
||||
register_ioport_read(base, 36, 4, mipsnet_ioport_read, s);
|
||||
|
||||
s->io_base = base;
|
||||
s->irq = irq;
|
||||
s->nd = nd;
|
||||
if (nd && nd->vlan) {
|
||||
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
mipsnet_receive, mipsnet_can_receive, s);
|
||||
s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
mipsnet_receive,
|
||||
mipsnet_can_receive,
|
||||
mipsnet_cleanup, s);
|
||||
} else {
|
||||
s->vc = NULL;
|
||||
}
|
||||
|
||||
qemu_format_nic_info_str(s->vc, s->nd->macaddr);
|
||||
qemu_format_nic_info_str(s->vc, nd->macaddr);
|
||||
|
||||
mipsnet_reset(s);
|
||||
register_savevm("mipsnet", 0, 0, mipsnet_save, mipsnet_load, s);
|
||||
|
@@ -545,6 +545,7 @@ typedef struct mv88w8618_eth_state {
|
||||
uint32_t smir;
|
||||
uint32_t icr;
|
||||
uint32_t imr;
|
||||
int mmio_index;
|
||||
int vlan_header;
|
||||
mv88w8618_tx_desc *tx_queue[2];
|
||||
mv88w8618_rx_desc *rx_queue[4];
|
||||
@@ -705,20 +706,29 @@ static CPUWriteMemoryFunc *mv88w8618_eth_writefn[] = {
|
||||
mv88w8618_eth_write
|
||||
};
|
||||
|
||||
static void eth_cleanup(VLANClientState *vc)
|
||||
{
|
||||
mv88w8618_eth_state *s = vc->opaque;
|
||||
|
||||
cpu_unregister_io_memory(s->mmio_index);
|
||||
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
static void mv88w8618_eth_init(NICInfo *nd, uint32_t base, qemu_irq irq)
|
||||
{
|
||||
mv88w8618_eth_state *s;
|
||||
int iomemtype;
|
||||
|
||||
qemu_check_nic_model(nd, "mv88w8618");
|
||||
|
||||
s = qemu_mallocz(sizeof(mv88w8618_eth_state));
|
||||
s->irq = irq;
|
||||
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
eth_receive, eth_can_receive, s);
|
||||
iomemtype = cpu_register_io_memory(0, mv88w8618_eth_readfn,
|
||||
mv88w8618_eth_writefn, s);
|
||||
cpu_register_physical_memory(base, MP_ETH_SIZE, iomemtype);
|
||||
eth_receive, eth_can_receive,
|
||||
eth_cleanup, s);
|
||||
s->mmio_index = cpu_register_io_memory(0, mv88w8618_eth_readfn,
|
||||
mv88w8618_eth_writefn, s);
|
||||
cpu_register_physical_memory(base, MP_ETH_SIZE, s->mmio_index);
|
||||
}
|
||||
|
||||
/* LCD register offsets */
|
||||
|
33
hw/ne2000.c
33
hw/ne2000.c
@@ -140,6 +140,7 @@ typedef struct NE2000State {
|
||||
uint8_t curpag;
|
||||
uint8_t mult[8]; /* multicast mask array */
|
||||
qemu_irq irq;
|
||||
int isa_io_base;
|
||||
PCIDevice *pci_dev;
|
||||
VLANClientState *vc;
|
||||
uint8_t macaddr[6];
|
||||
@@ -718,6 +719,19 @@ static int ne2000_load(QEMUFile* f,void* opaque,int version_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void isa_ne2000_cleanup(VLANClientState *vc)
|
||||
{
|
||||
NE2000State *s = vc->opaque;
|
||||
|
||||
unregister_savevm("ne2000", s);
|
||||
|
||||
isa_unassign_ioport(s->isa_io_base, 16);
|
||||
isa_unassign_ioport(s->isa_io_base + 0x10, 2);
|
||||
isa_unassign_ioport(s->isa_io_base + 0x1f, 1);
|
||||
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd)
|
||||
{
|
||||
NE2000State *s;
|
||||
@@ -736,13 +750,15 @@ void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd)
|
||||
|
||||
register_ioport_write(base + 0x1f, 1, 1, ne2000_reset_ioport_write, s);
|
||||
register_ioport_read(base + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
|
||||
s->isa_io_base = base;
|
||||
s->irq = irq;
|
||||
memcpy(s->macaddr, nd->macaddr, 6);
|
||||
|
||||
ne2000_reset(s);
|
||||
|
||||
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
ne2000_receive, ne2000_can_receive, s);
|
||||
s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
ne2000_receive, ne2000_can_receive,
|
||||
isa_ne2000_cleanup, s);
|
||||
|
||||
qemu_format_nic_info_str(s->vc, s->macaddr);
|
||||
|
||||
@@ -777,6 +793,13 @@ static void ne2000_map(PCIDevice *pci_dev, int region_num,
|
||||
register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
|
||||
}
|
||||
|
||||
static void ne2000_cleanup(VLANClientState *vc)
|
||||
{
|
||||
NE2000State *s = vc->opaque;
|
||||
|
||||
unregister_savevm("ne2000", s);
|
||||
}
|
||||
|
||||
PCIDevice *pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn)
|
||||
{
|
||||
PCINE2000State *d;
|
||||
@@ -787,6 +810,9 @@ PCIDevice *pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn)
|
||||
"NE2000", sizeof(PCINE2000State),
|
||||
devfn,
|
||||
NULL, NULL);
|
||||
if (!d)
|
||||
return NULL;
|
||||
|
||||
pci_conf = d->dev.config;
|
||||
pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_REALTEK);
|
||||
pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_REALTEK_RTL8029);
|
||||
@@ -802,7 +828,8 @@ PCIDevice *pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn)
|
||||
memcpy(s->macaddr, nd->macaddr, 6);
|
||||
ne2000_reset(s);
|
||||
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
ne2000_receive, ne2000_can_receive, s);
|
||||
ne2000_receive, ne2000_can_receive,
|
||||
ne2000_cleanup, s);
|
||||
|
||||
qemu_format_nic_info_str(s->vc, s->macaddr);
|
||||
|
||||
|
53
hw/pc.c
53
hw/pc.c
@@ -63,6 +63,30 @@ static PITState *pit;
|
||||
static IOAPICState *ioapic;
|
||||
static PCIDevice *i440fx_state;
|
||||
|
||||
typedef struct rom_reset_data {
|
||||
uint8_t *data;
|
||||
target_phys_addr_t addr;
|
||||
unsigned size;
|
||||
} RomResetData;
|
||||
|
||||
static void option_rom_reset(void *_rrd)
|
||||
{
|
||||
RomResetData *rrd = _rrd;
|
||||
|
||||
cpu_physical_memory_write_rom(rrd->addr, rrd->data, rrd->size);
|
||||
}
|
||||
|
||||
static void option_rom_setup_reset(target_phys_addr_t addr, unsigned size)
|
||||
{
|
||||
RomResetData *rrd = qemu_malloc(sizeof *rrd);
|
||||
|
||||
rrd->data = qemu_malloc(size);
|
||||
cpu_physical_memory_read(addr, rrd->data, size);
|
||||
rrd->addr = addr;
|
||||
rrd->size = size;
|
||||
qemu_register_reset(option_rom_reset, rrd);
|
||||
}
|
||||
|
||||
static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
|
||||
{
|
||||
}
|
||||
@@ -447,7 +471,7 @@ static void bochs_bios_init(void)
|
||||
|
||||
/* Generate an initial boot sector which sets state and jump to
|
||||
a specified vector */
|
||||
static void generate_bootsect(uint8_t *option_rom,
|
||||
static void generate_bootsect(target_phys_addr_t option_rom,
|
||||
uint32_t gpr[8], uint16_t segs[6], uint16_t ip)
|
||||
{
|
||||
uint8_t rom[512], *p, *reloc;
|
||||
@@ -521,7 +545,8 @@ static void generate_bootsect(uint8_t *option_rom,
|
||||
sum += rom[i];
|
||||
rom[sizeof(rom) - 1] = -sum;
|
||||
|
||||
memcpy(option_rom, rom, sizeof(rom));
|
||||
cpu_physical_memory_write_rom(option_rom, rom, sizeof(rom));
|
||||
option_rom_setup_reset(option_rom, sizeof (rom));
|
||||
}
|
||||
|
||||
static long get_file_size(FILE *f)
|
||||
@@ -538,10 +563,11 @@ static long get_file_size(FILE *f)
|
||||
return size;
|
||||
}
|
||||
|
||||
static void load_linux(uint8_t *option_rom,
|
||||
static void load_linux(target_phys_addr_t option_rom,
|
||||
const char *kernel_filename,
|
||||
const char *initrd_filename,
|
||||
const char *kernel_cmdline)
|
||||
const char *kernel_cmdline,
|
||||
target_phys_addr_t max_ram_size)
|
||||
{
|
||||
uint16_t protocol;
|
||||
uint32_t gpr[8];
|
||||
@@ -607,8 +633,8 @@ static void load_linux(uint8_t *option_rom,
|
||||
else
|
||||
initrd_max = 0x37ffffff;
|
||||
|
||||
if (initrd_max >= ram_size-ACPI_DATA_SIZE)
|
||||
initrd_max = ram_size-ACPI_DATA_SIZE-1;
|
||||
if (initrd_max >= max_ram_size-ACPI_DATA_SIZE)
|
||||
initrd_max = max_ram_size-ACPI_DATA_SIZE-1;
|
||||
|
||||
/* kernel command line */
|
||||
pstrcpy_targphys(cmdline_addr, 4096, kernel_cmdline);
|
||||
@@ -650,9 +676,6 @@ static void load_linux(uint8_t *option_rom,
|
||||
initrd_size = get_file_size(fi);
|
||||
initrd_addr = (initrd_max-initrd_size) & ~4095;
|
||||
|
||||
fprintf(stderr, "qemu: loading initrd (%#x bytes) at 0x" TARGET_FMT_plx
|
||||
"\n", initrd_size, initrd_addr);
|
||||
|
||||
if (!fread_targphys_ok(initrd_addr, initrd_size, fi)) {
|
||||
fprintf(stderr, "qemu: read error on initial ram disk '%s'\n",
|
||||
initrd_filename);
|
||||
@@ -689,6 +712,12 @@ static void load_linux(uint8_t *option_rom,
|
||||
memset(gpr, 0, sizeof gpr);
|
||||
gpr[4] = cmdline_addr-real_addr-16; /* SP (-16 is paranoia) */
|
||||
|
||||
option_rom_setup_reset(real_addr, setup_size);
|
||||
option_rom_setup_reset(prot_addr, kernel_size);
|
||||
option_rom_setup_reset(cmdline_addr, cmdline_size);
|
||||
if (initrd_filename)
|
||||
option_rom_setup_reset(initrd_addr, initrd_size);
|
||||
|
||||
generate_bootsect(option_rom, gpr, seg, 0);
|
||||
}
|
||||
|
||||
@@ -896,10 +925,10 @@ vga_bios_error:
|
||||
offset = 0;
|
||||
if (linux_boot) {
|
||||
option_rom_offset = qemu_ram_alloc(TARGET_PAGE_SIZE);
|
||||
load_linux(phys_ram_base + option_rom_offset,
|
||||
kernel_filename, initrd_filename, kernel_cmdline);
|
||||
cpu_register_physical_memory(0xd0000, TARGET_PAGE_SIZE,
|
||||
option_rom_offset | IO_MEM_ROM);
|
||||
option_rom_offset);
|
||||
load_linux(0xd0000,
|
||||
kernel_filename, initrd_filename, kernel_cmdline, below_4g_mem_size);
|
||||
offset = TARGET_PAGE_SIZE;
|
||||
}
|
||||
|
||||
|
@@ -37,10 +37,10 @@ static PCIDevice *qemu_pci_hot_add_nic(PCIBus *pci_bus, const char *opts)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = net_client_init ("nic", opts);
|
||||
if (ret < 0 || !nd_table[ret].model)
|
||||
ret = net_client_init("nic", opts);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
return pci_nic_init (pci_bus, &nd_table[ret], -1, "rtl8139");
|
||||
return pci_nic_init(pci_bus, &nd_table[ret], -1, "rtl8139");
|
||||
}
|
||||
|
||||
void drive_hot_add(const char *pci_addr, const char *opts)
|
||||
@@ -95,19 +95,22 @@ static PCIDevice *qemu_pci_hot_add_storage(PCIBus *pci_bus, const char *opts)
|
||||
type = IF_SCSI;
|
||||
else if (!strcmp(buf, "virtio")) {
|
||||
type = IF_VIRTIO;
|
||||
} else {
|
||||
term_printf("type %s not a hotpluggable PCI device.\n", buf);
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
term_printf("no if= specified\n");
|
||||
return NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (get_param_value(buf, sizeof(buf), "file", opts)) {
|
||||
drive_idx = add_init_drive(opts);
|
||||
if (drive_idx < 0)
|
||||
return NULL;
|
||||
goto out;
|
||||
} else if (type == IF_VIRTIO) {
|
||||
term_printf("virtio requires a backing file/device.\n");
|
||||
return NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
@@ -120,10 +123,9 @@ static PCIDevice *qemu_pci_hot_add_storage(PCIBus *pci_bus, const char *opts)
|
||||
case IF_VIRTIO:
|
||||
opaque = virtio_blk_init (pci_bus, drives_table[drive_idx].bdrv);
|
||||
break;
|
||||
default:
|
||||
term_printf ("type %s not a hotpluggable PCI device.\n", buf);
|
||||
}
|
||||
|
||||
out:
|
||||
return opaque;
|
||||
}
|
||||
|
||||
|
4
hw/pci.c
4
hw/pci.c
@@ -494,6 +494,8 @@ void pci_default_write_config(PCIDevice *d,
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
case 0x08:
|
||||
case 0x09:
|
||||
case 0x0a:
|
||||
@@ -517,6 +519,8 @@ void pci_default_write_config(PCIDevice *d,
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
case 0x08:
|
||||
case 0x09:
|
||||
case 0x0a:
|
||||
|
60
hw/pcnet.c
60
hw/pcnet.c
@@ -75,6 +75,7 @@ struct PCNetState_st {
|
||||
uint8_t buffer[4096];
|
||||
int tx_busy;
|
||||
qemu_irq irq;
|
||||
qemu_irq *reset_irq;
|
||||
void (*phys_mem_read)(void *dma_opaque, target_phys_addr_t addr,
|
||||
uint8_t *buf, int len, int do_bswap);
|
||||
void (*phys_mem_write)(void *dma_opaque, target_phys_addr_t addr,
|
||||
@@ -1929,7 +1930,15 @@ static int pcnet_load(QEMUFile *f, void *opaque, int version_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pcnet_common_init(PCNetState *d, NICInfo *nd)
|
||||
static void pcnet_common_cleanup(PCNetState *d)
|
||||
{
|
||||
unregister_savevm("pcnet", d);
|
||||
|
||||
qemu_del_timer(d->poll_timer);
|
||||
qemu_free_timer(d->poll_timer);
|
||||
}
|
||||
|
||||
static void pcnet_common_init(PCNetState *d, NICInfo *nd, NetCleanup *cleanup)
|
||||
{
|
||||
d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d);
|
||||
|
||||
@@ -1937,7 +1946,8 @@ static void pcnet_common_init(PCNetState *d, NICInfo *nd)
|
||||
|
||||
if (nd && nd->vlan) {
|
||||
d->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
pcnet_receive, pcnet_can_receive, d);
|
||||
pcnet_receive, pcnet_can_receive,
|
||||
cleanup, d);
|
||||
|
||||
qemu_format_nic_info_str(d->vc, d->nd->macaddr);
|
||||
} else {
|
||||
@@ -1985,6 +1995,22 @@ static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr,
|
||||
cpu_physical_memory_read(addr, buf, len);
|
||||
}
|
||||
|
||||
static void pci_pcnet_cleanup(VLANClientState *vc)
|
||||
{
|
||||
PCNetState *d = vc->opaque;
|
||||
|
||||
pcnet_common_cleanup(d);
|
||||
}
|
||||
|
||||
static int pci_pcnet_uninit(PCIDevice *dev)
|
||||
{
|
||||
PCNetState *d = (PCNetState *)dev;
|
||||
|
||||
cpu_unregister_io_memory(d->mmio_index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PCIDevice *pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn)
|
||||
{
|
||||
PCNetState *d;
|
||||
@@ -1997,6 +2023,10 @@ PCIDevice *pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn)
|
||||
|
||||
d = (PCNetState *)pci_register_device(bus, "PCNet", sizeof(PCNetState),
|
||||
devfn, NULL, NULL);
|
||||
if (!d)
|
||||
return NULL;
|
||||
|
||||
d->dev.unregister = pci_pcnet_uninit;
|
||||
|
||||
pci_conf = d->dev.config;
|
||||
|
||||
@@ -2031,7 +2061,8 @@ PCIDevice *pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn)
|
||||
d->phys_mem_write = pci_physical_memory_write;
|
||||
d->pci_dev = &d->dev;
|
||||
|
||||
pcnet_common_init(d, nd);
|
||||
pcnet_common_init(d, nd, pci_pcnet_cleanup);
|
||||
|
||||
return (PCIDevice *)d;
|
||||
}
|
||||
|
||||
@@ -2081,29 +2112,42 @@ static CPUWriteMemoryFunc *lance_mem_write[3] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void lance_cleanup(VLANClientState *vc)
|
||||
{
|
||||
PCNetState *d = vc->opaque;
|
||||
|
||||
pcnet_common_cleanup(d);
|
||||
|
||||
qemu_free_irqs(d->reset_irq);
|
||||
|
||||
cpu_unregister_io_memory(d->mmio_index);
|
||||
|
||||
qemu_free(d);
|
||||
}
|
||||
|
||||
void lance_init(NICInfo *nd, target_phys_addr_t leaddr, void *dma_opaque,
|
||||
qemu_irq irq, qemu_irq *reset)
|
||||
{
|
||||
PCNetState *d;
|
||||
int lance_io_memory;
|
||||
|
||||
qemu_check_nic_model(nd, "lance");
|
||||
|
||||
d = qemu_mallocz(sizeof(PCNetState));
|
||||
|
||||
lance_io_memory =
|
||||
d->mmio_index =
|
||||
cpu_register_io_memory(0, lance_mem_read, lance_mem_write, d);
|
||||
|
||||
d->dma_opaque = dma_opaque;
|
||||
|
||||
*reset = *qemu_allocate_irqs(parent_lance_reset, d, 1);
|
||||
d->reset_irq = qemu_allocate_irqs(parent_lance_reset, d, 1);
|
||||
*reset = *d->reset_irq;
|
||||
|
||||
cpu_register_physical_memory(leaddr, 4, lance_io_memory);
|
||||
cpu_register_physical_memory(leaddr, 4, d->mmio_index);
|
||||
|
||||
d->irq = irq;
|
||||
d->phys_mem_read = ledma_memory_read;
|
||||
d->phys_mem_write = ledma_memory_write;
|
||||
|
||||
pcnet_common_init(d, nd);
|
||||
pcnet_common_init(d, nd, lance_cleanup);
|
||||
}
|
||||
#endif /* TARGET_SPARC */
|
||||
|
38
hw/ps2.c
38
hw/ps2.c
@@ -488,9 +488,8 @@ void ps2_write_mouse(void *opaque, int val)
|
||||
}
|
||||
}
|
||||
|
||||
static void ps2_reset(void *opaque)
|
||||
static void ps2_common_reset(PS2State *s)
|
||||
{
|
||||
PS2State *s = (PS2State *)opaque;
|
||||
PS2Queue *q;
|
||||
s->write_cmd = -1;
|
||||
q = &s->queue;
|
||||
@@ -500,6 +499,33 @@ static void ps2_reset(void *opaque)
|
||||
s->update_irq(s->update_arg, 0);
|
||||
}
|
||||
|
||||
static void ps2_kbd_reset(void *opaque)
|
||||
{
|
||||
PS2KbdState *s = (PS2KbdState *) opaque;
|
||||
|
||||
ps2_common_reset(&s->common);
|
||||
s->scan_enabled = 0;
|
||||
s->translate = 0;
|
||||
s->scancode_set = 0;
|
||||
}
|
||||
|
||||
static void ps2_mouse_reset(void *opaque)
|
||||
{
|
||||
PS2MouseState *s = (PS2MouseState *) opaque;
|
||||
|
||||
ps2_common_reset(&s->common);
|
||||
s->mouse_status = 0;
|
||||
s->mouse_resolution = 0;
|
||||
s->mouse_sample_rate = 0;
|
||||
s->mouse_wrap = 0;
|
||||
s->mouse_type = 0;
|
||||
s->mouse_detect_state = 0;
|
||||
s->mouse_dx = 0;
|
||||
s->mouse_dy = 0;
|
||||
s->mouse_dz = 0;
|
||||
s->mouse_buttons = 0;
|
||||
}
|
||||
|
||||
static void ps2_common_save (QEMUFile *f, PS2State *s)
|
||||
{
|
||||
qemu_put_be32 (f, s->write_cmd);
|
||||
@@ -590,10 +616,10 @@ void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
|
||||
s->common.update_irq = update_irq;
|
||||
s->common.update_arg = update_arg;
|
||||
s->scancode_set = 2;
|
||||
ps2_reset(&s->common);
|
||||
ps2_kbd_reset(s);
|
||||
register_savevm("ps2kbd", 0, 3, ps2_kbd_save, ps2_kbd_load, s);
|
||||
qemu_add_kbd_event_handler(ps2_put_keycode, s);
|
||||
qemu_register_reset(ps2_reset, &s->common);
|
||||
qemu_register_reset(ps2_kbd_reset, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -603,9 +629,9 @@ void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
|
||||
|
||||
s->common.update_irq = update_irq;
|
||||
s->common.update_arg = update_arg;
|
||||
ps2_reset(&s->common);
|
||||
ps2_mouse_reset(s);
|
||||
register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s);
|
||||
qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
|
||||
qemu_register_reset(ps2_reset, &s->common);
|
||||
qemu_register_reset(ps2_mouse_reset, s);
|
||||
return s;
|
||||
}
|
||||
|
18
hw/r2d.c
18
hw/r2d.c
@@ -37,6 +37,9 @@
|
||||
|
||||
#define SM501_VRAM_SIZE 0x800000
|
||||
|
||||
/* CONFIG_BOOT_LINK_OFFSET of Linux kernel */
|
||||
#define LINUX_LOAD_OFFSET 0x800000
|
||||
|
||||
#define PA_IRLMSK 0x00
|
||||
#define PA_POWOFF 0x30
|
||||
#define PA_VERREG 0x32
|
||||
@@ -233,20 +236,27 @@ static void r2d_init(ram_addr_t ram_size, int vga_ram_size,
|
||||
pci_nic_init(pci, &nd_table[i], (i==0)? 2<<3: -1, "rtl8139");
|
||||
|
||||
/* Todo: register on board registers */
|
||||
{
|
||||
if (kernel_filename) {
|
||||
int kernel_size;
|
||||
/* initialization which should be done by firmware */
|
||||
stl_phys(SH7750_BCR1, 1<<3); /* cs3 SDRAM */
|
||||
stw_phys(SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */
|
||||
|
||||
kernel_size = load_image(kernel_filename, phys_ram_base);
|
||||
if (kernel_cmdline) {
|
||||
kernel_size = load_image_targphys(kernel_filename,
|
||||
SDRAM_BASE + LINUX_LOAD_OFFSET,
|
||||
SDRAM_SIZE - LINUX_LOAD_OFFSET);
|
||||
env->pc = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000;
|
||||
pstrcpy_targphys(SDRAM_BASE + 0x10100, 256, kernel_cmdline);
|
||||
} else {
|
||||
kernel_size = load_image_targphys(kernel_filename, SDRAM_BASE, SDRAM_SIZE);
|
||||
env->pc = SDRAM_BASE | 0xa0000000; /* Start from P2 area */
|
||||
}
|
||||
|
||||
if (kernel_size < 0) {
|
||||
fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
env->pc = SDRAM_BASE | 0xa0000000; /* Start from P2 area */
|
||||
}
|
||||
}
|
||||
|
||||
|
35
hw/rtl8139.c
35
hw/rtl8139.c
@@ -3414,6 +3414,33 @@ static void rtl8139_timer(void *opaque)
|
||||
}
|
||||
#endif /* RTL8139_ONBOARD_TIMER */
|
||||
|
||||
static void rtl8139_cleanup(VLANClientState *vc)
|
||||
{
|
||||
RTL8139State *s = vc->opaque;
|
||||
|
||||
if (s->cplus_txbuffer) {
|
||||
qemu_free(s->cplus_txbuffer);
|
||||
s->cplus_txbuffer = NULL;
|
||||
}
|
||||
|
||||
#ifdef RTL8139_ONBOARD_TIMER
|
||||
qemu_del_timer(s->timer);
|
||||
qemu_free_timer(s->timer);
|
||||
#endif
|
||||
|
||||
unregister_savevm("rtl8139", s);
|
||||
}
|
||||
|
||||
static int pci_rtl8139_uninit(PCIDevice *dev)
|
||||
{
|
||||
PCIRTL8139State *d = (PCIRTL8139State *)dev;
|
||||
RTL8139State *s = &d->rtl8139;
|
||||
|
||||
cpu_unregister_io_memory(s->rtl8139_mmio_io_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PCIDevice *pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn)
|
||||
{
|
||||
PCIRTL8139State *d;
|
||||
@@ -3424,6 +3451,11 @@ PCIDevice *pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn)
|
||||
"RTL8139", sizeof(PCIRTL8139State),
|
||||
devfn,
|
||||
NULL, NULL);
|
||||
if (!d)
|
||||
return NULL;
|
||||
|
||||
d->dev.unregister = pci_rtl8139_uninit;
|
||||
|
||||
pci_conf = d->dev.config;
|
||||
pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_REALTEK);
|
||||
pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_REALTEK_8139);
|
||||
@@ -3450,7 +3482,8 @@ PCIDevice *pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn)
|
||||
memcpy(s->macaddr, nd->macaddr, 6);
|
||||
rtl8139_reset(s);
|
||||
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
rtl8139_receive, rtl8139_can_receive, s);
|
||||
rtl8139_receive, rtl8139_can_receive,
|
||||
rtl8139_cleanup, s);
|
||||
|
||||
qemu_format_nic_info_str(s->vc, s->macaddr);
|
||||
|
||||
|
@@ -586,6 +586,8 @@ static int serial_can_receive(SerialState *s)
|
||||
static void serial_receive_break(SerialState *s)
|
||||
{
|
||||
s->rbr = 0;
|
||||
/* When the LSR_DR is set a null byte is pushed into the fifo */
|
||||
fifo_put(s, RECV_FIFO, '\0');
|
||||
s->lsr |= UART_LSR_BI | UART_LSR_DR;
|
||||
serial_update_irq(s);
|
||||
}
|
||||
|
@@ -42,6 +42,7 @@ typedef struct {
|
||||
uint8_t int_level;
|
||||
uint8_t int_mask;
|
||||
uint8_t macaddr[6];
|
||||
int mmio_index;
|
||||
} smc91c111_state;
|
||||
|
||||
#define RCR_SOFT_RST 0x8000
|
||||
@@ -690,24 +691,32 @@ static CPUWriteMemoryFunc *smc91c111_writefn[] = {
|
||||
smc91c111_writel
|
||||
};
|
||||
|
||||
static void smc91c111_cleanup(VLANClientState *vc)
|
||||
{
|
||||
smc91c111_state *s = vc->opaque;
|
||||
|
||||
cpu_unregister_io_memory(s->mmio_index);
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq irq)
|
||||
{
|
||||
smc91c111_state *s;
|
||||
int iomemtype;
|
||||
|
||||
qemu_check_nic_model(nd, "smc91c111");
|
||||
|
||||
s = (smc91c111_state *)qemu_mallocz(sizeof(smc91c111_state));
|
||||
iomemtype = cpu_register_io_memory(0, smc91c111_readfn,
|
||||
smc91c111_writefn, s);
|
||||
cpu_register_physical_memory(base, 16, iomemtype);
|
||||
s->mmio_index = cpu_register_io_memory(0, smc91c111_readfn,
|
||||
smc91c111_writefn, s);
|
||||
cpu_register_physical_memory(base, 16, s->mmio_index);
|
||||
s->irq = irq;
|
||||
memcpy(s->macaddr, nd->macaddr, 6);
|
||||
|
||||
smc91c111_reset(s);
|
||||
|
||||
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
smc91c111_receive, smc91c111_can_receive, s);
|
||||
smc91c111_receive, smc91c111_can_receive,
|
||||
smc91c111_cleanup, s);
|
||||
qemu_format_nic_info_str(s->vc, s->macaddr);
|
||||
/* ??? Save/restore. */
|
||||
}
|
||||
|
@@ -69,6 +69,7 @@ typedef struct {
|
||||
VLANClientState *vc;
|
||||
qemu_irq irq;
|
||||
uint8_t macaddr[6];
|
||||
int mmio_index;
|
||||
} stellaris_enet_state;
|
||||
|
||||
static void stellaris_enet_update(stellaris_enet_state *s)
|
||||
@@ -384,23 +385,35 @@ static int stellaris_enet_load(QEMUFile *f, void *opaque, int version_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void stellaris_enet_cleanup(VLANClientState *vc)
|
||||
{
|
||||
stellaris_enet_state *s = vc->opaque;
|
||||
|
||||
unregister_savevm("stellaris_enet", s);
|
||||
|
||||
cpu_unregister_io_memory(s->mmio_index);
|
||||
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
void stellaris_enet_init(NICInfo *nd, uint32_t base, qemu_irq irq)
|
||||
{
|
||||
stellaris_enet_state *s;
|
||||
int iomemtype;
|
||||
|
||||
qemu_check_nic_model(nd, "stellaris");
|
||||
|
||||
s = (stellaris_enet_state *)qemu_mallocz(sizeof(stellaris_enet_state));
|
||||
iomemtype = cpu_register_io_memory(0, stellaris_enet_readfn,
|
||||
stellaris_enet_writefn, s);
|
||||
cpu_register_physical_memory(base, 0x00001000, iomemtype);
|
||||
s->mmio_index = cpu_register_io_memory(0, stellaris_enet_readfn,
|
||||
stellaris_enet_writefn, s);
|
||||
cpu_register_physical_memory(base, 0x00001000, s->mmio_index);
|
||||
s->irq = irq;
|
||||
memcpy(s->macaddr, nd->macaddr, 6);
|
||||
|
||||
if (nd->vlan) {
|
||||
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
stellaris_enet_receive, stellaris_enet_can_receive, s);
|
||||
stellaris_enet_receive,
|
||||
stellaris_enet_can_receive,
|
||||
stellaris_enet_cleanup, s);
|
||||
qemu_format_nic_info_str(s->vc, s->macaddr);
|
||||
}
|
||||
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include "usb.h"
|
||||
#include "block.h"
|
||||
#include "scsi-disk.h"
|
||||
#include "console.h"
|
||||
|
||||
//#define DEBUG_MSD
|
||||
|
||||
@@ -513,7 +514,7 @@ static void usb_msd_handle_destroy(USBDevice *dev)
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
USBDevice *usb_msd_init(const char *filename)
|
||||
USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs)
|
||||
{
|
||||
MSDState *s;
|
||||
BlockDriverState *bdrv;
|
||||
@@ -552,9 +553,8 @@ USBDevice *usb_msd_init(const char *filename)
|
||||
bdrv = bdrv_new("usb");
|
||||
if (bdrv_open2(bdrv, filename, 0, drv) < 0)
|
||||
goto fail;
|
||||
if (qemu_key_check(bdrv, filename))
|
||||
goto fail;
|
||||
s->bs = bdrv;
|
||||
*pbs = bdrv;
|
||||
|
||||
s->dev.speed = USB_SPEED_FULL;
|
||||
s->dev.handle_packet = usb_generic_handle_packet;
|
||||
|
16
hw/usb-net.c
16
hw/usb-net.c
@@ -1415,14 +1415,20 @@ static int usbnet_can_receive(void *opaque)
|
||||
return !s->in_len;
|
||||
}
|
||||
|
||||
static void usbnet_cleanup(VLANClientState *vc)
|
||||
{
|
||||
USBNetState *s = vc->opaque;
|
||||
|
||||
rndis_clear_responsequeue(s);
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
static void usb_net_handle_destroy(USBDevice *dev)
|
||||
{
|
||||
USBNetState *s = (USBNetState *) dev;
|
||||
|
||||
/* TODO: remove the nd_table[] entry */
|
||||
qemu_del_vlan_client(s->vc);
|
||||
rndis_clear_responsequeue(s);
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
USBDevice *usb_net_init(NICInfo *nd)
|
||||
@@ -1451,8 +1457,10 @@ USBDevice *usb_net_init(NICInfo *nd)
|
||||
|
||||
pstrcpy(s->dev.devname, sizeof(s->dev.devname),
|
||||
"QEMU USB Network Interface");
|
||||
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
usbnet_receive, usbnet_can_receive, s);
|
||||
s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
usbnet_receive,
|
||||
usbnet_can_receive,
|
||||
usbnet_cleanup, s);
|
||||
|
||||
qemu_format_nic_info_str(s->vc, s->mac);
|
||||
|
||||
|
5
hw/usb.h
5
hw/usb.h
@@ -21,6 +21,9 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "block.h"
|
||||
|
||||
#define USB_TOKEN_SETUP 0x2d
|
||||
#define USB_TOKEN_IN 0x69 /* device -> host */
|
||||
#define USB_TOKEN_OUT 0xe1 /* host -> device */
|
||||
@@ -250,7 +253,7 @@ USBDevice *usb_keyboard_init(void);
|
||||
void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *));
|
||||
|
||||
/* usb-msd.c */
|
||||
USBDevice *usb_msd_init(const char *filename);
|
||||
USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs);
|
||||
|
||||
/* usb-net.c */
|
||||
USBDevice *usb_net_init(NICInfo *nd);
|
||||
|
31
hw/vga.c
31
hw/vga.c
@@ -1616,6 +1616,16 @@ static void vga_draw_graphic(VGAState *s, int full_update)
|
||||
s->double_scan = double_scan;
|
||||
}
|
||||
|
||||
if (shift_control == 0) {
|
||||
if (s->sr[0x01] & 8) {
|
||||
disp_width <<= 1;
|
||||
}
|
||||
} else if (shift_control == 1) {
|
||||
if (s->sr[0x01] & 8) {
|
||||
disp_width <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
depth = s->get_bpp(s);
|
||||
if (s->line_offset != s->last_line_offset ||
|
||||
disp_width != s->last_width ||
|
||||
@@ -1661,7 +1671,6 @@ static void vga_draw_graphic(VGAState *s, int full_update)
|
||||
full_update |= update_palette16(s);
|
||||
if (s->sr[0x01] & 8) {
|
||||
v = VGA_DRAW_LINE4D2;
|
||||
disp_width <<= 1;
|
||||
} else {
|
||||
v = VGA_DRAW_LINE4;
|
||||
}
|
||||
@@ -1670,7 +1679,6 @@ static void vga_draw_graphic(VGAState *s, int full_update)
|
||||
full_update |= update_palette16(s);
|
||||
if (s->sr[0x01] & 8) {
|
||||
v = VGA_DRAW_LINE2D2;
|
||||
disp_width <<= 1;
|
||||
} else {
|
||||
v = VGA_DRAW_LINE2;
|
||||
}
|
||||
@@ -2482,6 +2490,17 @@ int isa_vga_mm_init(uint8_t *vga_ram_base,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pci_vga_write_config(PCIDevice *d,
|
||||
uint32_t address, uint32_t val, int len)
|
||||
{
|
||||
PCIVGAState *pvs = container_of(d, PCIVGAState, dev);
|
||||
VGAState *s = &pvs->vga_state;
|
||||
|
||||
vga_dirty_log_stop(s);
|
||||
pci_default_write_config(d, address, val, len);
|
||||
vga_dirty_log_start(s);
|
||||
}
|
||||
|
||||
int pci_vga_init(PCIBus *bus, uint8_t *vga_ram_base,
|
||||
unsigned long vga_ram_offset, int vga_ram_size,
|
||||
unsigned long vga_bios_offset, int vga_bios_size)
|
||||
@@ -2492,7 +2511,7 @@ int pci_vga_init(PCIBus *bus, uint8_t *vga_ram_base,
|
||||
|
||||
d = (PCIVGAState *)pci_register_device(bus, "VGA",
|
||||
sizeof(PCIVGAState),
|
||||
-1, NULL, NULL);
|
||||
-1, NULL, pci_vga_write_config);
|
||||
if (!d)
|
||||
return -1;
|
||||
s = &d->vga_state;
|
||||
@@ -2587,8 +2606,9 @@ static void vga_screen_dump_blank(VGAState *s, const char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
unsigned int y, x, w, h;
|
||||
unsigned char blank_sample[3] = { 0, 0, 0 };
|
||||
|
||||
w = s->last_scr_width * sizeof(uint32_t);
|
||||
w = s->last_scr_width;
|
||||
h = s->last_scr_height;
|
||||
|
||||
f = fopen(filename, "wb");
|
||||
@@ -2597,7 +2617,7 @@ static void vga_screen_dump_blank(VGAState *s, const char *filename)
|
||||
fprintf(f, "P6\n%d %d\n%d\n", w, h, 255);
|
||||
for (y = 0; y < h; y++) {
|
||||
for (x = 0; x < w; x++) {
|
||||
fputc(0, f);
|
||||
fwrite(blank_sample, 3, 1, f);
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
@@ -2659,4 +2679,5 @@ static void vga_screen_dump(void *opaque, const char *filename)
|
||||
vga_screen_dump_graphic(s, filename);
|
||||
else
|
||||
vga_screen_dump_text(s, filename);
|
||||
vga_invalidate_display(s);
|
||||
}
|
||||
|
@@ -247,6 +247,7 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
|
||||
|
||||
bdrv_get_geometry(s->bs, &capacity);
|
||||
bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs);
|
||||
memset(&blkcfg, 0, sizeof(blkcfg));
|
||||
stq_raw(&blkcfg.capacity, capacity);
|
||||
stl_raw(&blkcfg.seg_max, 128 - 2);
|
||||
stw_raw(&blkcfg.cylinders, cylinders);
|
||||
|
@@ -113,6 +113,21 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev)
|
||||
return features;
|
||||
}
|
||||
|
||||
static uint32_t virtio_net_bad_features(VirtIODevice *vdev)
|
||||
{
|
||||
uint32_t features = 0;
|
||||
|
||||
/* Linux kernel 2.6.25. It understood MAC (as everyone must),
|
||||
* but also these: */
|
||||
features |= (1 << VIRTIO_NET_F_MAC);
|
||||
features |= (1 << VIRTIO_NET_F_GUEST_CSUM);
|
||||
features |= (1 << VIRTIO_NET_F_GUEST_TSO4);
|
||||
features |= (1 << VIRTIO_NET_F_GUEST_TSO6);
|
||||
features |= (1 << VIRTIO_NET_F_GUEST_ECN);
|
||||
|
||||
return features & virtio_net_get_features(vdev);
|
||||
}
|
||||
|
||||
static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
|
||||
{
|
||||
VirtIONet *n = to_virtio_net(vdev);
|
||||
@@ -228,7 +243,7 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
|
||||
}
|
||||
|
||||
if (elem.out_sg[0].iov_len < sizeof(ctrl) ||
|
||||
elem.out_sg[elem.in_num - 1].iov_len < sizeof(status)) {
|
||||
elem.in_sg[elem.in_num - 1].iov_len < sizeof(status)) {
|
||||
fprintf(stderr, "virtio-net ctrl header not in correct element\n");
|
||||
exit(1);
|
||||
}
|
||||
@@ -323,11 +338,6 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size)
|
||||
if (n->promisc)
|
||||
return 1;
|
||||
|
||||
#ifdef TAP_VNET_HDR
|
||||
if (tap_has_vnet_hdr(n->vc->vlan->first_client))
|
||||
ptr += sizeof(struct virtio_net_hdr);
|
||||
#endif
|
||||
|
||||
if (!memcmp(&ptr[12], vlan, sizeof(vlan))) {
|
||||
int vid = be16_to_cpup((uint16_t *)(ptr + 14)) & 0xfff;
|
||||
if (!(n->vlans[vid >> 5] & (1U << (vid & 0x1f))))
|
||||
@@ -560,6 +570,21 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void virtio_net_cleanup(VLANClientState *vc)
|
||||
{
|
||||
VirtIONet *n = vc->opaque;
|
||||
|
||||
unregister_savevm("virtio-net", n);
|
||||
|
||||
qemu_free(n->mac_table.macs);
|
||||
qemu_free(n->vlans);
|
||||
|
||||
qemu_del_timer(n->tx_timer);
|
||||
qemu_free_timer(n->tx_timer);
|
||||
|
||||
virtio_cleanup(&n->vdev);
|
||||
}
|
||||
|
||||
PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
|
||||
{
|
||||
VirtIONet *n;
|
||||
@@ -580,6 +605,7 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
|
||||
n->vdev.set_config = virtio_net_set_config;
|
||||
n->vdev.get_features = virtio_net_get_features;
|
||||
n->vdev.set_features = virtio_net_set_features;
|
||||
n->vdev.bad_features = virtio_net_bad_features;
|
||||
n->vdev.reset = virtio_net_reset;
|
||||
n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx);
|
||||
n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx);
|
||||
@@ -587,7 +613,9 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
|
||||
memcpy(n->mac, nd->macaddr, ETH_ALEN);
|
||||
n->status = VIRTIO_NET_S_LINK_UP;
|
||||
n->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
|
||||
virtio_net_receive, virtio_net_can_receive, n);
|
||||
virtio_net_receive,
|
||||
virtio_net_can_receive,
|
||||
virtio_net_cleanup, n);
|
||||
n->vc->link_status_changed = virtio_net_set_link_status;
|
||||
|
||||
qemu_format_nic_info_str(n->vc, n->mac);
|
||||
|
23
hw/virtio.c
23
hw/virtio.c
@@ -516,6 +516,13 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
|
||||
|
||||
switch (addr) {
|
||||
case VIRTIO_PCI_GUEST_FEATURES:
|
||||
/* Guest does not negotiate properly? We have to assume nothing. */
|
||||
if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
|
||||
if (vdev->bad_features)
|
||||
val = vdev->bad_features(vdev);
|
||||
else
|
||||
val = 0;
|
||||
}
|
||||
if (vdev->set_features)
|
||||
vdev->set_features(vdev, val);
|
||||
vdev->features = val;
|
||||
@@ -555,7 +562,7 @@ static uint32_t virtio_ioport_read(void *opaque, uint32_t addr)
|
||||
switch (addr) {
|
||||
case VIRTIO_PCI_HOST_FEATURES:
|
||||
ret = vdev->get_features(vdev);
|
||||
ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
|
||||
ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY) | (1 << VIRTIO_F_BAD_FEATURE);
|
||||
break;
|
||||
case VIRTIO_PCI_GUEST_FEATURES:
|
||||
ret = vdev->features;
|
||||
@@ -726,9 +733,10 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
|
||||
|
||||
void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
|
||||
{
|
||||
/* Always notify when queue is empty */
|
||||
if ((vq->inuse || vring_avail_idx(vq) != vq->last_avail_idx) &&
|
||||
(vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT))
|
||||
/* Always notify when queue is empty (when feature acknowledge) */
|
||||
if ((vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT) &&
|
||||
(!(vdev->features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) ||
|
||||
(vq->inuse || vring_avail_idx(vq) != vq->last_avail_idx)))
|
||||
return;
|
||||
|
||||
vdev->isr |= 0x01;
|
||||
@@ -807,6 +815,13 @@ void virtio_load(VirtIODevice *vdev, QEMUFile *f)
|
||||
virtio_update_irq(vdev);
|
||||
}
|
||||
|
||||
void virtio_cleanup(VirtIODevice *vdev)
|
||||
{
|
||||
if (vdev->config)
|
||||
qemu_free(vdev->config);
|
||||
qemu_free(vdev->vq);
|
||||
}
|
||||
|
||||
VirtIODevice *virtio_init_pci(PCIBus *bus, const char *name,
|
||||
uint16_t vendor, uint16_t device,
|
||||
uint16_t subvendor, uint16_t subdevice,
|
||||
|
@@ -32,6 +32,8 @@
|
||||
/* We notify when the ring is completely used, even if the guest is supressing
|
||||
* callbacks */
|
||||
#define VIRTIO_F_NOTIFY_ON_EMPTY 24
|
||||
/* A guest should never accept this. It implies negotiation is broken. */
|
||||
#define VIRTIO_F_BAD_FEATURE 30
|
||||
|
||||
/* from Linux's linux/virtio_ring.h */
|
||||
|
||||
@@ -82,6 +84,7 @@ struct VirtIODevice
|
||||
size_t config_len;
|
||||
void *config;
|
||||
uint32_t (*get_features)(VirtIODevice *vdev);
|
||||
uint32_t (*bad_features)(VirtIODevice *vdev);
|
||||
void (*set_features)(VirtIODevice *vdev, uint32_t val);
|
||||
void (*get_config)(VirtIODevice *vdev, uint8_t *config);
|
||||
void (*set_config)(VirtIODevice *vdev, const uint8_t *config);
|
||||
@@ -114,6 +117,8 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f);
|
||||
|
||||
void virtio_load(VirtIODevice *vdev, QEMUFile *f);
|
||||
|
||||
void virtio_cleanup(VirtIODevice *vdev);
|
||||
|
||||
void virtio_notify_config(VirtIODevice *vdev);
|
||||
|
||||
void virtio_queue_set_notification(VirtQueue *vq, int enable);
|
||||
|
70
kvm-all.c
70
kvm-all.c
@@ -280,14 +280,28 @@ int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int kvm_check_extension(KVMState *s, unsigned int extension)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = kvm_ioctl(s, KVM_CHECK_EXTENSION, extension);
|
||||
if (ret < 0) {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int kvm_init(int smp_cpus)
|
||||
{
|
||||
KVMState *s;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (smp_cpus > 1)
|
||||
if (smp_cpus > 1) {
|
||||
fprintf(stderr, "No SMP KVM support, use '-smp 1'\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s = qemu_mallocz(sizeof(KVMState));
|
||||
|
||||
@@ -325,10 +339,8 @@ int kvm_init(int smp_cpus)
|
||||
* just use a user allocated buffer so we can use phys_ram_base
|
||||
* unmodified. Make sure we have a sufficiently modern version of KVM.
|
||||
*/
|
||||
ret = kvm_ioctl(s, KVM_CHECK_EXTENSION, KVM_CAP_USER_MEMORY);
|
||||
if (ret <= 0) {
|
||||
if (ret == 0)
|
||||
ret = -EINVAL;
|
||||
if (!kvm_check_extension(s, KVM_CAP_USER_MEMORY)) {
|
||||
ret = -EINVAL;
|
||||
fprintf(stderr, "kvm does not support KVM_CAP_USER_MEMORY\n");
|
||||
goto err;
|
||||
}
|
||||
@@ -336,11 +348,8 @@ int kvm_init(int smp_cpus)
|
||||
/* There was a nasty bug in < kvm-80 that prevents memory slots from being
|
||||
* destroyed properly. Since we rely on this capability, refuse to work
|
||||
* with any kernel without this capability. */
|
||||
ret = kvm_ioctl(s, KVM_CHECK_EXTENSION,
|
||||
KVM_CAP_DESTROY_MEMORY_REGION_WORKS);
|
||||
if (ret <= 0) {
|
||||
if (ret == 0)
|
||||
ret = -EINVAL;
|
||||
if (!kvm_check_extension(s, KVM_CAP_DESTROY_MEMORY_REGION_WORKS)) {
|
||||
ret = -EINVAL;
|
||||
|
||||
fprintf(stderr,
|
||||
"KVM kernel module broken (DESTROY_MEMORY_REGION)\n"
|
||||
@@ -348,11 +357,10 @@ int kvm_init(int smp_cpus)
|
||||
goto err;
|
||||
}
|
||||
|
||||
s->coalesced_mmio = 0;
|
||||
#ifdef KVM_CAP_COALESCED_MMIO
|
||||
ret = kvm_ioctl(s, KVM_CHECK_EXTENSION, KVM_CAP_COALESCED_MMIO);
|
||||
if (ret > 0)
|
||||
s->coalesced_mmio = ret;
|
||||
s->coalesced_mmio = kvm_check_extension(s, KVM_CAP_COALESCED_MMIO);
|
||||
#else
|
||||
s->coalesced_mmio = 0;
|
||||
#endif
|
||||
|
||||
ret = kvm_arch_init(s, smp_cpus);
|
||||
@@ -443,14 +451,13 @@ int kvm_cpu_exec(CPUState *env)
|
||||
dprintf("kvm_cpu_exec()\n");
|
||||
|
||||
do {
|
||||
kvm_arch_pre_run(env, run);
|
||||
|
||||
if ((env->interrupt_request & CPU_INTERRUPT_EXIT)) {
|
||||
if (env->exit_request) {
|
||||
dprintf("interrupt exit requested\n");
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
kvm_arch_pre_run(env, run);
|
||||
ret = kvm_vcpu_ioctl(env, KVM_RUN, 0);
|
||||
kvm_arch_post_run(env, run);
|
||||
|
||||
@@ -512,8 +519,8 @@ int kvm_cpu_exec(CPUState *env)
|
||||
}
|
||||
} while (ret > 0);
|
||||
|
||||
if ((env->interrupt_request & CPU_INTERRUPT_EXIT)) {
|
||||
env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
|
||||
if (env->exit_request) {
|
||||
env->exit_request = 0;
|
||||
env->exception_index = EXCP_INTERRUPT;
|
||||
}
|
||||
|
||||
@@ -650,9 +657,26 @@ int kvm_has_sync_mmu(void)
|
||||
#ifdef KVM_CAP_SYNC_MMU
|
||||
KVMState *s = kvm_state;
|
||||
|
||||
if (kvm_ioctl(s, KVM_CHECK_EXTENSION, KVM_CAP_SYNC_MMU) > 0)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
return kvm_check_extension(s, KVM_CAP_SYNC_MMU);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void kvm_setup_guest_memory(void *start, size_t size)
|
||||
{
|
||||
if (!kvm_has_sync_mmu()) {
|
||||
#ifdef MADV_DONTFORK
|
||||
int ret = madvise(start, size, MADV_DONTFORK);
|
||||
|
||||
if (ret) {
|
||||
perror("madvice");
|
||||
exit(1);
|
||||
}
|
||||
#else
|
||||
fprintf(stderr,
|
||||
"Need MADV_DONTFORK in absence of synchronous KVM MMU\n");
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
6
kvm.h
6
kvm.h
@@ -46,6 +46,8 @@ int kvm_log_stop(target_phys_addr_t phys_addr, target_phys_addr_t len);
|
||||
|
||||
int kvm_has_sync_mmu(void);
|
||||
|
||||
void kvm_setup_guest_memory(void *start, size_t size);
|
||||
|
||||
int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);
|
||||
int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);
|
||||
|
||||
@@ -76,4 +78,8 @@ int kvm_arch_init(KVMState *s, int smp_cpus);
|
||||
|
||||
int kvm_arch_init_vcpu(CPUState *env);
|
||||
|
||||
int kvm_check_extension(KVMState *s, unsigned int extension);
|
||||
|
||||
uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
|
||||
int reg);
|
||||
#endif
|
||||
|
7
loader.c
7
loader.c
@@ -90,11 +90,12 @@ int fread_targphys(target_phys_addr_t dst_addr, size_t nbytes, FILE *f)
|
||||
while (nbytes) {
|
||||
want = nbytes > sizeof(buf) ? sizeof(buf) : nbytes;
|
||||
did = fread(buf, 1, want, f);
|
||||
if (did != want) break;
|
||||
|
||||
cpu_physical_memory_write_rom(dst_addr, buf, did);
|
||||
dst_addr += did;
|
||||
nbytes -= did;
|
||||
if (did != want)
|
||||
break;
|
||||
}
|
||||
return dst_addr - dst_begin;
|
||||
}
|
||||
@@ -382,7 +383,7 @@ static void *zalloc(void *x, unsigned items, unsigned size)
|
||||
return (p);
|
||||
}
|
||||
|
||||
static void zfree(void *x, void *addr, unsigned nb)
|
||||
static void zfree(void *x, void *addr)
|
||||
{
|
||||
qemu_free(addr);
|
||||
}
|
||||
@@ -430,7 +431,7 @@ static ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src,
|
||||
}
|
||||
|
||||
s.zalloc = zalloc;
|
||||
s.zfree = (free_func)zfree;
|
||||
s.zfree = zfree;
|
||||
|
||||
r = inflateInit2(&s, -MAX_WBITS);
|
||||
if (r != Z_OK) {
|
||||
|
@@ -108,9 +108,27 @@ err_after_alloc:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void exec_accept_incoming_migration(void *opaque)
|
||||
{
|
||||
QEMUFile *f = opaque;
|
||||
int ret;
|
||||
|
||||
ret = qemu_loadvm_state(f);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "load of migration failed\n");
|
||||
goto err;
|
||||
}
|
||||
qemu_announce_self();
|
||||
dprintf("successfully loaded vm state\n");
|
||||
/* we've successfully migrated, close the fd */
|
||||
qemu_set_fd_handler2(qemu_popen_fd(f), NULL, NULL, NULL, NULL);
|
||||
|
||||
err:
|
||||
qemu_fclose(f);
|
||||
}
|
||||
|
||||
int exec_start_incoming_migration(const char *command)
|
||||
{
|
||||
int ret;
|
||||
QEMUFile *f;
|
||||
|
||||
dprintf("Attempting to start an incoming migration\n");
|
||||
@@ -119,19 +137,10 @@ int exec_start_incoming_migration(const char *command)
|
||||
dprintf("Unable to apply qemu wrapper to popen file\n");
|
||||
return -errno;
|
||||
}
|
||||
vm_stop(0); /* just in case */
|
||||
ret = qemu_loadvm_state(f);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "load of migration failed\n");
|
||||
goto err;
|
||||
}
|
||||
qemu_announce_self();
|
||||
dprintf("successfully loaded vm state\n");
|
||||
vm_start();
|
||||
qemu_fclose(f);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
qemu_fclose(f);
|
||||
return -errno;
|
||||
qemu_set_fd_handler2(qemu_popen_fd(f), NULL,
|
||||
exec_accept_incoming_migration, NULL,
|
||||
(void *)(unsigned long)f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -159,7 +159,6 @@ static void tcp_accept_incoming_migration(void *opaque)
|
||||
goto out;
|
||||
}
|
||||
|
||||
vm_stop(0); /* just in case */
|
||||
ret = qemu_loadvm_state(f);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "load of migration failed\n");
|
||||
@@ -172,8 +171,6 @@ static void tcp_accept_incoming_migration(void *opaque)
|
||||
qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL);
|
||||
close(s);
|
||||
|
||||
vm_start();
|
||||
|
||||
out_fopen:
|
||||
qemu_fclose(f);
|
||||
out:
|
||||
|
19
migration.c
19
migration.c
@@ -168,7 +168,7 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size)
|
||||
|
||||
do {
|
||||
ret = s->write(s, data, size);
|
||||
} while (ret == -1 && ((s->get_error(s)) == EINTR || (s->get_error(s)) == EWOULDBLOCK));
|
||||
} while (ret == -1 && ((s->get_error(s)) == EINTR));
|
||||
|
||||
if (ret == -1)
|
||||
ret = -(s->get_error(s));
|
||||
@@ -212,13 +212,24 @@ void migrate_fd_put_ready(void *opaque)
|
||||
|
||||
dprintf("iterate\n");
|
||||
if (qemu_savevm_state_iterate(s->file) == 1) {
|
||||
int state;
|
||||
int old_vm_running = vm_running;
|
||||
|
||||
dprintf("done iterating\n");
|
||||
vm_stop(0);
|
||||
|
||||
qemu_aio_flush();
|
||||
bdrv_flush_all();
|
||||
qemu_savevm_state_complete(s->file);
|
||||
s->state = MIG_STATE_COMPLETED;
|
||||
if ((qemu_savevm_state_complete(s->file)) < 0) {
|
||||
if (old_vm_running) {
|
||||
vm_start();
|
||||
}
|
||||
state = MIG_STATE_ERROR;
|
||||
} else {
|
||||
state = MIG_STATE_COMPLETED;
|
||||
}
|
||||
migrate_fd_cleanup(s);
|
||||
s->state = state;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,5 +288,7 @@ void migrate_fd_wait_for_unfreeze(void *opaque)
|
||||
int migrate_fd_close(void *opaque)
|
||||
{
|
||||
FdMigrationState *s = opaque;
|
||||
|
||||
qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
|
||||
return s->close(s);
|
||||
}
|
||||
|
47
monitor.c
47
monitor.c
@@ -76,6 +76,8 @@ static uint8_t term_outbuf[1024];
|
||||
static int term_outbuf_index;
|
||||
|
||||
static void monitor_start_input(void);
|
||||
static void monitor_readline(const char *prompt, int is_password,
|
||||
char *buf, int buf_size);
|
||||
|
||||
static CPUState *mon_cpu = NULL;
|
||||
|
||||
@@ -433,7 +435,7 @@ static void do_change_block(const char *device, const char *filename, const char
|
||||
if (eject_device(bs, 0) < 0)
|
||||
return;
|
||||
bdrv_open2(bs, filename, 0, drv);
|
||||
qemu_key_check(bs, filename);
|
||||
monitor_read_bdrv_key(bs);
|
||||
}
|
||||
|
||||
static void do_change_vnc(const char *target, const char *arg)
|
||||
@@ -494,9 +496,24 @@ static void do_stop(void)
|
||||
vm_stop(EXCP_INTERRUPT);
|
||||
}
|
||||
|
||||
static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
|
||||
{
|
||||
int *err = opaque;
|
||||
|
||||
if (bdrv_key_required(bs))
|
||||
*err = monitor_read_bdrv_key(bs);
|
||||
else
|
||||
*err = 0;
|
||||
}
|
||||
|
||||
static void do_cont(void)
|
||||
{
|
||||
vm_start();
|
||||
int err = 0;
|
||||
|
||||
bdrv_iterate(encrypted_bdrv_it, &err);
|
||||
/* only resume the vm if all keys are set and valid */
|
||||
if (!err)
|
||||
vm_start();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GDBSTUB
|
||||
@@ -2679,8 +2696,9 @@ static void file_completion(const char *input)
|
||||
closedir(ffs);
|
||||
}
|
||||
|
||||
static void block_completion_it(void *opaque, const char *name)
|
||||
static void block_completion_it(void *opaque, BlockDriverState *bs)
|
||||
{
|
||||
const char *name = bdrv_get_device_name(bs);
|
||||
const char *input = opaque;
|
||||
|
||||
if (input[0] == '\0' ||
|
||||
@@ -2891,8 +2909,8 @@ static void monitor_readline_cb(void *opaque, const char *input)
|
||||
monitor_readline_started = 0;
|
||||
}
|
||||
|
||||
void monitor_readline(const char *prompt, int is_password,
|
||||
char *buf, int buf_size)
|
||||
static void monitor_readline(const char *prompt, int is_password,
|
||||
char *buf, int buf_size)
|
||||
{
|
||||
int i;
|
||||
int old_focus[MAX_MON];
|
||||
@@ -2922,3 +2940,22 @@ void monitor_readline(const char *prompt, int is_password,
|
||||
monitor_hd[i]->focus = old_focus[i];
|
||||
}
|
||||
}
|
||||
|
||||
int monitor_read_bdrv_key(BlockDriverState *bs)
|
||||
{
|
||||
char password[256];
|
||||
int i;
|
||||
|
||||
if (!bdrv_is_encrypted(bs))
|
||||
return 0;
|
||||
|
||||
term_printf("%s (%s) is encrypted.\n", bdrv_get_device_name(bs),
|
||||
bdrv_get_encrypted_filename(bs));
|
||||
for(i = 0; i < 3; i++) {
|
||||
monitor_readline("Password: ", 1, password, sizeof(password));
|
||||
if (bdrv_set_key(bs, password) == 0)
|
||||
return 0;
|
||||
term_printf("invalid password\n");
|
||||
}
|
||||
return -EPERM;
|
||||
}
|
||||
|
126
net.c
126
net.c
@@ -329,6 +329,7 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan,
|
||||
const char *name,
|
||||
IOReadHandler *fd_read,
|
||||
IOCanRWHandler *fd_can_read,
|
||||
NetCleanup *cleanup,
|
||||
void *opaque)
|
||||
{
|
||||
VLANClientState *vc, **pvc;
|
||||
@@ -340,6 +341,7 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan,
|
||||
vc->name = assign_name(vc, model);
|
||||
vc->fd_read = fd_read;
|
||||
vc->fd_can_read = fd_can_read;
|
||||
vc->cleanup = cleanup;
|
||||
vc->opaque = opaque;
|
||||
vc->vlan = vlan;
|
||||
|
||||
@@ -358,9 +360,12 @@ void qemu_del_vlan_client(VLANClientState *vc)
|
||||
while (*pvc != NULL)
|
||||
if (*pvc == vc) {
|
||||
*pvc = vc->next;
|
||||
if (vc->cleanup) {
|
||||
vc->cleanup(vc);
|
||||
}
|
||||
free(vc->name);
|
||||
free(vc->model);
|
||||
free(vc);
|
||||
qemu_free(vc);
|
||||
break;
|
||||
} else
|
||||
pvc = &(*pvc)->next;
|
||||
@@ -517,7 +522,7 @@ static int net_slirp_init(VLANState *vlan, const char *model, const char *name)
|
||||
slirp_init(slirp_restrict, slirp_ip);
|
||||
}
|
||||
slirp_vc = qemu_new_vlan_client(vlan, model, name,
|
||||
slirp_receive, NULL, NULL);
|
||||
slirp_receive, NULL, NULL, NULL);
|
||||
slirp_vc->info_str[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
@@ -698,7 +703,8 @@ typedef struct TAPState {
|
||||
char down_script_arg[128];
|
||||
} TAPState;
|
||||
|
||||
#ifdef HAVE_IOVEC
|
||||
static int launch_script(const char *setup_script, const char *ifname, int fd);
|
||||
|
||||
static ssize_t tap_receive_iov(void *opaque, const struct iovec *iov,
|
||||
int iovcnt)
|
||||
{
|
||||
@@ -711,7 +717,6 @@ static ssize_t tap_receive_iov(void *opaque, const struct iovec *iov,
|
||||
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void tap_receive(void *opaque, const uint8_t *buf, int size)
|
||||
{
|
||||
@@ -746,6 +751,18 @@ static void tap_send(void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
static void tap_cleanup(VLANClientState *vc)
|
||||
{
|
||||
TAPState *s = vc->opaque;
|
||||
|
||||
if (s->down_script[0])
|
||||
launch_script(s->down_script, s->down_script_arg, s->fd);
|
||||
|
||||
qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
|
||||
close(s->fd);
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
/* fd support */
|
||||
|
||||
static TAPState *net_tap_fd_init(VLANState *vlan,
|
||||
@@ -757,10 +774,9 @@ static TAPState *net_tap_fd_init(VLANState *vlan,
|
||||
|
||||
s = qemu_mallocz(sizeof(TAPState));
|
||||
s->fd = fd;
|
||||
s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive, NULL, s);
|
||||
#ifdef HAVE_IOVEC
|
||||
s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive,
|
||||
NULL, tap_cleanup, s);
|
||||
s->vc->fd_readv = tap_receive_iov;
|
||||
#endif
|
||||
qemu_set_fd_handler(s->fd, tap_send, NULL, s);
|
||||
snprintf(s->vc->info_str, sizeof(s->vc->info_str), "fd=%d", fd);
|
||||
return s;
|
||||
@@ -1015,8 +1031,6 @@ static int net_tap_init(VLANState *vlan, const char *model,
|
||||
return -1;
|
||||
}
|
||||
s = net_tap_fd_init(vlan, model, name, fd);
|
||||
if (!s)
|
||||
return -1;
|
||||
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
|
||||
"ifname=%s,script=%s,downscript=%s",
|
||||
ifname, setup_script, down_script);
|
||||
@@ -1060,6 +1074,14 @@ static void vde_from_qemu(void *opaque, const uint8_t *buf, int size)
|
||||
}
|
||||
}
|
||||
|
||||
static void vde_cleanup(VLANClientState *vc)
|
||||
{
|
||||
VDEState *s = vc->opaque;
|
||||
qemu_set_fd_handler(vde_datafd(s->vde), NULL, NULL, NULL);
|
||||
vde_close(s->vde);
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
static int net_vde_init(VLANState *vlan, const char *model,
|
||||
const char *name, const char *sock,
|
||||
int port, const char *group, int mode)
|
||||
@@ -1080,7 +1102,8 @@ static int net_vde_init(VLANState *vlan, const char *model,
|
||||
free(s);
|
||||
return -1;
|
||||
}
|
||||
s->vc = qemu_new_vlan_client(vlan, model, name, vde_from_qemu, NULL, s);
|
||||
s->vc = qemu_new_vlan_client(vlan, model, name, vde_from_qemu,
|
||||
NULL, vde_cleanup, s);
|
||||
qemu_set_fd_handler(vde_datafd(s->vde), vde_to_qemu, NULL, s);
|
||||
snprintf(s->vc->info_str, sizeof(s->vc->info_str), "sock=%s,fd=%d",
|
||||
sock, vde_datafd(s->vde));
|
||||
@@ -1265,6 +1288,14 @@ fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void net_socket_cleanup(VLANClientState *vc)
|
||||
{
|
||||
NetSocketState *s = vc->opaque;
|
||||
qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
|
||||
close(s->fd);
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan,
|
||||
const char *model,
|
||||
const char *name,
|
||||
@@ -1309,7 +1340,8 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan,
|
||||
s = qemu_mallocz(sizeof(NetSocketState));
|
||||
s->fd = fd;
|
||||
|
||||
s->vc = qemu_new_vlan_client(vlan, model, name, net_socket_receive_dgram, NULL, s);
|
||||
s->vc = qemu_new_vlan_client(vlan, model, name, net_socket_receive_dgram,
|
||||
NULL, net_socket_cleanup, s);
|
||||
qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s);
|
||||
|
||||
/* mcast: save bound address as dst */
|
||||
@@ -1336,8 +1368,8 @@ static NetSocketState *net_socket_fd_init_stream(VLANState *vlan,
|
||||
NetSocketState *s;
|
||||
s = qemu_mallocz(sizeof(NetSocketState));
|
||||
s->fd = fd;
|
||||
s->vc = qemu_new_vlan_client(vlan, model, name,
|
||||
net_socket_receive, NULL, s);
|
||||
s->vc = qemu_new_vlan_client(vlan, model, name, net_socket_receive,
|
||||
NULL, net_socket_cleanup, s);
|
||||
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
|
||||
"socket: fd=%d", fd);
|
||||
if (is_connected) {
|
||||
@@ -1436,7 +1468,7 @@ static int net_socket_listen_init(VLANState *vlan,
|
||||
}
|
||||
s->vlan = vlan;
|
||||
s->model = strdup(model);
|
||||
s->name = strdup(name);
|
||||
s->name = name ? strdup(name) : NULL;
|
||||
s->fd = fd;
|
||||
qemu_set_fd_handler(fd, net_socket_accept, NULL, s);
|
||||
return 0;
|
||||
@@ -1596,10 +1628,7 @@ int net_client_init(const char *device, const char *p)
|
||||
vlan_id = strtol(buf, NULL, 0);
|
||||
}
|
||||
vlan = qemu_find_vlan(vlan_id);
|
||||
if (!vlan) {
|
||||
fprintf(stderr, "Could not create vlan %d\n", vlan_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (get_param_value(buf, sizeof(buf), "name", p)) {
|
||||
name = strdup(buf);
|
||||
}
|
||||
@@ -1610,7 +1639,8 @@ int net_client_init(const char *device, const char *p)
|
||||
|
||||
if (idx == -1 || nb_nics >= MAX_NICS) {
|
||||
fprintf(stderr, "Too Many NICs\n");
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
nd = &nd_table[idx];
|
||||
macaddr = nd->macaddr;
|
||||
@@ -1624,7 +1654,8 @@ int net_client_init(const char *device, const char *p)
|
||||
if (get_param_value(buf, sizeof(buf), "macaddr", p)) {
|
||||
if (parse_macaddr(macaddr, buf) < 0) {
|
||||
fprintf(stderr, "invalid syntax for ethernet address\n");
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (get_param_value(buf, sizeof(buf), "model", p)) {
|
||||
@@ -1664,8 +1695,9 @@ int net_client_init(const char *device, const char *p)
|
||||
port = strtol(p, &devname, 10);
|
||||
devname++;
|
||||
if (port < 1 || port > 65535) {
|
||||
fprintf(stderr, "vmchannel wrong port number\n");
|
||||
return -1;
|
||||
fprintf(stderr, "vmchannel wrong port number\n");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
vmc = malloc(sizeof(struct VMChannel));
|
||||
snprintf(name, 20, "vmchannel%ld", port);
|
||||
@@ -1673,7 +1705,8 @@ int net_client_init(const char *device, const char *p)
|
||||
if (!vmc->hd) {
|
||||
fprintf(stderr, "qemu: could not open vmchannel device"
|
||||
"'%s'\n", devname);
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
vmc->port = port;
|
||||
slirp_add_exec(3, vmc->hd, 4, port);
|
||||
@@ -1687,7 +1720,8 @@ int net_client_init(const char *device, const char *p)
|
||||
char ifname[64];
|
||||
if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) {
|
||||
fprintf(stderr, "tap: no interface name\n");
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
vlan->nb_host_devs++;
|
||||
ret = tap_win32_init(vlan, device, name, ifname);
|
||||
@@ -1702,9 +1736,8 @@ int net_client_init(const char *device, const char *p)
|
||||
if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
|
||||
fd = strtol(buf, NULL, 0);
|
||||
fcntl(fd, F_SETFL, O_NONBLOCK);
|
||||
ret = -1;
|
||||
if (net_tap_fd_init(vlan, device, name, fd))
|
||||
ret = 0;
|
||||
net_tap_fd_init(vlan, device, name, fd);
|
||||
ret = 0;
|
||||
} else {
|
||||
if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) {
|
||||
ifname[0] = '\0';
|
||||
@@ -1734,7 +1767,8 @@ int net_client_init(const char *device, const char *p)
|
||||
ret = net_socket_mcast_init(vlan, device, name, buf);
|
||||
} else {
|
||||
fprintf(stderr, "Unknown socket options: %s\n", p);
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
vlan->nb_host_devs++;
|
||||
} else
|
||||
@@ -1764,13 +1798,13 @@ int net_client_init(const char *device, const char *p)
|
||||
#endif
|
||||
{
|
||||
fprintf(stderr, "Unknown network device: %s\n", device);
|
||||
if (name)
|
||||
free(name);
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Could not initialize device '%s'\n", device);
|
||||
}
|
||||
out:
|
||||
if (name)
|
||||
free(name);
|
||||
return ret;
|
||||
@@ -1818,16 +1852,7 @@ void net_host_device_remove(int vlan_id, const char *device)
|
||||
VLANState *vlan;
|
||||
VLANClientState *vc;
|
||||
|
||||
if (!net_host_check_device(device)) {
|
||||
term_printf("invalid host network device %s\n", device);
|
||||
return;
|
||||
}
|
||||
|
||||
vlan = qemu_find_vlan(vlan_id);
|
||||
if (!vlan) {
|
||||
term_printf("can't find vlan %d\n", vlan_id);
|
||||
return;
|
||||
}
|
||||
|
||||
for(vc = vlan->first_client; vc != NULL; vc = vc->next)
|
||||
if (!strcmp(vc->name, device))
|
||||
@@ -1906,27 +1931,18 @@ void net_cleanup(void)
|
||||
{
|
||||
VLANState *vlan;
|
||||
|
||||
#if !defined(_WIN32)
|
||||
/* close network clients */
|
||||
for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) {
|
||||
VLANClientState *vc;
|
||||
VLANClientState *vc = vlan->first_client;
|
||||
|
||||
for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
|
||||
if (vc->fd_read == tap_receive) {
|
||||
TAPState *s = vc->opaque;
|
||||
while (vc) {
|
||||
VLANClientState *next = vc->next;
|
||||
|
||||
if (s->down_script[0])
|
||||
launch_script(s->down_script, s->down_script_arg, s->fd);
|
||||
}
|
||||
#if defined(CONFIG_VDE)
|
||||
if (vc->fd_read == vde_from_qemu) {
|
||||
VDEState *s = vc->opaque;
|
||||
vde_close(s->vde);
|
||||
}
|
||||
#endif
|
||||
qemu_del_vlan_client(vc);
|
||||
|
||||
vc = next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void net_client_check(void)
|
||||
|
4
net.h
4
net.h
@@ -9,6 +9,7 @@ typedef ssize_t (IOReadvHandler)(void *, const struct iovec *, int);
|
||||
|
||||
typedef struct VLANClientState VLANClientState;
|
||||
|
||||
typedef void (NetCleanup) (VLANClientState *);
|
||||
typedef void (LinkStatusChanged)(VLANClientState *);
|
||||
|
||||
struct VLANClientState {
|
||||
@@ -17,6 +18,7 @@ struct VLANClientState {
|
||||
/* Packets may still be sent if this returns zero. It's used to
|
||||
rate-limit the slirp code. */
|
||||
IOCanRWHandler *fd_can_read;
|
||||
NetCleanup *cleanup;
|
||||
LinkStatusChanged *link_status_changed;
|
||||
int link_down;
|
||||
void *opaque;
|
||||
@@ -40,6 +42,7 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan,
|
||||
const char *name,
|
||||
IOReadHandler *fd_read,
|
||||
IOCanRWHandler *fd_can_read,
|
||||
NetCleanup *cleanup,
|
||||
void *opaque);
|
||||
void qemu_del_vlan_client(VLANClientState *vc);
|
||||
VLANClientState *qemu_find_vlan_client(VLANState *vlan, void *opaque);
|
||||
@@ -65,6 +68,7 @@ struct NICInfo {
|
||||
const char *model;
|
||||
const char *name;
|
||||
VLANState *vlan;
|
||||
VLANClientState *vc;
|
||||
void *private;
|
||||
int used;
|
||||
};
|
||||
|
@@ -0,0 +1,38 @@
|
||||
Fix non-ACPI Timer Interrupt Routing (Beth Kon)
|
||||
|
||||
Replicate ACPI irq0->inti2 override in mp table for non-acpi case.
|
||||
|
||||
v1 -> v2 adds comment suggested by Ryan.
|
||||
|
||||
Signed-off-by: Beth Kon <eak@us.ibm.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
|
||||
diff --git a/bios/rombios32.c b/bios/rombios32.c
|
||||
index 7be4216..dc7b5f3 100644
|
||||
--- a/bios/rombios32.c
|
||||
+++ b/bios/rombios32.c
|
||||
@@ -1168,6 +1168,12 @@ static void mptable_init(void)
|
||||
|
||||
/* irqs */
|
||||
for(i = 0; i < 16; i++) {
|
||||
+#ifdef BX_QEMU
|
||||
+ /* One entry per ioapic input. Input 2 is covered by
|
||||
+ irq0->inti2 override (i == 0). irq 2 is unused */
|
||||
+ if (i == 2)
|
||||
+ continue;
|
||||
+#endif
|
||||
putb(&q, 3); /* entry type = I/O interrupt */
|
||||
putb(&q, 0); /* interrupt type = vectored interrupt */
|
||||
putb(&q, 0); /* flags: po=0, el=0 */
|
||||
@@ -1175,7 +1181,11 @@ static void mptable_init(void)
|
||||
putb(&q, 0); /* source bus ID = ISA */
|
||||
putb(&q, i); /* source bus IRQ */
|
||||
putb(&q, ioapic_id); /* dest I/O APIC ID */
|
||||
+#ifdef BX_QEMU
|
||||
+ putb(&q, i == 0 ? 2 : i); /* dest I/O APIC interrupt in */
|
||||
+#else
|
||||
putb(&q, i); /* dest I/O APIC interrupt in */
|
||||
+#endif
|
||||
}
|
||||
/* patch length */
|
||||
len = q - mp_config_table;
|
@@ -0,0 +1,20 @@
|
||||
Enable power button event generation.
|
||||
|
||||
Signed-off-by: Gleb Natapov <gleb@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
|
||||
diff --git a/bios/rombios32.c b/bios/rombios32.c
|
||||
index 81e3bad..9986531 100644
|
||||
--- a/bios/rombios32.c
|
||||
+++ b/bios/rombios32.c
|
||||
@@ -1767,8 +1767,8 @@ void acpi_bios_init(void)
|
||||
fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported
|
||||
fadt->gpe0_blk = cpu_to_le32(0xafe0);
|
||||
fadt->gpe0_blk_len = 4;
|
||||
- /* WBINVD + PROC_C1 + PWR_BUTTON + SLP_BUTTON + FIX_RTC */
|
||||
- fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 6));
|
||||
+ /* WBINVD + PROC_C1 + SLP_BUTTON + FIX_RTC */
|
||||
+ fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 5) | (1 << 6));
|
||||
acpi_build_table_header((struct acpi_table_header *)fadt, "FACP",
|
||||
sizeof(*fadt), 1);
|
||||
|
@@ -9,3 +9,5 @@
|
||||
0009_qemu-bios-pci-hotplug-support.patch
|
||||
0010_bios-mark-the-acpi-sci-interrupt-as-connected-to-irq-9.patch
|
||||
0011_read-additional-acpi-tables-from-a-vm.patch
|
||||
0013_fix-non-acpi-timer-interrupt-routing.patch
|
||||
0015_enable-power-button-even-generation.patch
|
||||
|
BIN
pc-bios/bios.bin
BIN
pc-bios/bios.bin
Binary file not shown.
@@ -24,9 +24,10 @@ typedef int (AioFlushHandler)(void *opaque);
|
||||
* outstanding AIO operations have been completed or cancelled. */
|
||||
void qemu_aio_flush(void);
|
||||
|
||||
/* Wait for a single AIO completion to occur. This function will until a
|
||||
* single AIO opeartion has completed. It is intended to be used as a looping
|
||||
* primative when simulating synchronous IO based on asynchronous IO. */
|
||||
/* Wait for a single AIO completion to occur. This function will wait
|
||||
* until a single AIO event has completed and it will ensure something
|
||||
* has moved before returning. This can issue new pending aio as
|
||||
* result of executing I/O completion or bh callbacks. */
|
||||
void qemu_aio_wait(void);
|
||||
|
||||
/* Register a file descriptor and associated callbacks. Behaves very similarly
|
||||
|
65
qemu-char.c
65
qemu-char.c
@@ -101,6 +101,10 @@
|
||||
/***********************************************************/
|
||||
/* character device */
|
||||
|
||||
static TAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
|
||||
TAILQ_HEAD_INITIALIZER(chardevs);
|
||||
static int initial_reset_issued;
|
||||
|
||||
static void qemu_chr_event(CharDriverState *s, int event)
|
||||
{
|
||||
if (!s->chr_event)
|
||||
@@ -118,12 +122,23 @@ static void qemu_chr_reset_bh(void *opaque)
|
||||
|
||||
void qemu_chr_reset(CharDriverState *s)
|
||||
{
|
||||
if (s->bh == NULL) {
|
||||
if (s->bh == NULL && initial_reset_issued) {
|
||||
s->bh = qemu_bh_new(qemu_chr_reset_bh, s);
|
||||
qemu_bh_schedule(s->bh);
|
||||
}
|
||||
}
|
||||
|
||||
void qemu_chr_initial_reset(void)
|
||||
{
|
||||
CharDriverState *chr;
|
||||
|
||||
initial_reset_issued = 1;
|
||||
|
||||
TAILQ_FOREACH(chr, &chardevs, next) {
|
||||
qemu_chr_reset(chr);
|
||||
}
|
||||
}
|
||||
|
||||
int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len)
|
||||
{
|
||||
return s->chr_write(s, buf, len);
|
||||
@@ -210,12 +225,15 @@ typedef struct {
|
||||
IOEventHandler *chr_event[MAX_MUX];
|
||||
void *ext_opaque[MAX_MUX];
|
||||
CharDriverState *drv;
|
||||
unsigned char buffer[MUX_BUFFER_SIZE];
|
||||
int prod;
|
||||
int cons;
|
||||
int mux_cnt;
|
||||
int term_got_escape;
|
||||
int max_size;
|
||||
/* Intermediate input buffer allows to catch escape sequences even if the
|
||||
currently active device is not accepting any input - but only until it
|
||||
is full as well. */
|
||||
unsigned char buffer[MAX_MUX][MUX_BUFFER_SIZE];
|
||||
int prod[MAX_MUX];
|
||||
int cons[MAX_MUX];
|
||||
} MuxDriver;
|
||||
|
||||
|
||||
@@ -345,11 +363,11 @@ static void mux_chr_accept_input(CharDriverState *chr)
|
||||
int m = chr->focus;
|
||||
MuxDriver *d = chr->opaque;
|
||||
|
||||
while (d->prod != d->cons &&
|
||||
while (d->prod[m] != d->cons[m] &&
|
||||
d->chr_can_read[m] &&
|
||||
d->chr_can_read[m](d->ext_opaque[m])) {
|
||||
d->chr_read[m](d->ext_opaque[m],
|
||||
&d->buffer[d->cons++ & MUX_BUFFER_MASK], 1);
|
||||
&d->buffer[m][d->cons[m]++ & MUX_BUFFER_MASK], 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,11 +375,12 @@ static int mux_chr_can_read(void *opaque)
|
||||
{
|
||||
CharDriverState *chr = opaque;
|
||||
MuxDriver *d = chr->opaque;
|
||||
int m = chr->focus;
|
||||
|
||||
if ((d->prod - d->cons) < MUX_BUFFER_SIZE)
|
||||
if ((d->prod[m] - d->cons[m]) < MUX_BUFFER_SIZE)
|
||||
return 1;
|
||||
if (d->chr_can_read[chr->focus])
|
||||
return d->chr_can_read[chr->focus](d->ext_opaque[chr->focus]);
|
||||
if (d->chr_can_read[m])
|
||||
return d->chr_can_read[m](d->ext_opaque[m]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -376,12 +395,12 @@ static void mux_chr_read(void *opaque, const uint8_t *buf, int size)
|
||||
|
||||
for(i = 0; i < size; i++)
|
||||
if (mux_proc_byte(chr, d, buf[i])) {
|
||||
if (d->prod == d->cons &&
|
||||
if (d->prod[m] == d->cons[m] &&
|
||||
d->chr_can_read[m] &&
|
||||
d->chr_can_read[m](d->ext_opaque[m]))
|
||||
d->chr_read[m](d->ext_opaque[m], &buf[i], 1);
|
||||
else
|
||||
d->buffer[d->prod++ & MUX_BUFFER_MASK] = buf[i];
|
||||
d->buffer[m][d->prod[m]++ & MUX_BUFFER_MASK] = buf[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -898,6 +917,8 @@ static void pty_chr_close(struct CharDriverState *chr)
|
||||
|
||||
qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
|
||||
close(s->fd);
|
||||
qemu_del_timer(s->timer);
|
||||
qemu_free_timer(s->timer);
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
@@ -1727,6 +1748,16 @@ static void udp_chr_update_read_handler(CharDriverState *chr)
|
||||
}
|
||||
}
|
||||
|
||||
static void udp_chr_close(CharDriverState *chr)
|
||||
{
|
||||
NetCharDriver *s = chr->opaque;
|
||||
if (s->fd >= 0) {
|
||||
qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
|
||||
closesocket(s->fd);
|
||||
}
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
static CharDriverState *qemu_chr_open_udp(const char *def)
|
||||
{
|
||||
CharDriverState *chr = NULL;
|
||||
@@ -1760,6 +1791,7 @@ static CharDriverState *qemu_chr_open_udp(const char *def)
|
||||
chr->opaque = s;
|
||||
chr->chr_write = udp_chr_write;
|
||||
chr->chr_update_read_handler = udp_chr_update_read_handler;
|
||||
chr->chr_close = udp_chr_close;
|
||||
return chr;
|
||||
|
||||
return_err:
|
||||
@@ -1962,10 +1994,14 @@ static void tcp_chr_accept(void *opaque)
|
||||
static void tcp_chr_close(CharDriverState *chr)
|
||||
{
|
||||
TCPCharDriver *s = chr->opaque;
|
||||
if (s->fd >= 0)
|
||||
if (s->fd >= 0) {
|
||||
qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
|
||||
closesocket(s->fd);
|
||||
if (s->listen_fd >= 0)
|
||||
}
|
||||
if (s->listen_fd >= 0) {
|
||||
qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
|
||||
closesocket(s->listen_fd);
|
||||
}
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
@@ -2076,9 +2112,6 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static TAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs
|
||||
= TAILQ_HEAD_INITIALIZER(chardevs);
|
||||
|
||||
CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s))
|
||||
{
|
||||
const char *p;
|
||||
|
@@ -74,6 +74,7 @@ void qemu_chr_add_handlers(CharDriverState *s,
|
||||
void *opaque);
|
||||
int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg);
|
||||
void qemu_chr_reset(CharDriverState *s);
|
||||
void qemu_chr_initial_reset(void);
|
||||
int qemu_chr_can_read(CharDriverState *s);
|
||||
void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len);
|
||||
void qemu_chr_accept_input(CharDriverState *s);
|
||||
|
@@ -3413,16 +3413,6 @@ make install
|
||||
@end example
|
||||
to install QEMU in @file{/usr/local}.
|
||||
|
||||
@subsection GCC version
|
||||
|
||||
In order to compile QEMU successfully, it is very important that you
|
||||
have the right tools. The most important one is gcc. On most hosts and
|
||||
in particular on x86 ones, @emph{gcc 4.x is not supported}. If your
|
||||
Linux distribution includes a gcc 4.x compiler, you can usually
|
||||
install an older version (it is invoked by @code{gcc32} or
|
||||
@code{gcc34}). The QEMU configure script automatically probes for
|
||||
these older versions so that usually you don't have to do anything.
|
||||
|
||||
@node Windows
|
||||
@section Windows
|
||||
|
||||
|
14
qemu-img.c
14
qemu-img.c
@@ -74,8 +74,8 @@ static void help(void)
|
||||
" differ\n"
|
||||
" 'fmt' is the disk image format. It is guessed automatically in most cases\n"
|
||||
" 'size' is the disk image size in kilobytes. Optional suffixes\n"
|
||||
" 'M' (megabyte, 1024 * 1024) and 'G' (gigabyte, 1024 * 1024 * 1024) are"
|
||||
" supported any @code{k} or @code{K} is ignored\n"
|
||||
" 'M' (megabyte, 1024 * 1024) and 'G' (gigabyte, 1024 * 1024 * 1024) are\n"
|
||||
" supported any 'k' or 'K' is ignored\n"
|
||||
" 'output_filename' is the destination disk image filename\n"
|
||||
" 'output_fmt' is the destination format\n"
|
||||
" '-c' indicates that target image must be compressed (qcow format only)\n"
|
||||
@@ -290,6 +290,8 @@ static int img_create(int argc, char **argv)
|
||||
if (ret < 0) {
|
||||
if (ret == -ENOTSUP) {
|
||||
error("Formatting or formatting option not supported for file format '%s'", fmt);
|
||||
} else if (ret == -EFBIG) {
|
||||
error("The image size is too large for file format '%s'", fmt);
|
||||
} else {
|
||||
error("Error while formatting");
|
||||
}
|
||||
@@ -477,7 +479,9 @@ static int img_convert(int argc, char **argv)
|
||||
ret = bdrv_create(drv, out_filename, total_sectors, out_baseimg, flags);
|
||||
if (ret < 0) {
|
||||
if (ret == -ENOTSUP) {
|
||||
error("Formatting not supported for file format '%s'", fmt);
|
||||
error("Formatting not supported for file format '%s'", out_fmt);
|
||||
} else if (ret == -EFBIG) {
|
||||
error("The image size is too large for file format '%s'", out_fmt);
|
||||
} else {
|
||||
error("Error while formatting '%s'", out_filename);
|
||||
}
|
||||
@@ -730,10 +734,6 @@ static int img_info(int argc, char **argv)
|
||||
if (bdrv_get_info(bs, &bdi) >= 0) {
|
||||
if (bdi.cluster_size != 0)
|
||||
printf("cluster_size: %d\n", bdi.cluster_size);
|
||||
if (bdi.highest_alloc)
|
||||
printf("highest_alloc: %" PRId64 "\n", bdi.highest_alloc);
|
||||
if (bdi.num_free_bytes)
|
||||
printf("num_free_bytes: %" PRId64 "\n", bdi.num_free_bytes);
|
||||
}
|
||||
bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
|
||||
if (backing_filename[0] != '\0') {
|
||||
|
100
savevm.c
100
savevm.c
@@ -103,29 +103,46 @@ static int announce_self_create(uint8_t *buf,
|
||||
|
||||
/* FIXME: should we send a different packet (arp/rarp/ping)? */
|
||||
|
||||
memset(buf, 0, 64);
|
||||
memset(buf, 0xff, 6); /* h_dst */
|
||||
memcpy(buf + 6, mac_addr, 6); /* h_src */
|
||||
memcpy(buf + 12, &proto, 2); /* h_proto */
|
||||
memcpy(buf + 14, &magic, 4); /* magic */
|
||||
|
||||
return 18; /* len */
|
||||
return 64; /* len */
|
||||
}
|
||||
|
||||
static void qemu_announce_self_once(void *opaque)
|
||||
{
|
||||
int i, len;
|
||||
VLANState *vlan;
|
||||
VLANClientState *vc;
|
||||
uint8_t buf[256];
|
||||
static int count = SELF_ANNOUNCE_ROUNDS;
|
||||
QEMUTimer *timer = *(QEMUTimer **)opaque;
|
||||
|
||||
for (i = 0; i < MAX_NICS; i++) {
|
||||
if (!nd_table[i].used)
|
||||
continue;
|
||||
len = announce_self_create(buf, nd_table[i].macaddr);
|
||||
vlan = nd_table[i].vlan;
|
||||
for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
|
||||
vc->fd_read(vc->opaque, buf, len);
|
||||
}
|
||||
}
|
||||
if (count--) {
|
||||
qemu_mod_timer(timer, qemu_get_clock(rt_clock) + 100);
|
||||
} else {
|
||||
qemu_del_timer(timer);
|
||||
qemu_free_timer(timer);
|
||||
}
|
||||
}
|
||||
|
||||
void qemu_announce_self(void)
|
||||
{
|
||||
int i, j, len;
|
||||
VLANState *vlan;
|
||||
VLANClientState *vc;
|
||||
uint8_t buf[256];
|
||||
|
||||
for (i = 0; i < nb_nics; i++) {
|
||||
len = announce_self_create(buf, nd_table[i].macaddr);
|
||||
vlan = nd_table[i].vlan;
|
||||
for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
|
||||
for (j=0; j < SELF_ANNOUNCE_ROUNDS; j++)
|
||||
vc->fd_read(vc->opaque, buf, len);
|
||||
}
|
||||
}
|
||||
static QEMUTimer *timer;
|
||||
timer = qemu_new_timer(rt_clock, qemu_announce_self_once, &timer);
|
||||
qemu_announce_self_once(&timer);
|
||||
}
|
||||
|
||||
/***********************************************************/
|
||||
@@ -193,7 +210,14 @@ static int popen_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int s
|
||||
static int popen_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
|
||||
{
|
||||
QEMUFilePopen *s = opaque;
|
||||
return fread(buf, 1, size, s->popen_file);
|
||||
FILE *fp = s->popen_file;
|
||||
int bytes;
|
||||
|
||||
do {
|
||||
clearerr(fp);
|
||||
bytes = fread(buf, 1, size, fp);
|
||||
} while ((bytes == 0) && ferror(fp) && (errno == EINTR));
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static int popen_close(void *opaque)
|
||||
@@ -222,7 +246,6 @@ QEMUFile *qemu_popen(FILE *popen_file, const char *mode)
|
||||
} else {
|
||||
s->file = qemu_fopen_ops(s, popen_put_buffer, NULL, popen_close, NULL);
|
||||
}
|
||||
fprintf(stderr, "qemu_popen: returning result of qemu_fopen_ops\n");
|
||||
return s->file;
|
||||
}
|
||||
|
||||
@@ -238,6 +261,17 @@ QEMUFile *qemu_popen_cmd(const char *command, const char *mode)
|
||||
return qemu_popen(popen_file, mode);
|
||||
}
|
||||
|
||||
int qemu_popen_fd(QEMUFile *f)
|
||||
{
|
||||
QEMUFilePopen *p;
|
||||
int fd;
|
||||
|
||||
p = (QEMUFilePopen *)f->opaque;
|
||||
fd = fileno(p->popen_file);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
QEMUFile *qemu_fopen_socket(int fd)
|
||||
{
|
||||
QEMUFileSocket *s = qemu_mallocz(sizeof(QEMUFileSocket));
|
||||
@@ -304,18 +338,18 @@ typedef struct QEMUFileBdrv
|
||||
int64_t base_offset;
|
||||
} QEMUFileBdrv;
|
||||
|
||||
static int bdrv_put_buffer(void *opaque, const uint8_t *buf,
|
||||
static int block_put_buffer(void *opaque, const uint8_t *buf,
|
||||
int64_t pos, int size)
|
||||
{
|
||||
QEMUFileBdrv *s = opaque;
|
||||
bdrv_pwrite(s->bs, s->base_offset + pos, buf, size);
|
||||
bdrv_put_buffer(s->bs, buf, s->base_offset + pos, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static int bdrv_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
|
||||
static int block_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
|
||||
{
|
||||
QEMUFileBdrv *s = opaque;
|
||||
return bdrv_pread(s->bs, s->base_offset + pos, buf, size);
|
||||
return bdrv_get_buffer(s->bs, buf, s->base_offset + pos, size);
|
||||
}
|
||||
|
||||
static int bdrv_fclose(void *opaque)
|
||||
@@ -335,9 +369,9 @@ static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int64_t offset, int is_wr
|
||||
s->base_offset = offset;
|
||||
|
||||
if (is_writable)
|
||||
return qemu_fopen_ops(s, bdrv_put_buffer, NULL, bdrv_fclose, NULL);
|
||||
return qemu_fopen_ops(s, block_put_buffer, NULL, bdrv_fclose, NULL);
|
||||
|
||||
return qemu_fopen_ops(s, NULL, bdrv_get_buffer, bdrv_fclose, NULL);
|
||||
return qemu_fopen_ops(s, NULL, block_get_buffer, bdrv_fclose, NULL);
|
||||
}
|
||||
|
||||
QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer,
|
||||
@@ -364,6 +398,11 @@ int qemu_file_has_error(QEMUFile *f)
|
||||
return f->has_error;
|
||||
}
|
||||
|
||||
void qemu_file_set_error(QEMUFile *f)
|
||||
{
|
||||
f->has_error = 1;
|
||||
}
|
||||
|
||||
void qemu_fflush(QEMUFile *f)
|
||||
{
|
||||
if (!f->put_buffer)
|
||||
@@ -636,6 +675,22 @@ int register_savevm(const char *idstr,
|
||||
NULL, save_state, load_state, opaque);
|
||||
}
|
||||
|
||||
void unregister_savevm(const char *idstr, void *opaque)
|
||||
{
|
||||
SaveStateEntry **pse;
|
||||
|
||||
pse = &first_se;
|
||||
while (*pse != NULL) {
|
||||
if (strcmp((*pse)->idstr, idstr) == 0 && (*pse)->opaque == opaque) {
|
||||
SaveStateEntry *next = (*pse)->next;
|
||||
qemu_free(*pse);
|
||||
*pse = next;
|
||||
continue;
|
||||
}
|
||||
pse = &(*pse)->next;
|
||||
}
|
||||
}
|
||||
|
||||
#define QEMU_VM_FILE_MAGIC 0x5145564d
|
||||
#define QEMU_VM_FILE_VERSION_COMPAT 0x00000002
|
||||
#define QEMU_VM_FILE_VERSION 0x00000003
|
||||
@@ -828,6 +883,7 @@ static int qemu_loadvm_state_v2(QEMUFile *f)
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n",
|
||||
instance_id, idstr);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
/* always seek to exact end of record */
|
||||
|
41
sdl.c
41
sdl.c
@@ -27,7 +27,7 @@
|
||||
#include "x_keymap.h"
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL/SDL_syswm.h>
|
||||
#include <SDL_syswm.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <signal.h>
|
||||
@@ -144,32 +144,35 @@ static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
|
||||
static int check_for_evdev(void)
|
||||
{
|
||||
SDL_SysWMinfo info;
|
||||
XkbDescPtr desc;
|
||||
XkbDescPtr desc = NULL;
|
||||
int has_evdev = 0;
|
||||
const char *keycodes;
|
||||
char *keycodes = NULL;
|
||||
|
||||
SDL_VERSION(&info.version);
|
||||
if (!SDL_GetWMInfo(&info))
|
||||
if (!SDL_GetWMInfo(&info)) {
|
||||
return 0;
|
||||
|
||||
}
|
||||
desc = XkbGetKeyboard(info.info.x11.display,
|
||||
XkbGBN_AllComponentsMask,
|
||||
XkbUseCoreKbd);
|
||||
if (desc == NULL || desc->names == NULL)
|
||||
return 0;
|
||||
|
||||
keycodes = XGetAtomName(info.info.x11.display, desc->names->keycodes);
|
||||
if (keycodes == NULL)
|
||||
fprintf(stderr, "could not lookup keycode name\n");
|
||||
else if (strstart(keycodes, "evdev_", NULL))
|
||||
has_evdev = 1;
|
||||
else if (!strstart(keycodes, "xfree86_", NULL))
|
||||
fprintf(stderr,
|
||||
"unknown keycodes `%s', please report to qemu-devel@nongnu.org\n",
|
||||
keycodes);
|
||||
|
||||
XkbFreeClientMap(desc, XkbGBN_AllComponentsMask, True);
|
||||
if (desc && desc->names) {
|
||||
keycodes = XGetAtomName(info.info.x11.display, desc->names->keycodes);
|
||||
if (keycodes == NULL) {
|
||||
fprintf(stderr, "could not lookup keycode name\n");
|
||||
} else if (strstart(keycodes, "evdev", NULL)) {
|
||||
has_evdev = 1;
|
||||
} else if (!strstart(keycodes, "xfree86", NULL)) {
|
||||
fprintf(stderr, "unknown keycodes `%s', please report to "
|
||||
"qemu-devel@nongnu.org\n", keycodes);
|
||||
}
|
||||
}
|
||||
|
||||
if (desc) {
|
||||
XkbFreeKeyboard(desc, XkbGBN_AllComponentsMask, True);
|
||||
}
|
||||
if (keycodes) {
|
||||
XFree(keycodes);
|
||||
}
|
||||
return has_evdev;
|
||||
}
|
||||
#else
|
||||
|
15
tap-win32.c
15
tap-win32.c
@@ -639,6 +639,18 @@ static int tap_win32_open(tap_win32_overlapped_t **phandle,
|
||||
tap_win32_overlapped_t *handle;
|
||||
} TAPState;
|
||||
|
||||
static void tap_cleanup(VLANClientState *vc)
|
||||
{
|
||||
TAPState *s = vc->opaque;
|
||||
|
||||
qemu_del_wait_object(s->handle->tap_semaphore, NULL, NULL);
|
||||
|
||||
/* FIXME: need to kill thread and close file handle:
|
||||
tap_win32_close(s);
|
||||
*/
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
static void tap_receive(void *opaque, const uint8_t *buf, int size)
|
||||
{
|
||||
TAPState *s = opaque;
|
||||
@@ -673,7 +685,8 @@ int tap_win32_init(VLANState *vlan, const char *model,
|
||||
return -1;
|
||||
}
|
||||
|
||||
s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive, NULL, s);
|
||||
s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive,
|
||||
NULL, tap_cleanup, s);
|
||||
|
||||
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
|
||||
"tap: ifname=%s", ifname);
|
||||
|
@@ -957,7 +957,8 @@ static void gen_tst_cc (DisasContext *dc, TCGv cc, int cond)
|
||||
else if (dc->cc_size == 2)
|
||||
bits = 15;
|
||||
|
||||
tcg_gen_shri_tl(cc, cc_result, 31);
|
||||
tcg_gen_shri_tl(cc, cc_result, bits);
|
||||
tcg_gen_andi_tl(cc, cc, 1);
|
||||
}
|
||||
else {
|
||||
cris_evaluate_flags(dc);
|
||||
|
@@ -32,61 +32,79 @@
|
||||
|
||||
//#define DEBUG_MMU
|
||||
|
||||
/* feature flags taken from "Intel Processor Identification and the CPUID
|
||||
* Instruction" and AMD's "CPUID Specification". In cases of disagreement
|
||||
* about feature names, the Linux name is used. */
|
||||
static const char *feature_name[] = {
|
||||
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
|
||||
"cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
|
||||
"pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */, NULL, "ds" /* Intel dts */, "acpi", "mmx",
|
||||
"fxsr", "sse", "sse2", "ss", "ht" /* Intel htt */, "tm", "ia64", "pbe",
|
||||
};
|
||||
static const char *ext_feature_name[] = {
|
||||
"pni" /* Intel,AMD sse3 */, NULL, NULL, "monitor", "ds_cpl", "vmx", NULL /* Linux smx */, "est",
|
||||
"tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
|
||||
NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
};
|
||||
static const char *ext2_feature_name[] = {
|
||||
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
|
||||
"cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall", "mtrr", "pge", "mca", "cmov",
|
||||
"pat", "pse36", NULL, NULL /* Linux mp */, "nx" /* Intel xd */, NULL, "mmxext", "mmx",
|
||||
"fxsr", "fxsr_opt" /* AMD ffxsr */, "pdpe1gb" /* AMD Page1GB */, "rdtscp", NULL, "lm" /* Intel 64 */, "3dnowext", "3dnow",
|
||||
};
|
||||
static const char *ext3_feature_name[] = {
|
||||
"lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */, "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
|
||||
"3dnowprefetch", "osvw", NULL /* Linux ibs */, NULL, "skinit", "wdt", NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
};
|
||||
|
||||
static void add_flagname_to_bitmaps(char *flagname, uint32_t *features,
|
||||
uint32_t *ext_features,
|
||||
uint32_t *ext2_features,
|
||||
uint32_t *ext3_features)
|
||||
{
|
||||
int i;
|
||||
/* feature flags taken from "Intel Processor Identification and the CPUID
|
||||
* Instruction" and AMD's "CPUID Specification". In cases of disagreement
|
||||
* about feature names, the Linux name is used. */
|
||||
static const char *feature_name[] = {
|
||||
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
|
||||
"cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
|
||||
"pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */, NULL, "ds" /* Intel dts */, "acpi", "mmx",
|
||||
"fxsr", "sse", "sse2", "ss", "ht" /* Intel htt */, "tm", "ia64", "pbe",
|
||||
};
|
||||
static const char *ext_feature_name[] = {
|
||||
"pni" /* Intel,AMD sse3 */, NULL, NULL, "monitor", "ds_cpl", "vmx", NULL /* Linux smx */, "est",
|
||||
"tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
|
||||
NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
};
|
||||
static const char *ext2_feature_name[] = {
|
||||
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
|
||||
"cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall", "mtrr", "pge", "mca", "cmov",
|
||||
"pat", "pse36", NULL, NULL /* Linux mp */, "nx" /* Intel xd */, NULL, "mmxext", "mmx",
|
||||
"fxsr", "fxsr_opt" /* AMD ffxsr */, "pdpe1gb" /* AMD Page1GB */, "rdtscp", NULL, "lm" /* Intel 64 */, "3dnowext", "3dnow",
|
||||
};
|
||||
static const char *ext3_feature_name[] = {
|
||||
"lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */, "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
|
||||
"3dnowprefetch", "osvw", NULL /* Linux ibs */, NULL, "skinit", "wdt", NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
};
|
||||
int found = 0;
|
||||
|
||||
for ( i = 0 ; i < 32 ; i++ )
|
||||
if (feature_name[i] && !strcmp (flagname, feature_name[i])) {
|
||||
*features |= 1 << i;
|
||||
return;
|
||||
found = 1;
|
||||
}
|
||||
for ( i = 0 ; i < 32 ; i++ )
|
||||
if (ext_feature_name[i] && !strcmp (flagname, ext_feature_name[i])) {
|
||||
*ext_features |= 1 << i;
|
||||
return;
|
||||
found = 1;
|
||||
}
|
||||
for ( i = 0 ; i < 32 ; i++ )
|
||||
if (ext2_feature_name[i] && !strcmp (flagname, ext2_feature_name[i])) {
|
||||
*ext2_features |= 1 << i;
|
||||
return;
|
||||
found = 1;
|
||||
}
|
||||
for ( i = 0 ; i < 32 ; i++ )
|
||||
if (ext3_feature_name[i] && !strcmp (flagname, ext3_feature_name[i])) {
|
||||
*ext3_features |= 1 << i;
|
||||
return;
|
||||
found = 1;
|
||||
}
|
||||
fprintf(stderr, "CPU feature %s not found\n", flagname);
|
||||
if (!found) {
|
||||
fprintf(stderr, "CPU feature %s not found\n", flagname);
|
||||
}
|
||||
}
|
||||
|
||||
static void kvm_trim_features(uint32_t *features, uint32_t supported,
|
||||
const char *names[])
|
||||
{
|
||||
int i;
|
||||
uint32_t mask;
|
||||
|
||||
for (i = 0; i < 32; ++i) {
|
||||
mask = 1U << i;
|
||||
if ((*features & mask) && !(supported & mask)) {
|
||||
*features &= ~mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct x86_def_t {
|
||||
@@ -476,17 +494,23 @@ void cpu_reset(CPUX86State *env)
|
||||
env->tr.flags = DESC_P_MASK | (11 << DESC_TYPE_SHIFT);
|
||||
|
||||
cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff,
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK | DESC_R_MASK);
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK |
|
||||
DESC_R_MASK | DESC_A_MASK);
|
||||
cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff,
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_W_MASK);
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
|
||||
DESC_A_MASK);
|
||||
cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff,
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_W_MASK);
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
|
||||
DESC_A_MASK);
|
||||
cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff,
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_W_MASK);
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
|
||||
DESC_A_MASK);
|
||||
cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff,
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_W_MASK);
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
|
||||
DESC_A_MASK);
|
||||
cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff,
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_W_MASK);
|
||||
DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
|
||||
DESC_A_MASK);
|
||||
|
||||
env->eip = 0xfff0;
|
||||
env->regs[R_EDX] = env->cpuid_version;
|
||||
@@ -1421,10 +1445,10 @@ static void host_cpuid(uint32_t function, uint32_t count,
|
||||
#else
|
||||
asm volatile("pusha \n\t"
|
||||
"cpuid \n\t"
|
||||
"mov %%eax, 0(%1) \n\t"
|
||||
"mov %%ebx, 4(%1) \n\t"
|
||||
"mov %%ecx, 8(%1) \n\t"
|
||||
"mov %%edx, 12(%1) \n\t"
|
||||
"mov %%eax, 0(%2) \n\t"
|
||||
"mov %%ebx, 4(%2) \n\t"
|
||||
"mov %%ecx, 8(%2) \n\t"
|
||||
"mov %%edx, 12(%2) \n\t"
|
||||
"popa"
|
||||
: : "a"(function), "c"(count), "S"(vec)
|
||||
: "memory", "cc");
|
||||
@@ -1670,5 +1694,20 @@ CPUX86State *cpu_x86_init(const char *cpu_model)
|
||||
#endif
|
||||
if (kvm_enabled())
|
||||
kvm_init_vcpu(env);
|
||||
if (kvm_enabled()) {
|
||||
kvm_trim_features(&env->cpuid_features,
|
||||
kvm_arch_get_supported_cpuid(env, 1, R_EDX),
|
||||
feature_name);
|
||||
kvm_trim_features(&env->cpuid_ext_features,
|
||||
kvm_arch_get_supported_cpuid(env, 1, R_ECX),
|
||||
ext_feature_name);
|
||||
kvm_trim_features(&env->cpuid_ext2_features,
|
||||
kvm_arch_get_supported_cpuid(env, 0x80000001, R_EDX),
|
||||
ext2_feature_name);
|
||||
kvm_trim_features(&env->cpuid_ext3_features,
|
||||
kvm_arch_get_supported_cpuid(env, 0x80000001, R_ECX),
|
||||
ext3_feature_name);
|
||||
}
|
||||
|
||||
return env;
|
||||
}
|
||||
|
@@ -33,6 +33,89 @@
|
||||
do { } while (0)
|
||||
#endif
|
||||
|
||||
#ifdef KVM_CAP_EXT_CPUID
|
||||
|
||||
static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max)
|
||||
{
|
||||
struct kvm_cpuid2 *cpuid;
|
||||
int r, size;
|
||||
|
||||
size = sizeof(*cpuid) + max * sizeof(*cpuid->entries);
|
||||
cpuid = (struct kvm_cpuid2 *)qemu_mallocz(size);
|
||||
cpuid->nent = max;
|
||||
r = kvm_ioctl(s, KVM_GET_SUPPORTED_CPUID, cpuid);
|
||||
if (r == 0 && cpuid->nent >= max) {
|
||||
r = -E2BIG;
|
||||
}
|
||||
if (r < 0) {
|
||||
if (r == -E2BIG) {
|
||||
qemu_free(cpuid);
|
||||
return NULL;
|
||||
} else {
|
||||
fprintf(stderr, "KVM_GET_SUPPORTED_CPUID failed: %s\n",
|
||||
strerror(-r));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
return cpuid;
|
||||
}
|
||||
|
||||
uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function, int reg)
|
||||
{
|
||||
struct kvm_cpuid2 *cpuid;
|
||||
int i, max;
|
||||
uint32_t ret = 0;
|
||||
uint32_t cpuid_1_edx;
|
||||
|
||||
if (!kvm_check_extension(env->kvm_state, KVM_CAP_EXT_CPUID)) {
|
||||
return -1U;
|
||||
}
|
||||
|
||||
max = 1;
|
||||
while ((cpuid = try_get_cpuid(env->kvm_state, max)) == NULL) {
|
||||
max *= 2;
|
||||
}
|
||||
|
||||
for (i = 0; i < cpuid->nent; ++i) {
|
||||
if (cpuid->entries[i].function == function) {
|
||||
switch (reg) {
|
||||
case R_EAX:
|
||||
ret = cpuid->entries[i].eax;
|
||||
break;
|
||||
case R_EBX:
|
||||
ret = cpuid->entries[i].ebx;
|
||||
break;
|
||||
case R_ECX:
|
||||
ret = cpuid->entries[i].ecx;
|
||||
break;
|
||||
case R_EDX:
|
||||
ret = cpuid->entries[i].edx;
|
||||
if (function == 0x80000001) {
|
||||
/* On Intel, kvm returns cpuid according to the Intel spec,
|
||||
* so add missing bits according to the AMD spec:
|
||||
*/
|
||||
cpuid_1_edx = kvm_arch_get_supported_cpuid(env, 1, R_EDX);
|
||||
ret |= cpuid_1_edx & 0xdfeff7ff;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qemu_free(cpuid);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function, int reg)
|
||||
{
|
||||
return -1U;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int kvm_arch_init_vcpu(CPUState *env)
|
||||
{
|
||||
struct {
|
||||
@@ -40,12 +123,11 @@ int kvm_arch_init_vcpu(CPUState *env)
|
||||
struct kvm_cpuid_entry2 entries[100];
|
||||
} __attribute__((packed)) cpuid_data;
|
||||
uint32_t limit, i, j, cpuid_i;
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
uint32_t unused;
|
||||
|
||||
cpuid_i = 0;
|
||||
|
||||
cpu_x86_cpuid(env, 0, 0, &eax, &ebx, &ecx, &edx);
|
||||
limit = eax;
|
||||
cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused);
|
||||
|
||||
for (i = 0; i <= limit; i++) {
|
||||
struct kvm_cpuid_entry2 *c = &cpuid_data.entries[cpuid_i++];
|
||||
@@ -55,26 +137,17 @@ int kvm_arch_init_vcpu(CPUState *env)
|
||||
/* Keep reading function 2 till all the input is received */
|
||||
int times;
|
||||
|
||||
cpu_x86_cpuid(env, i, 0, &eax, &ebx, &ecx, &edx);
|
||||
times = eax & 0xff;
|
||||
|
||||
c->function = i;
|
||||
c->flags |= KVM_CPUID_FLAG_STATEFUL_FUNC;
|
||||
c->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT;
|
||||
c->eax = eax;
|
||||
c->ebx = ebx;
|
||||
c->ecx = ecx;
|
||||
c->edx = edx;
|
||||
c->flags = KVM_CPUID_FLAG_STATEFUL_FUNC |
|
||||
KVM_CPUID_FLAG_STATE_READ_NEXT;
|
||||
cpu_x86_cpuid(env, i, 0, &c->eax, &c->ebx, &c->ecx, &c->edx);
|
||||
times = c->eax & 0xff;
|
||||
|
||||
for (j = 1; j < times; ++j) {
|
||||
cpu_x86_cpuid(env, i, 0, &eax, &ebx, &ecx, &edx);
|
||||
c = &cpuid_data.entries[cpuid_i++];
|
||||
c->function = i;
|
||||
c->flags |= KVM_CPUID_FLAG_STATEFUL_FUNC;
|
||||
c->eax = eax;
|
||||
c->ebx = ebx;
|
||||
c->ecx = ecx;
|
||||
c->edx = edx;
|
||||
c = &cpuid_data.entries[++cpuid_i];
|
||||
c->flags = KVM_CPUID_FLAG_STATEFUL_FUNC;
|
||||
cpu_x86_cpuid(env, i, 0, &c->eax, &c->ebx, &c->ecx, &c->edx);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -82,46 +155,36 @@ int kvm_arch_init_vcpu(CPUState *env)
|
||||
case 0xb:
|
||||
case 0xd:
|
||||
for (j = 0; ; j++) {
|
||||
cpu_x86_cpuid(env, i, j, &eax, &ebx, &ecx, &edx);
|
||||
c->function = i;
|
||||
c->flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
|
||||
c->index = j;
|
||||
c->eax = eax;
|
||||
c->ebx = ebx;
|
||||
c->ecx = ecx;
|
||||
c->edx = edx;
|
||||
c = &cpuid_data.entries[++cpuid_i];
|
||||
cpu_x86_cpuid(env, i, j, &c->eax, &c->ebx, &c->ecx, &c->edx);
|
||||
|
||||
if (i == 4 && eax == 0)
|
||||
if (i == 4 && c->eax == 0)
|
||||
break;
|
||||
if (i == 0xb && !(ecx & 0xff00))
|
||||
if (i == 0xb && !(c->ecx & 0xff00))
|
||||
break;
|
||||
if (i == 0xd && eax == 0)
|
||||
if (i == 0xd && c->eax == 0)
|
||||
break;
|
||||
|
||||
c = &cpuid_data.entries[cpuid_i++];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cpu_x86_cpuid(env, i, 0, &eax, &ebx, &ecx, &edx);
|
||||
c->function = i;
|
||||
c->eax = eax;
|
||||
c->ebx = ebx;
|
||||
c->ecx = ecx;
|
||||
c->edx = edx;
|
||||
c->flags = 0;
|
||||
cpu_x86_cpuid(env, i, 0, &c->eax, &c->ebx, &c->ecx, &c->edx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
cpu_x86_cpuid(env, 0x80000000, 0, &eax, &ebx, &ecx, &edx);
|
||||
limit = eax;
|
||||
cpu_x86_cpuid(env, 0x80000000, 0, &limit, &unused, &unused, &unused);
|
||||
|
||||
for (i = 0x80000000; i <= limit; i++) {
|
||||
struct kvm_cpuid_entry2 *c = &cpuid_data.entries[cpuid_i++];
|
||||
|
||||
cpu_x86_cpuid(env, i, 0, &eax, &ebx, &ecx, &edx);
|
||||
c->function = i;
|
||||
c->eax = eax;
|
||||
c->ebx = ebx;
|
||||
c->ecx = ecx;
|
||||
c->edx = edx;
|
||||
c->flags = 0;
|
||||
cpu_x86_cpuid(env, i, 0, &c->eax, &c->ebx, &c->ecx, &c->edx);
|
||||
}
|
||||
|
||||
cpuid_data.cpuid.nent = cpuid_i;
|
||||
|
@@ -3241,6 +3241,8 @@ target_ulong helper_lsl(target_ulong selector1)
|
||||
|
||||
selector = selector1 & 0xffff;
|
||||
eflags = helper_cc_compute_all(CC_OP);
|
||||
if ((selector & 0xfffc) == 0)
|
||||
goto fail;
|
||||
if (load_segment(&e1, &e2, selector) != 0)
|
||||
goto fail;
|
||||
rpl = selector & 3;
|
||||
|
96
vl.c
96
vl.c
@@ -201,6 +201,7 @@ ram_addr_t ram_size;
|
||||
int nb_nics;
|
||||
NICInfo nd_table[MAX_NICS];
|
||||
int vm_running;
|
||||
static int autostart;
|
||||
static int rtc_utc = 1;
|
||||
static int rtc_date_offset = -1; /* -1 means no change */
|
||||
int cirrus_vga_enabled = 1;
|
||||
@@ -893,7 +894,7 @@ struct qemu_alarm_timer {
|
||||
|
||||
static inline int alarm_has_dynticks(struct qemu_alarm_timer *t)
|
||||
{
|
||||
return t->flags & ALARM_FLAG_DYNTICKS;
|
||||
return t && (t->flags & ALARM_FLAG_DYNTICKS);
|
||||
}
|
||||
|
||||
static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
|
||||
@@ -1337,7 +1338,7 @@ static void host_alarm_handler(int host_signum)
|
||||
static const char byte = 0;
|
||||
write(alarm_timer_wfd, &byte, sizeof(byte));
|
||||
#endif
|
||||
alarm_timer->flags |= ALARM_FLAG_EXPIRED;
|
||||
if (alarm_timer) alarm_timer->flags |= ALARM_FLAG_EXPIRED;
|
||||
|
||||
if (env) {
|
||||
/* stop the currently executing cpu because a timer occured */
|
||||
@@ -1527,6 +1528,11 @@ static int dynticks_start_timer(struct qemu_alarm_timer *t)
|
||||
|
||||
sigaction(SIGALRM, &act, NULL);
|
||||
|
||||
/*
|
||||
* Initialize ev struct to 0 to avoid valgrind complaining
|
||||
* about uninitialized data in timer_create call
|
||||
*/
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
ev.sigev_value.sival_int = 0;
|
||||
ev.sigev_notify = SIGEV_SIGNAL;
|
||||
ev.sigev_signo = SIGALRM;
|
||||
@@ -2565,7 +2571,7 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque)
|
||||
drives_table[drives_table_idx].unit = unit_id;
|
||||
drives_table[drives_table_idx].onerror = onerror;
|
||||
drives_table[drives_table_idx].drive_opt_idx = arg - drives_opt;
|
||||
strncpy(drives_table[nb_drives].serial, serial, sizeof(serial));
|
||||
strncpy(drives_table[drives_table_idx].serial, serial, sizeof(serial));
|
||||
nb_drives++;
|
||||
|
||||
switch(type) {
|
||||
@@ -2607,11 +2613,13 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque)
|
||||
bdrv_flags |= BDRV_O_CACHE_WB;
|
||||
else if (cache == 3) /* not specified */
|
||||
bdrv_flags |= BDRV_O_CACHE_DEF;
|
||||
if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0 || qemu_key_check(bdrv, file)) {
|
||||
if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0) {
|
||||
fprintf(stderr, "qemu: could not open disk image %s\n",
|
||||
file);
|
||||
return -1;
|
||||
}
|
||||
if (bdrv_key_required(bdrv))
|
||||
autostart = 0;
|
||||
return drives_table_idx;
|
||||
}
|
||||
|
||||
@@ -2658,7 +2666,7 @@ int usb_device_add_dev(USBDevice *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usb_device_add(const char *devname)
|
||||
static int usb_device_add(const char *devname, int is_hotplug)
|
||||
{
|
||||
const char *p;
|
||||
USBDevice *dev;
|
||||
@@ -2675,7 +2683,18 @@ static int usb_device_add(const char *devname)
|
||||
} else if (!strcmp(devname, "keyboard")) {
|
||||
dev = usb_keyboard_init();
|
||||
} else if (strstart(devname, "disk:", &p)) {
|
||||
dev = usb_msd_init(p);
|
||||
BlockDriverState *bs;
|
||||
|
||||
dev = usb_msd_init(p, &bs);
|
||||
if (!dev)
|
||||
return -1;
|
||||
if (bdrv_key_required(bs)) {
|
||||
autostart = 0;
|
||||
if (is_hotplug && monitor_read_bdrv_key(bs) < 0) {
|
||||
dev->handle_destroy(dev);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(devname, "wacom-tablet")) {
|
||||
dev = usb_wacom_init();
|
||||
} else if (strstart(devname, "serial:", &p)) {
|
||||
@@ -2756,7 +2775,7 @@ static int usb_device_del(const char *devname)
|
||||
|
||||
void do_usb_add(const char *devname)
|
||||
{
|
||||
usb_device_add(devname);
|
||||
usb_device_add(devname, 1);
|
||||
}
|
||||
|
||||
void do_usb_del(const char *devname)
|
||||
@@ -3206,10 +3225,10 @@ static int ram_save_live(QEMUFile *f, int stage, void *opaque)
|
||||
/* try transferring iterative blocks of memory */
|
||||
|
||||
if (stage == 3) {
|
||||
cpu_physical_memory_set_dirty_tracking(0);
|
||||
|
||||
/* flush all remaining blocks regardless of rate limiting */
|
||||
while (ram_save_block(f) != 0);
|
||||
cpu_physical_memory_set_dirty_tracking(0);
|
||||
}
|
||||
|
||||
qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
|
||||
@@ -4230,9 +4249,7 @@ static const QEMUOption qemu_options[] = {
|
||||
{ "boot", HAS_ARG, QEMU_OPTION_boot },
|
||||
{ "snapshot", 0, QEMU_OPTION_snapshot },
|
||||
{ "m", HAS_ARG, QEMU_OPTION_m },
|
||||
#ifndef _WIN32
|
||||
{ "k", HAS_ARG, QEMU_OPTION_k },
|
||||
#endif
|
||||
#ifdef HAS_AUDIO
|
||||
{ "audio-help", 0, QEMU_OPTION_audio_help },
|
||||
{ "soundhw", HAS_ARG, QEMU_OPTION_soundhw },
|
||||
@@ -4334,45 +4351,6 @@ static const QEMUOption qemu_options[] = {
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
/* password input */
|
||||
|
||||
int qemu_key_check(BlockDriverState *bs, const char *name)
|
||||
{
|
||||
char password[256];
|
||||
int i;
|
||||
|
||||
if (!bdrv_is_encrypted(bs))
|
||||
return 0;
|
||||
|
||||
term_printf("%s is encrypted.\n", name);
|
||||
for(i = 0; i < 3; i++) {
|
||||
monitor_readline("Password: ", 1, password, sizeof(password));
|
||||
if (bdrv_set_key(bs, password) == 0)
|
||||
return 0;
|
||||
term_printf("invalid password\n");
|
||||
}
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static BlockDriverState *get_bdrv(int index)
|
||||
{
|
||||
if (index > nb_drives)
|
||||
return NULL;
|
||||
return drives_table[index].bdrv;
|
||||
}
|
||||
|
||||
static void read_passwords(void)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 6; i++) {
|
||||
bs = get_bdrv(i);
|
||||
if (bs)
|
||||
qemu_key_check(bs, bdrv_get_device_name(bs));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAS_AUDIO
|
||||
struct soundhw soundhw[] = {
|
||||
#ifdef HAS_AUDIO_CHOICE
|
||||
@@ -4639,7 +4617,6 @@ int main(int argc, char **argv, char **envp)
|
||||
int fds[2];
|
||||
int tb_size;
|
||||
const char *pid_file = NULL;
|
||||
int autostart;
|
||||
const char *incoming = NULL;
|
||||
int fd = 0;
|
||||
struct passwd *pwd = NULL;
|
||||
@@ -4696,7 +4673,7 @@ int main(int argc, char **argv, char **envp)
|
||||
kernel_cmdline = "";
|
||||
cyls = heads = secs = 0;
|
||||
translation = BIOS_ATA_TRANSLATION_AUTO;
|
||||
monitor_device = "vc";
|
||||
monitor_device = "vc:80Cx24C";
|
||||
|
||||
serial_devices[0] = "vc:80Cx24C";
|
||||
for(i = 1; i < MAX_SERIAL_PORTS; i++)
|
||||
@@ -5513,6 +5490,7 @@ int main(int argc, char **argv, char **envp)
|
||||
cpu_exec_init_all(tb_size * 1024 * 1024);
|
||||
|
||||
bdrv_init();
|
||||
dma_helper_init();
|
||||
|
||||
/* we always create the cdrom drive, even if no disk is there */
|
||||
|
||||
@@ -5637,7 +5615,7 @@ int main(int argc, char **argv, char **envp)
|
||||
/* init USB devices */
|
||||
if (usb_enabled) {
|
||||
for(i = 0; i < usb_devices_index; i++) {
|
||||
if (usb_device_add(usb_devices[i]) < 0) {
|
||||
if (usb_device_add(usb_devices[i], 0) < 0) {
|
||||
fprintf(stderr, "Warning: could not add USB device %s\n",
|
||||
usb_devices[i]);
|
||||
}
|
||||
@@ -5693,6 +5671,7 @@ int main(int argc, char **argv, char **envp)
|
||||
}
|
||||
|
||||
text_consoles_set_display(display_state);
|
||||
qemu_chr_initial_reset();
|
||||
|
||||
if (monitor_device && monitor_hd)
|
||||
monitor_init(monitor_hd, !nographic);
|
||||
@@ -5742,18 +5721,11 @@ int main(int argc, char **argv, char **envp)
|
||||
if (loadvm)
|
||||
do_loadvm(loadvm);
|
||||
|
||||
if (incoming) {
|
||||
autostart = 0; /* fixme how to deal with -daemonize */
|
||||
if (incoming)
|
||||
qemu_start_incoming_migration(incoming);
|
||||
}
|
||||
|
||||
{
|
||||
/* XXX: simplify init */
|
||||
read_passwords();
|
||||
if (autostart) {
|
||||
vm_start();
|
||||
}
|
||||
}
|
||||
if (autostart)
|
||||
vm_start();
|
||||
|
||||
if (daemonize) {
|
||||
uint8_t status = 0;
|
||||
|
12
vnc.c
12
vnc.c
@@ -1216,30 +1216,39 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
|
||||
case 0xb8: /* Right ALT */
|
||||
break;
|
||||
case 0xc8:
|
||||
case 0x48:
|
||||
kbd_put_keysym(QEMU_KEY_UP);
|
||||
break;
|
||||
case 0xd0:
|
||||
case 0x50:
|
||||
kbd_put_keysym(QEMU_KEY_DOWN);
|
||||
break;
|
||||
case 0xcb:
|
||||
case 0x4b:
|
||||
kbd_put_keysym(QEMU_KEY_LEFT);
|
||||
break;
|
||||
case 0xcd:
|
||||
case 0x4d:
|
||||
kbd_put_keysym(QEMU_KEY_RIGHT);
|
||||
break;
|
||||
case 0xd3:
|
||||
case 0x53:
|
||||
kbd_put_keysym(QEMU_KEY_DELETE);
|
||||
break;
|
||||
case 0xc7:
|
||||
case 0x47:
|
||||
kbd_put_keysym(QEMU_KEY_HOME);
|
||||
break;
|
||||
case 0xcf:
|
||||
case 0x4f:
|
||||
kbd_put_keysym(QEMU_KEY_END);
|
||||
break;
|
||||
case 0xc9:
|
||||
case 0x49:
|
||||
kbd_put_keysym(QEMU_KEY_PAGEUP);
|
||||
break;
|
||||
case 0xd1:
|
||||
case 0x51:
|
||||
kbd_put_keysym(QEMU_KEY_PAGEDOWN);
|
||||
break;
|
||||
default:
|
||||
@@ -2297,9 +2306,8 @@ static void vnc_listen_read(void *opaque)
|
||||
|
||||
void vnc_display_init(DisplayState *ds)
|
||||
{
|
||||
VncDisplay *vs;
|
||||
VncDisplay *vs = qemu_mallocz(sizeof(*vs));
|
||||
|
||||
vs = qemu_mallocz(sizeof(VncState));
|
||||
dcl = qemu_mallocz(sizeof(DisplayChangeListener));
|
||||
|
||||
ds->opaque = vs;
|
||||
|
Reference in New Issue
Block a user