Compare commits

...

38 Commits

Author SHA1 Message Date
Anthony Liguori
34aee2552f Update for 0.10.4 release
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-11 13:13:19 -05:00
Kevin Wolf
9fd0e57dc9 Improve block range checks
This patch makes the range checks for block requests more strict: It fixes a
potential integer overflow and checks for negative offsets. Also, it adds the
check for compressed writes.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-08 16:04:20 -05:00
Amit Shah
2fd0f93286 e1000: Do not reinit pci config space to 0
pci_register_device already mallocs the pci config space buffer filled
with zeroes.

Doing this again breaks some default config space writes like
setting the subsystem vendor id and subsystem device id.

Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-08 15:57:41 -05:00
Alexander Graf
8bd8199f70 AIO deletion race fix
When deleting an fd event there is a chance the object doesn't get
deleted, but only ->deleted set positive and deleted somewhere later.

Now, if we create a handler for the fd again before the actual
deletion occurs, we end up writing data into an object that has
->deleted set, which is obviously wrong.

I see two ways to fix this:

1. Don't return ->deleted objects in the search
2. Unset ->deleted in the search

This patch implements 1. which feels safer to do. It fixes AIO issues
I've seen with curl, as libcurl unsets fd event listeners pretty
frequently.

Signed-off-by: Alexander Graf <alex@csgraf.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-08 15:57:33 -05:00
Glauber Costa
2da1e39864 reset state for load_linux
The linux loader is just an option rom like any other, just with
some special requirements. Right now, our option rom resetting
mechanism is not being applied to it. As a result, users using
-kernel will not be able to successfully reboot their machines

This patch fixes it by saving all the data we generated in
the load_linux() function, to be used later by the option rom
resetting mechanism.

Signed-off-by: Glauber Costa <glommer@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-08 15:57:20 -05:00
Glauber Costa
b468f27acd register reset handler for option_roms
Currently, boot options are not preserved across a system reset.
option roms can modify themselves, or can for instance restore the real
int 0x19 vector after they tried to boot from it.

To properly do that, we need a reset handler registered to deal with option
roms. This patch is based on current version on qemu-kvm.git

Signed-off-by: Glauber Costa <glommer@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-08 15:55:22 -05:00
Gleb Natapov
8bc2ad6a6a Fix cluster freeing in qcow2
Need to drop QCOW_OFLAG_COPIED from a cluster pointer before freeing it.

Add an explanation how thing meant to work.

Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-08 15:54:06 -05:00
Anthony Liguori
f24f1e2a85 Enable power button even generation.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-08 10:20:48 -05:00
Anthony Liguori
5d00b89b12 Update version for 0.10.3 release
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-01 11:57:29 -05:00
aliguori
a2b8ec7d7d Implement cancellation method for dma async I/O (Avi Kivity)
Move the dma helpers to a private aio pool, and implement a cancellation
method for them.  Should prevent issues when cancelling I/O while dma is
in progress.

Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6872 c046a42c-6fe2-441c-8c8c-71466251a162
2009-05-01 11:06:12 -05:00
aliguori
a95ad7bcbb Convert vectored aio emulation to use a dedicated pool (Avi Kivity)
This allows us to remove a hack in the vectored aio cancellation code.

Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6871 c046a42c-6fe2-441c-8c8c-71466251a162
2009-05-01 11:06:04 -05:00
aliguori
3d2d1e3960 Refactor aio callback allocation to use an aiocb pool (Avi Kivity)
Move the AIOCB allocation code to use a dedicate structure, AIOPool.  AIOCB
specific information, such as the AIOCB size and cancellation routine, is
moved into the pool.

At present, there is exactly one pool per block format driver, maintaining
the status quo.

Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6870 c046a42c-6fe2-441c-8c8c-71466251a162
2009-05-01 11:05:57 -05:00
Alex Williamson
3382d425bc Fix hw/acpi.c build w/ DEBUG enabled
Trivial build warning/fixes when the local DEBUG define is enabled.

Signed-off-by: Alex Williamson <alex.williamson@hp.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-01 10:13:40 -05:00
Anthony Liguori
2031cfc4ea Make sure not to fall through on error in loadvm
This is from the KVM tree

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-01 10:13:32 -05:00
Chris Wright
260437cba3 Pci nic: pci_register_device can fail
The pci_register_device() call in PCI nic initialization routines can
fail.  Handle this failure and propagate a meaningful error message to
the user instead of generating a SEGV.

