Compare commits

...

146 Commits

Author SHA1 Message Date
Anthony Liguori
9eab386edb Update changelot for 0.10.6 release 2009-07-16 18:50:52 -05:00
Dinesh Subhraveti
0def14568c Initialize PS2 keyboard / mouse state on reset
Currently only common PS2 state is initialized, leaving keyboard and
mouse specific state to contain stale values.

Signed-off-by: Dinesh Subhraveti <dineshs@us.ibm.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-07-16 18:49:08 -05:00
Beth Kon
ca888361bb Reset HPET config register on hpet_reset
Without this, after system reset, hpet does not detect transition from
non-legacy to legacy mode.

Signed-off-by: Beth Kon <eak@us.ibm.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-07-16 18:49:08 -05:00
Paolo Bonzini
df97ff696b honor -S on incoming migration
-S is not honored by qemu on incoming migration.  If a domain is migrated
while paused, thus, it will start running on the remote machine; this
is wrong.

Given the trivial patch to fix this, it looks more like a thinko
than anything else, probably dating back to the qemu-kvm merge.
The interesting part is that the -S mechanism was in fact *used* when
migrating (setting autostart = 0) and the incoming migration code was
starting the VM at the end of the migration.

Since I was removing the vm_start from there, I also corrected a related
imprecision.  The code was doing a vm_stop "just in case", but we can
be sure that the VM is not running---the vm_start call in vl.c has not
been reached yet.  So the vm_stop is removed together with the vm_start.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-07-16 18:49:07 -05:00
Anthony Liguori
cc15f92832 Update for 0.10.6 release 2009-07-10 17:57:42 -05:00
Anthony Liguori
2670257db0 Revert "Make sure to use SDL_CFLAGS everywhere we include SDL headers"
This reverts commit accceed914.

This has proven to cause all sorts of odd build breakages.  I don't think it's
quite ready for stable.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-07-10 17:57:42 -05:00
Glauber Costa
aae9547639 flush pending aio requests
When we finish migration, there may be pending async io requests
in flight. If we don't flush it before stage3 starting, it might be
the case that the guest loses it.

Signed-off-by: Glauber Costa <glommer@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-07-10 17:26:09 -05:00
Anthony Liguori
2872b8a445 Make sure to only vm_start() a failed migration if we were running to begin
with.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-07-10 17:26:09 -05:00
Mark McLoughlin
51224c6f78 Unregister savevm callback in eeprom93xx_free()
Otherwise if you hot remove an eepro100 NIC and then migrate,
you get:

  Unknown savevm section or instance 'eeprom' 0

on the destination side.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-07-10 17:26:09 -05:00
Mark McLoughlin
ed8f8da7a6 Don't leak VLANClientState on PCI hot remove
destroy_nic() requires that NICInfo::private by a PCIDevice pointer,
but then goes on to require that the same pointer matches
VLANClientState::opaque.

That is no longer the case for virtio-net since qdev and wasn't
previously the case for rtl8139, ne2k_pci or eepro100.

Make the situation a lot more clear by maintaining a VLANClientState
pointer in NICInfo.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-07-10 17:26:03 -05:00
G 3
960b646371 Substitute O_DSYNC with O_SYNC or O_FSYNC when needed.
Signed-off-by: John Arbuckle <programmingkidx@gmail.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-07-10 17:15:03 -05:00
Jan Kiszka
fc78bd4503 sdl: Fix memory leakage
Valgrind was so kind to remark that no one bothers to release keycodes
after use and that something is fishy about cleaning up the requested
keyboard descriptor. With this patch applied, we no longer leak about
12k during startup.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-07-10 17:15:03 -05:00
Isaku Yamahata
259cf68eb1 cpu_unregister_map_client: fix memory leak.
fix memory leak in cpu_unregister_map_client() and cpu_notify_map_clients().

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-07-10 17:15:03 -05:00
Eduardo Habkost
41de90f32c Fix vga_screen_dump_blank() PPM generation
vga_screen_dump_blank() was not generating a valid PPM file: the width of the
image made no sense (why it was multiplied by sizeof(uint32_t)?), and there was
only one sample per pixel, instead of three.

(cherry picked from commit 77d4db015c)

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-06-16 17:46:59 -05:00
Mark McLoughlin
3e6b53eb32 Prevent CD-ROM media eject while device is locked
Section 10.8.25 ("START/STOP UNIT Command") of SFF-8020i states that
if the device is locked we should refuse to eject if the device is
locked.

ASC_MEDIA_REMOVAL_PREVENTED is the appropriate return in this case.

In order to stop itself from ejecting the media it is running from,
Fedora's installer (anaconda) requires the CDROMEJECT ioctl() to fail
if the drive has been previously locked.

See also https://bugzilla.redhat.com/501412