Cc: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Chris Wright <chrisw@sous-sol.org>
Signed-off-by: Avi Kivity <avi@qumranet.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-01 10:13:24 -05:00
Anthony Liguori
233e01e475 Fix serial option with -drive
This is from the KVM tree.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-01 10:13:17 -05:00
Glauber Costa
544995e22e suport device driver initialization model
According to PnP specification, Appendix B, Option ROMs
that support DDIM (device driver initialization model) should
have their memory space writeable.

KVM deviates from us here, by removing the IO_MEM_ROM flag,
to allow for PCI option ROMs (they require DDIM). However,
there's absolutely no reason we can't do the same.

Signed-off-by: Glauber Costa <glommer@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-01 10:12:27 -05:00
Jan Kiszka
57ba0792ca kvm: Avoid COW if KVM MMU is asynchronous
Avi Kivity wrote:
> Suggest wrapping in a function and hiding it deep inside kvm-all.c.
>

Done in v2:

---------->

If the KVM MMU is asynchronous (kernel does not support MMU_NOTIFIER),
we have to avoid COW for the guest memory. Otherwise we risk serious
breakage when guest pages change there physical locations due to COW
after fork. Seen when forking smbd during runtime via -smb.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-01 10:11:02 -05:00
Gerd Hoffmann
a2daabc49a vnc: windup keypad keys for qemu console emulation
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-01 10:08:16 -05:00
aliguori
530a491fc3 block-vpc: Don't silently create smaller image than requested (Kevin Wolf)
The algorithm from the VHD specification for CHS calculation silently limits
images to 127 GB which may confuse a user who requested a larger image. Better
output an error message and abort.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7183 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-18 15:39:10 +00:00
aliguori
2fcc1d5b69 Regenerate BIOS for stable branch
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7173 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-17 21:12:04 +00:00
aliguori
cb2768eb3c 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>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7172 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-17 21:09:14 +00:00
aliguori
202e9d440e hpet: Fix emulation of HPET_TN_SETVAL (Jan Kiszka)
While Intel's spec is not that clear here, latest changes to Linux' HPET
code (commit c23e253e67c9d8a91a0ffa33c1f571a17f0a2403, "x86: hpet: stop
HPET_COUNTER when programming periodic mode") strongly suggest that
HPET_TN_SETVAL rather means: Set _both_ the comparator value and
register.

With this patch applied, I'm again able to boot 2.6.30-rc kernels as
they no longer panic like this (which was due to the comparator
register remaining 0):

ENABLING IO-APIC IRQs
..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1
..MP-BIOS bug: 8254 timer not connected to IO-APIC
...trying to set up timer (IRQ0) through the 8259A ...
..... (found apic 0 pin 2) ...
....... failed.
...trying to set up timer as Virtual Wire IRQ...
..... failed.
...trying to set up timer as ExtINT IRQ...
..... failed :(.
Kernel panic - not syncing: IO-APIC + timer doesn't work! [...]

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7171 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-17 21:05:45 +00:00
aliguori
3c398c0f86 kvm: Fix cpuid initialization (Jan Kiszka)
Fix (more or less) spurious guest boot failures due to corrupted cpuid
states. The reason was insufficient initialization of cpuid entries
before passing them to the kernel.

At this chance also fix improper entry pointer progression and simplify
the code a bit.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7170 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-17 21:05:41 +00:00
aliguori
4df8f71ee5 qcow2 corruption: Fix alloc_cluster_link_l2 (Kevin Wolf)
This patch fixes a qcow2 corruption bug introduced in SVN Rev 5861. L2 tables
are big endian, so entries must be converted before being passed to functions.

This bug is easy to trigger. The following script will create and destroy a
qcow2 image (the header is gone after three loop iterations):

    #!/bin/bash
    qemu-img create -f qcow2 test.qcow 1M
    for i in $(seq 1 10); do
    qemu-system-x86_64 -hda test.qcow -monitor stdio > /dev/null 2>&1 <<EOF
    savevm test-$i
    quit
    EOF
    done

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7166 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-17 20:44:41 +00:00
aliguori
84eba9b8f1 Free VLANClientState using qemu_free() (Mark McLoughlin)
It's allocated using qemu_mallocz(), so ...

The name and model strings are strdup() allocated, so free()
is still appropriate for them.

Reported-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7161 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-17 18:07:01 +00:00
aliguori
a34b6eb776 Introduce VLANClientState::cleanup() (Mark McLoughlin)
We're currently leaking memory and file descriptors on device
hot-unplug.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7160 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-17 18:06:56 +00:00
aliguori
1ed3d07a22 Use NICInfo::model for eepro100 savevm ID string (Mark McLoughlin)
NICInfo::model will always be identical to the device name strings
we're currently passing to nic_init(). Just re-use NICInfo::model.

This makes it clear why we use vc->model for unregister_savevm()
in a subsequent patch.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7159 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-17 18:06:50 +00:00
aliguori
00f56b3dcf Add unregister_savevm() (Mark McLoughlin)
Currently there's no way to unregister a savevm callback, so
e.g. if a NIC is hot-unplugged and a savevm is issued, we'll
segfault.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7158 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-17 18:06:46 +00:00
aliguori
71dc1b6fcb Remove NICInfo from e1000 and mipsnet state (Mark McLoughlin)
NICInfo isn't used after initialization, so remove it from the driver
state structures.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7157 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-17 18:06:42 +00:00
aliguori
eb5951f333 Remove some useless malloc() checking (Mark McLoughlin)
Now that we abort() on malloc, neither qemu_find_vlan() nor
net_tap_fd_init() can fail.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7156 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-17 18:06:38 +00:00
aliguori
8cacc9ad14 Don't fail PCI hotplug if no NIC model is supplied (Mark McLoughlin)
It's perfectly fine to not supply a NIC model when adding
a new NIC - we supply the default model to pci_nic_init()
and it uses that if one wasn't explicitly supplied.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7155 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-17 18:06:34 +00:00
aliguori
76dcd4921c Fix error handling in net_client_init() (Mark McLoughlin)
We weren't freeing the name string everywhere.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7154 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-17 18:06:31 +00:00
aliguori
0ee50993ce struct iovec is now universally available (Mark McLoughlin)
struct iovec is now defined in qemu-common.h if needed, so we don't need
the tap code to handle !defined(HAVE_IOVEC).

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7153 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-17 18:06:27 +00:00
aliguori
7020c09209 Remove stray GSO code from virtio_net (Mark McLoughlin)
Obviously merged from kvm-userspace accidentally.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7152 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-17 18:06:24 +00:00
aliguori
8bb66d8601 Recognise evdev(xx)_aliases(yy) and xfree86(xx)_aliases(yy) as keymap names.
Newer Xorg use these with non-default kemaps (such as the ThinkPad keymap).

aliguori: this is from r7097 in trunk by balrog

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7098 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-13 13:29:40 +00:00
aliguori
bcb8c5535d Make PCI config status register read-only
From the documentation I can find, this register is supposed to be read-only.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7071 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-10 20:49:44 +00:00
aliguori
da95f49a9d Fix crash on resolution change -> screen dump -> vga redraw (Avi Kivity)
The vga screen dump function updates last_width and last_height,
but does not change the DisplaySurface that these variables describe.
A consequent vga_draw_graphic() will therefore fail to resize the
surface and crash.

Fix by invalidating the display state after a screen dump, forcing
vga_draw_graphic() to reallocate the DisplaySurface.

Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7069 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-10 18:36:38 +00:00
47 changed files with 687 additions and 198 deletions

View File

@@ -1,3 +1,29 @@
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)

View File

@@ -1 +1 @@
0.10.2
0.10.4

3
aio.c
View File

@@ -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;

View File

@@ -903,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];
@@ -916,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:

View File

@@ -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

69
block.c
View File

@@ -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;
}
@@ -530,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;
@@ -1167,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);
}
@@ -1332,6 +1340,13 @@ typedef struct VectorTranslationState {
BlockDriverAIOCB *this_aiocb;
} VectorTranslationState;
static void bdrv_aio_cancel_vector(BlockDriverAIOCB *acb)
{
VectorTranslationState *s = acb->opaque;
bdrv_aio_cancel(s->aiocb);
}
static void bdrv_aio_rw_vector_cb(void *opaque, int ret)
{
VectorTranslationState *s = opaque;
@@ -1354,7 +1369,8 @@ static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
{
VectorTranslationState *s = qemu_mallocz(sizeof(*s));
BlockDriverAIOCB *aiocb = qemu_aio_get(bs, cb, opaque);
BlockDriverAIOCB *aiocb = qemu_aio_get_pool(&vectored_aio_pool, bs,
cb, opaque);
s->this_aiocb = aiocb;
s->iov = iov;
@@ -1443,14 +1459,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);
}
@@ -1551,6 +1560,9 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
void bdrv_init(void)
{
aio_pool_init(&vectored_aio_pool, sizeof(BlockDriverAIOCB),
bdrv_aio_cancel_vector);
bdrv_register(&bdrv_raw);
bdrv_register(&bdrv_host_device);
#ifndef _WIN32
@@ -1568,18 +1580,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;
@@ -1587,12 +1606,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;
}
/**************************************************************/