(cherry picked from commit aea2a33c73)

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-06-16 17:46:59 -05:00
Jan Kiszka
80de8ace66 kvm: Fix IRQ injection into full queue
User space may only inject interrupts during kvm_arch_pre_run if
ready_for_interrupt_injection is set in kvm_run. But that field is
updated on exit from KVM_RUN, so we must ensure that we enter the
kernel after potentially queuing an interrupt, otherwise we risk to
loose one - like it happens with the current code against latest
kernel modules (since kvm-86) that started to queue only a single
interrupt.

Fix the problem by reordering kvm_cpu_exec.

Credits go to Gleb Natapov for analyzing the issue in details.

(cherry picked from commit 8c14c17395)

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-06-16 17:46:58 -05:00
Nitin A Kamble
ea0c91a0af QEMU KVM: i386: Fix the cpu reset state
As per the IA32 processor manual, the accessed bit is set to 1 in the
processor state after reset. qemu pc cpu_reset code was missing this
accessed bit setting.

(cherry picked from commit 538f368612)

Signed-off-by: Nitin A Kamble <nitin.a.kamble@intel.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-06-16 17:46:58 -05:00
Gerd Hoffmann
71080d96fd virtio blk: fix warning.
(cherry picked from commit 5c5dafdc5e)

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-06-16 17:46:58 -05:00
Sebastian Herbszt
a5617318fe lsi53c895a: Implement write access to DMA Byte Counter
Adds CASE_SET_REG24 and fixes the following errors:

lsi_scsi: error: Unhandled writeb 0x24 = 0x0
lsi_scsi: error: Unhandled writeb 0x25 = 0x0

(cherry picked from commit 49c47daa32)

Signed-off-by: Sebastian Herbszt <herbszt@gmx.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-06-16 17:46:58 -05:00
Sebastian Herbszt
73cf22cb60 lsi53c895a: Implement read and write access to DMA Next Address
Fixes the following errors:

lsi_scsi: error: Unhandled writeb 0x28 = 0x0
lsi_scsi: error: Unhandled writeb 0x29 = 0x0
lsi_scsi: error: Unhandled writeb 0x2a = 0x0
lsi_scsi: error: Unhandled writeb 0x2b = 0x0

(cherry picked from commit 4b9a2d6de7)

Signed-off-by: Sebastian Herbszt <herbszt@gmx.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-06-16 17:46:58 -05:00
Sebastian Herbszt
04f4e710a0 lsi53c895a: Implement Scratch Byte Register
Fixes the following errors:

lsi_scsi: error: Unhandled writeb 0x3a = 0x0
lsi_scsi: error: readb 0x3a

(cherry picked from commit bd8ee11a6b)

Signed-off-by: Sebastian Herbszt <herbszt@gmx.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-06-16 17:46:57 -05:00
Anthony Liguori
accceed914 Make sure to use SDL_CFLAGS everywhere we include SDL headers
(cherry picked from commit 537fe2d63f)

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-06-16 17:46:57 -05:00
Andrea Arcangeli
f29602ca0e fix qemu_aio_flush
qemu_aio_wait by invoking the bh or one of the aio completion
callbacks, could end up submitting new pending aio, breaking the
invariant that qemu_aio_flush returns only when no pending aio is
outstanding (possibly a problem for migration as such).

(cherry picked from commit 986c28d655)

Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: Kevin Wolf <kwolf@redhat.com>
2009-06-16 17:46:57 -05:00
Uri Lublin
17489dd7e9 migrate_fd_close: delete associated io-handler before closing the fd
It may happen that the io-handler is still registered. That causes
select() to return with EBADF, not calling handlers for other fds.

The io-handler would be registered when (on the source) the whole state
was written but not yet flushed. For example when using QEMUFileBuffered,
(tcp-migration) there may be data left in a buffer waiting to be transferred.
In such a case buffered_close() calls buffered_flush() which calls
migrate_fd_put_buffer, which may, upon EAGAIN, register migrate_fd_put_notify
as a handler.

(cherry picked from commit e19252d32c)

Signed-off-by: Uri Lublin <uril@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-06-16 17:11:19 -05:00
Uri Lublin
936d7bf944 exec-migration: handle EINTR in popen_get_buffer()
Sometimes, upon interrupt, fread returns with no data, and
the (incoming exec) migration fails.

Fix by retrying on such a case.

(cherry picked from commit 8a67ec4d84)

Signed-off-by: Uri Lublin <uril@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-06-16 17:11:13 -05:00
Stefan Weil
d13317e197 Fix prototype of function zfree.
(cherry picked from commit d084eab6f8)

Signed-off-by: Stefan Weil <weil@mail.berlios.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-06-16 17:11:02 -05:00
Jason Wessel
75204ffc5b serial: fix lost character after sysrq
After creating an automated regression test to test the sysrq
responses while running a linux image in qemu, I found that the
simulated uart was eating the character right after the sysrq about
75% of the time.

The problem is that the qemu sets the LSR_DR (data ready) bit on a
serial break.  The automated tests can send a break and the sysrq
character quickly enough that the qemu serial fifo has a real
character available. When there is valid character in the fifo, it
gets consumed by the serial driver in the guest OS.

The real hardware also appears to set the LSR_DR but always appears to
have a null byte in this condition.  This patch changes the qemu
behavior to match the tested characteristics of a real 16550 chip.

Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Signed-off-by: Glauber Costa <glommer@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-28 02:04:20 -05:00
Gleb Natapov
9fb2ec9a1e Don't send all gratuitous packets at once.
Use timer to separate them in time.

Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Glauber Costa <glommer@redhat.com>
2009-05-28 02:02:38 -05:00
Gleb Natapov
a8bc8570fa Minimal ethernet frame length is 64 bytes.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Glauber Costa <glommer@redhat.com>
2009-05-28 02:02:34 -05:00
aliguori
700ece804f net: Fix -net socket,listen (Jan Kiszka)
In case no symbolic name is provided when requesting VLAN connection via
listening TCP socket ('-net socket,listen=...'), qemu crashes. This
fixes the cause.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Glauber Costa <glommer@redhat.com>
2009-05-28 02:02:04 -05:00
Chris Lalancette
71c55593c0 Allow monitor interaction when using migrate -exec
All,
     I've recently been playing around with migration via exec.  Unfortunately,
when starting the incoming qemu process with "-incoming exec:cmd", it suffers
the same problem that -incoming tcp used to suffer; namely, that you can't
interact with the monitor until after the migration has happened.  This causes
problems for libvirt usage of -incoming exec, since libvirt expects to be able
to access the monitor ahead of time.  This fairly simple patch allows you to
access the monitor both before and after the migration has completed using exec.

(note: developed/tested with qemu-kvm, but applies perfectly fine to qemu)

Signed-off-by: Chris Lalancette <clalance@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-27 09:47:39 -05:00
Christoph Hellwig
5982abd9ca fix raw_pread_aligned return value
raw_pread_aligned currently returns the raw return value from
lseek/read, which is always -1 in case of an error.  But the
callers higher up the stack expect it to return the negated
errno just like raw_pwrite_aligned.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-27 09:47:30 -05:00
Stefan Weil
738208b656 VNC: Fix memory allocation (wrong structure size).
Pointer vs addresses a VncDisplay structure,
so it is sufficient to allocate sizeof(VncDisplay)
or sizeof(*vs) bytes instead of the much larger
sizeof(VncState).

Maybe the misleading name should be fixed, too:
the code contains many places where vs is used,
sometimes it is a VncState *, sometimes it is a
VncDisplay *. vd would be a better name.

Signed-off-by: Stefan Weil <weil@mail.berlios.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-27 09:47:25 -05:00
Kevin Wolf
61348b076b e1000: Ignore reset command
When a reset is requested, the current e1000 emulation never clears the
reset bit which may cause a driver to hang. This patch masks the reset
bit out when setting the control registert, so the reset is immediately
completed.

Signed-off-by: Kevin Wolf <mail@kevin-wolf.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-27 09:47:11 -05:00
Anthony Liguori
9e3a7df77c Update for 0.10.5 release
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-20 15:42:42 -05:00
Mark McLoughlin
0926c7a4e5 kvm: work around supported cpuid ioctl() brokenness
KVM_GET_SUPPORTED_CPUID has been known to fail to return -E2BIG
when it runs out of entries. Detect this by always trying again
with a bigger table if the ioctl() fills the table.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Glauber Costa <glommer@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-20 15:21:28 -05:00
Anthony Liguori
a02ba54eed Remove noisy printf when KVM masks CPU features
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Glauber Costa <glommer@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-20 15:21:24 -05:00
Avi Kivity
578485d835 kvm: Trim cpu features not supported by kvm
Remove cpu features that are not supported by kvm from the cpuid features
reported to the guest.

Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Glauber Costa <glommer@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-20 15:21:20 -05:00
Avi Kivity
a675d9b8b5 Fix x86 feature modifications for features that set multiple bits
QEMU allows adding or removing cpu features by using the syntax '-cpu +feature'
or '-cpu -feature'.  Some cpuid features cause more than one bit to be set or
cleared; but QEMU stops after just one bit has been modified, causing the
feature bits to be inconsistent.

Fix by allowing all feature bits corresponding to a given name to be set.

Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Glauber Costa <glommer@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-20 15:21:14 -05:00
Avi Kivity
ce60db1da2 Make x86 cpuid feature names available in file scope
To be used later.

Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Glauber Costa <glommer@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-20 15:21:09 -05:00
Avi Kivity
428009b4aa kvm: Add support for querying supported cpu features
kvm does not support all cpu features; add support for dunamically querying
the supported feature set.

Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Glauber Costa <glommer@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-20 15:21:04 -05:00
Anthony Liguori
c87a097b4a Introduce kvm_check_extension to check if KVM extensions are supported
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Glauber Costa <glommer@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-20 15:20:56 -05:00
Mark McLoughlin
2fbc3b4c81 kvm: add error message for when SMP is requested
Right now, if you try e.g. '-smp 2' you just get 'failed to
initialize KVM'.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-20 13:21:36 -05:00
Richard W.M. Jones
8765893e9e Remove initrd warning message
Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-20 13:21:36 -05:00
Jean-Christophe Dubois
822624e5d6 initialize struct sigevent before timer_create
When qemu is run under valgrind, valgrind shows the following output
on exit:

==3648== 1 errors in context 2 of 2:
==3648== Syscall param timer_create(evp) points to uninitialised byte(s)
==3648==    at 0x54E936A: timer_create (in /lib/librt-2.9.so)
==3648==    by 0x405DCF: dynticks_start_timer (vl.c:1549)
==3648==    by 0x40A966: main (vl.c:1726)
==3648==  Address 0x7fefffb34 is on thread 1's stack
==3648==  Uninitialised value was created by a stack allocation
==3648==    at 0x405D60: dynticks_start_timer (vl.c:1534)

This patch is a simple fix to remove this potential problem.

Signed-off-by: Jean-Christophe DUBOIS <jcd@tribudubois.net>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-20 13:21:36 -05:00
Jean-Christophe Dubois
fe54857a13 Fix NULL alarm_timer pointer at exit
This fixes a SIGSEGV error on qemu exit.

Here is the valgrind output related to this error

==3648== Process terminating with default action of signal 11 (SIGSEGV)
==3648==  Access not within mapped region at address 0x8
==3648==    at 0x40636B: host_alarm_handler (vl.c:1345)
==3648==    by 0x52D807F: (within /lib/libpthread-2.9.so)
==3648==    by 0x5C0A12E: tcsetattr (in /lib/libc-2.9.so)
==3648==    by 0x4DD601: term_exit (qemu-char.c:700)
==3648==    by 0x5B636EC: exit (in /lib/libc-2.9.so)
==3648==    by 0x5B4B5AC: (below main) (in /lib/libc-2.9.so)

This simple fix check for a valid pointer as host_alarm_handler is
also called after alarm_timer is released in the exit path.

Signed-off-by: Jean-Christophe DUBOIS <jcd@tribudubois.net>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-20 13:21:36 -05:00
Glauber Costa
ee60269c23 keep initrd in below 4g area.
initrd must be kept on the memory area below 4g. By not doing this,
we're seeing guests break while using -initrd and values of -mem
superior to 4096.

Signed-off-by: Glauber Costa <glommer@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-20 13:21:36 -05:00
Uri Lublin
3978d7b4c8 migrate.c: migrate_fd_put_buffer: Do not busyloop: stop writing if EWOULDBLOCK
The migration code is non-blocking, designed for live migration.

Practically migrate_fd_put_buffer busy-loops trying to write, as
on many machines EWOULDBLOCK==EAGAIN (look in include/asm-generic/errno.h).

Signed-off-by: Uri Lublin <uril@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-20 13:21:24 -05:00
Hollis Blanchard
dc0be040c2 remove gcc 3.x requirement from documentation
This text is no longer accurate. After the patch is applied, the
generated version at http://www.nongnu.org/qemu/qemu-doc.html should be
regenerated.

This patch is also a candidate for the stable branch. (The URL above is
probably generated from the stable branch anyways, so maybe it goes
without saying.)

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-20 13:19:43 -05:00
Edgar E. Iglesias
1570841432 ETRAX: Correct passing of kernel command line.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
2009-05-15 21:43:56 +02:00
Edgar E. Iglesias
a59cc95e23 ETRAX: Correct setting of ethernet station address.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
2009-05-15 21:43:44 +02:00
Edgar E. Iglesias
2058679372 CRIS: Fix bmi.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
2009-05-15 21:43:31 +02:00
aliguori
f1cfb26c5a Fix DMA API when handling an immediate error from block layer (Avi Kivity)
The block layer may signal an immediate error on an asynchronous request
by returning NULL.  The DMA API did not handle this correctly, returning
an AIO request which would never complete (and which would crash if
cancelled).

Fix by detecting the failure and propagating it.

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@6893 c046a42c-6fe2-441c-8c8c-71466251a162
2009-05-14 08:09:31 -05:00
aliguori
662524f5dc Fix vectored aio bounce handling immediate errors (Avi Kivity)
If a bounced vectored aio fails immediately (the inner aio submission
returning NULL) then the bounce handler erronously returns an aio
request which will never be completed (and which crashes when cancelled).

Fix by detecting that the inner request has failed and propagating the
error.

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@6892 c046a42c-6fe2-441c-8c8c-71466251a162
2009-05-14 08:09:24 -05:00
aliguori
5f6521c78e Move block dma helpers aiocb to store dma state (Avi Kivity)
Use the dedicated dma aiocb to store intermediate state for dma block
transactions.

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@6874 c046a42c-6fe2-441c-8c8c-71466251a162
2009-05-14 08:09:17 -05:00
aliguori
abe73c324e Use vectored aiocb storage to store vector translation state (Avi Kivity)
Now that we have a dedicated acb pool for vector translation acbs, we can
store the vector translation state in the acbs instead of in an external
structure.

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@6873 c046a42c-6fe2-441c-8c8c-71466251a162
2009-05-14 08:09:10 -05:00
Glauber Costa
ed16937820 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.

This also includes Mark's fix for -kernel

Signed-off-by: Glauber Costa <glommer@redhat.com>
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-13 08:08:09 -05:00
Anthony Liguori
faf8a63492 Revert "reset state for load_linux"
This reverts commit 2da1e39864.

This fix on the stable branch:

  commit 2da1e39864
  Author: Glauber Costa <glommer@redhat.com>
  Date:   Fri May 8 02:22:13 2009 -0300

    reset state for load_linux

Caused -kernel to break.

The problem is that we're passing the ROM's ram_addr_t to
load_linux() rather than its target_phys_addr_t. We also
need to register the memory before trying to write to
it.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-05-13 08:06:54 -05:00
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
aliguori
06b393452f Update version for release
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7012 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-07 01:57:17 +00:00
aliguori
b7d11af2e0 Fix find_device_type() to correctly identify floppy disk devices; (Luca Tettamanti)
they are reported as DRIVE_REMOVABLE by win32.

Signed-off-by: Luca Tettamanti <kronos.it@gmail.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7011 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-07 01:46:18 +00:00
aliguori
8d47bb6162 Fix savevm after BDRV_FILE size enforcement
We now enforce that you cannot write beyond the end of a non-growable file.
 qcow2 files are not growable but we rely on them being growable to do
 savevm/loadvm.  Temporarily allow them to be growable by introducing a new
 API specifically for savevm read/write operations.
 
 Reported-by: malc
 Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
 


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7005 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-05 21:07:26 +00:00
aliguori
80acab6c50 stop dirty tracking just at the end of migration (Glauber Costa)
If there is still work to do, it is not safe to assume we
can end the dirty tracking. Specifically, kvm can update the dirty
tracking log inside ram_save_block(), leaving pages still out of sync
if we go with the current code.

Based on a patch by Yaniv Kamay

Signed-off-by: Glauber Costa <glommer@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7002 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-05 19:33:41 +00:00
aliguori
da0ac2bc13 create qemu_file_set_error (Glauber Costa)
This is mainly for consistency, since we don't want
anything outside of savevm setting it explicitly. There
are current no users of that in qemu tree, but there
are potential candidates on kvm-userspace. And avi
is a nice guy, let's be nice with him.

Based on a patch by Yaniv Kamay

Signed-off-by: Glauber Costa <glommer@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7001 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-05 19:33:37 +00:00
aliguori
d3c2632047 propagate error on failed completion (Glauber Costa)
migrate_fd_put_ready() calls qemu_savevm_state_complete(),
but the later can fail.

If it happens, re-start the vm and propagate the error up

Based on a patch by Yaniv Kamay

Signed-off-by: Glauber Costa <glommer@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@7000 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-05 19:33:33 +00:00
aliguori
7cc73776e7 qcow2: fix image creation for large, > ~2TB, images (Chris Wright)
When creating large disk images w/ qcow2 format, qcow2_create is hard
coded to creating a single refcount block.  This is insufficient for
large images, and will cause qemu-img to segfault as it walks off the
end of the refcount block.  Keep track of the space needed during image
create and create proper number of refcount blocks accordingly.

https://bugzilla.redhat.com/show_bug.cgi?id=491943

Signed-off-by: Chris Wright <chrisw@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@6988 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-05 18:16:10 +00:00
aliguori
937e9a1c83 pci_add storage: fix error handling for 'if' parameter (Eduardo Habkost)
This fixes:

 - The error message to show the actual if= argument value. It was showing
   the filename instead, because 'buf' is reaused on the filename parsing.
 - A bug that makes a block device to be created even when an unsupported if= arg
   is passed to pci_add.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@6987 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-05 18:16:04 +00:00
aliguori
4498819404 Fix (at least one cause of) qcow2 corruption. (Nolan Leake)
qcow2's get_cluster_offset() scans forward in the l2 table to find other
clusters that have the same allocation status as the first cluster.
This is used by (among others) qcow_is_allocated().

Unfortunately, it was not checking to be sure that it didn't fall off
the end of the l2 table.  This patch adds that check.

The symptom that motivated me to look into this was that
bdrv_is_allocated() was returning false when there was in fact data
there.  This is one of many ways this bug could lead to data corruption.

I checked the other place that scans for consecutive unallocated blocks
(alloc_cluster_offset()) and it appears to be OK:
    nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
appears to prevent the same problem from occurring.

Signed-off-by: Nolan Leake <nolan <at> sigbus.net>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@6986 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-05 18:15:59 +00:00
aliguori
c61ad61830 Fix oops on 2.6.25 guest (Rusty Russell)
I believe this is behind the following:
https://bugs.edge.launchpad.net/ubuntu/jaunty/+source/linux/+bug/331128

virtio_pci in 2.6.25 didn't do feature negotiation correctly: it acked every
bit.  Fortunately, we can detect this.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@6985 c046a42c-6fe2-441c-8c8c-71466251a162
2009-04-05 18:15:54 +00:00
aurel32
65297bc408 SH4: Add support for kernel cmdline
Backport of revisions 6792, 6916, 6919 from trunk.



git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@6960 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-31 05:55:16 +00:00
aliguori
02d400ead7 char: Fix closing of various char devices (Jan Kiszka)
This patch fixes several issues around closing char devices. Affected
were pty (timer was left behind, even running), udp (no close handling
at all) and tcp (missing async IO handler cleanup). The bugs either
caused segfaults or stalled the qemu process. So far, hot-unplugging USB
serial adapters suffered from this.

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@6912 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-28 18:01:29 +00:00
aliguori
20a9c6ac7f host_device_remove: remove incorrect check for device name (Eduardo Habkost)
There is no need to check for valid prefixes on the the device name
when removing it. If the device name is found on the vlan client list,
it can be removed, regardless of the prefix used on its name.

To reproduce the bug, just run this on the monitor:

 (qemu) host_net_add user name=foobar
 (qemu) host_net_remove 0 foobar
 invalid host network device foobar
 (qemu)

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@6890 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-28 15:51:46 +00:00
aliguori
bd0b264c21 Enable -k option on Win32 (Herve Poussineau)
Attached patch enables -k option on Win32. There is no reason to disable it.

Signed-off-by: Herve Poussineau <hpoussin@reactos.org>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@6889 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-28 15:46:15 +00:00
aliguori
0f31aac44f configure sensitive to user locale (Andreas Faerber)
On German Fedora 9, no KVM errors are displayed.
This is because configure greps for "error:", which is locale-sensitive.

Use LANG=C for configure to find and display errors as expected.

Signed-off-by: Andreas Faerber <andreas.faerber@web.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@6883 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-22 03:01:39 +00:00
aliguori
30b15843b2 Fix VGA issue introduced by r6349 (malc)
Thanks to Robert Riebisch for bisection

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



git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@6882 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-22 02:59:21 +00:00
aliguori
04ffdd7f94 Update version for release
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@6880 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-21 23:02:41 +00:00
aliguori
7648bb760d Rename stable branch
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@6879 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-21 23:00:32 +00:00
aliguori
ebb7184720 Restore old stable branch
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10_0@6878 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-21 22:59:47 +00:00
aliguori
3f546bd0b1 Add release_0_10_1 tag
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10@6876 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-21 22:34:21 +00:00
aliguori
00614a4cb4 Update Changelog
git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10_0@6869 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-20 16:22:31 +00:00
aliguori
7c14db42cb virtio: Allow guest to defer VIRTIO_F_NOTIFY_ON_EMPTY (Alex Williamson)
There may be cases where the guest does not want the avail queue
interrupt, even when it's empty.  For the virtio-net case, the
guest may use a different buffering scheme or decide polling for
used buffers is more efficient.  This can be accomplished by simply
checking for whether the guest has acknowledged the existing notify
on empty flag.

Signed-off-by: Alex Williamson <alex.williamson@hp.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10_0@6868 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-20 16:18:45 +00:00
aliguori
e58843d0f1 e1000: Fix RX descriptor low threshold interrupt logic (Alex Williamson)
The RXDMT0 interrupt is supposed to fire when the number of free
RX descriptors drops to some fraction of the total descriptors.
However in practice, it seems like we're adding this interrupt
cause on every RX.  Fix the logic to treat (tail - head) as the
number of free entries rather than the number of used entries.

Signed-off-by: Alex Williamson <alex.williamson@hp.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10_0@6867 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-20 16:18:39 +00:00
aliguori
0e39d3f89b x86: Add NULL check to lsl (Jan Kiszka)
According to the Intel specs, lsl performs a check against NULL for the
provided selector, just like lar does. helper_lar() includes the
corresponding code, helper_lsl() was lacking it so far.

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_0@6866 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-20 16:18:35 +00:00
aliguori
5389a9df53 temporarily disable logging around pci config writes (Avi Kivity)
A pci config write may remap the vga linear frame buffer, confusing the
memory slot dirty logging logic.

Fixed Windows with -vga std.

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


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10_0@6854 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-13 18:11:21 +00:00
aliguori
21fd832512 stop dirty logging while updating cirrus bank memory (Glauber Costa)
Otherwise, slot tracking gets confused.

This fixes a screen corruption bug with Ubuntu guest installation.

Signed-off-by: Glauber Costa <glommer@redhat.com>
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_0@6853 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-13 18:11:17 +00:00
aliguori
15d4afd55b Update changelog
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10_0@6848 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-13 16:22:40 +00:00
aliguori
3df962a30d qemu:virtio-net: Check return size on the correct sg list (Alex Williamson)
When checking that the size of the control virtqueue return field
is sufficient, use the correct sg list.

Signed-off-by: Alex Williamson <alex.williamson@hp.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10_0@6847 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-13 16:19:04 +00:00
aliguori
4827c90cef make qemu_announce_self handle non contiguous net tables (Marcelo Tosatti)
With hotplug nd_table might contain holes.

Noticed by Eduardo Habkost.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10_0@6846 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-13 16:18:57 +00:00
aliguori
0f56231dce Revert r6404
This series is broken by design as it requires expensive IO operations at
open time causing very long delays when starting a virtual machine for the
first time.

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


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10_0@6821 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-11 20:16:16 +00:00
aliguori
523faf1b92 Revert r6405
This series is broken by design as it requires expensive IO operations at
open time causing very long delays when starting a virtual machine for the
first time.

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


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10_0@6820 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-11 20:16:12 +00:00
aliguori
414c078104 Revert r6406
This series is broken by design as it requires expensive IO operations at
open time causing very long delays when starting a virtual machine for the
first time.

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


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10_0@6819 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-11 20:16:05 +00:00
aliguori
9cecf0f570 Revert r6407
This series is broken by design as it requires expensive IO operations at
open time causing very long delays when starting a virtual machine for the
first time.

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


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10_0@6818 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-11 20:16:01 +00:00
aliguori
4ca9f3dd71 Revert r6408
This series is broken by design as it requires expensive IO operations at
open time causing very long delays when starting a virtual machine for the
first time.

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


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10_0@6817 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-11 20:15:55 +00:00
aurel32
f902c4192e qemu-img: fix help message
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10_0@6788 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-08 19:52:43 +00:00
aliguori
b96a313d3d Remove unnecessary prefix on SDL_syswm.h. This fixes the build for certain
installs of SDL.

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



git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10_0@6781 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-08 15:04:13 +00:00
aurel32
d9aa1fce5a Clear CPU_INTERRUPT_EXIT on VM load
CPU_INTERRUPT_EXIT is not set anymore in env->interrupt_request since
revision 6729. Make sure the bit is cleared on VM load.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10_0@6760 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-07 21:08:39 +00:00
aurel32
8a11f5ff08 Fix race condition on access to env->interrupt_request
env->interrupt_request is accessed as the bit level from both main code
and signal handler, making a race condition possible even on CISC CPU.
This causes freeze of QEMU under high load when running the dyntick
clock.

The patch below move the bit corresponding to CPU_INTERRUPT_EXIT in a
separate variable, declared as volatile sig_atomic_t, so it should be
work even on RISC CPU.

We may want to move the cpu_interrupt(env, CPU_INTERRUPT_EXIT) case in
its own function and get rid of CPU_INTERRUPT_EXIT. That can be done
later, I wanted to keep the patch short for easier review.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10_0@6729 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-06 21:49:37 +00:00
aliguori
b786b7ccbd monitor: Rework early disk password inquiry (Jan Kiszka)
Reading the passwords for encrypted hard disks during early startup is
broken (I guess for quiet a while now):
 - No monitor terminal is ready for input at this point
 - Forcing all mux'ed terminals into monitor mode can confuse other
   users of that channels

To overcome these issues and to lay the ground for a clean decoupling of
monitor terminals, this patch changes the initial password inquiry as
follows:
 - Prevent autostart if there is some encrypted disk
 - Once the user tries to resume the VM, prompt for all missing
   passwords
 - Only resume if all passwords were accepted

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_0@6699 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-05 19:42:40 +00:00
aliguori
d3be2b2f71 monitor: Report encrypted disks in snapshot mode (Jan Kiszka)
If the backing file is encrypted, 'info block' currently does not report
the disk as encrypted. Fix this by using the standard API to check disk
encryption mode. Moreover, switch to a canonical output format.

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_0@6698 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-05 19:42:36 +00:00
aliguori
e36fb2a3a2 monitor: Use reasonable default virtual console size (Jan Kiszka)
If a target uses a tiny display (like the MusicPal), the default monitor
is currently set to the same size. Fix this by applying the same
defaults like already used serial and virtio consoles.

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_0@6697 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-05 19:42:30 +00:00
aliguori
4978045781 block: Introduce bdrv_get_encrypted_filename (Jan Kiszka)
Introduce bdrv_get_encrypted_filename service to allow more informative
password prompting.

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_0@6696 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-05 19:42:19 +00:00
aliguori
cb5745c529 block: Improve bdrv_iterate (Jan Kiszka)
Make bdrv_iterate more useful by passing the BlockDriverState to the
iterator instead of the device name.

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_0@6695 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-05 19:42:15 +00:00
aliguori
295b492cfa block: Polish error handling of brdv_open2 (Jan Kiszka)
Make sure that we always delete temporary disk images on error, remove
obsolete malloc error checks and return proper error codes.

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_0@6694 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-05 19:42:11 +00:00
aliguori
af8222c0f8 char-mux: Use separate input buffers (Jan Kiszka)
Currently, the intermediate input buffer of mux'ed character devices
records data across all sub-devices. This has the side effect that we
easily leak data recorded over one sub-devices to another once we switch
the focus. Avoid data loss and confusion by defining exclusive buffers.

Note: In contrast to the original author's claim, the buffering concept
still breaks down when the fifo of the currently active sub-device is
full. As we cannot accept futher data from this point on without risking
to loose it, we will also miss escape sequences, just like without all
that buffering. In short: There is no reliable escape sequence handling
without infinite buffers or the risk of loosing some data.

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_0@6693 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-05 19:42:07 +00:00
aliguori
249139f4e6 char: Fix initial reset (Jan Kiszka)
Recent changes to the graphical console initialization broke the initial
CHR_EVENT_RESET distribution. The reset BHs generated on char device
initialization are now already consumed during machine init (ide init
... -> qemu_aio_wait -> qemu_bh_poll). Therefore, this patch moves the
initial qemu_chr_reset calls into a separate funtion which is called
after machine init.

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_0@6692 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-05 19:42:04 +00:00
aliguori
8ae0978ed5 Fix cpuid KVM crash on i386 (Lubomir Rintel)
Cpuid should return into vec, not overwrite past address in count.
Changeset 6565 broke this.

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10_0@6691 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-05 19:01:53 +00:00
aliguori
c0024a8257 lsi: add ISTAT1 register read (Ryan Harper)
SLES10 SP2 installer complains when probing a scsi disk and exits qemu
when failing to read one of the registers.

lsi_scsi: error: readb 0x15


-- 
Ryan Harper
Software Engineer; Linux Technology Center
IBM Corp., Austin, Tx
ryanh@us.ibm.com



diffstat output:
 lsi53c895a.c |    2 ++
 1 files changed, 2 insertions(+)

Signed-off-by: Ryan Harper <ryanh@us.ibm.com>
---
Subject: [PATCH] lsi: add ISTAT1 register read
From: Ryan Harper <ryanh@us.ibm.com>
Cc: kvm@vger.kernel.org

SLES10 SP2 installer complains when probing a scsi disk and exits qemu when
failing to read one of the registers.

lsi_scsi: error: readb 0x15

Signed-off-by: Ryan Harper <ryanh@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_0@6690 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-05 19:01:46 +00:00
aliguori
e9af78a859 Add stable branch
git-svn-id: svn://svn.savannah.nongnu.org/qemu/branches/stable_0_10_0@6687 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-05 18:52:51 +00:00
aliguori
25c4fde177 Add property to tag
git-svn-id: svn://svn.savannah.nongnu.org/qemu/tags/release_0_10_0@6686 c046a42c-6fe2-441c-8c8c-71466251a162
2009-03-05 18:51:35 +00:00
79 changed files with 1650 additions and 654 deletions

111
Changelog
View File

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

View File

@@ -1 +1 @@
0.10.0
0.10.6

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

View File

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

View File

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

View File

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

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

205
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;
}
@@ -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
View File

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

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

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

View File

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

View File

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

View File

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

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

19
exec.c
View File

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

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

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

View File

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

View File

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

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

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

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

View File

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

View File

@@ -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[] = {
&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)
{
@@ -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;

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

View File

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

View File

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

View File

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

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

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

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

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

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

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

View File

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

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

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

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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
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) {
@@ -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
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);
@@ -65,6 +68,7 @@ struct NICInfo {
const char *model;
const char *name;
VLANState *vlan;
VLANClientState *vc;
void *private;
int used;
};

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

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

View File

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

View File

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

View File

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

View File

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

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

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

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

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

View File

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

View File

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

View File

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

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