View File

@@ -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;
@@ -90,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;
};
@@ -140,6 +146,7 @@ struct BlockDriverState {
};
struct BlockDriverAIOCB {
AIOPool *pool;
BlockDriverState *bs;
BlockDriverCompletionFunc *cb;
void *opaque;
@@ -148,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;

View File

@@ -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));
@@ -126,7 +128,7 @@ static BlockDriverAIOCB *dma_bdrv_io(
DMABlockState *dbs = qemu_malloc(sizeof(*dbs));
dbs->bs = bs;
dbs->acb = qemu_aio_get(bs, cb, opaque);
dbs->acb = qemu_aio_get_pool(&dma_aio_pool, bs, cb, opaque);
dbs->sg = sg;
dbs->sector_num = sector_num;
dbs->sg_cur_index = 0;
@@ -153,3 +155,14 @@ BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs,
return dma_bdrv_io(bs, sg, sector, cb, opaque, 1);
}
static void dma_aio_cancel(BlockDriverAIOCB *acb)
{
DMABlockState *dbs = (DMABlockState *)acb->opaque;
bdrv_aio_cancel(dbs->acb);
}
void dma_helper_init(void)
{
aio_pool_init(&dma_aio_pool, sizeof(BlockDriverAIOCB), dma_aio_cancel);
}

1
dma.h
View File

@@ -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

4
exec.c
View File

@@ -2386,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;
}

View File

@@ -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
}

View File

@@ -75,7 +75,6 @@ enum {
typedef struct E1000State_st {
PCIDevice dev;
VLANClientState *vc;
NICInfo *nd;
int mmio_index;
uint32_t mac_reg[0x8000];
@@ -1034,6 +1033,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 +1063,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 +1087,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 +1104,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;

View File

@@ -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 */

View File

@@ -554,6 +554,16 @@ static CPUWriteMemoryFunc *eth_write[] = {
&eth_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)
{
@@ -585,7 +595,8 @@ void *etraxfs_eth_init(NICInfo *nd, CPUState *env,
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_receive, eth_can_receive,
eth_cleanup, eth);
eth->vc->opaque = eth;
eth->vc->link_status_changed = eth_set_link;

View File

@@ -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

View File

@@ -239,6 +239,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);

View File

@@ -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);
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);
}

View File

@@ -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,17 @@ 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);
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);

View File

@@ -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 */

View File

@@ -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);
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);

41
hw/pc.c
View File

@@ -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,7 +563,7 @@ 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)
@@ -689,6 +714,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 +927,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,
load_linux(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);
offset = TARGET_PAGE_SIZE;
}

View File

@@ -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)

View File

@@ -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:

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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. */
}

View File

@@ -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);
}

View File

@@ -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)
@@ -1452,7 +1458,9 @@ 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);
usbnet_receive,
usbnet_can_receive,
usbnet_cleanup, s);
qemu_format_nic_info_str(s->vc, s->mac);

View File

@@ -2678,4 +2678,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);
}

View File

@@ -338,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))))
@@ -575,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;
@@ -603,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);

View File

@@ -815,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,

View File

@@ -117,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);

View File

@@ -656,3 +656,21 @@ int kvm_has_sync_mmu(void)
return 0;
}
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
}
}

2
kvm.h
View File

@@ -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);

119
net.c
View File

@@ -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) {
@@ -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;
@@ -1819,10 +1853,6 @@ void net_host_device_remove(int vlan_id, const char *device)
VLANClientState *vc;
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))
@@ -1901,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)

3
net.h
View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

Binary file not shown.

View File

@@ -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);
}

View File

@@ -643,6 +643,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
@@ -835,6 +851,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 */

4
sdl.c
View File

@@ -161,9 +161,9 @@ static int check_for_evdev(void)
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))
else if (strstart(keycodes, "evdev", NULL))
has_evdev = 1;
else if (!strstart(keycodes, "xfree86_", NULL))
else if (!strstart(keycodes, "xfree86", NULL))
fprintf(stderr,
"unknown keycodes `%s', please report to qemu-devel@nongnu.org\n",
keycodes);

View File

@@ -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);

View File

@@ -40,12 +40,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 +54,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 +72,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;

3
vl.c
View File

@@ -2566,7 +2566,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) {
@@ -5485,6 +5485,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 */

9
vnc.c
View File

@@ -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: