Compare commits

..

112 Commits

Author SHA1 Message Date
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
754 changed files with 30773 additions and 70570 deletions

7
.gitignore vendored
View File

@@ -4,8 +4,6 @@ i386
*-darwin-user
*-linux-user
*-bsd-user
libhw32
libhw64
qemu-doc.html
qemu-tech.html
qemu-doc.info
@@ -18,11 +16,6 @@ qemu-img
qemu-nbd
qemu-nbd.8
qemu-nbd.pod
qemu-options.texi
qemu-img-cmds.texi
qemu-img-cmds.h
qemu-io
qemu-monitor.texi
.gdbinit
*.a
*.aux

View File

@@ -1,78 +0,0 @@
Qemu Coding Style
=================
1. Whitespace
Of course, the most important aspect in any coding style is whitespace.
Crusty old coders who have trouble spotting the glasses on their noses
can tell the difference between a tab and eight spaces from a distance
of approximately fifteen parsecs. Many a flamewar have been fought and
lost on this issue.
QEMU indents are four spaces. Tabs are never used, except in Makefiles
where they have been irreversibly coded into the syntax.
Spaces of course are superior to tabs because:
- You have just one way to specify whitespace, not two. Ambiguity breeds
mistakes.
- The confusion surrounding 'use tabs to indent, spaces to justify' is gone.
- Tab indents push your code to the right, making your screen seriously
unbalanced.
- Tabs will be rendered incorrectly on editors who are misconfigured not
to use tab stops of eight positions.
- Tabs are rendered badly in patches, causing off-by-one errors in almost
every line.
- It is the QEMU coding style.
Do not leave whitespace dangling off the ends of lines.
2. Line width
Lines are 80 characters; not longer.
Rationale:
- Some people like to tile their 24" screens with a 6x4 matrix of 80x24
xterms and use vi in all of them. The best way to punish them is to
let them keep doing it.
- Code and especially patches is much more readable if limited to a sane
line length. Eighty is traditional.
- It is the QEMU coding style.
3. Naming
Variables are lower_case_with_underscores; easy to type and read. Structured
type names are in CamelCase; harder to type but standing out. Scalar type
names are lower_case_with_underscores_ending_with_a_t, like the POSIX
uint64_t and family. Note that this last convention contradicts POSIX
and is therefore likely to be changed.
Typedefs are used to eliminate the redundant 'struct' keyword. It is the
QEMU coding style.
4. Block structure
Every indented statement is braced; even if the block contains just one
statement. The opening brace is on the line that contains the control
flow statement that introduces the new block; the closing brace is on the
same line as the else keyword, or on a line by itself if there is no else
keyword. Example:
if (a == 5) {
printf("a was 5.\n");
} else if (a == 6) {
printf("a was 6.\n");
} else {
printf("a was something else entirely.\n");
}
An exception is the opening brace for a function; for reasons of tradition
and clarity it comes on a line by itself:
void a_function(void)
{
do_something();
}
Rationale: a consistent (except for functions...) bracing style reduces
ambiguity and avoids needless churn when lines are added or removed.
Furthermore, it is the QEMU coding style.

View File

@@ -1,87 +1,3 @@
version 0.11.0-rc2
- mips: fix conditional move off fp conditions codes (Nath Froyd)
- fix migration to obey -S (Paolo Bonzini)
- remove pc-0-10 machine type (Mark McLoughlin)
- vnc: fix copyrect screen corruption (Gerd Hoffman)
- fix vm state change handlers running order (Markus Armbruster)
- e1000: fix eerc and ics emulation (Bill Paul)
- fix sdl zooming with pl110 (Blue Swirl)
- sparc64: flush pending conditional evaluations (Igor Kovalenko)
- esp: fix interrupt register read (Blue Swirl)
- option rom makefile fixes (Paul Brook)
- fix sparse warnings (Blue Swirl)
- fix symfind (Laurent Desnogues)
- win32: fix default prefix (Stefan Weil)
- fix checksum writing in signboot (Alex Graf)
- fix sdl window resize (Stefano Stabellini)
- do not resize the screen on hw_invalidate (Stefano Stabellini)
- Add checks for -smbios option (Beth Kon)
- fix do_set_link (Luiz Capitulino)
- fix do_commit behavior (Luiz Capitulino)
- make windows notice media change (Gleb Natapov)
- check for PR_SET_NAME being defined (Nathan Froyd)
- fix migration for ide devices (Anthony Liguori)
- Use correct depth in vmware vga (Reimar Doffiner)
- support 32bpp cursors in sdl (Reimar Doffinger)
- fix device name completion for eject (Blue Swirl)
- make screendump use DisplayState properly (Stefano Stabellini)
- fix autostart with live migration (Avi Kivity)
- fix detached migration with exec (Chris Lalancette)
- fix segv when changing vnc password in sdl (Zach Amsden)
- fix vnc password clearing with stdio monitor (Zach Amsden)
- clean up VGA type selection (Zach Amsden)
- add missing linefeed in error message (Stefan Weil)
version 0.11.0-rc1
- add machine aliasing support (Mark McLoughlin)
- add getfd/closefd monitor commands (Mark McLoughlin)
- use correct headers for tap-win32 (Filip Navara)
- fix live migration (Glauber Costa)
- slirp: use monotonic clock if available (Ed Swierk)
- clear msix_entries_nr on error (Michael Tsirkin)
- HPET: fix reg writes (Beth Kon)
- slirp: fix guestfwd for incoming data (Jan Kiszka)
- fix build of qemu-thread.c on win32 (Sebastian Herbszt)
- improve signrom.sh portability (Christoph Egger)
- fix qemu-img convert to copy unallocated parts of the image
(Akkarit Sangpetch)
- vmdk: fix backing file handling (Kevin Wolf)
- scsi: add save/restore support (Nolan Leake)
- fix live migration for SCSI (Nolan Leake)
- various sparc build fixes (Blue Swirl)
- fix OpenBSD build (Blue Swirl)
- only allow -cpu host when using KVM (Anthony Liguori)
- fix build breakage when !KVM (Anthony Liguori)
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)
@@ -139,6 +55,11 @@ version 0.10.2:
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)

View File

@@ -19,7 +19,6 @@ M68K Paul Brook
SH4 ?
CRIS Edgar E. Iglesias
Alpha ?
MicroBlaze Edgar E. Iglesias
Machines (sorted by CPU):
-------------------------
@@ -59,10 +58,7 @@ SH4
r2d.c Magnus Damm
CRIS
etraxfs.c Edgar E. Iglesias
axis_dev88.c Edgar E. Iglesias
Alpha
MicroBlaze
petalogix_s3adsp1800.c Edgar E. Iglesias
Generic Subsystems:
-------------------

299
Makefile
View File

@@ -1,24 +1,19 @@
# Makefile for QEMU.
ifneq ($(wildcard config-host.mak),)
# Put the all: rule here so that config-host.mak can contain dependencies.
all: build-all
include config-host.mak
include $(SRC_PATH)/rules.mak
else
config-host.mak:
@echo "Please call configure before running make!"
@exit 1
endif
.PHONY: all clean cscope distclean dvi html info install install-doc \
recurse-all speed tar tarbin test
VPATH=$(SRC_PATH):$(SRC_PATH)/hw
CFLAGS += $(OS_CFLAGS) $(ARCH_CFLAGS)
LDFLAGS += $(OS_LDFLAGS) $(ARCH_LDFLAGS)
CPPFLAGS += -I. -I$(SRC_PATH) -MMD -MP -MT $@
CPPFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
CPPFLAGS += -U_FORTIFY_SOURCE
LIBS=
ifdef CONFIG_STATIC
LDFLAGS += -static
@@ -29,8 +24,7 @@ else
DOCS=
endif
LIBS+=$(PTHREADLIBS)
LIBS+=$(CLOCKLIBS)
LIBS+=$(AIOLIBS)
ifdef CONFIG_SOLARIS
LIBS+=-lsocket -lnsl -lresolv
@@ -40,216 +34,175 @@ ifdef CONFIG_WIN32
LIBS+=-lwinmm -lws2_32 -liphlpapi
endif
build-all: $(TOOLS) $(DOCS) recurse-all
all: $(TOOLS) $(DOCS) recurse-all
config-host.mak: configure
ifneq ($(wildcard config-host.mak),)
@echo $@ is out-of-date, running configure
@sed -n "/.*Configured with/s/[^:]*: //p" $@ | sh
endif
SUBDIR_MAKEFLAGS=$(if $(V),,--no-print-directory)
SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
subdir-%:
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C $* V="$(V)" TARGET_DIR="$*/" all,)
$(call quiet-command,$(MAKE) -C $* V="$(V)" TARGET_DIR="$*/" all,)
$(filter %-softmmu,$(SUBDIR_RULES)): libqemu_common.a
$(filter %-user,$(SUBDIR_RULES)): libqemu_user.a
ROMSUBDIR_RULES=$(patsubst %,romsubdir-%, $(ROMS))
romsubdir-%:
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C pc-bios/$* V="$(V)" TARGET_DIR="$*/",)
ALL_SUBDIRS=$(TARGET_DIRS) $(patsubst %,pc-bios/%, $(ROMS))
recurse-all: $(SUBDIR_RULES) $(ROMSUBDIR_RULES)
recurse-all: $(SUBDIR_RULES)
#######################################################################
# block-obj-y is code used by both qemu system emulation and qemu-img
block-obj-y = cutils.o cache-utils.o qemu-malloc.o qemu-option.o module.o
block-obj-y += nbd.o block.o aio.o aes.o
block-nested-y += cow.o qcow.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o
block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o
block-nested-y += parallels.o nbd.o
# BLOCK_OBJS is code used by both qemu system emulation and qemu-img
BLOCK_OBJS=cutils.o qemu-malloc.o
BLOCK_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o
BLOCK_OBJS+=block-dmg.o block-bochs.o block-vpc.o block-vvfat.o
BLOCK_OBJS+=block-qcow2.o block-parallels.o block-nbd.o
BLOCK_OBJS+=nbd.o block.o aio.o
ifdef CONFIG_WIN32
block-nested-y += raw-win32.o
BLOCK_OBJS += block-raw-win32.o
else
ifdef CONFIG_AIO
block-obj-y += posix-aio-compat.o
BLOCK_OBJS += posix-aio-compat.o
endif
block-nested-y += raw-posix.o
BLOCK_OBJS += block-raw-posix.o
endif
block-nested-$(CONFIG_CURL) += curl.o
block-obj-y += $(addprefix block/, $(block-nested-y))
######################################################################
# libqemu_common.a: Target independent part of system emulation. The
# long term path is to suppress *all* target specific code in case of
# system emulation, i.e. a single QEMU executable should support all
# CPUs and machines.
obj-y = $(block-obj-y)
obj-y += readline.o console.o
OBJS=$(BLOCK_OBJS)
OBJS+=readline.o console.o
obj-y += irq.o ptimer.o
obj-y += i2c.o smbus.o smbus_eeprom.o max7310.o max111x.o wm8750.o
obj-y += ssd0303.o ssd0323.o ads7846.o stellaris_input.o twl92230.o
obj-y += tmp105.o lm832x.o eeprom93xx.o tsc2005.o
obj-y += scsi-disk.o cdrom.o
obj-y += scsi-generic.o
obj-y += usb.o usb-hub.o usb-$(HOST_USB).o usb-hid.o usb-msd.o usb-wacom.o
obj-y += usb-serial.o usb-net.o
obj-y += sd.o ssi-sd.o
obj-y += bt.o bt-host.o bt-vhci.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o usb-bt.o
obj-y += bt-hci-csr.o
obj-y += buffered_file.o migration.o migration-tcp.o net.o qemu-sockets.o
obj-y += qemu-char.o aio.o net-checksum.o savevm.o
obj-y += msmouse.o ps2.o
obj-y += qdev.o qdev-properties.o ssi.o
obj-$(CONFIG_BRLAPI) += baum.o
OBJS+=irq.o
OBJS+=i2c.o smbus.o smbus_eeprom.o max7310.o max111x.o wm8750.o
OBJS+=ssd0303.o ssd0323.o ads7846.o stellaris_input.o twl92230.o
OBJS+=tmp105.o lm832x.o
OBJS+=scsi-disk.o cdrom.o
OBJS+=scsi-generic.o
OBJS+=usb.o usb-hub.o usb-$(HOST_USB).o usb-hid.o usb-msd.o usb-wacom.o
OBJS+=usb-serial.o usb-net.o
OBJS+=sd.o ssi-sd.o
OBJS+=bt.o bt-host.o bt-vhci.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o usb-bt.o
OBJS+=buffered_file.o migration.o migration-tcp.o net.o qemu-sockets.o
OBJS+=qemu-char.o aio.o net-checksum.o savevm.o cache-utils.o
ifdef CONFIG_BRLAPI
OBJS+= baum.o
LIBS+=-lbrlapi
endif
ifdef CONFIG_WIN32
obj-y += tap-win32.o
OBJS+=tap-win32.o
else
obj-y += migration-exec.o
OBJS+=migration-exec.o
endif
AUDIO_OBJS = audio.o noaudio.o wavaudio.o mixeng.o
ifdef CONFIG_SDL
AUDIO_OBJS += sdlaudio.o
endif
ifdef CONFIG_OSS
AUDIO_OBJS += ossaudio.o
endif
ifdef CONFIG_COREAUDIO
AUDIO_PT = y
AUDIO_OBJS += coreaudio.o
AUDIO_PT = yes
endif
ifdef CONFIG_ALSA
AUDIO_OBJS += alsaaudio.o
endif
ifdef CONFIG_DSOUND
AUDIO_OBJS += dsoundaudio.o
endif
ifdef CONFIG_FMOD
AUDIO_OBJS += fmodaudio.o
audio/audio.o audio/fmodaudio.o: CPPFLAGS := -I$(CONFIG_FMOD_INC) $(CPPFLAGS)
endif
ifdef CONFIG_ESD
AUDIO_PT = y
AUDIO_PT_INT = y
AUDIO_PT = yes
AUDIO_PT_INT = yes
AUDIO_OBJS += esdaudio.o
endif
ifdef CONFIG_PA
AUDIO_PT = y
AUDIO_PT_INT = y
AUDIO_PT = yes
AUDIO_PT_INT = yes
AUDIO_OBJS += paaudio.o
endif
ifdef AUDIO_PT
LDFLAGS += -pthread
endif
ifdef AUDIO_PT_INT
AUDIO_OBJS += audio_pt_int.o
endif
AUDIO_OBJS+= wavcapture.o
OBJS+=$(addprefix audio/, $(AUDIO_OBJS))
audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
audio-obj-$(CONFIG_SDL) += sdlaudio.o
audio-obj-$(CONFIG_OSS) += ossaudio.o
audio-obj-$(CONFIG_COREAUDIO) += coreaudio.o
audio-obj-$(CONFIG_ALSA) += alsaaudio.o
audio-obj-$(CONFIG_DSOUND) += dsoundaudio.o
audio-obj-$(CONFIG_FMOD) += fmodaudio.o
audio-obj-$(CONFIG_ESD) += esdaudio.o
audio-obj-$(CONFIG_PA) += paaudio.o
audio-obj-$(AUDIO_PT_INT) += audio_pt_int.o
audio-obj-y += wavcapture.o
obj-y += $(addprefix audio/, $(audio-obj-y))
ifdef CONFIG_SDL
OBJS+=sdl.o x_keymap.o
endif
ifdef CONFIG_CURSES
OBJS+=curses.o
endif
OBJS+=vnc.o d3des.o
obj-y += keymaps.o
obj-$(CONFIG_SDL) += sdl.o sdl_zoom.o x_keymap.o
obj-$(CONFIG_CURSES) += curses.o
obj-y += vnc.o acl.o d3des.o
obj-$(CONFIG_VNC_TLS) += vnc-tls.o vnc-auth-vencrypt.o
obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
obj-$(CONFIG_COCOA) += cocoa.o
obj-$(CONFIG_IOTHREAD) += qemu-thread.o
ifdef CONFIG_COCOA
OBJS+=cocoa.o
endif
ifdef CONFIG_SLIRP
CPPFLAGS+=-I$(SRC_PATH)/slirp
SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \
slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o \
tcp_subr.o tcp_timer.o udp.o bootp.o debug.o tftp.o
OBJS+=$(addprefix slirp/, $(SLIRP_OBJS))
endif
slirp-obj-y = cksum.o if.o ip_icmp.o ip_input.o ip_output.o
slirp-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o
slirp-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o
obj-$(CONFIG_SLIRP) += $(addprefix slirp/, $(slirp-obj-y))
LIBS+=$(VDE_LIBS)
# xen backend driver support
obj-$(CONFIG_XEN) += xen_backend.o xen_devconfig.o
obj-$(CONFIG_XEN) += xen_console.o xenfb.o xen_disk.o xen_nic.o
LIBS+=$(CURL_LIBS)
cocoa.o: cocoa.m
keymaps.o: keymaps.c keymaps.h
sdl.o: sdl.c keymaps.c sdl_keysym.h
sdl_zoom.o: sdl_zoom.c sdl_zoom.h sdl_zoom_template.h
sdl.o audio/sdlaudio.o: CFLAGS += $(SDL_CFLAGS)
sdl.o: sdl.c keymaps.h sdl_keysym.h sdl_zoom.h
sdl.o audio/sdlaudio.o sdl_zoom.o baum.o: CFLAGS += $(SDL_CFLAGS)
acl.o: acl.h acl.c
vnc.h: vnc-tls.h vnc-auth-vencrypt.h vnc-auth-sasl.h keymaps.h
vnc.o: vnc.c vnc.h vnc_keysym.h vnchextile.h d3des.c d3des.h acl.h
vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h d3des.c d3des.h
vnc.o: CFLAGS += $(CONFIG_VNC_TLS_CFLAGS)
vnc-tls.o: vnc-tls.c vnc.h
vnc-auth-vencrypt.o: vnc-auth-vencrypt.c vnc.h
vnc-auth-sasl.o: vnc-auth-sasl.c vnc.h
curses.o: curses.c keymaps.h curses_keys.h
curses.o: curses.c keymaps.c curses_keys.h
bt-host.o: CFLAGS += $(CONFIG_BLUEZ_CFLAGS)
libqemu_common.a: $(obj-y)
libqemu_common.a: $(OBJS)
#######################################################################
# user-obj-y is code used by qemu userspace emulation
user-obj-y = cutils.o cache-utils.o
# USER_OBJS is code used by qemu userspace emulation
USER_OBJS=cutils.o cache-utils.o
libqemu_user.a: $(user-obj-y)
libqemu_user.a: $(USER_OBJS)
######################################################################
qemu-img.o: qemu-img-cmds.h
qemu-img$(EXESUF): qemu-img.o qemu-tool.o osdep.o $(BLOCK_OBJS)
qemu-img$(EXESUF): qemu-img.o qemu-tool.o tool-osdep.o $(block-obj-y)
qemu-nbd$(EXESUF): qemu-nbd.o qemu-tool.o osdep.o $(BLOCK_OBJS)
qemu-nbd$(EXESUF): qemu-nbd.o qemu-tool.o tool-osdep.o $(block-obj-y)
qemu-io$(EXESUF): qemu-io.o qemu-tool.o tool-osdep.o cmd.o $(block-obj-y)
qemu-img$(EXESUF) qemu-nbd$(EXESUF) qemu-io$(EXESUF): LIBS += -lz
qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
$(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@," GEN $@")
qemu-img$(EXESUF) qemu-nbd$(EXESUF): LIBS += -lz
clean:
# avoid old build problems by removing potentially incorrect old files
rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
rm -f *.o *.d *.a $(TOOLS) TAGS cscope.* *.pod *~ */*~
rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d block/*.o block/*.d
rm -f qemu-img-cmds.h
rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d
$(MAKE) -C tests clean
for d in $(ALL_SUBDIRS) libhw32 libhw64; do \
for d in $(TARGET_DIRS); do \
$(MAKE) -C $$d $@ || exit 1 ; \
done
distclean: clean
rm -f config-host.mak config-host.h $(DOCS) qemu-options.texi qemu-img-cmds.texi
rm -f config-host.mak config-host.h $(DOCS)
rm -f qemu-{doc,tech}.{info,aux,cp,dvi,fn,info,ky,log,pg,toc,tp,vr}
for d in $(TARGET_DIRS) libhw32 libhw64; do \
for d in $(TARGET_DIRS); do \
rm -rf $$d || exit 1 ; \
done
@@ -261,37 +214,38 @@ ifdef INSTALL_BLOBS
BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
video.x openbios-sparc32 openbios-sparc64 openbios-ppc \
pxe-ne2k_pci.bin pxe-rtl8139.bin pxe-pcnet.bin pxe-e1000.bin \
bamboo.dtb petalogix-s3adsp1800.dtb \
multiboot.bin
bamboo.dtb
else
BLOBS=
endif
install-doc: $(DOCS)
$(INSTALL_DIR) "$(DESTDIR)$(docdir)"
$(INSTALL_DATA) qemu-doc.html qemu-tech.html "$(DESTDIR)$(docdir)"
mkdir -p "$(DESTDIR)$(docdir)"
$(INSTALL) -m 644 qemu-doc.html qemu-tech.html "$(DESTDIR)$(docdir)"
ifndef CONFIG_WIN32
$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1"
$(INSTALL_DATA) qemu.1 qemu-img.1 "$(DESTDIR)$(mandir)/man1"
$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man8"
$(INSTALL_DATA) qemu-nbd.8 "$(DESTDIR)$(mandir)/man8"
mkdir -p "$(DESTDIR)$(mandir)/man1"
$(INSTALL) -m 644 qemu.1 qemu-img.1 "$(DESTDIR)$(mandir)/man1"
mkdir -p "$(DESTDIR)$(mandir)/man8"
$(INSTALL) -m 644 qemu-nbd.8 "$(DESTDIR)$(mandir)/man8"
endif
install: all $(if $(BUILD_DOCS),install-doc)
$(INSTALL_DIR) "$(DESTDIR)$(bindir)"
mkdir -p "$(DESTDIR)$(bindir)"
ifneq ($(TOOLS),)
$(INSTALL_PROG) $(STRIP_OPT) $(TOOLS) "$(DESTDIR)$(bindir)"
$(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)"
endif
ifneq ($(BLOBS),)
$(INSTALL_DIR) "$(DESTDIR)$(datadir)"
mkdir -p "$(DESTDIR)$(datadir)"
set -e; for x in $(BLOBS); do \
$(INSTALL_DATA) $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \
$(INSTALL) -m 644 $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \
done
endif
$(INSTALL_DIR) "$(DESTDIR)$(datadir)/keymaps"
ifndef CONFIG_WIN32
mkdir -p "$(DESTDIR)$(datadir)/keymaps"
set -e; for x in $(KEYMAPS); do \
$(INSTALL_DATA) $(SRC_PATH)/pc-bios/keymaps/$$x "$(DESTDIR)$(datadir)/keymaps"; \
$(INSTALL) -m 644 $(SRC_PATH)/keymaps/$$x "$(DESTDIR)$(datadir)/keymaps"; \
done
endif
for d in $(TARGET_DIRS); do \
$(MAKE) -C $$d $@ || exit 1 ; \
done
@@ -301,7 +255,7 @@ test speed: all
$(MAKE) -C tests $@
TAGS:
etags *.[ch] tests/*.[ch] block/*.[ch] hw/*.[ch]
etags *.[ch] tests/*.[ch]
cscope:
rm -f ./cscope.*
@@ -310,40 +264,25 @@ cscope:
# documentation
%.html: %.texi
$(call quiet-command,texi2html -I=. -monolithic -number $<," GEN $@")
texi2html -monolithic -number $<
%.info: %.texi
$(call quiet-command,makeinfo -I . $< -o $@," GEN $@")
makeinfo $< -o $@
%.dvi: %.texi
$(call quiet-command,texi2dvi -I . $<," GEN $@")
texi2dvi $<
qemu-options.texi: $(SRC_PATH)/qemu-options.hx
$(call quiet-command,sh $(SRC_PATH)/hxtool -t < $< > $@," GEN $@")
qemu.1: qemu-doc.texi
$(SRC_PATH)/texi2pod.pl $< qemu.pod
pod2man --section=1 --center=" " --release=" " qemu.pod > $@
qemu-monitor.texi: $(SRC_PATH)/qemu-monitor.hx
$(call quiet-command,sh $(SRC_PATH)/hxtool -t < $< > $@," GEN $@")
qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx
$(call quiet-command,sh $(SRC_PATH)/hxtool -t < $< > $@," GEN $@")
qemu.1: qemu-doc.texi qemu-options.texi qemu-monitor.texi
$(call quiet-command, \
perl -Ww -- $(SRC_PATH)/texi2pod.pl $< qemu.pod && \
pod2man --section=1 --center=" " --release=" " qemu.pod > $@, \
" GEN $@")
qemu-img.1: qemu-img.texi qemu-img-cmds.texi
$(call quiet-command, \
perl -Ww -- $(SRC_PATH)/texi2pod.pl $< qemu-img.pod && \
pod2man --section=1 --center=" " --release=" " qemu-img.pod > $@, \
" GEN $@")
qemu-img.1: qemu-img.texi
$(SRC_PATH)/texi2pod.pl $< qemu-img.pod
pod2man --section=1 --center=" " --release=" " qemu-img.pod > $@
qemu-nbd.8: qemu-nbd.texi
$(call quiet-command, \
perl -Ww -- $(SRC_PATH)/texi2pod.pl $< qemu-nbd.pod && \
pod2man --section=8 --center=" " --release=" " qemu-nbd.pod > $@, \
" GEN $@")
$(SRC_PATH)/texi2pod.pl $< qemu-nbd.pod
pod2man --section=8 --center=" " --release=" " qemu-nbd.pod > $@
info: qemu-doc.info qemu-tech.info
@@ -351,7 +290,7 @@ dvi: qemu-doc.dvi qemu-tech.dvi
html: qemu-doc.html qemu-tech.html
qemu-doc.dvi qemu-doc.html qemu-doc.info: qemu-img.texi qemu-nbd.texi qemu-options.texi qemu-monitor.texi qemu-img-cmds.texi
qemu-doc.dvi qemu-doc.html qemu-doc.info: qemu-img.texi qemu-nbd.texi
VERSION ?= $(shell cat VERSION)
FILE = qemu-$(VERSION)
@@ -419,4 +358,4 @@ tarbin:
$(mandir)/man8/qemu-nbd.8
# Include automatically generated dependency files
-include $(wildcard *.d audio/*.d slirp/*.d block/*.d)
-include $(wildcard *.d audio/*.d slirp/*.d)

View File

@@ -1,38 +0,0 @@
# Makefile for qemu target independent devices.
include config.mak
include ../config-host.mak
include $(SRC_PATH)/rules.mak
.PHONY: all
VPATH=$(SRC_PATH):$(SRC_PATH)/hw
CPPFLAGS += -I. -I.. -I$(SRC_PATH) -MMD -MP -MT $@
CPPFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
CPPFLAGS+=-I$(SRC_PATH)/fpu
obj-y =
obj-y += virtio.o virtio-pci.o
obj-y += fw_cfg.o
obj-y += watchdog.o
obj-y += nand.o ecc.o
obj-y += m48t59.o escc.o
# SCSI layer
obj-y += lsi53c895a.o esp.o
obj-y += dma-helpers.o sysbus.o qdev-addr.o
all: $(HWLIB)
# Dummy command so that make thinks it has done something
@true
$(HWLIB): $(obj-y)
clean:
rm -f *.o *.d *.a *~
# Include automatically generated dependency files
-include $(wildcard *.d */*.d)

View File

@@ -1,11 +1,62 @@
include config.mak
include $(SRC_PATH)/rules.mak
TARGET_BASE_ARCH:=$(TARGET_ARCH)
ifeq ($(TARGET_ARCH), x86_64)
TARGET_BASE_ARCH:=i386
endif
ifeq ($(TARGET_ARCH), mipsn32)
TARGET_BASE_ARCH:=mips
endif
ifeq ($(TARGET_ARCH), mips64)
TARGET_BASE_ARCH:=mips
endif
ifeq ($(TARGET_ARCH), ppc64)
TARGET_BASE_ARCH:=ppc
endif
ifeq ($(TARGET_ARCH), ppc64h)
TARGET_BASE_ARCH:=ppc
endif
ifeq ($(TARGET_ARCH), ppcemb)
TARGET_BASE_ARCH:=ppc
endif
ifeq ($(TARGET_ARCH), sparc64)
TARGET_BASE_ARCH:=sparc
endif
TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)
VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw
CPPFLAGS=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH) -MMD -MT $@ -MP -DNEED_CPU_H
#CFLAGS+=-Werror
LIBS=
# user emulator name
ifndef TARGET_ARCH2
TARGET_ARCH2=$(TARGET_ARCH)
endif
ifeq ($(TARGET_ARCH),arm)
ifeq ($(TARGET_WORDS_BIGENDIAN),yes)
TARGET_ARCH2=armeb
endif
endif
ifeq ($(TARGET_ARCH),sh4)
ifeq ($(TARGET_WORDS_BIGENDIAN),yes)
TARGET_ARCH2=sh4eb
endif
endif
ifeq ($(TARGET_ARCH),mips)
ifneq ($(TARGET_WORDS_BIGENDIAN),yes)
TARGET_ARCH2=mipsel
endif
endif
ifeq ($(TARGET_ARCH),mipsn32)
ifneq ($(TARGET_WORDS_BIGENDIAN),yes)
TARGET_ARCH2=mipsn32el
endif
endif
ifeq ($(TARGET_ARCH),mips64)
ifneq ($(TARGET_WORDS_BIGENDIAN),yes)
TARGET_ARCH2=mips64el
endif
endif
ifdef CONFIG_USER_ONLY
# user emulator name
@@ -33,13 +84,19 @@ ifeq ($(ARCH),i386)
HELPER_CFLAGS+=-fomit-frame-pointer
endif
ifeq ($(subst ppc64,ppc,$(ARCH))$(TARGET_BASE_ARCH),ppcppc)
translate.o: CFLAGS := $(CFLAGS) $(call cc-option, $(CFLAGS), -fno-unit-at-a-time,)
ifeq ($(ARCH),sparc)
CFLAGS+=-ffixed-g2 -ffixed-g3
ifneq ($(CONFIG_SOLARIS),yes)
CFLAGS+=-ffixed-g1 -ffixed-g6
HELPER_CFLAGS+=-ffixed-i0
endif
endif
ifeq ($(ARCH),sparc)
ifneq ($(CONFIG_SOLARIS),y)
HELPER_CFLAGS+=-ffixed-i0
ifeq ($(ARCH),sparc64)
ifneq ($(CONFIG_SOLARIS),yes)
CFLAGS+=-ffixed-g5 -ffixed-g6 -ffixed-g7
else
CFLAGS+=-ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7
endif
endif
@@ -48,12 +105,18 @@ ifeq ($(ARCH),alpha)
CFLAGS+=-msmall-data
endif
ifeq ($(ARCH),hppa)
BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
endif
ifeq ($(ARCH),ia64)
CFLAGS+=-mno-sdata
endif
CFLAGS+=$(OS_CFLAGS) $(ARCH_CFLAGS)
LDFLAGS+=$(OS_LDFLAGS) $(ARCH_LDFLAGS)
CPPFLAGS+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
CPPFLAGS+=-U_FORTIFY_SOURCE
LIBS+=-lm
ifdef CONFIG_WIN32
LIBS+=-lwinmm -lws2_32 -liphlpapi
@@ -71,89 +134,83 @@ kvm.o: CFLAGS+=$(KVM_CFLAGS)
kvm-all.o: CFLAGS+=$(KVM_CFLAGS)
all: $(PROGS)
# Dummy command so that make thinks it has done something
@true
#########################################################
# cpu emulator library
libobj-y = exec.o translate-all.o cpu-exec.o translate.o host-utils.o
libobj-$(CONFIG_KQEMU) += kqemu.o
LIBOBJS=exec.o kqemu.o translate-all.o cpu-exec.o\
translate.o host-utils.o
# TCG code generator
libobj-y += tcg/tcg.o tcg/tcg-runtime.o
LIBOBJS+= tcg/tcg.o tcg/tcg-runtime.o
CPPFLAGS+=-I$(SRC_PATH)/tcg -I$(SRC_PATH)/tcg/$(ARCH)
ifeq ($(ARCH),sparc64)
CPPFLAGS+=-I$(SRC_PATH)/tcg/sparc
endif
ifdef CONFIG_SOFTFLOAT
libobj-y += fpu/softfloat.o
LIBOBJS+=fpu/softfloat.o
else
libobj-y += fpu/softfloat-native.o
LIBOBJS+=fpu/softfloat-native.o
endif
CPPFLAGS+=-I$(SRC_PATH)/fpu
libobj-y += op_helper.o helper.o
LIBOBJS+= op_helper.o helper.o
ifeq ($(TARGET_BASE_ARCH), arm)
libobj-y += neon_helper.o iwmmxt_helper.o
LIBOBJS+= neon_helper.o iwmmxt_helper.o
endif
ifeq ($(TARGET_BASE_ARCH), alpha)
libobj-y += alpha_palcode.o
LIBOBJS+= alpha_palcode.o
endif
ifeq ($(TARGET_BASE_ARCH), cris)
libobj-y += cris-dis.o
LIBOBJS+= cris-dis.o
ifndef CONFIG_USER_ONLY
libobj-y += mmu.o
LIBOBJS+= mmu.o
endif
endif
# NOTE: the disassembler code is only needed for debugging
libobj-y += disas.o
LIBOBJS+=disas.o
ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
USE_I386_DIS=y
endif
ifeq ($(findstring x86_64, $(TARGET_ARCH) $(ARCH)),x86_64)
USE_I386_DIS=y
endif
libobj-$(USE_I386_DIS) += i386-dis.o
ifdef USE_I386_DIS
LIBOBJS+=i386-dis.o
endif
ifeq ($(findstring alpha, $(TARGET_ARCH) $(ARCH)),alpha)
libobj-y += alpha-dis.o
LIBOBJS+=alpha-dis.o
endif
ifeq ($(findstring ppc, $(TARGET_BASE_ARCH) $(ARCH)),ppc)
libobj-y += ppc-dis.o
endif
ifeq ($(findstring microblaze, $(TARGET_BASE_ARCH) $(ARCH)),microblaze)
libobj-y += microblaze-dis.o
ifndef CONFIG_USER_ONLY
libobj-y += mmu.o
endif
LIBOBJS+=ppc-dis.o
endif
ifeq ($(findstring mips, $(TARGET_BASE_ARCH) $(ARCH)),mips)
libobj-y += mips-dis.o
LIBOBJS+=mips-dis.o
endif
ifeq ($(findstring sparc, $(TARGET_BASE_ARCH) $(ARCH)),sparc)
libobj-y += sparc-dis.o
LIBOBJS+=sparc-dis.o
endif
ifeq ($(findstring arm, $(TARGET_ARCH) $(ARCH)),arm)
libobj-y += arm-dis.o
LIBOBJS+=arm-dis.o
endif
ifeq ($(findstring m68k, $(TARGET_ARCH) $(ARCH)),m68k)
libobj-y += m68k-dis.o
LIBOBJS+=m68k-dis.o
endif
ifeq ($(findstring sh4, $(TARGET_ARCH) $(ARCH)),sh4)
libobj-y += sh4-dis.o
LIBOBJS+=sh4-dis.o
endif
ifeq ($(findstring hppa, $(TARGET_BASE_ARCH) $(ARCH)),hppa)
libobj-y += hppa-dis.o
LIBOBJS+=hppa-dis.o
endif
ifeq ($(findstring s390, $(TARGET_ARCH) $(ARCH)),s390)
libobj-y += s390-dis.o
LIBOBJS+=s390-dis.o
endif
# libqemu
libqemu.a: $(libobj-y)
libqemu.a: $(LIBOBJS)
translate.o: translate.c cpu.h
@@ -163,7 +220,7 @@ tcg/tcg.o: cpu.h
# HELPER_CFLAGS is used for all the code compiled with static register
# variables
op_helper.o: CFLAGS += $(HELPER_CFLAGS)
op_helper.o: CFLAGS += $(HELPER_CFLAGS) $(I386_CFLAGS)
cpu-exec.o: CFLAGS += $(HELPER_CFLAGS)
@@ -172,6 +229,9 @@ cpu-exec.o: CFLAGS += $(HELPER_CFLAGS)
ifdef CONFIG_LINUX_USER
ifndef TARGET_ABI_DIR
TARGET_ABI_DIR=$(TARGET_ARCH)
endif
VPATH+=:$(SRC_PATH)/linux-user:$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR)
CPPFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR)
@@ -259,36 +319,48 @@ LDFLAGS+=-p
CFLAGS+=-p
endif
obj-y = main.o syscall.o strace.o mmap.o signal.o path.o thunk.o \
elfload.o linuxload.o uaccess.o envlist.o gdbstub.o gdbstub-xml.o \
ioport-user.o
obj-$(TARGET_HAS_BFLT) += flatload.o
OBJS= main.o syscall.o strace.o mmap.o signal.o path.o thunk.o \
elfload.o linuxload.o uaccess.o envlist.o
LIBS+= $(AIOLIBS)
ifdef TARGET_HAS_BFLT
OBJS+= flatload.o
endif
ifdef TARGET_HAS_ELFLOAD32
OBJS+= elfload32.o
elfload32.o: elfload.c
endif
obj-$(TARGET_HAS_ELFLOAD32) += elfload32.o
ifeq ($(TARGET_ARCH), i386)
obj-y += vm86.o
OBJS+= vm86.o
endif
ifeq ($(TARGET_ARCH), arm)
OBJS+=nwfpe/fpa11.o nwfpe/fpa11_cpdo.o \
nwfpe/fpa11_cpdt.o nwfpe/fpa11_cprt.o nwfpe/fpopcode.o nwfpe/single_cpdo.o \
nwfpe/double_cpdo.o nwfpe/extended_cpdo.o arm-semi.o
endif
ifeq ($(TARGET_ARCH), m68k)
OBJS+= m68k-sim.o m68k-semi.o
endif
nwfpe-obj-y := fpa11.o fpa11_cpdo.o fpa11_cpdt.o fpa11_cprt.o fpopcode.o
nwfpe-obj-y += single_cpdo.o double_cpdo.o extended_cpdo.o
obj-arm-y += $(addprefix nwfpe/, $(nwfpe-obj-y))
obj-arm-y += arm-semi.o
ifdef CONFIG_GDBSTUB
OBJS+=gdbstub.o gdbstub-xml.o
endif
obj-m68k-y += m68k-sim.o m68k-semi.o
OBJS+= libqemu.a
# Note: this is a workaround. The real fix is to avoid compiling
# cpu_signal_handler() in cpu-exec.c.
signal.o: CFLAGS += $(HELPER_CFLAGS)
ARLIBS=../libqemu_user.a libqemu.a
endif #CONFIG_LINUX_USER
$(QEMU_PROG): $(OBJS) ../libqemu_user.a
$(LINK)
ifeq ($(ARCH),alpha)
# Mark as 32 bit binary, i. e. it will be mapped into the low 31 bit of
# the address space (31 bit so sign extending doesn't matter)
echo -ne '\001\000\000\000' | dd of=qemu bs=1 seek=48 count=4 conv=notrunc
endif
LIBS+= $(PTHREADLIBS)
LIBS+= $(CLOCKLIBS)
endif #CONFIG_LINUX_USER
#########################################################
# Darwin user emulator target
@@ -303,14 +375,20 @@ LDFLAGS+=-Wl,-segaddr,__STD_PROG_ZONE,0x1000 -image_base 0x0e000000
LIBS+=-lmx
obj-y = main.o commpage.o machload.o mmap.o signal.o syscall.o thunk.o \
gdbstub.o gdbstub-xml.o ioport-user.o
OBJS= main.o commpage.o machload.o mmap.o signal.o syscall.o thunk.o
OBJS+= libqemu.a
ifdef CONFIG_GDBSTUB
OBJS+=gdbstub.o gdbstub-xml.o
endif
# Note: this is a workaround. The real fix is to avoid compiling
# cpu_signal_handler() in cpu-exec.c.
signal.o: CFLAGS += $(HELPER_CFLAGS)
ARLIBS=libqemu.a
$(QEMU_PROG): $(OBJS)
$(LINK)
endif #CONFIG_DARWIN_USER
@@ -400,15 +478,21 @@ LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH)el.ld
endif
endif
obj-y = main.o bsdload.o elfload.o mmap.o path.o signal.o strace.o syscall.o \
gdbstub.o gdbstub-xml.o ioport-user.o
obj-y += uaccess.o
OBJS= main.o bsdload.o elfload.o mmap.o path.o signal.o strace.o syscall.o
OBJS+= uaccess.o
OBJS+= libqemu.a
ifdef CONFIG_GDBSTUB
OBJS+=gdbstub.o
endif
# Note: this is a workaround. The real fix is to avoid compiling
# cpu_signal_handler() in cpu-exec.c.
signal.o: CFLAGS += $(HELPER_CFLAGS)
ARLIBS=libqemu.a ../libqemu_user.a
$(QEMU_PROG): $(OBJS) ../libqemu_user.a
$(LINK)
endif #CONFIG_BSD_USER
@@ -416,12 +500,22 @@ endif #CONFIG_BSD_USER
# System emulator target
ifndef CONFIG_USER_ONLY
obj-y = vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o \
gdbstub.o gdbstub-xml.o msix.o ioport.o
OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o dma-helpers.o
# virtio has to be here due to weird dependency between PCI and virtio-net.
# need to fix this properly
obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o
obj-$(CONFIG_KVM) += kvm.o kvm-all.o
OBJS+=virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o
OBJS+=fw_cfg.o
ifdef CONFIG_KVM
OBJS+=kvm.o kvm-all.o
endif
ifdef CONFIG_WIN32
OBJS+=block-raw-win32.o
else
ifdef CONFIG_AIO
OBJS+=posix-aio-compat.o
endif
OBJS+=block-raw-posix.o
endif
LIBS+=-lz
ifdef CONFIG_ALSA
@@ -443,172 +537,150 @@ ifdef CONFIG_OSS
LIBS += $(CONFIG_OSS_LIB)
endif
sound-obj-y =
sound-obj-$(CONFIG_SB16) += sb16.o
sound-obj-$(CONFIG_ES1370) += es1370.o
sound-obj-$(CONFIG_AC97) += ac97.o
sound-obj-$(CONFIG_ADLIB) += fmopl.o adlib.o
sound-obj-$(CONFIG_GUS) += gus.o gusemu_hal.o gusemu_mixer.o
sound-obj-$(CONFIG_CS4231A) += cs4231a.o
SOUND_HW = sb16.o es1370.o ac97.o
ifdef CONFIG_ADLIB
SOUND_HW += fmopl.o adlib.o
adlib.o fmopl.o: CFLAGS := ${CFLAGS} -DBUILD_Y8950=0
endif
ifdef CONFIG_GUS
SOUND_HW += gus.o gusemu_hal.o gusemu_mixer.o
endif
ifdef CONFIG_CS4231A
SOUND_HW += cs4231a.o
endif
ifdef CONFIG_VNC_TLS
CPPFLAGS += $(CONFIG_VNC_TLS_CFLAGS)
LIBS += $(CONFIG_VNC_TLS_LIBS)
endif
ifdef CONFIG_VNC_SASL
CPPFLAGS += $(CONFIG_VNC_SASL_CFLAGS)
LIBS += $(CONFIG_VNC_SASL_LIBS)
endif
ifdef CONFIG_BLUEZ
LIBS += $(CONFIG_BLUEZ_LIBS)
endif
# xen backend driver support
obj-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o
ifeq ($(CONFIG_XEN), y)
LIBS += $(XEN_LIBS)
endif
# SCSI layer
OBJS+= lsi53c895a.o esp.o
# USB layer
obj-y += usb-ohci.o
OBJS+= usb-ohci.o
# EEPROM emulation
OBJS += eeprom93xx.o
# PCI network cards
obj-y += eepro100.o
obj-y += ne2000.o
obj-y += pcnet.o
obj-y += rtl8139.o
obj-y += e1000.o
OBJS += eepro100.o
OBJS += ne2000.o
OBJS += pcnet.o
OBJS += rtl8139.o
OBJS += e1000.o
# Generic watchdog support and some watchdog devices
obj-y += wdt_ib700.o wdt_i6300esb.o
# Hardware support
obj-i386-y = ide.o pckbd.o vga.o $(sound-obj-y) dma.o
obj-i386-y += fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
obj-i386-y += cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o
obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o
# Serial mouse
OBJS += msmouse.o
ifeq ($(TARGET_BASE_ARCH), i386)
# Hardware support
OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o
OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
OBJS+= cirrus_vga.o apic.o parallel.o acpi.o piix_pci.o
OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
OBJS += device-hotplug.o pci-hotplug.o
CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
endif
# shared objects
obj-ppc-y = ppc.o ide.o vga.o $(sound-obj-y) dma.o openpic.o
# PREP target
obj-ppc-y += pckbd.o serial.o i8259.o i8254.o fdc.o mc146818rtc.o
obj-ppc-y += prep_pci.o ppc_prep.o
# Mac shared devices
obj-ppc-y += macio.o cuda.o adb.o mac_nvram.o mac_dbdma.o
# OldWorld PowerMac
obj-ppc-y += heathrow_pic.o grackle_pci.o ppc_oldworld.o
# NewWorld PowerMac
obj-ppc-y += unin_pci.o ppc_newworld.o
# PowerPC 4xx boards
obj-ppc-y += pflash_cfi02.o ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
obj-ppc-y += ppc440.o ppc440_bamboo.o
# PowerPC E500 boards
obj-ppc-y += ppce500_pci.o ppce500_mpc8544ds.o
obj-ppc-$(CONFIG_KVM) += kvm_ppc.o
ifeq ($(TARGET_BASE_ARCH), ppc)
CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
endif
# shared objects
OBJS+= ppc.o ide.o vga.o $(SOUND_HW) dma.o openpic.o
# PREP target
OBJS+= pckbd.o ps2.o serial.o i8259.o i8254.o fdc.o m48t59.o mc146818rtc.o
OBJS+= prep_pci.o ppc_prep.o
# Mac shared devices
OBJS+= macio.o cuda.o adb.o mac_nvram.o mac_dbdma.o escc.o
# OldWorld PowerMac
OBJS+= heathrow_pic.o grackle_pci.o ppc_oldworld.o
# NewWorld PowerMac
OBJS+= unin_pci.o ppc_newworld.o
# PowerPC 4xx boards
OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
OBJS+= ppc440.o ppc440_bamboo.o
# PowerPC E500 boards
OBJS+= ppce500_pci.o ppce500_mpc8544ds.o
ifdef FDT_LIBS
obj-ppc-y += device_tree.o
OBJS+= device_tree.o
LIBS+= $(FDT_LIBS)
endif
obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
obj-mips-y += mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o rc4030.o
obj-mips-y += g364fb.o jazz_led.o dp8393x.o
obj-mips-y += ide.o gt64xxx.o pckbd.o fdc.o mc146818rtc.o usb-uhci.o acpi.o ds1225y.o
obj-mips-y += piix_pci.o parallel.o cirrus_vga.o pcspk.o $(sound-obj-y)
obj-mips-y += mipsnet.o
obj-mips-y += pflash_cfi01.o
obj-mips-y += vmware_vga.o
ifdef CONFIG_KVM
OBJS+= kvm_ppc.o
endif
endif
ifeq ($(TARGET_BASE_ARCH), mips)
OBJS+= mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
OBJS+= mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o rc4030.o
OBJS+= g364fb.o jazz_led.o
OBJS+= ide.o gt64xxx.o pckbd.o ps2.o fdc.o mc146818rtc.o usb-uhci.o acpi.o ds1225y.o
OBJS+= piix_pci.o parallel.o cirrus_vga.o pcspk.o $(SOUND_HW)
OBJS+= mipsnet.o
OBJS+= pflash_cfi01.o
OBJS+= vmware_vga.o
CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
endif
obj-microblaze-y = petalogix_s3adsp1800_mmu.o
obj-microblaze-y += microblaze_pic_cpu.o
obj-microblaze-y += xilinx_intc.o
obj-microblaze-y += xilinx_timer.o
obj-microblaze-y += xilinx_uartlite.o
obj-microblaze-y += xilinx_ethlite.o
obj-microblaze-y += pflash_cfi02.o
ifdef FDT_LIBS
obj-microblaze-y += device_tree.o
LIBS+= $(FDT_LIBS)
endif
ifeq ($(TARGET_BASE_ARCH), cris)
# Boards
obj-cris-y = cris_pic_cpu.o etraxfs.o axis_dev88.o
OBJS+= etraxfs.o axis_dev88.o
# IO blocks
obj-cris-y += etraxfs_dma.o
obj-cris-y += etraxfs_pic.o
obj-cris-y += etraxfs_eth.o
obj-cris-y += etraxfs_timer.o
obj-cris-y += etraxfs_ser.o
OBJS+= etraxfs_dma.o
OBJS+= etraxfs_pic.o
OBJS+= etraxfs_eth.o
OBJS+= etraxfs_timer.o
OBJS+= etraxfs_ser.o
obj-cris-y += pflash_cfi02.o
ifeq ($(TARGET_ARCH), sparc64)
obj-sparc-y = sun4u.o ide.o pckbd.o vga.o apb_pci.o
obj-sparc-y += fdc.o mc146818rtc.o serial.o
obj-sparc-y += cirrus_vga.o parallel.o
else
obj-sparc-y = sun4m.o tcx.o iommu.o slavio_intctl.o
obj-sparc-y += slavio_timer.o slavio_misc.o fdc.o sparc32_dma.o
obj-sparc-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o
OBJS+= ptimer.o
OBJS+= pflash_cfi02.o nand.o
endif
ifeq ($(TARGET_BASE_ARCH), sparc)
ifeq ($(TARGET_ARCH), sparc64)
OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o apb_pci.o
OBJS+= fdc.o mc146818rtc.o serial.o m48t59.o
OBJS+= cirrus_vga.o parallel.o ptimer.o
else
OBJS+= sun4m.o tcx.o pcnet.o iommu.o m48t59.o slavio_intctl.o
OBJS+= slavio_timer.o escc.o slavio_misc.o fdc.o sparc32_dma.o
OBJS+= cs4231.o ptimer.o eccmemctl.o sbi.o sun4c_intctl.o
endif
endif
obj-arm-y = integratorcp.o versatilepb.o smc91c111.o arm_pic.o arm_timer.o
obj-arm-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
obj-arm-y += versatile_pci.o
obj-arm-y += realview_gic.o realview.o arm_sysctl.o mpcore.o
obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
obj-arm-y += pl061.o
obj-arm-y += arm-semi.o
obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
obj-arm-y += pflash_cfi01.o gumstix.o
obj-arm-y += zaurus.o ide.o serial.o spitz.o tosa.o tc6393xb.o
obj-arm-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o
obj-arm-y += omap2.o omap_dss.o soc_dma.o
obj-arm-y += omap_sx1.o palm.o tsc210x.o
obj-arm-y += nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
obj-arm-y += mst_fpga.o mainstone.o
obj-arm-y += musicpal.o pflash_cfi02.o
obj-arm-y += framebuffer.o
obj-arm-y += syborg.o syborg_fb.o syborg_interrupt.o syborg_keyboard.o
obj-arm-y += syborg_serial.o syborg_timer.o syborg_pointer.o syborg_rtc.o
obj-arm-y += syborg_virtio.o
ifeq ($(TARGET_BASE_ARCH), arm)
OBJS+= integratorcp.o versatilepb.o ps2.o smc91c111.o arm_pic.o arm_timer.o
OBJS+= arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
OBJS+= versatile_pci.o ptimer.o
OBJS+= realview_gic.o realview.o arm_sysctl.o mpcore.o
OBJS+= armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
OBJS+= pl061.o
OBJS+= arm-semi.o
OBJS+= pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
OBJS+= pflash_cfi01.o gumstix.o
OBJS+= zaurus.o ide.o serial.o nand.o ecc.o spitz.o tosa.o tc6393xb.o
OBJS+= omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o
OBJS+= omap2.o omap_dss.o soc_dma.o
OBJS+= omap_sx1.o palm.o tsc210x.o
OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
OBJS+= tsc2005.o bt-hci-csr.o
OBJS+= mst_fpga.o mainstone.o
OBJS+= musicpal.o pflash_cfi02.o
CPPFLAGS += -DHAS_AUDIO
endif
obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
obj-sh4-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o serial.o
obj-sh4-y += ide.o
obj-m68k-y = an5206.o mcf5206.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
obj-m68k-y += m68k-semi.o dummy_m68k.o
ifeq ($(TARGET_BASE_ARCH), sh4)
OBJS+= shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
OBJS+= sh_timer.o ptimer.o sh_serial.o sh_intc.o sh_pci.o sm501.o serial.o
OBJS+= ide.o
endif
ifeq ($(TARGET_BASE_ARCH), m68k)
OBJS+= an5206.o mcf5206.o ptimer.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
OBJS+= m68k-semi.o dummy_m68k.o
endif
ifdef CONFIG_GDBSTUB
OBJS+=gdbstub.o gdbstub-xml.o
endif
ifdef CONFIG_COCOA
COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa -framework IOKit
ifdef CONFIG_COREAUDIO
@@ -619,6 +691,7 @@ ifdef CONFIG_SLIRP
CPPFLAGS+=-I$(SRC_PATH)/slirp
endif
LIBS+=$(AIOLIBS)
# specific flags are needed for non soft mmu emulator
ifdef CONFIG_STATIC
LDFLAGS+=-static
@@ -651,42 +724,28 @@ LDFLAGS+=-p
main.o: CFLAGS+=-p
endif
vl.o: CFLAGS+=$(SDL_CFLAGS)
$(QEMU_PROG): LIBS += $(SDL_LIBS) $(COCOA_LIBS) $(CURSES_LIBS) $(BRLAPI_LIBS) $(VDE_LIBS)
vl.o: qemu-options.h
monitor.o: qemu-monitor.h
LIBS += $(SDL_LIBS) $(COCOA_LIBS) $(CURSES_LIBS) $(BRLAPI_LIBS) $(VDE_LIBS) $(CURL_LIBS)
ARLIBS=../libqemu_common.a libqemu.a $(HWLIB)
$(QEMU_PROG): $(OBJS) ../libqemu_common.a libqemu.a
$(LINK)
endif # !CONFIG_USER_ONLY
$(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y) $(ARLIBS)
$(call LINK,$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y))
gdbstub-xml.c: $(TARGET_XML_FILES) feature_to_c.sh
rm -f $@
ifeq ($(TARGET_XML_FILES),)
$(call quiet-command,rm -f $@ && echo > $@," GEN $(TARGET_DIR)$@")
echo > $@
else
$(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/feature_to_c.sh $@ $(TARGET_XML_FILES)," GEN $(TARGET_DIR)$@")
$(SHELL) $(SRC_PATH)/feature_to_c.sh $@ $(TARGET_XML_FILES)
endif
qemu-options.h: $(SRC_PATH)/qemu-options.hx
$(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
qemu-monitor.h: $(SRC_PATH)/qemu-monitor.hx
$(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
clean:
rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o
rm -f *.d */*.d tcg/*.o
rm -f qemu-options.h qemu-monitor.h gdbstub-xml.c
install: all
ifneq ($(PROGS),)
$(INSTALL) -m 755 $(STRIP_OPT) $(PROGS) "$(DESTDIR)$(bindir)"
$(INSTALL) -m 755 -s $(PROGS) "$(DESTDIR)$(bindir)"
endif
# Include automatically generated dependency files

View File

@@ -1 +1 @@
0.10.92
0.10.5

185
acl.c
View File

@@ -1,185 +0,0 @@
/*
* QEMU access control list management
*
* Copyright (C) 2009 Red Hat, Inc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "qemu-common.h"
#include "sysemu.h"
#include "acl.h"
#ifdef HAVE_FNMATCH_H
#include <fnmatch.h>
#endif
static unsigned int nacls = 0;
static qemu_acl **acls = NULL;
qemu_acl *qemu_acl_find(const char *aclname)
{
int i;
for (i = 0 ; i < nacls ; i++) {
if (strcmp(acls[i]->aclname, aclname) == 0)
return acls[i];
}
return NULL;
}
qemu_acl *qemu_acl_init(const char *aclname)
{
qemu_acl *acl;
acl = qemu_acl_find(aclname);
if (acl)
return acl;
acl = qemu_malloc(sizeof(*acl));
acl->aclname = qemu_strdup(aclname);
/* Deny by default, so there is no window of "open
* access" between QEMU starting, and the user setting
* up ACLs in the monitor */
acl->defaultDeny = 1;
acl->nentries = 0;
TAILQ_INIT(&acl->entries);
acls = qemu_realloc(acls, sizeof(*acls) * (nacls +1));
acls[nacls] = acl;
nacls++;
return acl;
}
int qemu_acl_party_is_allowed(qemu_acl *acl,
const char *party)
{
qemu_acl_entry *entry;
TAILQ_FOREACH(entry, &acl->entries, next) {
#ifdef HAVE_FNMATCH_H
if (fnmatch(entry->match, party, 0) == 0)
return entry->deny ? 0 : 1;
#else
/* No fnmatch, so fallback to exact string matching
* instead of allowing wildcards */
if (strcmp(entry->match, party) == 0)
return entry->deny ? 0 : 1;
#endif
}
return acl->defaultDeny ? 0 : 1;
}
void qemu_acl_reset(qemu_acl *acl)
{
qemu_acl_entry *entry;
/* Put back to deny by default, so there is no window
* of "open access" while the user re-initializes the
* access control list */
acl->defaultDeny = 1;
TAILQ_FOREACH(entry, &acl->entries, next) {
TAILQ_REMOVE(&acl->entries, entry, next);
free(entry->match);
free(entry);
}
acl->nentries = 0;
}
int qemu_acl_append(qemu_acl *acl,
int deny,
const char *match)
{
qemu_acl_entry *entry;
entry = qemu_malloc(sizeof(*entry));
entry->match = qemu_strdup(match);
entry->deny = deny;
TAILQ_INSERT_TAIL(&acl->entries, entry, next);
acl->nentries++;
return acl->nentries;
}
int qemu_acl_insert(qemu_acl *acl,
int deny,
const char *match,
int index)
{
qemu_acl_entry *entry;
qemu_acl_entry *tmp;
int i = 0;
if (index <= 0)
return -1;
if (index >= acl->nentries)
return qemu_acl_append(acl, deny, match);
entry = qemu_malloc(sizeof(*entry));
entry->match = qemu_strdup(match);
entry->deny = deny;
TAILQ_FOREACH(tmp, &acl->entries, next) {
i++;
if (i == index) {
TAILQ_INSERT_BEFORE(tmp, entry, next);
acl->nentries++;
break;
}
}
return i;
}
int qemu_acl_remove(qemu_acl *acl,
const char *match)
{
qemu_acl_entry *entry;
int i = 0;
TAILQ_FOREACH(entry, &acl->entries, next) {
i++;
if (strcmp(entry->match, match) == 0) {
TAILQ_REMOVE(&acl->entries, entry, next);
return i;
}
}
return -1;
}
/*
* Local variables:
* c-indent-level: 4
* c-basic-offset: 4
* tab-width: 8
* End:
*/

74
acl.h
View File

@@ -1,74 +0,0 @@
/*
* QEMU access control list management
*
* Copyright (C) 2009 Red Hat, Inc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __QEMU_ACL_H__
#define __QEMU_ACL_H__
#include "sys-queue.h"
typedef struct qemu_acl_entry qemu_acl_entry;
typedef struct qemu_acl qemu_acl;
struct qemu_acl_entry {
char *match;
int deny;
TAILQ_ENTRY(qemu_acl_entry) next;
};
struct qemu_acl {
char *aclname;
unsigned int nentries;
TAILQ_HEAD(,qemu_acl_entry) entries;
int defaultDeny;
};
qemu_acl *qemu_acl_init(const char *aclname);
qemu_acl *qemu_acl_find(const char *aclname);
int qemu_acl_party_is_allowed(qemu_acl *acl,
const char *party);
void qemu_acl_reset(qemu_acl *acl);
int qemu_acl_append(qemu_acl *acl,
int deny,
const char *match);
int qemu_acl_insert(qemu_acl *acl,
int deny,
const char *match,
int index);
int qemu_acl_remove(qemu_acl *acl,
const char *match);
#endif /* __QEMU_ACL_H__ */
/*
* Local variables:
* c-indent-level: 4
* c-basic-offset: 4
* tab-width: 8
* End:
*/

6
aes.c
View File

@@ -34,10 +34,16 @@
#define NDEBUG
#endif
#include <assert.h>
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
#define MAXKC (256/32)
#define MAXKB (256/8)
#define MAXNR 14
/* This controls loop-unrolling in aes_core.c */
#undef FULL_UNROLL
# define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]))

10
aio.c
View File

@@ -103,16 +103,12 @@ 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);
}
} while (qemu_bh_poll() || ret > 0);
qemu_aio_wait();
} while (ret > 0);
}
void qemu_aio_wait(void)

View File

@@ -16,8 +16,9 @@ warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this file; see the file COPYING. If not, see
<http://www.gnu.org/licenses/>. */
along with this file; see the file COPYING. If not, write to the Free
Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
02110-1301, USA. */
#include <stdio.h>
#include "dis-asm.h"

View File

@@ -17,7 +17,8 @@
more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>. */
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
/* Start of qemu specific additions. Mostly this is stub definitions
for things we don't care about. */
@@ -1553,6 +1554,32 @@ enum map_type last_type;
int last_mapping_sym = -1;
bfd_vma last_mapping_addr = 0;
/* Functions. */
int
get_arm_regname_num_options (void)
{
return NUM_ARM_REGNAMES;
}
int
set_arm_regname_option (int option)
{
int old = regname_selected;
regname_selected = option;
return old;
}
int
get_arm_regnames (int option, const char **setname, const char **setdescription,
const char *const **register_names)
{
*setname = regnames[option].name;
*setdescription = regnames[option].description;
*register_names = regnames[option].reg_names;
return 16;
}
/* Decode a bitfield of the form matching regexp (N(-N)?,)*N(-N)?.
Returns pointer to following character of the format string and
fills in *VALUEP and *WIDTHP with the extracted value and number of
@@ -4117,3 +4144,22 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info)
}
return size;
}
void
print_arm_disassembler_options (FILE *stream)
{
int i;
fprintf (stream, _("\n\
The following ARM specific disassembler options are supported for use with\n\
the -M switch:\n"));
for (i = NUM_ARM_REGNAMES; i--;)
fprintf (stream, " reg-names-%s %*c%s\n",
regnames[i].name,
(int)(14 - strlen (regnames[i].name)), ' ',
regnames[i].description);
fprintf (stream, " force-thumb Assume all insns are Thumb insns\n");
fprintf (stream, " no-force-thumb Examine preceeding label to determine an insn's type\n\n");
}

View File

@@ -15,7 +15,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <sys/types.h>

View File

@@ -25,10 +25,6 @@
#include "qemu-common.h"
#include "audio.h"
#if QEMU_GNUC_PREREQ(4, 3)
#pragma GCC diagnostic ignored "-Waddress"
#endif
#define AUDIO_CAP "alsa"
#include "audio_int.h"
@@ -630,9 +626,8 @@ static int alsa_init_out (HWVoiceOut *hw, struct audsettings *as)
req.period_size = conf.period_size_out;
req.buffer_size = conf.buffer_size_out;
req.size_in_usec = conf.size_in_usec_out;
req.override_mask =
(conf.period_size_out_overridden ? 1 : 0) |
(conf.buffer_size_out_overridden ? 2 : 0);
req.override_mask = !!conf.period_size_out_overridden
| (!!conf.buffer_size_out_overridden << 1);
if (alsa_open (0, &req, &obt, &handle)) {
return -1;
@@ -711,9 +706,8 @@ static int alsa_init_in (HWVoiceIn *hw, struct audsettings *as)
req.period_size = conf.period_size_in;
req.buffer_size = conf.buffer_size_in;
req.size_in_usec = conf.size_in_usec_in;
req.override_mask =
(conf.period_size_in_overridden ? 1 : 0) |
(conf.buffer_size_in_overridden ? 2 : 0);
req.override_mask = !!conf.period_size_in_overridden
| (!!conf.buffer_size_in_overridden << 1);
if (alsa_open (1, &req, &obt, &handle)) {
return -1;

View File

@@ -23,7 +23,7 @@
*/
#include "hw/hw.h"
#include "audio.h"
#include "monitor.h"
#include "console.h"
#include "qemu-timer.h"
#include "sysemu.h"
@@ -328,10 +328,10 @@ void AUD_vlog (const char *cap, const char *fmt, va_list ap)
{
if (conf.log_to_monitor) {
if (cap) {
monitor_printf(cur_mon, "%s: ", cap);
term_printf ("%s: ", cap);
}
monitor_vprintf(cur_mon, fmt, ap);
term_vprintf (fmt, ap);
}
else {
if (cap) {
@@ -707,11 +707,11 @@ static void noop_conv (struct st_sample *dst, const void *src,
}
static CaptureVoiceOut *audio_pcm_capture_find_specific (
AudioState *s,
struct audsettings *as
)
{
CaptureVoiceOut *cap;
AudioState *s = &glob_audio_state;
for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {
if (audio_pcm_info_eq (&cap->hw.info, as)) {
@@ -786,9 +786,8 @@ static void audio_detach_capture (HWVoiceOut *hw)
}
}
static int audio_attach_capture (HWVoiceOut *hw)
static int audio_attach_capture (AudioState *s, HWVoiceOut *hw)
{
AudioState *s = &glob_audio_state;
CaptureVoiceOut *cap;
audio_detach_capture (hw);
@@ -1296,7 +1295,7 @@ static void audio_run_out (AudioState *s)
HWVoiceOut *hw = NULL;
SWVoiceOut *sw;
while ((hw = audio_pcm_hw_find_any_enabled_out (hw))) {
while ((hw = audio_pcm_hw_find_any_enabled_out (s, hw))) {
int played;
int live, free, nb_live, cleanup_required, prev_rpos;
@@ -1391,7 +1390,7 @@ static void audio_run_out (AudioState *s)
#ifdef DEBUG_PLIVE
dolog ("Finishing with old voice\n");
#endif
audio_close_out (sw);
audio_close_out (s, sw);
}
sw = sw1;
}
@@ -1403,7 +1402,7 @@ static void audio_run_in (AudioState *s)
{
HWVoiceIn *hw = NULL;
while ((hw = audio_pcm_hw_find_any_enabled_in (hw))) {
while ((hw = audio_pcm_hw_find_any_enabled_in (s, hw))) {
SWVoiceIn *sw;
int captured, min;
@@ -1611,8 +1610,8 @@ static int audio_driver_init (AudioState *s, struct audio_driver *drv)
s->drv_opaque = drv->init ();
if (s->drv_opaque) {
audio_init_nb_voices_out (drv);
audio_init_nb_voices_in (drv);
audio_init_nb_voices_out (s, drv);
audio_init_nb_voices_in (s, drv);
s->drv = drv;
return 0;
}
@@ -1631,11 +1630,11 @@ static void audio_vm_change_state_handler (void *opaque, int running,
int op = running ? VOICE_ENABLE : VOICE_DISABLE;
s->vm_running = running;
while ((hwo = audio_pcm_hw_find_any_enabled_out (hwo))) {
while ((hwo = audio_pcm_hw_find_any_enabled_out (s, hwo))) {
hwo->pcm_ops->ctl_out (hwo, op);
}
while ((hwi = audio_pcm_hw_find_any_enabled_in (hwi))) {
while ((hwi = audio_pcm_hw_find_any_enabled_in (s, hwi))) {
hwi->pcm_ops->ctl_in (hwi, op);
}
}
@@ -1646,7 +1645,7 @@ static void audio_atexit (void)
HWVoiceOut *hwo = NULL;
HWVoiceIn *hwi = NULL;
while ((hwo = audio_pcm_hw_find_any_enabled_out (hwo))) {
while ((hwo = audio_pcm_hw_find_any_enabled_out (s, hwo))) {
SWVoiceCap *sc;
hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE);
@@ -1662,7 +1661,7 @@ static void audio_atexit (void)
}
}
while ((hwi = audio_pcm_hw_find_any_enabled_in (hwi))) {
while ((hwi = audio_pcm_hw_find_any_enabled_in (s, hwi))) {
hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);
hwi->pcm_ops->fini_in (hwi);
}
@@ -1690,17 +1689,28 @@ static int audio_load (QEMUFile *f, void *opaque, int version_id)
return 0;
}
static void audio_init (void)
void AUD_register_card (AudioState *s, const char *name, QEMUSoundCard *card)
{
card->audio = s;
card->name = qemu_strdup (name);
memset (&card->entries, 0, sizeof (card->entries));
LIST_INSERT_HEAD (&s->card_head, card, entries);
}
void AUD_remove_card (QEMUSoundCard *card)
{
LIST_REMOVE (card, entries);
card->audio = NULL;
qemu_free (card->name);
}
AudioState *AUD_init (void)
{
size_t i;
int done = 0;
const char *drvname;
AudioState *s = &glob_audio_state;
if (s->drv) {
return;
}
LIST_INIT (&s->hw_head_out);
LIST_INIT (&s->hw_head_in);
LIST_INIT (&s->cap_head);
@@ -1708,7 +1718,8 @@ static void audio_init (void)
s->ts = qemu_new_timer (vm_clock, audio_timer, s);
if (!s->ts) {
hw_error("Could not create audio timer\n");
dolog ("Could not create audio timer\n");
return NULL;
}
audio_process_options ("AUDIO", audio_options);
@@ -1761,62 +1772,60 @@ static void audio_init (void)
if (!done) {
done = !audio_driver_init (s, &no_audio_driver);
if (!done) {
hw_error("Could not initialize audio subsystem\n");
dolog ("Could not initialize audio subsystem\n");
}
else {
dolog ("warning: Using timer based audio emulation\n");
}
}
VMChangeStateEntry *e;
if (done) {
VMChangeStateEntry *e;
if (conf.period.hertz <= 0) {
if (conf.period.hertz < 0) {
dolog ("warning: Timer period is negative - %d "
"treating as zero\n",
conf.period.hertz);
if (conf.period.hertz <= 0) {
if (conf.period.hertz < 0) {
dolog ("warning: Timer period is negative - %d "
"treating as zero\n",
conf.period.hertz);
}
conf.period.ticks = 1;
}
else {
conf.period.ticks = ticks_per_sec / conf.period.hertz;
}
conf.period.ticks = 1;
} else {
conf.period.ticks = ticks_per_sec / conf.period.hertz;
}
e = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s);
if (!e) {
dolog ("warning: Could not register change state handler\n"
"(Audio can continue looping even after stopping the VM)\n");
e = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s);
if (!e) {
dolog ("warning: Could not register change state handler\n"
"(Audio can continue looping even after stopping the VM)\n");
}
}
else {
qemu_del_timer (s->ts);
return NULL;
}
LIST_INIT (&s->card_head);
register_savevm ("audio", 0, 1, audio_save, audio_load, s);
qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);
return s;
}
void AUD_register_card (const char *name, QEMUSoundCard *card)
{
audio_init ();
card->name = qemu_strdup (name);
memset (&card->entries, 0, sizeof (card->entries));
LIST_INSERT_HEAD (&glob_audio_state.card_head, card, entries);
}
void AUD_remove_card (QEMUSoundCard *card)
{
LIST_REMOVE (card, entries);
qemu_free (card->name);
}
CaptureVoiceOut *AUD_add_capture (
AudioState *s,
struct audsettings *as,
struct audio_capture_ops *ops,
void *cb_opaque
)
{
AudioState *s = &glob_audio_state;
CaptureVoiceOut *cap;
struct capture_callback *cb;
if (!s) {
/* XXX suppress */
s = &glob_audio_state;
}
if (audio_validate_settings (as)) {
dolog ("Invalid settings were passed when trying to add capture\n");
audio_print_settings (as);
@@ -1832,7 +1841,7 @@ CaptureVoiceOut *AUD_add_capture (
cb->ops = *ops;
cb->opaque = cb_opaque;
cap = audio_pcm_capture_find_specific (as);
cap = audio_pcm_capture_find_specific (s, as);
if (cap) {
LIST_INSERT_HEAD (&cap->cb_head, cb, entries);
return cap;
@@ -1882,8 +1891,8 @@ CaptureVoiceOut *AUD_add_capture (
LIST_INSERT_HEAD (&cap->cb_head, cb, entries);
hw = NULL;
while ((hw = audio_pcm_hw_find_any_out (hw))) {
audio_attach_capture (hw);
while ((hw = audio_pcm_hw_find_any_out (s, hw))) {
audio_attach_capture (s, hw);
}
return cap;

View File

@@ -78,6 +78,7 @@ typedef struct CaptureVoiceOut CaptureVoiceOut;
typedef struct SWVoiceIn SWVoiceIn;
typedef struct QEMUSoundCard {
AudioState *audio;
char *name;
LIST_ENTRY (QEMUSoundCard) entries;
} QEMUSoundCard;
@@ -93,10 +94,12 @@ void AUD_log (const char *cap, const char *fmt, ...)
#endif
;
AudioState *AUD_init (void);
void AUD_help (void);
void AUD_register_card (const char *name, QEMUSoundCard *card);
void AUD_register_card (AudioState *s, const char *name, QEMUSoundCard *card);
void AUD_remove_card (QEMUSoundCard *card);
CaptureVoiceOut *AUD_add_capture (
AudioState *s,
struct audsettings *as,
struct audio_capture_ops *ops,
void *opaque

View File

@@ -104,7 +104,6 @@ typedef struct HWVoiceIn {
} HWVoiceIn;
struct SWVoiceOut {
QEMUSoundCard *card;
struct audio_pcm_info info;
t_sample *conv;
int64_t ratio;
@@ -121,7 +120,6 @@ struct SWVoiceOut {
};
struct SWVoiceIn {
QEMUSoundCard *card;
int active;
struct audio_pcm_info info;
int64_t ratio;

View File

@@ -36,9 +36,11 @@
#define HWBUF hw->conv_buf
#endif
static void glue (audio_init_nb_voices_, TYPE) (struct audio_driver *drv)
static void glue (audio_init_nb_voices_, TYPE) (
AudioState *s,
struct audio_driver *drv
)
{
AudioState *s = &glob_audio_state;
int max_voices = glue (drv->max_voices_, TYPE);
int voice_size = glue (drv->voice_size_, TYPE);
@@ -192,9 +194,8 @@ static void glue (audio_pcm_hw_del_sw_, TYPE) (SW *sw)
LIST_REMOVE (sw, entries);
}
static void glue (audio_pcm_hw_gc_, TYPE) (HW **hwp)
static void glue (audio_pcm_hw_gc_, TYPE) (AudioState *s, HW **hwp)
{
AudioState *s = &glob_audio_state;
HW *hw = *hwp;
if (!hw->sw_head.lh_first) {
@@ -210,15 +211,14 @@ static void glue (audio_pcm_hw_gc_, TYPE) (HW **hwp)
}
}
static HW *glue (audio_pcm_hw_find_any_, TYPE) (HW *hw)
static HW *glue (audio_pcm_hw_find_any_, TYPE) (AudioState *s, HW *hw)
{
AudioState *s = &glob_audio_state;
return hw ? hw->entries.le_next : glue (s->hw_head_, TYPE).lh_first;
return hw ? hw->entries.le_next : s->glue (hw_head_, TYPE).lh_first;
}
static HW *glue (audio_pcm_hw_find_any_enabled_, TYPE) (HW *hw)
static HW *glue (audio_pcm_hw_find_any_enabled_, TYPE) (AudioState *s, HW *hw)
{
while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (hw))) {
while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (s, hw))) {
if (hw->enabled) {
return hw;
}
@@ -227,11 +227,12 @@ static HW *glue (audio_pcm_hw_find_any_enabled_, TYPE) (HW *hw)
}
static HW *glue (audio_pcm_hw_find_specific_, TYPE) (
AudioState *s,
HW *hw,
struct audsettings *as
)
{
while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (hw))) {
while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (s, hw))) {
if (audio_pcm_info_eq (&hw->info, as)) {
return hw;
}
@@ -239,10 +240,10 @@ static HW *glue (audio_pcm_hw_find_specific_, TYPE) (
return NULL;
}
static HW *glue (audio_pcm_hw_add_new_, TYPE) (struct audsettings *as)
static HW *glue (audio_pcm_hw_add_new_, TYPE) (AudioState *s,
struct audsettings *as)
{
HW *hw;
AudioState *s = &glob_audio_state;
struct audio_driver *drv = s->drv;
if (!glue (s->nb_hw_voices_, TYPE)) {
@@ -297,7 +298,7 @@ static HW *glue (audio_pcm_hw_add_new_, TYPE) (struct audsettings *as)
LIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries);
glue (s->nb_hw_voices_, TYPE) -= 1;
#ifdef DAC
audio_attach_capture (hw);
audio_attach_capture (s, hw);
#endif
return hw;
@@ -308,31 +309,33 @@ static HW *glue (audio_pcm_hw_add_new_, TYPE) (struct audsettings *as)
return NULL;
}
static HW *glue (audio_pcm_hw_add_, TYPE) (struct audsettings *as)
static HW *glue (audio_pcm_hw_add_, TYPE) (AudioState *s,
struct audsettings *as)
{
HW *hw;
if (glue (conf.fixed_, TYPE).enabled && glue (conf.fixed_, TYPE).greedy) {
hw = glue (audio_pcm_hw_add_new_, TYPE) (as);
hw = glue (audio_pcm_hw_add_new_, TYPE) (s, as);
if (hw) {
return hw;
}
}
hw = glue (audio_pcm_hw_find_specific_, TYPE) (NULL, as);
hw = glue (audio_pcm_hw_find_specific_, TYPE) (s, NULL, as);
if (hw) {
return hw;
}
hw = glue (audio_pcm_hw_add_new_, TYPE) (as);
hw = glue (audio_pcm_hw_add_new_, TYPE) (s, as);
if (hw) {
return hw;
}
return glue (audio_pcm_hw_find_any_, TYPE) (NULL);
return glue (audio_pcm_hw_find_any_, TYPE) (s, NULL);
}
static SW *glue (audio_pcm_create_voice_pair_, TYPE) (
AudioState *s,
const char *sw_name,
struct audsettings *as
)
@@ -355,7 +358,7 @@ static SW *glue (audio_pcm_create_voice_pair_, TYPE) (
goto err1;
}
hw = glue (audio_pcm_hw_add_, TYPE) (&hw_as);
hw = glue (audio_pcm_hw_add_, TYPE) (s, &hw_as);
if (!hw) {
goto err2;
}
@@ -370,30 +373,31 @@ static SW *glue (audio_pcm_create_voice_pair_, TYPE) (
err3:
glue (audio_pcm_hw_del_sw_, TYPE) (sw);
glue (audio_pcm_hw_gc_, TYPE) (&hw);
glue (audio_pcm_hw_gc_, TYPE) (s, &hw);
err2:
qemu_free (sw);
err1:
return NULL;
}
static void glue (audio_close_, TYPE) (SW *sw)
static void glue (audio_close_, TYPE) (AudioState *s, SW *sw)
{
glue (audio_pcm_sw_fini_, TYPE) (sw);
glue (audio_pcm_hw_del_sw_, TYPE) (sw);
glue (audio_pcm_hw_gc_, TYPE) (&sw->hw);
glue (audio_pcm_hw_gc_, TYPE) (s, &sw->hw);
qemu_free (sw);
}
void glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw)
{
if (sw) {
if (audio_bug (AUDIO_FUNC, !card)) {
dolog ("card=%p\n", card);
if (audio_bug (AUDIO_FUNC, !card || !card->audio)) {
dolog ("card=%p card->audio=%p\n",
card, card ? card->audio : NULL);
return;
}
glue (audio_close_, TYPE) (sw);
glue (audio_close_, TYPE) (card->audio, sw);
}
}
@@ -406,7 +410,7 @@ SW *glue (AUD_open_, TYPE) (
struct audsettings *as
)
{
AudioState *s = &glob_audio_state;
AudioState *s;
#ifdef DAC
int live = 0;
SW *old_sw = NULL;
@@ -415,12 +419,15 @@ SW *glue (AUD_open_, TYPE) (
ldebug ("open %s, freq %d, nchannels %d, fmt %d\n",
name, as->freq, as->nchannels, as->fmt);
if (audio_bug (AUDIO_FUNC, !card || !name || !callback_fn || !as)) {
dolog ("card=%p name=%p callback_fn=%p as=%p\n",
card, name, callback_fn, as);
if (audio_bug (AUDIO_FUNC,
!card || !card->audio || !name || !callback_fn || !as)) {
dolog ("card=%p card->audio=%p name=%p callback_fn=%p as=%p\n",
card, card ? card->audio : NULL, name, callback_fn, as);
goto fail;
}
s = card->audio;
if (audio_bug (AUDIO_FUNC, audio_validate_settings (as))) {
audio_print_settings (as);
goto fail;
@@ -478,7 +485,7 @@ SW *glue (AUD_open_, TYPE) (
}
}
else {
sw = glue (audio_pcm_create_voice_pair_, TYPE) (name, as);
sw = glue (audio_pcm_create_voice_pair_, TYPE) (s, name, as);
if (!sw) {
dolog ("Failed to create voice `%s'\n", name);
return NULL;
@@ -486,7 +493,6 @@ SW *glue (AUD_open_, TYPE) (
}
if (sw) {
sw->card = card;
sw->vol = nominal_volume;
sw->callback.fn = callback_fn;
sw->callback.opaque = callback_opaque;

View File

@@ -32,6 +32,7 @@
#define AUDIO_CAP "dsound"
#include "audio_int.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mmsystem.h>
#include <objbase.h>

View File

@@ -481,7 +481,7 @@ static int oss_init_out (HWVoiceOut *hw, struct audsettings *as)
oss->mmapped = 0;
if (conf.try_mmap) {
oss->pcm_buf = mmap (
NULL,
0,
hw->samples << hw->info.shift,
PROT_READ | PROT_WRITE,
MAP_SHARED,

View File

@@ -340,7 +340,7 @@ static int qpa_init_out (HWVoiceOut *hw, struct audsettings *as)
return 0;
fail3:
qemu_free (pa->pcm_buf);
free (pa->pcm_buf);
pa->pcm_buf = NULL;
fail2:
pa_simple_free (pa->s);
@@ -394,7 +394,7 @@ static int qpa_init_in (HWVoiceIn *hw, struct audsettings *as)
return 0;
fail3:
qemu_free (pa->pcm_buf);
free (pa->pcm_buf);
pa->pcm_buf = NULL;
fail2:
pa_simple_free (pa->s);

View File

@@ -29,7 +29,7 @@
#ifndef _WIN32
#ifdef __sun__
#define _POSIX_PTHREAD_SEMANTICS 1
#elif defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
#elif defined(__OpenBSD__) || defined(__FreeBSD__)
#include <pthread.h>
#endif
#include <signal.h>
@@ -201,7 +201,7 @@ static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt)
}
#ifndef _WIN32
pthread_sigmask (SIG_SETMASK, &old, NULL);
pthread_sigmask (SIG_SETMASK, &old, 0);
#endif
return status;
}

View File

@@ -1,5 +1,5 @@
#include "hw/hw.h"
#include "monitor.h"
#include "console.h"
#include "audio.h"
typedef struct {
@@ -71,9 +71,9 @@ static void wav_capture_info (void *opaque)
WAVState *wav = opaque;
char *path = wav->path;
monitor_printf(cur_mon, "Capturing audio(%d,%d,%d) to %s: %d bytes\n",
wav->freq, wav->bits, wav->nchannels,
path ? path : "<not available>", wav->bytes);
term_printf ("Capturing audio(%d,%d,%d) to %s: %d bytes\n",
wav->freq, wav->bits, wav->nchannels,
path ? path : "<not available>", wav->bytes);
}
static struct capture_ops wav_capture_ops = {
@@ -84,7 +84,6 @@ static struct capture_ops wav_capture_ops = {
int wav_start_capture (CaptureState *s, const char *path, int freq,
int bits, int nchannels)
{
Monitor *mon = cur_mon;
WAVState *wav;
uint8_t hdr[] = {
0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56,
@@ -98,13 +97,13 @@ int wav_start_capture (CaptureState *s, const char *path, int freq,
CaptureVoiceOut *cap;
if (bits != 8 && bits != 16) {
monitor_printf(mon, "incorrect bit count %d, must be 8 or 16\n", bits);
term_printf ("incorrect bit count %d, must be 8 or 16\n", bits);
return -1;
}
if (nchannels != 1 && nchannels != 2) {
monitor_printf(mon, "incorrect channel count %d, must be 1 or 2\n",
nchannels);
term_printf ("incorrect channel count %d, must be 1 or 2\n",
nchannels);
return -1;
}
@@ -132,8 +131,8 @@ int wav_start_capture (CaptureState *s, const char *path, int freq,
wav->f = qemu_fopen (path, "wb");
if (!wav->f) {
monitor_printf(mon, "Failed to open wave file `%s'\nReason: %s\n",
path, strerror (errno));
term_printf ("Failed to open wave file `%s'\nReason: %s\n",
path, strerror (errno));
qemu_free (wav);
return -1;
}
@@ -145,9 +144,9 @@ int wav_start_capture (CaptureState *s, const char *path, int freq,
qemu_put_buffer (wav->f, hdr, sizeof (hdr));
cap = AUD_add_capture (&as, &ops, wav);
cap = AUD_add_capture (NULL, &as, &ops, wav);
if (!cap) {
monitor_printf(mon, "Failed to add audio capture\n");
term_printf ("Failed to add audio capture\n");
qemu_free (wav->path);
qemu_fclose (wav->f);
qemu_free (wav);

View File

@@ -24,7 +24,6 @@
*/
#include "qemu-common.h"
#include "block_int.h"
#include "module.h"
/**************************************************************/
@@ -242,18 +241,12 @@ static void bochs_close(BlockDriverState *bs)
close(s->fd);
}
static BlockDriver bdrv_bochs = {
.format_name = "bochs",
.instance_size = sizeof(BDRVBochsState),
.bdrv_probe = bochs_probe,
.bdrv_open = bochs_open,
.bdrv_read = bochs_read,
.bdrv_close = bochs_close,
BlockDriver bdrv_bochs = {
"bochs",
sizeof(BDRVBochsState),
bochs_probe,
bochs_open,
bochs_read,
NULL,
bochs_close,
};
static void bdrv_bochs_init(void)
{
bdrv_register(&bdrv_bochs);
}
block_init(bdrv_bochs_init);

View File

@@ -23,7 +23,6 @@
*/
#include "qemu-common.h"
#include "block_int.h"
#include "module.h"
#include <zlib.h>
typedef struct BDRVCloopState {
@@ -154,18 +153,12 @@ static void cloop_close(BlockDriverState *bs)
inflateEnd(&s->zstream);
}
static BlockDriver bdrv_cloop = {
.format_name = "cloop",
.instance_size = sizeof(BDRVCloopState),
.bdrv_probe = cloop_probe,
.bdrv_open = cloop_open,
.bdrv_read = cloop_read,
.bdrv_close = cloop_close,
BlockDriver bdrv_cloop = {
"cloop",
sizeof(BDRVCloopState),
cloop_probe,
cloop_open,
cloop_read,
NULL,
cloop_close,
};
static void bdrv_cloop_init(void)
{
bdrv_register(&bdrv_cloop);
}
block_init(bdrv_cloop_init);

View File

@@ -24,7 +24,6 @@
#ifndef _WIN32
#include "qemu-common.h"
#include "block_int.h"
#include "module.h"
#include <sys/mman.h>
/**************************************************************/
@@ -96,10 +95,10 @@ static int cow_open(BlockDriverState *bs, const char *filename, int flags)
/* mmap the bitmap */
s->cow_bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
s->cow_bitmap_addr = (void *)mmap(get_mmap_addr(s->cow_bitmap_size),
s->cow_bitmap_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, s->fd, 0);
s->cow_bitmap_addr = mmap(get_mmap_addr(s->cow_bitmap_size),
s->cow_bitmap_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, s->fd, 0);
if (s->cow_bitmap_addr == MAP_FAILED)
goto fail;
s->cow_bitmap = s->cow_bitmap_addr + sizeof(cow_header);
@@ -198,27 +197,19 @@ static int cow_write(BlockDriverState *bs, int64_t sector_num,
static void cow_close(BlockDriverState *bs)
{
BDRVCowState *s = bs->opaque;
munmap((void *)s->cow_bitmap_addr, s->cow_bitmap_size);
munmap(s->cow_bitmap_addr, s->cow_bitmap_size);
close(s->fd);
}
static int cow_create(const char *filename, QEMUOptionParameter *options)
static int cow_create(const char *filename, int64_t image_sectors,
const char *image_filename, int flags)
{
int fd, cow_fd;
struct cow_header_v2 cow_header;
struct stat st;
int64_t image_sectors = 0;
const char *image_filename = NULL;
/* Read out options */
while (options && options->name) {
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
image_sectors = options->value.n / 512;
} else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
image_filename = options->value.s;
}
options++;
}
if (flags)
return -ENOTSUP;
cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
0644);
@@ -261,39 +252,16 @@ static void cow_flush(BlockDriverState *bs)
fsync(s->fd);
}
static QEMUOptionParameter cow_create_options[] = {
{
.name = BLOCK_OPT_SIZE,
.type = OPT_SIZE,
.help = "Virtual disk size"
},
{
.name = BLOCK_OPT_BACKING_FILE,
.type = OPT_STRING,
.help = "File name of a base image"
},
{ NULL }
BlockDriver bdrv_cow = {
"cow",
sizeof(BDRVCowState),
cow_probe,
cow_open,
cow_read,
cow_write,
cow_close,
cow_create,
cow_flush,
cow_is_allocated,
};
static BlockDriver bdrv_cow = {
.format_name = "cow",
.instance_size = sizeof(BDRVCowState),
.bdrv_probe = cow_probe,
.bdrv_open = cow_open,
.bdrv_read = cow_read,
.bdrv_write = cow_write,
.bdrv_close = cow_close,
.bdrv_create = cow_create,
.bdrv_flush = cow_flush,
.bdrv_is_allocated = cow_is_allocated,
.create_options = cow_create_options,
};
static void bdrv_cow_init(void)
{
bdrv_register(&bdrv_cow);
}
block_init(bdrv_cow_init);
#endif

View File

@@ -24,7 +24,6 @@
#include "qemu-common.h"
#include "block_int.h"
#include "bswap.h"
#include "module.h"
#include <zlib.h>
typedef struct BDRVDMGState {
@@ -86,14 +85,14 @@ static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
return -errno;
bs->read_only = 1;
s->n_chunks = 0;
s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
s->offsets = s->lengths = s->sectors = s->sectorcounts = 0;
/* read offset of info blocks */
if(lseek(s->fd,-0x1d8,SEEK_END)<0) {
dmg_close:
close(s->fd);
/* open raw instead */
bs->drv=bdrv_find_format("raw");
bs->drv=&bdrv_raw;
return bs->drv->bdrv_open(bs, filename, flags);
}
info_begin=read_off(s->fd);
@@ -284,18 +283,12 @@ static void dmg_close(BlockDriverState *bs)
inflateEnd(&s->zstream);
}
static BlockDriver bdrv_dmg = {
.format_name = "dmg",
.instance_size = sizeof(BDRVDMGState),
.bdrv_probe = dmg_probe,
.bdrv_open = dmg_open,
.bdrv_read = dmg_read,
.bdrv_close = dmg_close,
BlockDriver bdrv_dmg = {
"dmg",
sizeof(BDRVDMGState),
dmg_probe,
dmg_open,
dmg_read,
NULL,
dmg_close,
};
static void bdrv_dmg_init(void)
{
bdrv_register(&bdrv_dmg);
}
block_init(bdrv_dmg_init);

View File

@@ -28,7 +28,6 @@
#include "qemu-common.h"
#include "nbd.h"
#include "module.h"
#include <sys/types.h>
#include <unistd.h>
@@ -177,20 +176,14 @@ static int64_t nbd_getlength(BlockDriverState *bs)
return s->size;
}
static BlockDriver bdrv_nbd = {
.format_name = "nbd",
.instance_size = sizeof(BDRVNBDState),
.bdrv_open = nbd_open,
.bdrv_read = nbd_read,
.bdrv_write = nbd_write,
.bdrv_close = nbd_close,
.bdrv_getlength = nbd_getlength,
.protocol_name = "nbd",
BlockDriver bdrv_nbd = {
"nbd",
sizeof(BDRVNBDState),
NULL, /* no probe for protocols */
nbd_open,
nbd_read,
nbd_write,
nbd_close,
.bdrv_getlength = nbd_getlength,
.protocol_name = "nbd",
};
static void bdrv_nbd_init(void)
{
bdrv_register(&bdrv_nbd);
}
block_init(bdrv_nbd_init);

View File

@@ -25,7 +25,6 @@
*/
#include "qemu-common.h"
#include "block_int.h"
#include "module.h"
/**************************************************************/
@@ -164,18 +163,12 @@ static void parallels_close(BlockDriverState *bs)
close(s->fd);
}
static BlockDriver bdrv_parallels = {
.format_name = "parallels",
.instance_size = sizeof(BDRVParallelsState),
.bdrv_probe = parallels_probe,
.bdrv_open = parallels_open,
.bdrv_read = parallels_read,
.bdrv_close = parallels_close,
BlockDriver bdrv_parallels = {
"parallels",
sizeof(BDRVParallelsState),
parallels_probe,
parallels_open,
parallels_read,
NULL,
parallels_close,
};
static void bdrv_parallels_init(void)
{
bdrv_register(&bdrv_parallels);
}
block_init(bdrv_parallels_init);

View File

@@ -23,7 +23,6 @@
*/
#include "qemu-common.h"
#include "block_int.h"
#include "module.h"
#include <zlib.h>
#include "aes.h"
@@ -488,59 +487,52 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
}
#endif
static int qcow_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVQcowState *s = bs->opaque;
int ret, index_in_cluster, n;
uint64_t cluster_offset;
while (nb_sectors > 0) {
index_in_cluster = sector_num & (s->cluster_sectors - 1);
n = s->cluster_sectors - index_in_cluster;
if (n > nb_sectors)
n = nb_sectors;
cluster_offset = get_cluster_offset(bs, sector_num << 9, 1, 0,
index_in_cluster,
index_in_cluster + n);
if (!cluster_offset)
return -1;
if (s->crypt_method) {
encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1,
&s->aes_encrypt_key);
ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512,
s->cluster_data, n * 512);
} else {
ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
}
if (ret != n * 512)
return -1;
nb_sectors -= n;
sector_num += n;
buf += n * 512;
}
s->cluster_cache_offset = -1; /* disable compressed cache */
return 0;
}
typedef struct QCowAIOCB {
BlockDriverAIOCB common;
int64_t sector_num;
QEMUIOVector *qiov;
uint8_t *buf;
void *orig_buf;
int nb_sectors;
int n;
uint64_t cluster_offset;
uint8_t *cluster_data;
struct iovec hd_iov;
QEMUIOVector hd_qiov;
BlockDriverAIOCB *hd_aiocb;
} QCowAIOCB;
static void qcow_aio_cancel(BlockDriverAIOCB *blockacb)
{
QCowAIOCB *acb = (QCowAIOCB *)blockacb;
if (acb->hd_aiocb)
bdrv_aio_cancel(acb->hd_aiocb);
qemu_aio_release(acb);
}
static AIOPool qcow_aio_pool = {
.aiocb_size = sizeof(QCowAIOCB),
.cancel = qcow_aio_cancel,
};
static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque, int is_write)
{
QCowAIOCB *acb;
acb = qemu_aio_get(&qcow_aio_pool, bs, cb, opaque);
if (!acb)
return NULL;
acb->hd_aiocb = NULL;
acb->sector_num = sector_num;
acb->qiov = qiov;
if (qiov->niov > 1) {
acb->buf = acb->orig_buf = qemu_blockalign(bs, qiov->size);
if (is_write)
qemu_iovec_to_buffer(qiov, acb->buf);
} else {
acb->buf = (uint8_t *)qiov->iov->iov_base;
}
acb->nb_sectors = nb_sectors;
acb->n = 0;
acb->cluster_offset = 0;
return acb;
}
static void qcow_aio_read_cb(void *opaque, int ret)
{
QCowAIOCB *acb = opaque;
@@ -549,8 +541,12 @@ static void qcow_aio_read_cb(void *opaque, int ret)
int index_in_cluster;
acb->hd_aiocb = NULL;
if (ret < 0)
goto done;
if (ret < 0) {
fail:
acb->common.cb(acb->common.opaque, ret);
qemu_aio_release(acb);
return;
}
redo:
/* post process the read buffer */
@@ -572,8 +568,9 @@ static void qcow_aio_read_cb(void *opaque, int ret)
if (acb->nb_sectors == 0) {
/* request completed */
ret = 0;
goto done;
acb->common.cb(acb->common.opaque, 0);
qemu_aio_release(acb);
return;
}
/* prepare next AIO request */
@@ -587,13 +584,10 @@ static void qcow_aio_read_cb(void *opaque, int ret)
if (!acb->cluster_offset) {
if (bs->backing_hd) {
/* read from the base image */
acb->hd_iov.iov_base = (void *)acb->buf;
acb->hd_iov.iov_len = acb->n * 512;
qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
acb->hd_aiocb = bdrv_aio_readv(bs->backing_hd, acb->sector_num,
&acb->hd_qiov, acb->n, qcow_aio_read_cb, acb);
acb->hd_aiocb = bdrv_aio_read(bs->backing_hd,
acb->sector_num, acb->buf, acb->n, qcow_aio_read_cb, acb);
if (acb->hd_aiocb == NULL)
goto done;
goto fail;
} else {
/* Note: in this case, no need to wait */
memset(acb->buf, 0, 512 * acb->n);
@@ -602,45 +596,38 @@ static void qcow_aio_read_cb(void *opaque, int ret)
} else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
/* add AIO support for compressed blocks ? */
if (decompress_cluster(s, acb->cluster_offset) < 0)
goto done;
goto fail;
memcpy(acb->buf,
s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
goto redo;
} else {
if ((acb->cluster_offset & 511) != 0) {
ret = -EIO;
goto done;
goto fail;
}
acb->hd_iov.iov_base = (void *)acb->buf;
acb->hd_iov.iov_len = acb->n * 512;
qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
acb->hd_aiocb = bdrv_aio_readv(s->hd,
acb->hd_aiocb = bdrv_aio_read(s->hd,
(acb->cluster_offset >> 9) + index_in_cluster,
&acb->hd_qiov, acb->n, qcow_aio_read_cb, acb);
acb->buf, acb->n, qcow_aio_read_cb, acb);
if (acb->hd_aiocb == NULL)
goto done;
goto fail;
}
return;
done:
if (acb->qiov->niov > 1) {
qemu_iovec_from_buffer(acb->qiov, acb->orig_buf, acb->qiov->size);
qemu_vfree(acb->orig_buf);
}
acb->common.cb(acb->common.opaque, ret);
qemu_aio_release(acb);
}
static BlockDriverAIOCB *qcow_aio_readv(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs,
int64_t sector_num, uint8_t *buf, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
QCowAIOCB *acb;
acb = qcow_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
acb = qemu_aio_get(bs, cb, opaque);
if (!acb)
return NULL;
acb->hd_aiocb = NULL;
acb->sector_num = sector_num;
acb->buf = buf;
acb->nb_sectors = nb_sectors;
acb->n = 0;
acb->cluster_offset = 0;
qcow_aio_read_cb(acb, 0);
return &acb->common;
@@ -657,8 +644,12 @@ static void qcow_aio_write_cb(void *opaque, int ret)
acb->hd_aiocb = NULL;
if (ret < 0)
goto done;
if (ret < 0) {
fail:
acb->common.cb(acb->common.opaque, ret);
qemu_aio_release(acb);
return;
}
acb->nb_sectors -= acb->n;
acb->sector_num += acb->n;
@@ -666,8 +657,9 @@ static void qcow_aio_write_cb(void *opaque, int ret)
if (acb->nb_sectors == 0) {
/* request completed */
ret = 0;
goto done;
acb->common.cb(acb->common.opaque, 0);
qemu_aio_release(acb);
return;
}
index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
@@ -679,14 +671,14 @@ static void qcow_aio_write_cb(void *opaque, int ret)
index_in_cluster + acb->n);
if (!cluster_offset || (cluster_offset & 511) != 0) {
ret = -EIO;
goto done;
goto fail;
}
if (s->crypt_method) {
if (!acb->cluster_data) {
acb->cluster_data = qemu_mallocz(s->cluster_size);
if (!acb->cluster_data) {
ret = -ENOMEM;
goto done;
goto fail;
}
}
encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf,
@@ -695,27 +687,16 @@ static void qcow_aio_write_cb(void *opaque, int ret)
} else {
src_buf = acb->buf;
}
acb->hd_iov.iov_base = (void *)src_buf;
acb->hd_iov.iov_len = acb->n * 512;
qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
acb->hd_aiocb = bdrv_aio_writev(s->hd,
(cluster_offset >> 9) + index_in_cluster,
&acb->hd_qiov, acb->n,
qcow_aio_write_cb, acb);
acb->hd_aiocb = bdrv_aio_write(s->hd,
(cluster_offset >> 9) + index_in_cluster,
src_buf, acb->n,
qcow_aio_write_cb, acb);
if (acb->hd_aiocb == NULL)
goto done;
return;
done:
if (acb->qiov->niov > 1)
qemu_vfree(acb->orig_buf);
acb->common.cb(acb->common.opaque, ret);
qemu_aio_release(acb);
goto fail;
}
static BlockDriverAIOCB *qcow_aio_writev(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs,
int64_t sector_num, const uint8_t *buf, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
BDRVQcowState *s = bs->opaque;
@@ -723,15 +704,27 @@ static BlockDriverAIOCB *qcow_aio_writev(BlockDriverState *bs,
s->cluster_cache_offset = -1; /* disable compressed cache */
acb = qcow_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
acb = qemu_aio_get(bs, cb, opaque);
if (!acb)
return NULL;
acb->hd_aiocb = NULL;
acb->sector_num = sector_num;
acb->buf = (uint8_t *)buf;
acb->nb_sectors = nb_sectors;
acb->n = 0;
qcow_aio_write_cb(acb, 0);
return &acb->common;
}
static void qcow_aio_cancel(BlockDriverAIOCB *blockacb)
{
QCowAIOCB *acb = (QCowAIOCB *)blockacb;
if (acb->hd_aiocb)
bdrv_aio_cancel(acb->hd_aiocb);
qemu_aio_release(acb);
}
static void qcow_close(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
@@ -742,26 +735,12 @@ static void qcow_close(BlockDriverState *bs)
bdrv_delete(s->hd);
}
static int qcow_create(const char *filename, QEMUOptionParameter *options)
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;
QCowHeader header;
uint64_t tmp;
int64_t total_size = 0;
const char *backing_file = NULL;
int flags = 0;
/* Read out options */
while (options && options->name) {
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
total_size = options->value.n / 512;
} else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
backing_file = options->value.s;
} else if (!strcmp(options->name, BLOCK_OPT_ENCRYPT)) {
flags |= options->value.n ? BLOCK_FLAG_ENCRYPT : 0;
}
options++;
}
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
if (fd < 0)
@@ -879,7 +858,7 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
/* could not compress: write normal cluster */
bdrv_write(bs, sector_num, buf, s->cluster_sectors);
qcow_write(bs, sector_num, buf, s->cluster_sectors);
} else {
cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,
out_len, 0, 0);
@@ -907,48 +886,24 @@ static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
return 0;
}
BlockDriver bdrv_qcow = {
"qcow",
sizeof(BDRVQcowState),
qcow_probe,
qcow_open,
NULL,
NULL,
qcow_close,
qcow_create,
qcow_flush,
qcow_is_allocated,
qcow_set_key,
qcow_make_empty,
static QEMUOptionParameter qcow_create_options[] = {
{
.name = BLOCK_OPT_SIZE,
.type = OPT_SIZE,
.help = "Virtual disk size"
},
{
.name = BLOCK_OPT_BACKING_FILE,
.type = OPT_STRING,
.help = "File name of a base image"
},
{
.name = BLOCK_OPT_ENCRYPT,
.type = OPT_FLAG,
.help = "Encrypt the image"
},
{ NULL }
};
static BlockDriver bdrv_qcow = {
.format_name = "qcow",
.instance_size = sizeof(BDRVQcowState),
.bdrv_probe = qcow_probe,
.bdrv_open = qcow_open,
.bdrv_close = qcow_close,
.bdrv_create = qcow_create,
.bdrv_flush = qcow_flush,
.bdrv_is_allocated = qcow_is_allocated,
.bdrv_set_key = qcow_set_key,
.bdrv_make_empty = qcow_make_empty,
.bdrv_aio_readv = qcow_aio_readv,
.bdrv_aio_writev = qcow_aio_writev,
.bdrv_aio_read = qcow_aio_read,
.bdrv_aio_write = qcow_aio_write,
.bdrv_aio_cancel = qcow_aio_cancel,
.aiocb_size = sizeof(QCowAIOCB),
.bdrv_write_compressed = qcow_write_compressed,
.bdrv_get_info = qcow_get_info,
.create_options = qcow_create_options,
.bdrv_get_info = qcow_get_info,
};
static void bdrv_qcow_init(void)
{
bdrv_register(&bdrv_qcow);
}
block_init(bdrv_qcow_init);

2664
block-qcow2.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -24,10 +24,11 @@
#include "qemu-common.h"
#include "qemu-timer.h"
#include "block_int.h"
#include "module.h"
#include <windows.h>
#include <assert.h>
#include <winioctl.h>
//#define WIN32_AIO
#define FTYPE_FILE 0
#define FTYPE_CD 1
#define FTYPE_HARDDISK 2
@@ -38,6 +39,13 @@ typedef struct BDRVRawState {
char drive_path[16]; /* format: "d:\" */
} BDRVRawState;
typedef struct RawAIOCB {
BlockDriverAIOCB common;
HANDLE hEvent;
OVERLAPPED ov;
int count;
} RawAIOCB;
int qemu_ftruncate64(int fd, int64_t length)
{
LARGE_INTEGER li;
@@ -91,7 +99,11 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
} else {
create_flags = OPEN_EXISTING;
}
#ifdef WIN32_AIO
overlapped = FILE_FLAG_OVERLAPPED;
#else
overlapped = FILE_ATTRIBUTE_NORMAL;
#endif
if ((flags & BDRV_O_NOCACHE))
overlapped |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH;
else if (!(flags & BDRV_O_CACHE_WB))
@@ -109,48 +121,149 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
return 0;
}
static int raw_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
static int raw_pread(BlockDriverState *bs, int64_t offset,
uint8_t *buf, int count)
{
BDRVRawState *s = bs->opaque;
OVERLAPPED ov;
DWORD ret_count;
int ret;
int64_t offset = sector_num * 512;
int count = nb_sectors * 512;
memset(&ov, 0, sizeof(ov));
ov.Offset = offset;
ov.OffsetHigh = offset >> 32;
ret = ReadFile(s->hfile, buf, count, &ret_count, &ov);
if (!ret)
return ret_count;
if (ret_count == count)
ret_count = 0;
if (!ret) {
#ifdef WIN32_AIO
ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
if (!ret)
return -EIO;
else
#endif
return ret_count;
}
return ret_count;
}
static int raw_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
static int raw_pwrite(BlockDriverState *bs, int64_t offset,
const uint8_t *buf, int count)
{
BDRVRawState *s = bs->opaque;
OVERLAPPED ov;
DWORD ret_count;
int ret;
int64_t offset = sector_num * 512;
int count = nb_sectors * 512;
memset(&ov, 0, sizeof(ov));
ov.Offset = offset;
ov.OffsetHigh = offset >> 32;
ret = WriteFile(s->hfile, buf, count, &ret_count, &ov);
if (!ret)
return ret_count;
if (ret_count == count)
ret_count = 0;
if (!ret) {
#ifdef WIN32_AIO
ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
if (!ret)
return -EIO;
else
#endif
return ret_count;
}
return ret_count;
}
#ifdef WIN32_AIO
static void raw_aio_cb(void *opaque)
{
RawAIOCB *acb = opaque;
BlockDriverState *bs = acb->common.bs;
BDRVRawState *s = bs->opaque;
DWORD ret_count;
int ret;
ret = GetOverlappedResult(s->hfile, &acb->ov, &ret_count, TRUE);
if (!ret || ret_count != acb->count) {
acb->common.cb(acb->common.opaque, -EIO);
} else {
acb->common.cb(acb->common.opaque, 0);
}
}
static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
int64_t sector_num, uint8_t *buf, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
RawAIOCB *acb;
int64_t offset;
acb = qemu_aio_get(bs, cb, opaque);
if (acb->hEvent) {
acb->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!acb->hEvent) {
qemu_aio_release(acb);
return NULL;
}
}
memset(&acb->ov, 0, sizeof(acb->ov));
offset = sector_num * 512;
acb->ov.Offset = offset;
acb->ov.OffsetHigh = offset >> 32;
acb->ov.hEvent = acb->hEvent;
acb->count = nb_sectors * 512;
qemu_add_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
return acb;
}
static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
int64_t sector_num, uint8_t *buf, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
BDRVRawState *s = bs->opaque;
RawAIOCB *acb;
int ret;
acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
if (!acb)
return NULL;
ret = ReadFile(s->hfile, buf, acb->count, NULL, &acb->ov);
if (!ret) {
qemu_aio_release(acb);
return NULL;
}
qemu_aio_release(acb);
return (BlockDriverAIOCB *)acb;
}
static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
int64_t sector_num, uint8_t *buf, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
BDRVRawState *s = bs->opaque;
RawAIOCB *acb;
int ret;
acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
if (!acb)
return NULL;
ret = WriteFile(s->hfile, buf, acb->count, NULL, &acb->ov);
if (!ret) {
qemu_aio_release(acb);
return NULL;
}
qemu_aio_release(acb);
return (BlockDriverAIOCB *)acb;
}
static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
{
RawAIOCB *acb = (RawAIOCB *)blockacb;
BlockDriverState *bs = acb->common.bs;
BDRVRawState *s = bs->opaque;
qemu_del_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
/* XXX: if more than one async I/O it is not correct */
CancelIo(s->hfile);
qemu_aio_release(acb);
}
#endif /* #if WIN32_AIO */
static void raw_flush(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
@@ -166,7 +279,7 @@ static void raw_close(BlockDriverState *bs)
static int raw_truncate(BlockDriverState *bs, int64_t offset)
{
BDRVRawState *s = bs->opaque;
LONG low, high;
DWORD low, high;
low = offset;
high = offset >> 32;
@@ -188,7 +301,7 @@ static int64_t raw_getlength(BlockDriverState *bs)
switch(s->type) {
case FTYPE_FILE:
l.LowPart = GetFileSize(s->hfile, (PDWORD)&l.HighPart);
l.LowPart = GetFileSize(s->hfile, &l.HighPart);
if (l.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
return -EIO;
break;
@@ -210,18 +323,13 @@ static int64_t raw_getlength(BlockDriverState *bs)
return l.QuadPart;
}
static int raw_create(const char *filename, QEMUOptionParameter *options)
static int raw_create(const char *filename, int64_t total_size,
const char *backing_file, int flags)
{
int fd;
int64_t total_size = 0;
/* Read out options */
while (options && options->name) {
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
total_size = options->value.n / 512;
}
options++;
}
if (flags || backing_file)
return -ENOTSUP;
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
0644);
@@ -233,28 +341,27 @@ static int raw_create(const char *filename, QEMUOptionParameter *options)
return 0;
}
static QEMUOptionParameter raw_create_options[] = {
{
.name = BLOCK_OPT_SIZE,
.type = OPT_SIZE,
.help = "Virtual disk size"
},
{ NULL }
};
BlockDriver bdrv_raw = {
"raw",
sizeof(BDRVRawState),
NULL, /* no probe for protocols */
raw_open,
NULL,
NULL,
raw_close,
raw_create,
raw_flush,
static BlockDriver bdrv_raw = {
.format_name = "raw",
.instance_size = sizeof(BDRVRawState),
.bdrv_open = raw_open,
.bdrv_close = raw_close,
.bdrv_create = raw_create,
.bdrv_flush = raw_flush,
.bdrv_read = raw_read,
.bdrv_write = raw_write,
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
.create_options = raw_create_options,
#ifdef WIN32_AIO
.bdrv_aio_read = raw_aio_read,
.bdrv_aio_write = raw_aio_write,
.bdrv_aio_cancel = raw_aio_cancel,
.aiocb_size = sizeof(RawAIOCB);
#endif
.bdrv_pread = raw_pread,
.bdrv_pwrite = raw_pwrite,
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
};
/***********************************************/
@@ -306,15 +413,6 @@ static int find_device_type(BlockDriverState *bs, const char *filename)
}
}
static int hdev_probe_device(const char *filename)
{
if (strstart(filename, "/dev/cdrom", NULL))
return 100;
if (is_windows_drive(filename))
return 100;
return 0;
}
static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVRawState *s = bs->opaque;
@@ -344,7 +442,11 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
}
create_flags = OPEN_EXISTING;
#ifdef WIN32_AIO
overlapped = FILE_FLAG_OVERLAPPED;
#else
overlapped = FILE_ATTRIBUTE_NORMAL;
#endif
if ((flags & BDRV_O_NOCACHE))
overlapped |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH;
else if (!(flags & BDRV_O_CACHE_WB))
@@ -397,23 +499,24 @@ static int raw_set_locked(BlockDriverState *bs, int locked)
}
#endif
static BlockDriver bdrv_host_device = {
.format_name = "host_device",
.instance_size = sizeof(BDRVRawState),
.bdrv_probe_device = hdev_probe_device,
.bdrv_open = hdev_open,
.bdrv_close = raw_close,
.bdrv_flush = raw_flush,
BlockDriver bdrv_host_device = {
"host_device",
sizeof(BDRVRawState),
NULL, /* no probe for protocols */
hdev_open,
NULL,
NULL,
raw_close,
NULL,
raw_flush,
.bdrv_read = raw_read,
.bdrv_write = raw_write,
.bdrv_getlength = raw_getlength,
#ifdef WIN32_AIO
.bdrv_aio_read = raw_aio_read,
.bdrv_aio_write = raw_aio_write,
.bdrv_aio_cancel = raw_aio_cancel,
.aiocb_size = sizeof(RawAIOCB);
#endif
.bdrv_pread = raw_pread,
.bdrv_pwrite = raw_pwrite,
.bdrv_getlength = raw_getlength,
};
static void bdrv_raw_init(void)
{
bdrv_register(&bdrv_raw);
bdrv_register(&bdrv_host_device);
}
block_init(bdrv_raw_init);

View File

@@ -25,7 +25,6 @@
#include "qemu-common.h"
#include "block_int.h"
#include "module.h"
#define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')
#define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V')
@@ -135,7 +134,7 @@ static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
cid_str_size = sizeof("CID");
}
if ((p_name = strstr(desc,cid_str)) != NULL) {
if ((p_name = strstr(desc,cid_str)) != 0) {
p_name += cid_str_size;
sscanf(p_name,"%x",&cid);
}
@@ -155,7 +154,7 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
tmp_str = strstr(desc,"parentCID");
pstrcpy(tmp_desc, sizeof(tmp_desc), tmp_str);
if ((p_name = strstr(desc,"CID")) != NULL) {
if ((p_name = strstr(desc,"CID")) != 0) {
p_name += sizeof("CID");
snprintf(p_name, sizeof(desc) - (p_name - desc), "%x\n", cid);
pstrcat(desc, sizeof(desc), tmp_desc);
@@ -170,7 +169,7 @@ static int vmdk_is_cid_valid(BlockDriverState *bs)
{
#ifdef CHECK_CID
BDRVVmdkState *s = bs->opaque;
BlockDriverState *p_bs = bs->backing_hd;
BlockDriverState *p_bs = s->hd->backing_hd;
uint32_t cur_pcid;
if (p_bs) {
@@ -240,7 +239,7 @@ static int vmdk_snapshot_create(const char *filename, const char *backing_file)
if (read(p_fd, p_desc, DESC_SIZE) != DESC_SIZE)
goto fail;
if ((p_name = strstr(p_desc,"CID")) != NULL) {
if ((p_name = strstr(p_desc,"CID")) != 0) {
p_name += sizeof("CID");
sscanf(p_name,"%x",&p_cid);
}
@@ -331,33 +330,33 @@ static int vmdk_parent_open(BlockDriverState *bs, const char * filename)
if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
return -1;
if ((p_name = strstr(desc,"parentFileNameHint")) != NULL) {
if ((p_name = strstr(desc,"parentFileNameHint")) != 0) {
char *end_name;
struct stat file_buf;
p_name += sizeof("parentFileNameHint") + 1;
if ((end_name = strchr(p_name,'\"')) == NULL)
if ((end_name = strchr(p_name,'\"')) == 0)
return -1;
if ((end_name - p_name) > sizeof (bs->backing_file) - 1)
if ((end_name - p_name) > sizeof (s->hd->backing_file) - 1)
return -1;
pstrcpy(bs->backing_file, end_name - p_name + 1, p_name);
if (stat(bs->backing_file, &file_buf) != 0) {
pstrcpy(s->hd->backing_file, end_name - p_name + 1, p_name);
if (stat(s->hd->backing_file, &file_buf) != 0) {
path_combine(parent_img_name, sizeof(parent_img_name),
filename, bs->backing_file);
filename, s->hd->backing_file);
} else {
pstrcpy(parent_img_name, sizeof(parent_img_name),
bs->backing_file);
s->hd->backing_file);
}
bs->backing_hd = bdrv_new("");
if (!bs->backing_hd) {
s->hd->backing_hd = bdrv_new("");
if (!s->hd->backing_hd) {
failure:
bdrv_close(s->hd);
return -1;
}
parent_open = 1;
if (bdrv_open(bs->backing_hd, parent_img_name, BDRV_O_RDONLY) < 0)
if (bdrv_open(s->hd->backing_hd, parent_img_name, BDRV_O_RDONLY) < 0)
goto failure;
parent_open = 0;
}
@@ -464,14 +463,13 @@ static int get_whole_cluster(BlockDriverState *bs, uint64_t cluster_offset,
// we will be here if it's first write on non-exist grain(cluster).
// try to read from parent image, if exist
if (bs->backing_hd) {
BDRVVmdkState *ps = bs->backing_hd->opaque;
if (s->hd->backing_hd) {
BDRVVmdkState *ps = s->hd->backing_hd->opaque;
if (!vmdk_is_cid_valid(bs))
return -1;
parent_cluster_offset = get_cluster_offset(bs->backing_hd, NULL,
offset, allocate);
parent_cluster_offset = get_cluster_offset(s->hd->backing_hd, NULL, offset, allocate);
if (parent_cluster_offset) {
BDRVVmdkState *act_s = activeBDRV.hd->opaque;
@@ -622,10 +620,10 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
n = nb_sectors;
if (!cluster_offset) {
// try to read from parent image, if exist
if (bs->backing_hd) {
if (s->hd->backing_hd) {
if (!vmdk_is_cid_valid(bs))
return -1;
ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
ret = bdrv_read(s->hd->backing_hd, sector_num, buf, n);
if (ret < 0)
return -1;
} else {
@@ -688,7 +686,8 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
return 0;
}
static int vmdk_create(const char *filename, QEMUOptionParameter *options)
static int vmdk_create(const char *filename, int64_t total_size,
const char *backing_file, int flags)
{
int fd, i;
VMDK4Header header;
@@ -713,21 +712,6 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options)
"ddb.adapterType = \"ide\"\n";
char desc[1024];
const char *real_filename, *temp_str;
int64_t total_size = 0;
const char *backing_file = NULL;
int flags = 0;
// Read out options
while (options && options->name) {
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
total_size = options->value.n / 512;
} else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
backing_file = options->value.s;
} else if (!strcmp(options->name, BLOCK_OPT_COMPAT6)) {
flags |= options->value.n ? BLOCK_FLAG_COMPAT6: 0;
}
options++;
}
/* XXX: add support for backing file */
if (backing_file) {
@@ -827,44 +811,15 @@ static void vmdk_flush(BlockDriverState *bs)
bdrv_flush(s->hd);
}
static QEMUOptionParameter vmdk_create_options[] = {
{
.name = BLOCK_OPT_SIZE,
.type = OPT_SIZE,
.help = "Virtual disk size"
},
{
.name = BLOCK_OPT_BACKING_FILE,
.type = OPT_STRING,
.help = "File name of a base image"
},
{
.name = BLOCK_OPT_COMPAT6,
.type = OPT_FLAG,
.help = "VMDK version 6 image"
},
{ NULL }
BlockDriver bdrv_vmdk = {
"vmdk",
sizeof(BDRVVmdkState),
vmdk_probe,
vmdk_open,
vmdk_read,
vmdk_write,
vmdk_close,
vmdk_create,
vmdk_flush,
vmdk_is_allocated,
};
static BlockDriver bdrv_vmdk = {
.format_name = "vmdk",
.instance_size = sizeof(BDRVVmdkState),
.bdrv_probe = vmdk_probe,
.bdrv_open = vmdk_open,
.bdrv_read = vmdk_read,
.bdrv_write = vmdk_write,
.bdrv_close = vmdk_close,
.bdrv_create = vmdk_create,
.bdrv_flush = vmdk_flush,
.bdrv_is_allocated = vmdk_is_allocated,
.create_options = vmdk_create_options,
};
static void bdrv_vmdk_init(void)
{
bdrv_register(&bdrv_vmdk);
}
block_init(bdrv_vmdk_init);

View File

@@ -24,7 +24,6 @@
*/
#include "qemu-common.h"
#include "block_int.h"
#include "module.h"
/**************************************************************/
@@ -477,7 +476,8 @@ static int calculate_geometry(int64_t total_sectors, uint16_t* cyls,
return 0;
}
static int vpc_create(const char *filename, QEMUOptionParameter *options)
static int vpc_create(const char *filename, int64_t total_sectors,
const char *backing_file, int flags)
{
uint8_t buf[1024];
struct vhd_footer* footer = (struct vhd_footer*) buf;
@@ -488,17 +488,10 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
uint8_t heads;
uint8_t secs_per_cyl;
size_t block_size, num_bat_entries;
int64_t total_sectors = 0;
// Read out options
while (options && options->name) {
if (!strcmp(options->name, "size")) {
total_sectors = options->value.n / 512;
}
options++;
}
if (backing_file != NULL)
return -ENOTSUP;
// Create the file
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
if (fd < 0)
return -EIO;
@@ -593,31 +586,13 @@ static void vpc_close(BlockDriverState *bs)
bdrv_delete(s->hd);
}
static QEMUOptionParameter vpc_create_options[] = {
{
.name = BLOCK_OPT_SIZE,
.type = OPT_SIZE,
.help = "Virtual disk size"
},
{ NULL }
BlockDriver bdrv_vpc = {
"vpc",
sizeof(BDRVVPCState),
vpc_probe,
vpc_open,
vpc_read,
vpc_write,
vpc_close,
vpc_create,
};
static BlockDriver bdrv_vpc = {
.format_name = "vpc",
.instance_size = sizeof(BDRVVPCState),
.bdrv_probe = vpc_probe,
.bdrv_open = vpc_open,
.bdrv_read = vpc_read,
.bdrv_write = vpc_write,
.bdrv_close = vpc_close,
.bdrv_create = vpc_create,
.create_options = vpc_create_options,
};
static void bdrv_vpc_init(void)
{
bdrv_register(&bdrv_vpc);
}
block_init(bdrv_vpc_init);

View File

@@ -24,9 +24,9 @@
*/
#include <sys/stat.h>
#include <dirent.h>
#include <assert.h>
#include "qemu-common.h"
#include "block_int.h"
#include "module.h"
#ifndef S_IWGRP
#define S_IWGRP 0
@@ -78,7 +78,7 @@ typedef struct array_t {
static inline void array_init(array_t* array,unsigned int item_size)
{
array->pointer = NULL;
array->pointer=0;
array->size=0;
array->next=0;
array->item_size=item_size;
@@ -129,7 +129,7 @@ static inline void* array_insert(array_t* array,unsigned int index,unsigned int
int increment=count*array->item_size;
array->pointer=qemu_realloc(array->pointer,array->size+increment);
if(!array->pointer)
return NULL;
return 0;
array->size+=increment;
}
memmove(array->pointer+(index+count)*array->item_size,
@@ -509,12 +509,9 @@ static inline uint8_t fat_chksum(const direntry_t* entry)
uint8_t chksum=0;
int i;
for(i=0;i<11;i++) {
unsigned char c;
c = (i <= 8) ? entry->name[i] : entry->extension[i-8];
chksum=(((chksum&0xfe)>>1)|((chksum&0x01)?0x80:0)) + c;
}
for(i=0;i<11;i++)
chksum=(((chksum&0xfe)>>1)|((chksum&0x01)?0x80:0))
+(unsigned char)entry->name[i];
return chksum;
}
@@ -607,8 +604,8 @@ static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
unsigned int directory_start, const char* filename, int is_dot)
{
int i,j,long_index=s->directory.next;
direntry_t* entry = NULL;
direntry_t* entry_long = NULL;
direntry_t* entry=0;
direntry_t* entry_long=0;
if(is_dot) {
entry=array_get_next(&(s->directory));
@@ -699,7 +696,7 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
int first_cluster = mapping->begin;
int parent_index = mapping->info.dir.parent_mapping_index;
mapping_t* parent_mapping = (mapping_t*)
(parent_index >= 0 ? array_get(&(s->mapping), parent_index) : NULL);
(parent_index >= 0 ? array_get(&(s->mapping), parent_index) : 0);
int first_cluster_of_parent = parent_mapping ? parent_mapping->begin : -1;
DIR* dir=opendir(dirname);
@@ -1128,10 +1125,10 @@ static inline mapping_t* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_
int index=find_mapping_for_cluster_aux(s,cluster_num,0,s->mapping.next);
mapping_t* mapping;
if(index>=s->mapping.next)
return NULL;
return 0;
mapping=array_get(&(s->mapping),index);
if(mapping->begin>cluster_num)
return NULL;
return 0;
assert(mapping->begin<=cluster_num && mapping->end>cluster_num);
return mapping;
}
@@ -1781,7 +1778,7 @@ DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)clu
}
for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
int cluster_count = 0;
int cluster_count;
DLOG(fprintf(stderr, "check direntry %d: \n", i); print_direntry(direntries + i));
if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
@@ -2762,15 +2759,14 @@ static void write_target_close(BlockDriverState *bs) {
}
static BlockDriver vvfat_write_target = {
.format_name = "vvfat_write_target",
.bdrv_write = write_target_commit,
.bdrv_close = write_target_close,
"vvfat_write_target", 0, NULL, NULL, NULL,
write_target_commit,
write_target_close,
NULL, NULL, NULL
};
static int enable_write_target(BDRVVVFATState *s)
{
BlockDriver *bdrv_qcow;
QEMUOptionParameter *options;
int size = sector2cluster(s, s->sector_count);
s->used_clusters = calloc(size, 1);
@@ -2778,13 +2774,8 @@ static int enable_write_target(BDRVVVFATState *s)
s->qcow_filename = qemu_malloc(1024);
get_tmp_filename(s->qcow_filename, 1024);
bdrv_qcow = bdrv_find_format("qcow");
options = parse_option_parameters("", bdrv_qcow->create_options, NULL);
set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512);
set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:");
if (bdrv_create(bdrv_qcow, s->qcow_filename, options) < 0)
if (bdrv_create(&bdrv_qcow,
s->qcow_filename, s->sector_count, "fat:", 0) < 0)
return -1;
s->qcow = bdrv_new("");
if (s->qcow == NULL || bdrv_open(s->qcow, s->qcow_filename, 0) < 0)
@@ -2813,24 +2804,20 @@ static void vvfat_close(BlockDriverState *bs)
free(s->cluster_buffer);
}
static BlockDriver bdrv_vvfat = {
.format_name = "vvfat",
.instance_size = sizeof(BDRVVVFATState),
.bdrv_open = vvfat_open,
.bdrv_read = vvfat_read,
.bdrv_write = vvfat_write,
.bdrv_close = vvfat_close,
.bdrv_is_allocated = vvfat_is_allocated,
.protocol_name = "fat",
BlockDriver bdrv_vvfat = {
"vvfat",
sizeof(BDRVVVFATState),
NULL, /* no probe for protocols */
vvfat_open,
vvfat_read,
vvfat_write,
vvfat_close,
NULL, /* ??? Not sure if we can do any meaningful flushing. */
NULL,
vvfat_is_allocated,
.protocol_name = "fat",
};
static void bdrv_vvfat_init(void)
{
bdrv_register(&bdrv_vvfat);
}
block_init(bdrv_vvfat_init);
#ifdef DEBUG
static void checkpoint(void) {
assert(((mapping_t*)array_get(&(vvv->mapping), 0))->end == 2);

613
block.c
View File

@@ -22,38 +22,40 @@
* THE SOFTWARE.
*/
#include "config-host.h"
#ifdef HOST_BSD
#ifdef _BSD
/* include native header before sys-queue.h */
#include <sys/queue.h>
#endif
#include "qemu-common.h"
#include "monitor.h"
#include "console.h"
#include "block_int.h"
#include "module.h"
#ifdef HOST_BSD
#ifdef _BSD
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#ifndef __DragonFly__
#include <sys/disk.h>
#endif
#endif
#ifdef _WIN32
#include <windows.h>
#endif
#define SECTOR_BITS 9
#define SECTOR_SIZE (1 << SECTOR_BITS)
static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
static AIOPool vectored_aio_pool;
typedef struct BlockDriverAIOCBSync {
BlockDriverAIOCB common;
QEMUBH *bh;
int ret;
} BlockDriverAIOCBSync;
static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
int64_t sector_num, uint8_t *buf, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);
static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
int64_t sector_num, const uint8_t *buf, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);
static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb);
static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors);
static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
@@ -127,17 +129,21 @@ void path_combine(char *dest, int dest_size,
}
}
void bdrv_register(BlockDriver *bdrv)
static void bdrv_register(BlockDriver *bdrv)
{
if (!bdrv->bdrv_aio_readv) {
if (!bdrv->bdrv_aio_read) {
/* add AIO emulation layer */
bdrv->bdrv_aio_readv = bdrv_aio_readv_em;
bdrv->bdrv_aio_writev = bdrv_aio_writev_em;
} else if (!bdrv->bdrv_read) {
bdrv->bdrv_aio_read = bdrv_aio_read_em;
bdrv->bdrv_aio_write = bdrv_aio_write_em;
bdrv->bdrv_aio_cancel = bdrv_aio_cancel_em;
bdrv->aiocb_size = sizeof(BlockDriverAIOCBSync);
} else if (!bdrv->bdrv_read && !bdrv->bdrv_pread) {
/* add synchronous IO emulation layer */
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;
}
@@ -169,13 +175,13 @@ BlockDriver *bdrv_find_format(const char *format_name)
return NULL;
}
int bdrv_create(BlockDriver *drv, const char* filename,
QEMUOptionParameter *options)
int bdrv_create(BlockDriver *drv,
const char *filename, int64_t size_in_sectors,
const char *backing_file, int flags)
{
if (!drv->bdrv_create)
return -ENOTSUP;
return drv->bdrv_create(filename, options);
return drv->bdrv_create(filename, size_in_sectors, backing_file, flags);
}
#ifdef _WIN32
@@ -209,7 +215,7 @@ static int is_windows_drive_prefix(const char *filename)
filename[1] == ':');
}
int is_windows_drive(const char *filename)
static int is_windows_drive(const char *filename)
{
if (is_windows_drive_prefix(filename) &&
filename[2] == '\0')
@@ -231,11 +237,11 @@ static BlockDriver *find_protocol(const char *filename)
#ifdef _WIN32
if (is_windows_drive(filename) ||
is_windows_drive_prefix(filename))
return bdrv_find_format("raw");
return &bdrv_raw;
#endif
p = strchr(filename, ':');
if (!p)
return bdrv_find_format("raw");
return &bdrv_raw;
len = p - filename;
if (len > sizeof(protocol) - 1)
len = sizeof(protocol) - 1;
@@ -249,28 +255,8 @@ static BlockDriver *find_protocol(const char *filename)
return NULL;
}
/*
* Detect host devices. By convention, /dev/cdrom[N] is always
* recognized as a host CDROM.
*/
static BlockDriver *find_hdev_driver(const char *filename)
{
int score_max = 0, score;
BlockDriver *drv = NULL, *d;
for (d = first_drv; d; d = d->next) {
if (d->bdrv_probe_device) {
score = d->bdrv_probe_device(filename);
if (score > score_max) {
score_max = score;
drv = d;
}
}
}
return drv;
}
/* XXX: force raw format if block or character device ? It would
simplify the BSD case */
static BlockDriver *find_image_format(const char *filename)
{
int ret, score, score_max;
@@ -278,9 +264,26 @@ static BlockDriver *find_image_format(const char *filename)
uint8_t buf[2048];
BlockDriverState *bs;
/* detect host devices. By convention, /dev/cdrom[N] is always
recognized as a host CDROM */
if (strstart(filename, "/dev/cdrom", NULL))
return &bdrv_host_device;
#ifdef _WIN32
if (is_windows_drive(filename))
return &bdrv_host_device;
#else
{
struct stat st;
if (stat(filename, &st) >= 0 &&
(S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
return &bdrv_host_device;
}
}
#endif
drv = find_protocol(filename);
/* no need to test disk image formats for vvfat */
if (drv && strcmp(drv->format_name, "vvfat") == 0)
if (drv == &bdrv_vvfat)
return drv;
ret = bdrv_file_open(&bs, filename, BDRV_O_RDONLY);
@@ -337,22 +340,18 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
bs->is_temporary = 0;
bs->encrypted = 0;
bs->valid_key = 0;
/* buffer_alignment defaulted to 512, drivers can change this value */
bs->buffer_alignment = 512;
if (flags & BDRV_O_SNAPSHOT) {
BlockDriverState *bs1;
int64_t total_size;
int is_protocol = 0;
BlockDriver *bdrv_qcow2;
QEMUOptionParameter *options;
/* if snapshot, we create a temporary backing file and open it
instead of opening 'filename' directly */
/* if there is a backing file, use it */
bs1 = bdrv_new("");
ret = bdrv_open2(bs1, filename, 0, drv);
ret = bdrv_open(bs1, filename, 0);
if (ret < 0) {
bdrv_delete(bs1);
return ret;
@@ -373,23 +372,12 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
else
realpath(filename, backing_filename);
bdrv_qcow2 = bdrv_find_format("qcow2");
options = parse_option_parameters("", bdrv_qcow2->create_options, NULL);
set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size * 512);
set_option_parameter(options, BLOCK_OPT_BACKING_FILE, backing_filename);
if (drv) {
set_option_parameter(options, BLOCK_OPT_BACKING_FMT,
drv->format_name);
}
ret = bdrv_create(bdrv_qcow2, tmp_filename, options);
ret = bdrv_create(&bdrv_qcow2, tmp_filename,
total_size, backing_filename, 0);
if (ret < 0) {
return ret;
}
filename = tmp_filename;
drv = bdrv_qcow2;
bs->is_temporary = 1;
}
@@ -397,10 +385,7 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
if (flags & BDRV_O_FILE) {
drv = find_protocol(filename);
} else if (!drv) {
drv = find_hdev_driver(filename);
if (!drv) {
drv = find_image_format(filename);
}
drv = find_image_format(filename);
}
if (!drv) {
ret = -ENOENT;
@@ -438,26 +423,21 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
#endif
if (bs->backing_file[0] != '\0') {
/* if there is a backing file, use it */
BlockDriver *back_drv = NULL;
bs->backing_hd = bdrv_new("");
path_combine(backing_filename, sizeof(backing_filename),
filename, bs->backing_file);
if (bs->backing_format[0] != '\0')
back_drv = bdrv_find_format(bs->backing_format);
ret = bdrv_open2(bs->backing_hd, backing_filename, open_flags,
back_drv);
ret = bdrv_open(bs->backing_hd, backing_filename, open_flags);
if (ret < 0) {
bdrv_close(bs);
return ret;
}
}
if (!bdrv_key_required(bs)) {
/* call the change callback */
bs->media_changed = 1;
if (bs->change_cb)
bs->change_cb(bs->change_opaque);
}
/* call the change callback */
bs->media_changed = 1;
if (bs->change_cb)
bs->change_cb(bs->change_opaque);
return 0;
}
@@ -497,20 +477,6 @@ void bdrv_delete(BlockDriverState *bs)
qemu_free(bs);
}
/*
* Run consistency checks on an image
*
* Returns the number of errors or -errno when an internal error occurs
*/
int bdrv_check(BlockDriverState *bs)
{
if (bs->drv->bdrv_check == NULL) {
return -ENOTSUP;
}
return bs->drv->bdrv_check(bs);
}
/* commit COW file into the raw image */
int bdrv_commit(BlockDriverState *bs)
{
@@ -579,7 +545,15 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
int nb_sectors)
{
return bdrv_check_byte_request(bs, sector_num * 512, nb_sectors * 512);
int64_t offset;
/* Deal with byte accesses */
if (sector_num < 0)
offset = -sector_num;
else
offset = sector_num * 512;
return bdrv_check_byte_request(bs, offset, nb_sectors * 512);
}
/* return < 0 if error. See bdrv_write() for the return codes */
@@ -593,7 +567,22 @@ int bdrv_read(BlockDriverState *bs, int64_t sector_num,
if (bdrv_check_request(bs, sector_num, nb_sectors))
return -EIO;
return drv->bdrv_read(bs, sector_num, buf, nb_sectors);
if (drv->bdrv_pread) {
int ret, len;
len = nb_sectors * 512;
ret = drv->bdrv_pread(bs, sector_num * 512, buf, len);
if (ret < 0)
return ret;
else if (ret != len)
return -EINVAL;
else {
bs->rd_bytes += (unsigned) len;
bs->rd_ops ++;
return 0;
}
} else {
return drv->bdrv_read(bs, sector_num, buf, nb_sectors);
}
}
/* Return < 0 if error. Important errors are:
@@ -613,11 +602,27 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num,
if (bdrv_check_request(bs, sector_num, nb_sectors))
return -EIO;
if (drv->bdrv_pwrite) {
int ret, len, count = 0;
len = nb_sectors * 512;
do {
ret = drv->bdrv_pwrite(bs, sector_num * 512, buf, len - count);
if (ret < 0) {
printf("bdrv_write ret=%d\n", ret);
return ret;
}
count += ret;
buf += ret;
} while (count != len);
bs->wr_bytes += (unsigned) len;
bs->wr_ops ++;
return 0;
}
return drv->bdrv_write(bs, sector_num, buf, nb_sectors);
}
int bdrv_pread(BlockDriverState *bs, int64_t offset,
void *buf, int count1)
static int bdrv_pread_em(BlockDriverState *bs, int64_t offset,
uint8_t *buf, int count1)
{
uint8_t tmp_buf[SECTOR_SIZE];
int len, nb_sectors, count;
@@ -660,8 +665,8 @@ int bdrv_pread(BlockDriverState *bs, int64_t offset,
return count1;
}
int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
const void *buf, int count1)
static int bdrv_pwrite_em(BlockDriverState *bs, int64_t offset,
const uint8_t *buf, int count1)
{
uint8_t tmp_buf[SECTOR_SIZE];
int len, nb_sectors, count;
@@ -708,6 +713,42 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
return count1;
}
/**
* Read with byte offsets (needed only for file protocols)
*/
int bdrv_pread(BlockDriverState *bs, int64_t offset,
void *buf1, int count1)
{
BlockDriver *drv = bs->drv;
if (!drv)
return -ENOMEDIUM;
if (bdrv_check_byte_request(bs, offset, count1))
return -EIO;
if (!drv->bdrv_pread)
return bdrv_pread_em(bs, offset, buf1, count1);
return drv->bdrv_pread(bs, offset, buf1, count1);
}
/**
* Write with byte offsets (needed only for file protocols)
*/
int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
const void *buf1, int count1)
{
BlockDriver *drv = bs->drv;
if (!drv)
return -ENOMEDIUM;
if (bdrv_check_byte_request(bs, offset, count1))
return -EIO;
if (!drv->bdrv_pwrite)
return bdrv_pwrite_em(bs, offset, buf1, count1);
return drv->bdrv_pwrite(bs, offset, buf1, count1);
}
/**
* Truncate file to 'offset' bytes (needed only for file protocols)
*/
@@ -954,15 +995,7 @@ int bdrv_set_key(BlockDriverState *bs, const char *key)
if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
return -1;
ret = bs->drv->bdrv_set_key(bs, key);
if (ret < 0) {
bs->valid_key = 0;
} else if (!bs->valid_key) {
bs->valid_key = 1;
/* call the change callback now, we skipped it on open */
bs->media_changed = 1;
if (bs->change_cb)
bs->change_cb(bs->change_opaque);
}
bs->valid_key = (ret == 0);
return ret;
}
@@ -1012,8 +1045,6 @@ const char *bdrv_get_device_name(BlockDriverState *bs)
void bdrv_flush(BlockDriverState *bs)
{
if (!bs->drv)
return;
if (bs->drv->bdrv_flush)
bs->drv->bdrv_flush(bs);
if (bs->backing_hd)
@@ -1057,60 +1088,60 @@ int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
return bs->drv->bdrv_is_allocated(bs, sector_num, nb_sectors, pnum);
}
void bdrv_info(Monitor *mon)
void bdrv_info(void)
{
BlockDriverState *bs;
for (bs = bdrv_first; bs != NULL; bs = bs->next) {
monitor_printf(mon, "%s:", bs->device_name);
monitor_printf(mon, " type=");
term_printf("%s:", bs->device_name);
term_printf(" type=");
switch(bs->type) {
case BDRV_TYPE_HD:
monitor_printf(mon, "hd");
term_printf("hd");
break;
case BDRV_TYPE_CDROM:
monitor_printf(mon, "cdrom");
term_printf("cdrom");
break;
case BDRV_TYPE_FLOPPY:
monitor_printf(mon, "floppy");
term_printf("floppy");
break;
}
monitor_printf(mon, " removable=%d", bs->removable);
term_printf(" removable=%d", bs->removable);
if (bs->removable) {
monitor_printf(mon, " locked=%d", bs->locked);
term_printf(" locked=%d", bs->locked);
}
if (bs->drv) {
monitor_printf(mon, " file=");
monitor_print_filename(mon, bs->filename);
term_printf(" file=");
term_print_filename(bs->filename);
if (bs->backing_file[0] != '\0') {
monitor_printf(mon, " backing_file=");
monitor_print_filename(mon, bs->backing_file);
}
monitor_printf(mon, " ro=%d", bs->read_only);
monitor_printf(mon, " drv=%s", bs->drv->format_name);
monitor_printf(mon, " encrypted=%d", bdrv_is_encrypted(bs));
term_printf(" backing_file=");
term_print_filename(bs->backing_file);
}
term_printf(" ro=%d", bs->read_only);
term_printf(" drv=%s", bs->drv->format_name);
term_printf(" encrypted=%d", bdrv_is_encrypted(bs));
} else {
monitor_printf(mon, " [not inserted]");
term_printf(" [not inserted]");
}
monitor_printf(mon, "\n");
term_printf("\n");
}
}
/* The "info blockstats" command. */
void bdrv_info_stats(Monitor *mon)
void bdrv_info_stats (void)
{
BlockDriverState *bs;
for (bs = bdrv_first; bs != NULL; bs = bs->next) {
monitor_printf(mon, "%s:"
" rd_bytes=%" PRIu64
" 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);
term_printf ("%s:"
" rd_bytes=%" PRIu64
" 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);
}
}
@@ -1158,26 +1189,24 @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
return drv->bdrv_get_info(bs, bdi);
}
int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
int64_t pos, int size)
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_save_vmstate)
if (!drv->bdrv_put_buffer)
return -ENOTSUP;
return drv->bdrv_save_vmstate(bs, buf, pos, size);
return drv->bdrv_put_buffer(bs, buf, pos, size);
}
int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
int64_t pos, int 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_load_vmstate)
if (!drv->bdrv_get_buffer)
return -ENOTSUP;
return drv->bdrv_load_vmstate(bs, buf, pos, size);
return drv->bdrv_get_buffer(bs, buf, pos, size);
}
/**************************************************************/
@@ -1303,9 +1332,90 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
/**************************************************************/
/* async I/Os */
typedef struct VectorTranslationAIOCB {
BlockDriverAIOCB common;
QEMUIOVector *iov;
uint8_t *bounce;
int is_write;
BlockDriverAIOCB *aiocb;
} 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)
{
VectorTranslationAIOCB *s = (VectorTranslationAIOCB *)opaque;
if (!s->is_write) {
qemu_iovec_from_buffer(s->iov, s->bounce, s->iov->size);
}
qemu_vfree(s->bounce);
s->common.cb(s->common.opaque, ret);
qemu_aio_release(s);
}
static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
int64_t sector_num,
QEMUIOVector *iov,
int nb_sectors,
BlockDriverCompletionFunc *cb,
void *opaque,
int is_write)
{
VectorTranslationAIOCB *s = qemu_aio_get_pool(&vectored_aio_pool, bs,
cb, opaque);
s->iov = iov;
s->bounce = qemu_memalign(512, nb_sectors * 512);
s->is_write = is_write;
if (is_write) {
qemu_iovec_to_buffer(s->iov, s->bounce);
s->aiocb = bdrv_aio_write(bs, sector_num, s->bounce, nb_sectors,
bdrv_aio_rw_vector_cb, s);
} else {
s->aiocb = bdrv_aio_read(bs, sector_num, s->bounce, nb_sectors,
bdrv_aio_rw_vector_cb, s);
}
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,
QEMUIOVector *qiov, int nb_sectors,
QEMUIOVector *iov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
if (bdrv_check_request(bs, sector_num, nb_sectors))
return NULL;
return bdrv_aio_rw_vector(bs, sector_num, iov, nb_sectors,
cb, opaque, 0);
}
BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
QEMUIOVector *iov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
if (bdrv_check_request(bs, sector_num, nb_sectors))
return NULL;
return bdrv_aio_rw_vector(bs, sector_num, iov, nb_sectors,
cb, opaque, 1);
}
BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
BlockDriver *drv = bs->drv;
BlockDriverAIOCB *ret;
@@ -1315,8 +1425,7 @@ BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
if (bdrv_check_request(bs, sector_num, nb_sectors))
return NULL;
ret = drv->bdrv_aio_readv(bs, sector_num, qiov, nb_sectors,
cb, opaque);
ret = drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque);
if (ret) {
/* Update stats even though technically transfer has not happened. */
@@ -1327,9 +1436,9 @@ BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
return ret;
}
BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
BlockDriver *drv = bs->drv;
BlockDriverAIOCB *ret;
@@ -1341,8 +1450,7 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
if (bdrv_check_request(bs, sector_num, nb_sectors))
return NULL;
ret = drv->bdrv_aio_writev(bs, sector_num, qiov, nb_sectors,
cb, opaque);
ret = drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque);
if (ret) {
/* Update stats even though technically transfer has not happened. */
@@ -1362,87 +1470,52 @@ void bdrv_aio_cancel(BlockDriverAIOCB *acb)
/**************************************************************/
/* async block device emulation */
typedef struct BlockDriverAIOCBSync {
BlockDriverAIOCB common;
QEMUBH *bh;
static void bdrv_aio_bh_cb(void *opaque)
{
BlockDriverAIOCBSync *acb = opaque;
acb->common.cb(acb->common.opaque, acb->ret);
qemu_aio_release(acb);
}
static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
int64_t sector_num, uint8_t *buf, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
BlockDriverAIOCBSync *acb;
int ret;
/* vector translation state */
QEMUIOVector *qiov;
uint8_t *bounce;
int is_write;
} BlockDriverAIOCBSync;
acb = qemu_aio_get(bs, cb, opaque);
if (!acb->bh)
acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
ret = bdrv_read(bs, sector_num, buf, nb_sectors);
acb->ret = ret;
qemu_bh_schedule(acb->bh);
return &acb->common;
}
static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
int64_t sector_num, const uint8_t *buf, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
BlockDriverAIOCBSync *acb;
int ret;
acb = qemu_aio_get(bs, cb, opaque);
if (!acb->bh)
acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
ret = bdrv_write(bs, sector_num, buf, nb_sectors);
acb->ret = ret;
qemu_bh_schedule(acb->bh);
return &acb->common;
}
static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
{
BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb;
qemu_bh_delete(acb->bh);
acb->bh = NULL;
qemu_bh_cancel(acb->bh);
qemu_aio_release(acb);
}
static AIOPool bdrv_em_aio_pool = {
.aiocb_size = sizeof(BlockDriverAIOCBSync),
.cancel = bdrv_aio_cancel_em,
};
static void bdrv_aio_bh_cb(void *opaque)
{
BlockDriverAIOCBSync *acb = opaque;
if (!acb->is_write)
qemu_iovec_from_buffer(acb->qiov, acb->bounce, acb->qiov->size);
qemu_vfree(acb->bounce);
acb->common.cb(acb->common.opaque, acb->ret);
qemu_bh_delete(acb->bh);
acb->bh = NULL;
qemu_aio_release(acb);
}
static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
int64_t sector_num,
QEMUIOVector *qiov,
int nb_sectors,
BlockDriverCompletionFunc *cb,
void *opaque,
int is_write)
{
BlockDriverAIOCBSync *acb;
acb = qemu_aio_get(&bdrv_em_aio_pool, bs, cb, opaque);
acb->is_write = is_write;
acb->qiov = qiov;
acb->bounce = qemu_blockalign(bs, qiov->size);
if (!acb->bh)
acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
if (is_write) {
qemu_iovec_to_buffer(acb->qiov, acb->bounce);
acb->ret = bdrv_write(bs, sector_num, acb->bounce, nb_sectors);
} else {
acb->ret = bdrv_read(bs, sector_num, acb->bounce, nb_sectors);
}
qemu_bh_schedule(acb->bh);
return &acb->common;
}
static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
}
static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
}
/**************************************************************/
/* sync block device emulation */
@@ -1458,15 +1531,10 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
{
int async_ret;
BlockDriverAIOCB *acb;
struct iovec iov;
QEMUIOVector qiov;
async_ret = NOT_DONE;
iov.iov_base = (void *)buf;
iov.iov_len = nb_sectors * 512;
qemu_iovec_init_external(&qiov, &iov, 1);
acb = bdrv_aio_readv(bs, sector_num, &qiov, nb_sectors,
bdrv_rw_em_cb, &async_ret);
acb = bdrv_aio_read(bs, sector_num, buf, nb_sectors,
bdrv_rw_em_cb, &async_ret);
if (acb == NULL)
return -1;
@@ -1482,15 +1550,10 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
{
int async_ret;
BlockDriverAIOCB *acb;
struct iovec iov;
QEMUIOVector qiov;
async_ret = NOT_DONE;
iov.iov_base = (void *)buf;
iov.iov_len = nb_sectors * 512;
qemu_iovec_init_external(&qiov, &iov, 1);
acb = bdrv_aio_writev(bs, sector_num, &qiov, nb_sectors,
bdrv_rw_em_cb, &async_ret);
acb = bdrv_aio_write(bs, sector_num, buf, nb_sectors,
bdrv_rw_em_cb, &async_ret);
if (acb == NULL)
return -1;
while (async_ret == NOT_DONE) {
@@ -1501,11 +1564,36 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
void bdrv_init(void)
{
module_call_init(MODULE_INIT_BLOCK);
aio_pool_init(&vectored_aio_pool, sizeof(VectorTranslationAIOCB),
bdrv_aio_cancel_vector);
bdrv_register(&bdrv_raw);
bdrv_register(&bdrv_host_device);
#ifndef _WIN32
bdrv_register(&bdrv_cow);
#endif
bdrv_register(&bdrv_qcow);
bdrv_register(&bdrv_vmdk);
bdrv_register(&bdrv_cloop);
bdrv_register(&bdrv_dmg);
bdrv_register(&bdrv_bochs);
bdrv_register(&bdrv_vpc);
bdrv_register(&bdrv_vvfat);
bdrv_register(&bdrv_qcow2);
bdrv_register(&bdrv_parallels);
bdrv_register(&bdrv_nbd);
}
void *qemu_aio_get(AIOPool *pool, 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)
{
BlockDriverAIOCB *acb;
@@ -1522,6 +1610,12 @@ void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs,
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 = (BlockDriverAIOCB *)p;
@@ -1570,15 +1664,11 @@ int bdrv_media_changed(BlockDriverState *bs)
/**
* If eject_flag is TRUE, eject the media. Otherwise, close the tray
*/
int bdrv_eject(BlockDriverState *bs, int eject_flag)
void 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 {
@@ -1587,10 +1677,7 @@ int 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)
@@ -1622,19 +1709,3 @@ int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
return drv->bdrv_ioctl(bs, req, buf);
return -ENOTSUP;
}
BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
unsigned long int req, void *buf,
BlockDriverCompletionFunc *cb, void *opaque)
{
BlockDriver *drv = bs->drv;
if (drv && drv->bdrv_aio_ioctl)
return drv->bdrv_aio_ioctl(bs, req, buf, cb, opaque);
return NULL;
}
void *qemu_blockalign(BlockDriverState *bs, size_t size)
{
return qemu_memalign((bs && bs->buffer_alignment) ? bs->buffer_alignment : 512, size);
}

57
block.h
View File

@@ -3,11 +3,24 @@
#include "qemu-aio.h"
#include "qemu-common.h"
#include "qemu-option.h"
/* block.c */
typedef struct BlockDriver BlockDriver;
extern BlockDriver bdrv_raw;
extern BlockDriver bdrv_host_device;
extern BlockDriver bdrv_cow;
extern BlockDriver bdrv_qcow;
extern BlockDriver bdrv_vmdk;
extern BlockDriver bdrv_cloop;
extern BlockDriver bdrv_dmg;
extern BlockDriver bdrv_bochs;
extern BlockDriver bdrv_vpc;
extern BlockDriver bdrv_vvfat;
extern BlockDriver bdrv_qcow2;
extern BlockDriver bdrv_parallels;
extern BlockDriver bdrv_nbd;
typedef struct BlockDriverInfo {
/* in bytes, 0 if irrelevant */
int cluster_size;
@@ -37,20 +50,18 @@ typedef struct QEMUSnapshotInfo {
bdrv_file_open()) */
#define BDRV_O_NOCACHE 0x0020 /* do not use the host page cache */
#define BDRV_O_CACHE_WB 0x0040 /* use write-back caching */
#define BDRV_O_CACHE_DEF 0x0080 /* use default caching */
#define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_CACHE_WB)
#define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_CACHE_DEF)
void bdrv_info(Monitor *mon);
void bdrv_info_stats(Monitor *mon);
void bdrv_info(void);
void bdrv_info_stats(void);
void bdrv_init(void);
BlockDriver *bdrv_find_format(const char *format_name);
int bdrv_create(BlockDriver *drv, const char* filename,
QEMUOptionParameter *options);
int bdrv_create2(BlockDriver *drv,
const char *filename, int64_t size_in_sectors,
const char *backing_file, const char *backing_format,
int flags);
int bdrv_create(BlockDriver *drv,
const char *filename, int64_t size_in_sectors,
const char *backing_file, int flags);
BlockDriverState *bdrv_new(const char *device_name);
void bdrv_delete(BlockDriverState *bs);
int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
@@ -58,7 +69,6 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags);
int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
BlockDriver *drv);
void bdrv_close(BlockDriverState *bs);
int bdrv_check(BlockDriverState *bs);
int bdrv_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors);
int bdrv_write(BlockDriverState *bs, int64_t sector_num,
@@ -72,8 +82,6 @@ int64_t bdrv_getlength(BlockDriverState *bs);
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs);
int bdrv_commit(BlockDriverState *bs);
void bdrv_register(BlockDriver *bdrv);
/* async block I/O */
typedef struct BlockDriverAIOCB BlockDriverAIOCB;
typedef void BlockDriverCompletionFunc(void *opaque, int ret);
@@ -84,13 +92,14 @@ BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
QEMUIOVector *iov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);
void bdrv_aio_cancel(BlockDriverAIOCB *acb);
/* sg packet commands */
int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf);
BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
unsigned long int req, void *buf,
BlockDriverCompletionFunc *cb, void *opaque);
BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);
BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);
void bdrv_aio_cancel(BlockDriverAIOCB *acb);
/* Ensure contents are flushed to disk. */
void bdrv_flush(BlockDriverState *bs);
@@ -123,7 +132,7 @@ 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);
int bdrv_eject(BlockDriverState *bs, int eject_flag);
void 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);
@@ -152,6 +161,7 @@ int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id);
int bdrv_snapshot_list(BlockDriverState *bs,
QEMUSnapshotInfo **psn_info);
char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn);
int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf);
char *get_human_readable_size(char *buf, int buf_size, int64_t size);
int path_is_absolute(const char *path);
@@ -159,10 +169,9 @@ void path_combine(char *dest, int dest_size,
const char *base_path,
const char *filename);
int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
int64_t pos, int size);
int bdrv_put_buffer(BlockDriverState *bs, const uint8_t *buf,
int64_t pos, int size);
int bdrv_load_vmstate(BlockDriverState *bs, 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

@@ -1,562 +0,0 @@
/*
* QEMU Block driver for CURL images
*
* Copyright (c) 2009 Alexander Graf <agraf@suse.de>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "qemu-common.h"
#include "block_int.h"
#include <curl/curl.h>
// #define DEBUG
// #define DEBUG_VERBOSE
#ifdef DEBUG_CURL
#define dprintf(fmt, ...) do { printf(fmt, ## __VA_ARGS__); } while (0)
#else
#define dprintf(fmt, ...) do { } while (0)
#endif
#define CURL_NUM_STATES 8
#define CURL_NUM_ACB 8
#define SECTOR_SIZE 512
#define READ_AHEAD_SIZE (256 * 1024)
#define FIND_RET_NONE 0
#define FIND_RET_OK 1
#define FIND_RET_WAIT 2
struct BDRVCURLState;
typedef struct CURLAIOCB {
BlockDriverAIOCB common;
QEMUIOVector *qiov;
size_t start;
size_t end;
} CURLAIOCB;
typedef struct CURLState
{
struct BDRVCURLState *s;
CURLAIOCB *acb[CURL_NUM_ACB];
CURL *curl;
char *orig_buf;
size_t buf_start;
size_t buf_off;
size_t buf_len;
char range[128];
char errmsg[CURL_ERROR_SIZE];
char in_use;
} CURLState;
typedef struct BDRVCURLState {
CURLM *multi;
size_t len;
CURLState states[CURL_NUM_STATES];
char *url;
size_t readahead_size;
} BDRVCURLState;
static void curl_clean_state(CURLState *s);
static void curl_multi_do(void *arg);
static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
void *s, void *sp)
{
dprintf("CURL (AIO): Sock action %d on fd %d\n", action, fd);
switch (action) {
case CURL_POLL_IN:
qemu_aio_set_fd_handler(fd, curl_multi_do, NULL, NULL, s);
break;
case CURL_POLL_OUT:
qemu_aio_set_fd_handler(fd, NULL, curl_multi_do, NULL, s);
break;
case CURL_POLL_INOUT:
qemu_aio_set_fd_handler(fd, curl_multi_do,
curl_multi_do, NULL, s);
break;
case CURL_POLL_REMOVE:
qemu_aio_set_fd_handler(fd, NULL, NULL, NULL, NULL);
break;
}
return 0;
}
static size_t curl_size_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
{
CURLState *s = ((CURLState*)opaque);
size_t realsize = size * nmemb;
long long fsize;
if(sscanf(ptr, "Content-Length: %lld", &fsize) == 1)
s->s->len = fsize;
return realsize;
}
static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
{
CURLState *s = ((CURLState*)opaque);
size_t realsize = size * nmemb;
int i;
dprintf("CURL: Just reading %lld bytes\n", (unsigned long long)realsize);
if (!s || !s->orig_buf)
goto read_end;
memcpy(s->orig_buf + s->buf_off, ptr, realsize);
s->buf_off += realsize;
for(i=0; i<CURL_NUM_ACB; i++) {
CURLAIOCB *acb = s->acb[i];
if (!acb)
continue;
if ((s->buf_off >= acb->end)) {
qemu_iovec_from_buffer(acb->qiov, s->orig_buf + acb->start,
acb->end - acb->start);
acb->common.cb(acb->common.opaque, 0);
qemu_aio_release(acb);
s->acb[i] = NULL;
}
}
read_end:
return realsize;
}
static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len,
CURLAIOCB *acb)
{
int i;
size_t end = start + len;
for (i=0; i<CURL_NUM_STATES; i++) {
CURLState *state = &s->states[i];
size_t buf_end = (state->buf_start + state->buf_off);
size_t buf_fend = (state->buf_start + state->buf_len);
if (!state->orig_buf)
continue;
if (!state->buf_off)
continue;
// Does the existing buffer cover our section?
if ((start >= state->buf_start) &&
(start <= buf_end) &&
(end >= state->buf_start) &&
(end <= buf_end))
{
char *buf = state->orig_buf + (start - state->buf_start);
qemu_iovec_from_buffer(acb->qiov, buf, len);
acb->common.cb(acb->common.opaque, 0);
return FIND_RET_OK;
}
// Wait for unfinished chunks
if ((start >= state->buf_start) &&
(start <= buf_fend) &&
(end >= state->buf_start) &&
(end <= buf_fend))
{
int j;
acb->start = start - state->buf_start;
acb->end = acb->start + len;
for (j=0; j<CURL_NUM_ACB; j++) {
if (!state->acb[j]) {
state->acb[j] = acb;
return FIND_RET_WAIT;
}
}
}
}
return FIND_RET_NONE;
}
static void curl_multi_do(void *arg)
{
BDRVCURLState *s = (BDRVCURLState *)arg;
int running;
int r;
int msgs_in_queue;
if (!s->multi)
return;
do {
r = curl_multi_socket_all(s->multi, &running);
} while(r == CURLM_CALL_MULTI_PERFORM);
/* Try to find done transfers, so we can free the easy
* handle again. */
do {
CURLMsg *msg;
msg = curl_multi_info_read(s->multi, &msgs_in_queue);
if (!msg)
break;
if (msg->msg == CURLMSG_NONE)
break;
switch (msg->msg) {
case CURLMSG_DONE:
{
CURLState *state = NULL;
curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, (char**)&state);
curl_clean_state(state);
break;
}
default:
msgs_in_queue = 0;
break;
}
} while(msgs_in_queue);
}
static CURLState *curl_init_state(BDRVCURLState *s)
{
CURLState *state = NULL;
int i, j;
do {
for (i=0; i<CURL_NUM_STATES; i++) {
for (j=0; j<CURL_NUM_ACB; j++)
if (s->states[i].acb[j])
continue;
if (s->states[i].in_use)
continue;
state = &s->states[i];
state->in_use = 1;
break;
}
if (!state) {
usleep(100);
curl_multi_do(s);
}
} while(!state);
if (state->curl)
goto has_curl;
state->curl = curl_easy_init();
if (!state->curl)
return NULL;
curl_easy_setopt(state->curl, CURLOPT_URL, s->url);
curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, 5);
curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, (void *)curl_read_cb);
curl_easy_setopt(state->curl, CURLOPT_WRITEDATA, (void *)state);
curl_easy_setopt(state->curl, CURLOPT_PRIVATE, (void *)state);
curl_easy_setopt(state->curl, CURLOPT_AUTOREFERER, 1);
curl_easy_setopt(state->curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(state->curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(state->curl, CURLOPT_ERRORBUFFER, state->errmsg);
#ifdef DEBUG_VERBOSE
curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1);
#endif
has_curl:
state->s = s;
return state;
}
static void curl_clean_state(CURLState *s)
{
if (s->s->multi)
curl_multi_remove_handle(s->s->multi, s->curl);
s->in_use = 0;
}
static int curl_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVCURLState *s = bs->opaque;
CURLState *state = NULL;
double d;
#define RA_OPTSTR ":readahead="
char *file;
char *ra;
const char *ra_val;
int parse_state = 0;
static int inited = 0;
file = strdup(filename);
s->readahead_size = READ_AHEAD_SIZE;
/* Parse a trailing ":readahead=#:" param, if present. */
ra = file + strlen(file) - 1;
while (ra >= file) {
if (parse_state == 0) {
if (*ra == ':')
parse_state++;
else
break;
} else if (parse_state == 1) {
if (*ra > '9' || *ra < '0') {
char *opt_start = ra - strlen(RA_OPTSTR) + 1;
if (opt_start > file &&
strncmp(opt_start, RA_OPTSTR, strlen(RA_OPTSTR)) == 0) {
ra_val = ra + 1;
ra -= strlen(RA_OPTSTR) - 1;
*ra = '\0';
s->readahead_size = atoi(ra_val);
break;
} else {
break;
}
}
}
ra--;
}
if ((s->readahead_size & 0x1ff) != 0) {
fprintf(stderr, "HTTP_READAHEAD_SIZE %Zd is not a multiple of 512\n",
s->readahead_size);
goto out_noclean;
}
if (!inited) {
curl_global_init(CURL_GLOBAL_ALL);
inited = 1;
}
dprintf("CURL: Opening %s\n", file);
s->url = file;
state = curl_init_state(s);
if (!state)
goto out_noclean;
// Get file size
curl_easy_setopt(state->curl, CURLOPT_NOBODY, 1);
curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, (void *)curl_size_cb);
if (curl_easy_perform(state->curl))
goto out;
curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d);
curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, (void *)curl_read_cb);
curl_easy_setopt(state->curl, CURLOPT_NOBODY, 0);
if (d)
s->len = (size_t)d;
else if(!s->len)
goto out;
dprintf("CURL: Size = %lld\n", (long long)s->len);
curl_clean_state(state);
curl_easy_cleanup(state->curl);
state->curl = NULL;
// Now we know the file exists and its size, so let's
// initialize the multi interface!
s->multi = curl_multi_init();
curl_multi_setopt( s->multi, CURLMOPT_SOCKETDATA, s);
curl_multi_setopt( s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb );
curl_multi_do(s);
return 0;
out:
fprintf(stderr, "CURL: Error opening file: %s\n", state->errmsg);
curl_easy_cleanup(state->curl);
state->curl = NULL;
out_noclean:
qemu_free(file);
return -EINVAL;
}
static void curl_aio_cancel(BlockDriverAIOCB *blockacb)
{
// Do we have to implement canceling? Seems to work without...
}
static AIOPool curl_aio_pool = {
.aiocb_size = sizeof(CURLAIOCB),
.cancel = curl_aio_cancel,
};
static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
BDRVCURLState *s = bs->opaque;
CURLAIOCB *acb;
size_t start = sector_num * SECTOR_SIZE;
size_t end;
CURLState *state;
acb = qemu_aio_get(&curl_aio_pool, bs, cb, opaque);
if (!acb)
return NULL;
acb->qiov = qiov;
// In case we have the requested data already (e.g. read-ahead),
// we can just call the callback and be done.
switch (curl_find_buf(s, start, nb_sectors * SECTOR_SIZE, acb)) {
case FIND_RET_OK:
qemu_aio_release(acb);
// fall through
case FIND_RET_WAIT:
return &acb->common;
default:
break;
}
// No cache found, so let's start a new request
state = curl_init_state(s);
if (!state)
return NULL;
acb->start = 0;
acb->end = (nb_sectors * SECTOR_SIZE);
state->buf_off = 0;
if (state->orig_buf)
qemu_free(state->orig_buf);
state->buf_start = start;
state->buf_len = acb->end + s->readahead_size;
end = MIN(start + state->buf_len, s->len) - 1;
state->orig_buf = qemu_malloc(state->buf_len);
state->acb[0] = acb;
snprintf(state->range, 127, "%lld-%lld", (long long)start, (long long)end);
dprintf("CURL (AIO): Reading %d at %lld (%s)\n", (nb_sectors * SECTOR_SIZE), start, state->range);
curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range);
curl_multi_add_handle(s->multi, state->curl);
curl_multi_do(s);
return &acb->common;
}
static void curl_close(BlockDriverState *bs)
{
BDRVCURLState *s = bs->opaque;
int i;
dprintf("CURL: Close\n");
for (i=0; i<CURL_NUM_STATES; i++) {
if (s->states[i].in_use)
curl_clean_state(&s->states[i]);
if (s->states[i].curl) {
curl_easy_cleanup(s->states[i].curl);
s->states[i].curl = NULL;
}
if (s->states[i].orig_buf) {
qemu_free(s->states[i].orig_buf);
s->states[i].orig_buf = NULL;
}
}
if (s->multi)
curl_multi_cleanup(s->multi);
if (s->url)
free(s->url);
}
static int64_t curl_getlength(BlockDriverState *bs)
{
BDRVCURLState *s = bs->opaque;
return s->len;
}
static BlockDriver bdrv_http = {
.format_name = "http",
.protocol_name = "http",
.instance_size = sizeof(BDRVCURLState),
.bdrv_open = curl_open,
.bdrv_close = curl_close,
.bdrv_getlength = curl_getlength,
.bdrv_aio_readv = curl_aio_readv,
};
static BlockDriver bdrv_https = {
.format_name = "https",
.protocol_name = "https",
.instance_size = sizeof(BDRVCURLState),
.bdrv_open = curl_open,
.bdrv_close = curl_close,
.bdrv_getlength = curl_getlength,
.bdrv_aio_readv = curl_aio_readv,
};
static BlockDriver bdrv_ftp = {
.format_name = "ftp",
.protocol_name = "ftp",
.instance_size = sizeof(BDRVCURLState),
.bdrv_open = curl_open,
.bdrv_close = curl_close,
.bdrv_getlength = curl_getlength,
.bdrv_aio_readv = curl_aio_readv,
};
static BlockDriver bdrv_ftps = {
.format_name = "ftps",
.protocol_name = "ftps",
.instance_size = sizeof(BDRVCURLState),
.bdrv_open = curl_open,
.bdrv_close = curl_close,
.bdrv_getlength = curl_getlength,
.bdrv_aio_readv = curl_aio_readv,
};
static BlockDriver bdrv_tftp = {
.format_name = "tftp",
.protocol_name = "tftp",
.instance_size = sizeof(BDRVCURLState),
.bdrv_open = curl_open,
.bdrv_close = curl_close,
.bdrv_getlength = curl_getlength,
.bdrv_aio_readv = curl_aio_readv,
};
static void curl_block_init(void)
{
bdrv_register(&bdrv_http);
bdrv_register(&bdrv_https);
bdrv_register(&bdrv_ftp);
bdrv_register(&bdrv_ftps);
bdrv_register(&bdrv_tftp);
}
block_init(curl_block_init);

View File

@@ -1,800 +0,0 @@
/*
* Block driver for the QCOW version 2 format
*
* Copyright (c) 2004-2006 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <zlib.h>
#include "qemu-common.h"
#include "block_int.h"
#include "block/qcow2.h"
int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
{
BDRVQcowState *s = bs->opaque;
int new_l1_size, new_l1_size2, ret, i;
uint64_t *new_l1_table;
uint64_t new_l1_table_offset;
uint8_t data[12];
new_l1_size = s->l1_size;
if (min_size <= new_l1_size)
return 0;
while (min_size > new_l1_size) {
new_l1_size = (new_l1_size * 3 + 1) / 2;
}
#ifdef DEBUG_ALLOC2
printf("grow l1_table from %d to %d\n", s->l1_size, new_l1_size);
#endif
new_l1_size2 = sizeof(uint64_t) * new_l1_size;
new_l1_table = qemu_mallocz(align_offset(new_l1_size2, 512));
memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
/* write new table (align to cluster) */
new_l1_table_offset = qcow2_alloc_clusters(bs, new_l1_size2);
for(i = 0; i < s->l1_size; i++)
new_l1_table[i] = cpu_to_be64(new_l1_table[i]);
ret = bdrv_pwrite(s->hd, new_l1_table_offset, new_l1_table, new_l1_size2);
if (ret != new_l1_size2)
goto fail;
for(i = 0; i < s->l1_size; i++)
new_l1_table[i] = be64_to_cpu(new_l1_table[i]);
/* set new table */
cpu_to_be32w((uint32_t*)data, new_l1_size);
cpu_to_be64w((uint64_t*)(data + 4), new_l1_table_offset);
if (bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_size), data,
sizeof(data)) != sizeof(data))
goto fail;
qemu_free(s->l1_table);
qcow2_free_clusters(bs, s->l1_table_offset, s->l1_size * sizeof(uint64_t));
s->l1_table_offset = new_l1_table_offset;
s->l1_table = new_l1_table;
s->l1_size = new_l1_size;
return 0;
fail:
qemu_free(s->l1_table);
return -EIO;
}
void qcow2_l2_cache_reset(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
memset(s->l2_cache, 0, s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
memset(s->l2_cache_offsets, 0, L2_CACHE_SIZE * sizeof(uint64_t));
memset(s->l2_cache_counts, 0, L2_CACHE_SIZE * sizeof(uint32_t));
}
static inline int l2_cache_new_entry(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
uint32_t min_count;
int min_index, i;
/* find a new entry in the least used one */
min_index = 0;
min_count = 0xffffffff;
for(i = 0; i < L2_CACHE_SIZE; i++) {
if (s->l2_cache_counts[i] < min_count) {
min_count = s->l2_cache_counts[i];
min_index = i;
}
}
return min_index;
}
/*
* seek_l2_table
*
* seek l2_offset in the l2_cache table
* if not found, return NULL,
* if found,
* increments the l2 cache hit count of the entry,
* if counter overflow, divide by two all counters
* return the pointer to the l2 cache entry
*
*/
static uint64_t *seek_l2_table(BDRVQcowState *s, uint64_t l2_offset)
{
int i, j;
for(i = 0; i < L2_CACHE_SIZE; i++) {
if (l2_offset == s->l2_cache_offsets[i]) {
/* increment the hit count */
if (++s->l2_cache_counts[i] == 0xffffffff) {
for(j = 0; j < L2_CACHE_SIZE; j++) {
s->l2_cache_counts[j] >>= 1;
}
}
return s->l2_cache + (i << s->l2_bits);
}
}
return NULL;
}
/*
* l2_load
*
* Loads a L2 table into memory. If the table is in the cache, the cache
* is used; otherwise the L2 table is loaded from the image file.
*
* Returns a pointer to the L2 table on success, or NULL if the read from
* the image file failed.
*/
static uint64_t *l2_load(BlockDriverState *bs, uint64_t l2_offset)
{
BDRVQcowState *s = bs->opaque;
int min_index;
uint64_t *l2_table;
/* seek if the table for the given offset is in the cache */
l2_table = seek_l2_table(s, l2_offset);
if (l2_table != NULL)
return l2_table;
/* not found: load a new entry in the least used one */
min_index = l2_cache_new_entry(bs);
l2_table = s->l2_cache + (min_index << s->l2_bits);
if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
s->l2_size * sizeof(uint64_t))
return NULL;
s->l2_cache_offsets[min_index] = l2_offset;
s->l2_cache_counts[min_index] = 1;
return l2_table;
}
/*
* Writes one sector of the L1 table to the disk (can't update single entries
* and we really don't want bdrv_pread to perform a read-modify-write)
*/
#define L1_ENTRIES_PER_SECTOR (512 / 8)
static int write_l1_entry(BDRVQcowState *s, int l1_index)
{
uint64_t buf[L1_ENTRIES_PER_SECTOR];
int l1_start_index;
int i;
l1_start_index = l1_index & ~(L1_ENTRIES_PER_SECTOR - 1);
for (i = 0; i < L1_ENTRIES_PER_SECTOR; i++) {
buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]);
}
if (bdrv_pwrite(s->hd, s->l1_table_offset + 8 * l1_start_index,
buf, sizeof(buf)) != sizeof(buf))
{
return -1;
}
return 0;
}
/*
* l2_allocate
*
* Allocate a new l2 entry in the file. If l1_index points to an already
* used entry in the L2 table (i.e. we are doing a copy on write for the L2
* table) copy the contents of the old L2 table into the newly allocated one.
* Otherwise the new table is initialized with zeros.
*
*/
static uint64_t *l2_allocate(BlockDriverState *bs, int l1_index)
{
BDRVQcowState *s = bs->opaque;
int min_index;
uint64_t old_l2_offset;
uint64_t *l2_table, l2_offset;
old_l2_offset = s->l1_table[l1_index];
/* allocate a new l2 entry */
l2_offset = qcow2_alloc_clusters(bs, s->l2_size * sizeof(uint64_t));
/* update the L1 entry */
s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;
if (write_l1_entry(s, l1_index) < 0) {
return NULL;
}
/* allocate a new entry in the l2 cache */
min_index = l2_cache_new_entry(bs);
l2_table = s->l2_cache + (min_index << s->l2_bits);
if (old_l2_offset == 0) {
/* if there was no old l2 table, clear the new table */
memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
} else {
/* if there was an old l2 table, read it from the disk */
if (bdrv_pread(s->hd, old_l2_offset,
l2_table, s->l2_size * sizeof(uint64_t)) !=
s->l2_size * sizeof(uint64_t))
return NULL;
}
/* write the l2 table to the file */
if (bdrv_pwrite(s->hd, l2_offset,
l2_table, s->l2_size * sizeof(uint64_t)) !=
s->l2_size * sizeof(uint64_t))
return NULL;
/* update the l2 cache entry */
s->l2_cache_offsets[min_index] = l2_offset;
s->l2_cache_counts[min_index] = 1;
return l2_table;
}
static int count_contiguous_clusters(uint64_t nb_clusters, int cluster_size,
uint64_t *l2_table, uint64_t start, uint64_t mask)
{
int i;
uint64_t offset = be64_to_cpu(l2_table[0]) & ~mask;
if (!offset)
return 0;
for (i = start; i < start + nb_clusters; i++)
if (offset + i * cluster_size != (be64_to_cpu(l2_table[i]) & ~mask))
break;
return (i - start);
}
static int count_contiguous_free_clusters(uint64_t nb_clusters, uint64_t *l2_table)
{
int i = 0;
while(nb_clusters-- && l2_table[i] == 0)
i++;
return i;
}
/* The crypt function is compatible with the linux cryptoloop
algorithm for < 4 GB images. NOTE: out_buf == in_buf is
supported */
void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
uint8_t *out_buf, const uint8_t *in_buf,
int nb_sectors, int enc,
const AES_KEY *key)
{
union {
uint64_t ll[2];
uint8_t b[16];
} ivec;
int i;
for(i = 0; i < nb_sectors; i++) {
ivec.ll[0] = cpu_to_le64(sector_num);
ivec.ll[1] = 0;
AES_cbc_encrypt(in_buf, out_buf, 512, key,
ivec.b, enc);
sector_num++;
in_buf += 512;
out_buf += 512;
}
}
static int qcow_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVQcowState *s = bs->opaque;
int ret, index_in_cluster, n, n1;
uint64_t cluster_offset;
while (nb_sectors > 0) {
n = nb_sectors;
cluster_offset = qcow2_get_cluster_offset(bs, sector_num << 9, &n);
index_in_cluster = sector_num & (s->cluster_sectors - 1);
if (!cluster_offset) {
if (bs->backing_hd) {
/* read from the base image */
n1 = qcow2_backing_read1(bs->backing_hd, sector_num, buf, n);
if (n1 > 0) {
ret = bdrv_read(bs->backing_hd, sector_num, buf, n1);
if (ret < 0)
return -1;
}
} else {
memset(buf, 0, 512 * n);
}
} else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
if (qcow2_decompress_cluster(s, cluster_offset) < 0)
return -1;
memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);
} else {
ret = bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
if (ret != n * 512)
return -1;
if (s->crypt_method) {
qcow2_encrypt_sectors(s, sector_num, buf, buf, n, 0,
&s->aes_decrypt_key);
}
}
nb_sectors -= n;
sector_num += n;
buf += n * 512;
}
return 0;
}
static int copy_sectors(BlockDriverState *bs, uint64_t start_sect,
uint64_t cluster_offset, int n_start, int n_end)
{
BDRVQcowState *s = bs->opaque;
int n, ret;
n = n_end - n_start;
if (n <= 0)
return 0;
ret = qcow_read(bs, start_sect + n_start, s->cluster_data, n);
if (ret < 0)
return ret;
if (s->crypt_method) {
qcow2_encrypt_sectors(s, start_sect + n_start,
s->cluster_data,
s->cluster_data, n, 1,
&s->aes_encrypt_key);
}
ret = bdrv_write(s->hd, (cluster_offset >> 9) + n_start,
s->cluster_data, n);
if (ret < 0)
return ret;
return 0;
}
/*
* get_cluster_offset
*
* For a given offset of the disk image, return cluster offset in
* qcow2 file.
*
* on entry, *num is the number of contiguous clusters we'd like to
* access following offset.
*
* on exit, *num is the number of contiguous clusters we can read.
*
* Return 1, if the offset is found
* Return 0, otherwise.
*
*/
uint64_t qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
int *num)
{
BDRVQcowState *s = bs->opaque;
int l1_index, l2_index;
uint64_t l2_offset, *l2_table, cluster_offset;
int l1_bits, c;
int index_in_cluster, nb_available, nb_needed, nb_clusters;
index_in_cluster = (offset >> 9) & (s->cluster_sectors - 1);
nb_needed = *num + index_in_cluster;
l1_bits = s->l2_bits + s->cluster_bits;
/* compute how many bytes there are between the offset and
* the end of the l1 entry
*/
nb_available = (1 << l1_bits) - (offset & ((1 << l1_bits) - 1));
/* compute the number of available sectors */
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 */
l1_index = offset >> l1_bits;
if (l1_index >= s->l1_size)
goto out;
l2_offset = s->l1_table[l1_index];
/* seek the l2 table of the given l2 offset */
if (!l2_offset)
goto out;
/* load the l2 table in memory */
l2_offset &= ~QCOW_OFLAG_COPIED;
l2_table = l2_load(bs, l2_offset);
if (l2_table == NULL)
return 0;
/* find the cluster offset for the given disk offset */
l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
cluster_offset = be64_to_cpu(l2_table[l2_index]);
nb_clusters = size_to_clusters(s, nb_needed << 9);
if (!cluster_offset) {
/* how many empty clusters ? */
c = count_contiguous_free_clusters(nb_clusters, &l2_table[l2_index]);
} else {
/* how many allocated clusters ? */
c = count_contiguous_clusters(nb_clusters, s->cluster_size,
&l2_table[l2_index], 0, QCOW_OFLAG_COPIED);
}
nb_available = (c * s->cluster_sectors);
out:
if (nb_available > nb_needed)
nb_available = nb_needed;
*num = nb_available - index_in_cluster;
return cluster_offset & ~QCOW_OFLAG_COPIED;
}
/*
* get_cluster_table
*
* for a given disk offset, load (and allocate if needed)
* the l2 table.
*
* the l2 table offset in the qcow2 file and the cluster index
* in the l2 table are given to the caller.
*
*/
static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
uint64_t **new_l2_table,
uint64_t *new_l2_offset,
int *new_l2_index)
{
BDRVQcowState *s = bs->opaque;
int l1_index, l2_index, ret;
uint64_t l2_offset, *l2_table;
/* seek the the l2 offset in the l1 table */
l1_index = offset >> (s->l2_bits + s->cluster_bits);
if (l1_index >= s->l1_size) {
ret = qcow2_grow_l1_table(bs, l1_index + 1);
if (ret < 0)
return 0;
}
l2_offset = s->l1_table[l1_index];
/* seek the l2 table of the given l2 offset */
if (l2_offset & QCOW_OFLAG_COPIED) {
/* load the l2 table in memory */
l2_offset &= ~QCOW_OFLAG_COPIED;
l2_table = l2_load(bs, l2_offset);
if (l2_table == NULL)
return 0;
} else {
if (l2_offset)
qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t));
l2_table = l2_allocate(bs, l1_index);
if (l2_table == NULL)
return 0;
l2_offset = s->l1_table[l1_index] & ~QCOW_OFLAG_COPIED;
}
/* find the cluster offset for the given disk offset */
l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
*new_l2_table = l2_table;
*new_l2_offset = l2_offset;
*new_l2_index = l2_index;
return 1;
}
/*
* alloc_compressed_cluster_offset
*
* For a given offset of the disk image, return cluster offset in
* qcow2 file.
*
* If the offset is not found, allocate a new compressed cluster.
*
* Return the cluster offset if successful,
* Return 0, otherwise.
*
*/
uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
uint64_t offset,
int compressed_size)
{
BDRVQcowState *s = bs->opaque;
int l2_index, ret;
uint64_t l2_offset, *l2_table, cluster_offset;
int nb_csectors;
ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index);
if (ret == 0)
return 0;
cluster_offset = be64_to_cpu(l2_table[l2_index]);
if (cluster_offset & QCOW_OFLAG_COPIED)
return cluster_offset & ~QCOW_OFLAG_COPIED;
if (cluster_offset)
qcow2_free_any_clusters(bs, cluster_offset, 1);
cluster_offset = qcow2_alloc_bytes(bs, compressed_size);
nb_csectors = ((cluster_offset + compressed_size - 1) >> 9) -
(cluster_offset >> 9);
cluster_offset |= QCOW_OFLAG_COMPRESSED |
((uint64_t)nb_csectors << s->csize_shift);
/* update L2 table */
/* compressed clusters never have the copied flag */
l2_table[l2_index] = cpu_to_be64(cluster_offset);
if (bdrv_pwrite(s->hd,
l2_offset + l2_index * sizeof(uint64_t),
l2_table + l2_index,
sizeof(uint64_t)) != sizeof(uint64_t))
return 0;
return cluster_offset;
}
/*
* Write L2 table updates to disk, writing whole sectors to avoid a
* read-modify-write in bdrv_pwrite
*/
#define L2_ENTRIES_PER_SECTOR (512 / 8)
static int write_l2_entries(BDRVQcowState *s, uint64_t *l2_table,
uint64_t l2_offset, int l2_index, int num)
{
int l2_start_index = l2_index & ~(L1_ENTRIES_PER_SECTOR - 1);
int start_offset = (8 * l2_index) & ~511;
int end_offset = (8 * (l2_index + num) + 511) & ~511;
size_t len = end_offset - start_offset;
if (bdrv_pwrite(s->hd, l2_offset + start_offset, &l2_table[l2_start_index],
len) != len)
{
return -1;
}
return 0;
}
int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, uint64_t cluster_offset,
QCowL2Meta *m)
{
BDRVQcowState *s = bs->opaque;
int i, j = 0, l2_index, ret;
uint64_t *old_cluster, start_sect, l2_offset, *l2_table;
if (m->nb_clusters == 0)
return 0;
old_cluster = qemu_malloc(m->nb_clusters * sizeof(uint64_t));
/* copy content of unmodified sectors */
start_sect = (m->offset & ~(s->cluster_size - 1)) >> 9;
if (m->n_start) {
ret = copy_sectors(bs, start_sect, cluster_offset, 0, m->n_start);
if (ret < 0)
goto err;
}
if (m->nb_available & (s->cluster_sectors - 1)) {
uint64_t end = m->nb_available & ~(uint64_t)(s->cluster_sectors - 1);
ret = copy_sectors(bs, start_sect + end, cluster_offset + (end << 9),
m->nb_available - end, s->cluster_sectors);
if (ret < 0)
goto err;
}
ret = -EIO;
/* update L2 table */
if (!get_cluster_table(bs, m->offset, &l2_table, &l2_offset, &l2_index))
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];
l2_table[l2_index + i] = cpu_to_be64((cluster_offset +
(i << s->cluster_bits)) | QCOW_OFLAG_COPIED);
}
if (write_l2_entries(s, l2_table, l2_offset, l2_index, m->nb_clusters) < 0) {
ret = -1;
goto err;
}
for (i = 0; i < j; i++)
qcow2_free_any_clusters(bs,
be64_to_cpu(old_cluster[i]) & ~QCOW_OFLAG_COPIED, 1);
ret = 0;
err:
qemu_free(old_cluster);
return ret;
}
/*
* alloc_cluster_offset
*
* For a given offset of the disk image, return cluster offset in
* qcow2 file.
*
* If the offset is not found, allocate a new cluster.
*
* Return the cluster offset if successful,
* Return 0, otherwise.
*
*/
uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs,
uint64_t offset,
int n_start, int n_end,
int *num, QCowL2Meta *m)
{
BDRVQcowState *s = bs->opaque;
int l2_index, ret;
uint64_t l2_offset, *l2_table, cluster_offset;
int nb_clusters, i = 0;
ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index);
if (ret == 0)
return 0;
nb_clusters = size_to_clusters(s, n_end << 9);
nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
cluster_offset = be64_to_cpu(l2_table[l2_index]);
/* We keep all QCOW_OFLAG_COPIED clusters */
if (cluster_offset & QCOW_OFLAG_COPIED) {
nb_clusters = count_contiguous_clusters(nb_clusters, s->cluster_size,
&l2_table[l2_index], 0, 0);
cluster_offset &= ~QCOW_OFLAG_COPIED;
m->nb_clusters = 0;
goto out;
}
/* for the moment, multiple compressed clusters are not managed */
if (cluster_offset & QCOW_OFLAG_COMPRESSED)
nb_clusters = 1;
/* how many available clusters ? */
while (i < nb_clusters) {
i += count_contiguous_clusters(nb_clusters - i, s->cluster_size,
&l2_table[l2_index], i, 0);
if(be64_to_cpu(l2_table[l2_index + i]))
break;
i += count_contiguous_free_clusters(nb_clusters - i,
&l2_table[l2_index + i]);
cluster_offset = be64_to_cpu(l2_table[l2_index + i]);
if ((cluster_offset & QCOW_OFLAG_COPIED) ||
(cluster_offset & QCOW_OFLAG_COMPRESSED))
break;
}
nb_clusters = i;
/* allocate a new cluster */
cluster_offset = qcow2_alloc_clusters(bs, nb_clusters * s->cluster_size);
/* save info needed for meta data update */
m->offset = offset;
m->n_start = n_start;
m->nb_clusters = nb_clusters;
out:
m->nb_available = MIN(nb_clusters << (s->cluster_bits - 9), n_end);
*num = m->nb_available - n_start;
return cluster_offset;
}
static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
const uint8_t *buf, int buf_size)
{
z_stream strm1, *strm = &strm1;
int ret, out_len;
memset(strm, 0, sizeof(*strm));
strm->next_in = (uint8_t *)buf;
strm->avail_in = buf_size;
strm->next_out = out_buf;
strm->avail_out = out_buf_size;
ret = inflateInit2(strm, -12);
if (ret != Z_OK)
return -1;
ret = inflate(strm, Z_FINISH);
out_len = strm->next_out - out_buf;
if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) ||
out_len != out_buf_size) {
inflateEnd(strm);
return -1;
}
inflateEnd(strm);
return 0;
}
int qcow2_decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
{
int ret, csize, nb_csectors, sector_offset;
uint64_t coffset;
coffset = cluster_offset & s->cluster_offset_mask;
if (s->cluster_cache_offset != coffset) {
nb_csectors = ((cluster_offset >> s->csize_shift) & s->csize_mask) + 1;
sector_offset = coffset & 511;
csize = nb_csectors * 512 - sector_offset;
ret = bdrv_read(s->hd, coffset >> 9, s->cluster_data, nb_csectors);
if (ret < 0) {
return -1;
}
if (decompress_buffer(s->cluster_cache, s->cluster_size,
s->cluster_data + sector_offset, csize) < 0) {
return -1;
}
s->cluster_cache_offset = coffset;
}
return 0;
}

View File

@@ -1,894 +0,0 @@
/*
* Block driver for the QCOW version 2 format
*
* Copyright (c) 2004-2006 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "qemu-common.h"
#include "block_int.h"
#include "block/qcow2.h"
static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size);
static int update_refcount(BlockDriverState *bs,
int64_t offset, int64_t length,
int addend);
static int cache_refcount_updates = 0;
static int write_refcount_block(BDRVQcowState *s)
{
size_t size = s->cluster_size;
if (s->refcount_block_cache_offset == 0) {
return 0;
}
if (bdrv_pwrite(s->hd, s->refcount_block_cache_offset,
s->refcount_block_cache, size) != size)
{
return -EIO;
}
return 0;
}
/*********************************************************/
/* refcount handling */
int qcow2_refcount_init(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
int ret, refcount_table_size2, i;
s->refcount_block_cache = qemu_malloc(s->cluster_size);
refcount_table_size2 = s->refcount_table_size * sizeof(uint64_t);
s->refcount_table = qemu_malloc(refcount_table_size2);
if (s->refcount_table_size > 0) {
ret = bdrv_pread(s->hd, s->refcount_table_offset,
s->refcount_table, refcount_table_size2);
if (ret != refcount_table_size2)
goto fail;
for(i = 0; i < s->refcount_table_size; i++)
be64_to_cpus(&s->refcount_table[i]);
}
return 0;
fail:
return -ENOMEM;
}
void qcow2_refcount_close(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
qemu_free(s->refcount_block_cache);
qemu_free(s->refcount_table);
}
static int load_refcount_block(BlockDriverState *bs,
int64_t refcount_block_offset)
{
BDRVQcowState *s = bs->opaque;
int ret;
if (cache_refcount_updates) {
write_refcount_block(s);
}
ret = bdrv_pread(s->hd, refcount_block_offset, s->refcount_block_cache,
s->cluster_size);
if (ret != s->cluster_size)
return -EIO;
s->refcount_block_cache_offset = refcount_block_offset;
return 0;
}
static int get_refcount(BlockDriverState *bs, int64_t cluster_index)
{
BDRVQcowState *s = bs->opaque;
int refcount_table_index, block_index;
int64_t refcount_block_offset;
refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
if (refcount_table_index >= s->refcount_table_size)
return 0;
refcount_block_offset = s->refcount_table[refcount_table_index];
if (!refcount_block_offset)
return 0;
if (refcount_block_offset != s->refcount_block_cache_offset) {
/* better than nothing: return allocated if read error */
if (load_refcount_block(bs, refcount_block_offset) < 0)
return 1;
}
block_index = cluster_index &
((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);
return be16_to_cpu(s->refcount_block_cache[block_index]);
}
static int grow_refcount_table(BlockDriverState *bs, int min_size)
{
BDRVQcowState *s = bs->opaque;
int new_table_size, new_table_size2, refcount_table_clusters, i, ret;
uint64_t *new_table;
int64_t table_offset;
uint8_t data[12];
int old_table_size;
int64_t old_table_offset;
if (min_size <= s->refcount_table_size)
return 0;
/* compute new table size */
refcount_table_clusters = s->refcount_table_size >> (s->cluster_bits - 3);
for(;;) {
if (refcount_table_clusters == 0) {
refcount_table_clusters = 1;
} else {
refcount_table_clusters = (refcount_table_clusters * 3 + 1) / 2;
}
new_table_size = refcount_table_clusters << (s->cluster_bits - 3);
if (min_size <= new_table_size)
break;
}
#ifdef DEBUG_ALLOC2
printf("grow_refcount_table from %d to %d\n",
s->refcount_table_size,
new_table_size);
#endif
new_table_size2 = new_table_size * sizeof(uint64_t);
new_table = qemu_mallocz(new_table_size2);
memcpy(new_table, s->refcount_table,
s->refcount_table_size * sizeof(uint64_t));
for(i = 0; i < s->refcount_table_size; i++)
cpu_to_be64s(&new_table[i]);
/* Note: we cannot update the refcount now to avoid recursion */
table_offset = alloc_clusters_noref(bs, new_table_size2);
ret = bdrv_pwrite(s->hd, table_offset, new_table, new_table_size2);
if (ret != new_table_size2)
goto fail;
for(i = 0; i < s->refcount_table_size; i++)
be64_to_cpus(&new_table[i]);
cpu_to_be64w((uint64_t*)data, table_offset);
cpu_to_be32w((uint32_t*)(data + 8), refcount_table_clusters);
if (bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_offset),
data, sizeof(data)) != sizeof(data))
goto fail;
qemu_free(s->refcount_table);
old_table_offset = s->refcount_table_offset;
old_table_size = s->refcount_table_size;
s->refcount_table = new_table;
s->refcount_table_size = new_table_size;
s->refcount_table_offset = table_offset;
update_refcount(bs, table_offset, new_table_size2, 1);
qcow2_free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t));
return 0;
fail:
qcow2_free_clusters(bs, table_offset, new_table_size2);
qemu_free(new_table);
return -EIO;
}
static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
{
BDRVQcowState *s = bs->opaque;
int64_t offset, refcount_block_offset;
int ret, refcount_table_index;
uint64_t data64;
int cache = cache_refcount_updates;
/* Find L1 index and grow refcount table if needed */
refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
if (refcount_table_index >= s->refcount_table_size) {
ret = grow_refcount_table(bs, refcount_table_index + 1);
if (ret < 0)
return ret;
}
/* Load or allocate the refcount block */
refcount_block_offset = s->refcount_table[refcount_table_index];
if (!refcount_block_offset) {
if (cache_refcount_updates) {
write_refcount_block(s);
cache_refcount_updates = 0;
}
/* create a new refcount block */
/* Note: we cannot update the refcount now to avoid recursion */
offset = alloc_clusters_noref(bs, s->cluster_size);
memset(s->refcount_block_cache, 0, s->cluster_size);
ret = bdrv_pwrite(s->hd, offset, s->refcount_block_cache, s->cluster_size);
if (ret != s->cluster_size)
return -EINVAL;
s->refcount_table[refcount_table_index] = offset;
data64 = cpu_to_be64(offset);
ret = bdrv_pwrite(s->hd, s->refcount_table_offset +
refcount_table_index * sizeof(uint64_t),
&data64, sizeof(data64));
if (ret != sizeof(data64))
return -EINVAL;
refcount_block_offset = offset;
s->refcount_block_cache_offset = offset;
update_refcount(bs, offset, s->cluster_size, 1);
cache_refcount_updates = cache;
} else {
if (refcount_block_offset != s->refcount_block_cache_offset) {
if (load_refcount_block(bs, refcount_block_offset) < 0)
return -EIO;
}
}
return refcount_block_offset;
}
#define REFCOUNTS_PER_SECTOR (512 >> REFCOUNT_SHIFT)
static int write_refcount_block_entries(BDRVQcowState *s,
int64_t refcount_block_offset, int first_index, int last_index)
{
size_t size;
if (cache_refcount_updates) {
return 0;
}
first_index &= ~(REFCOUNTS_PER_SECTOR - 1);
last_index = (last_index + REFCOUNTS_PER_SECTOR)
& ~(REFCOUNTS_PER_SECTOR - 1);
size = (last_index - first_index) << REFCOUNT_SHIFT;
if (bdrv_pwrite(s->hd,
refcount_block_offset + (first_index << REFCOUNT_SHIFT),
&s->refcount_block_cache[first_index], size) != size)
{
return -EIO;
}
return 0;
}
/* XXX: cache several refcount block clusters ? */
static int update_refcount(BlockDriverState *bs,
int64_t offset, int64_t length,
int addend)
{
BDRVQcowState *s = bs->opaque;
int64_t start, last, cluster_offset;
int64_t refcount_block_offset = 0;
int64_t table_index = -1, old_table_index;
int first_index = -1, last_index = -1;
#ifdef DEBUG_ALLOC2
printf("update_refcount: offset=%" PRId64 " size=%" PRId64 " addend=%d\n",
offset, length, addend);
#endif
if (length <= 0)
return -EINVAL;
start = offset & ~(s->cluster_size - 1);
last = (offset + length - 1) & ~(s->cluster_size - 1);
for(cluster_offset = start; cluster_offset <= last;
cluster_offset += s->cluster_size)
{
int block_index, refcount;
int64_t cluster_index = cluster_offset >> s->cluster_bits;
/* Only write refcount block to disk when we are done with it */
old_table_index = table_index;
table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
if ((old_table_index >= 0) && (table_index != old_table_index)) {
if (write_refcount_block_entries(s, refcount_block_offset,
first_index, last_index) < 0)
{
return -EIO;
}
first_index = -1;
last_index = -1;
}
/* Load the refcount block and allocate it if needed */
refcount_block_offset = alloc_refcount_block(bs, cluster_index);
if (refcount_block_offset < 0) {
return refcount_block_offset;
}
/* we can update the count and save it */
block_index = cluster_index &
((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);
if (first_index == -1 || block_index < first_index) {
first_index = block_index;
}
if (block_index > last_index) {
last_index = block_index;
}
refcount = be16_to_cpu(s->refcount_block_cache[block_index]);
refcount += addend;
if (refcount < 0 || refcount > 0xffff)
return -EINVAL;
if (refcount == 0 && cluster_index < s->free_cluster_index) {
s->free_cluster_index = cluster_index;
}
s->refcount_block_cache[block_index] = cpu_to_be16(refcount);
}
/* Write last changed block to disk */
if (refcount_block_offset != 0) {
if (write_refcount_block_entries(s, refcount_block_offset,
first_index, last_index) < 0)
{
return -EIO;
}
}
return 0;
}
/* addend must be 1 or -1 */
static int update_cluster_refcount(BlockDriverState *bs,
int64_t cluster_index,
int addend)
{
BDRVQcowState *s = bs->opaque;
int ret;
ret = update_refcount(bs, cluster_index << s->cluster_bits, 1, addend);
if (ret < 0) {
return ret;
}
return get_refcount(bs, cluster_index);
}
/*********************************************************/
/* cluster allocation functions */
/* return < 0 if error */
static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size)
{
BDRVQcowState *s = bs->opaque;
int i, nb_clusters;
nb_clusters = size_to_clusters(s, size);
retry:
for(i = 0; i < nb_clusters; i++) {
int64_t i = s->free_cluster_index++;
if (get_refcount(bs, i) != 0)
goto retry;
}
#ifdef DEBUG_ALLOC2
printf("alloc_clusters: size=%" PRId64 " -> %" PRId64 "\n",
size,
(s->free_cluster_index - nb_clusters) << s->cluster_bits);
#endif
return (s->free_cluster_index - nb_clusters) << s->cluster_bits;
}
int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size)
{
int64_t offset;
offset = alloc_clusters_noref(bs, size);
update_refcount(bs, offset, size, 1);
return offset;
}
/* only used to allocate compressed sectors. We try to allocate
contiguous sectors. size must be <= cluster_size */
int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
{
BDRVQcowState *s = bs->opaque;
int64_t offset, cluster_offset;
int free_in_cluster;
assert(size > 0 && size <= s->cluster_size);
if (s->free_byte_offset == 0) {
s->free_byte_offset = qcow2_alloc_clusters(bs, s->cluster_size);
}
redo:
free_in_cluster = s->cluster_size -
(s->free_byte_offset & (s->cluster_size - 1));
if (size <= free_in_cluster) {
/* enough space in current cluster */
offset = s->free_byte_offset;
s->free_byte_offset += size;
free_in_cluster -= size;
if (free_in_cluster == 0)
s->free_byte_offset = 0;
if ((offset & (s->cluster_size - 1)) != 0)
update_cluster_refcount(bs, offset >> s->cluster_bits, 1);
} else {
offset = qcow2_alloc_clusters(bs, s->cluster_size);
cluster_offset = s->free_byte_offset & ~(s->cluster_size - 1);
if ((cluster_offset + s->cluster_size) == offset) {
/* we are lucky: contiguous data */
offset = s->free_byte_offset;
update_cluster_refcount(bs, offset >> s->cluster_bits, 1);
s->free_byte_offset += size;
} else {
s->free_byte_offset = offset;
goto redo;
}
}
return offset;
}
void qcow2_free_clusters(BlockDriverState *bs,
int64_t offset, int64_t size)
{
update_refcount(bs, offset, size, -1);
}
/*
* free_any_clusters
*
* free clusters according to its type: compressed or not
*
*/
void qcow2_free_any_clusters(BlockDriverState *bs,
uint64_t cluster_offset, int nb_clusters)
{
BDRVQcowState *s = bs->opaque;
/* free the cluster */
if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
int nb_csectors;
nb_csectors = ((cluster_offset >> s->csize_shift) &
s->csize_mask) + 1;
qcow2_free_clusters(bs,
(cluster_offset & s->cluster_offset_mask) & ~511,
nb_csectors * 512);
return;
}
qcow2_free_clusters(bs, cluster_offset, nb_clusters << s->cluster_bits);
return;
}
/*********************************************************/
/* snapshots and image creation */
void qcow2_create_refcount_update(QCowCreateState *s, int64_t offset,
int64_t size)
{
int refcount;
int64_t start, last, cluster_offset;
uint16_t *p;
start = offset & ~(s->cluster_size - 1);
last = (offset + size - 1) & ~(s->cluster_size - 1);
for(cluster_offset = start; cluster_offset <= last;
cluster_offset += s->cluster_size) {
p = &s->refcount_block[cluster_offset >> s->cluster_bits];
refcount = be16_to_cpu(*p);
refcount++;
*p = cpu_to_be16(refcount);
}
}
/* update the refcounts of snapshots and the copied flag */
int qcow2_update_snapshot_refcount(BlockDriverState *bs,
int64_t l1_table_offset, int l1_size, int addend)
{
BDRVQcowState *s = bs->opaque;
uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2, l1_allocated;
int64_t old_offset, old_l2_offset;
int l2_size, i, j, l1_modified, l2_modified, nb_csectors, refcount;
qcow2_l2_cache_reset(bs);
cache_refcount_updates = 1;
l2_table = NULL;
l1_table = NULL;
l1_size2 = l1_size * sizeof(uint64_t);
l1_allocated = 0;
if (l1_table_offset != s->l1_table_offset) {
l1_table = qemu_mallocz(align_offset(l1_size2, 512));
l1_allocated = 1;
if (bdrv_pread(s->hd, l1_table_offset,
l1_table, l1_size2) != l1_size2)
goto fail;
for(i = 0;i < l1_size; i++)
be64_to_cpus(&l1_table[i]);
} else {
assert(l1_size == s->l1_size);
l1_table = s->l1_table;
l1_allocated = 0;
}
l2_size = s->l2_size * sizeof(uint64_t);
l2_table = qemu_malloc(l2_size);
l1_modified = 0;
for(i = 0; i < l1_size; i++) {
l2_offset = l1_table[i];
if (l2_offset) {
old_l2_offset = l2_offset;
l2_offset &= ~QCOW_OFLAG_COPIED;
l2_modified = 0;
if (bdrv_pread(s->hd, l2_offset, l2_table, l2_size) != l2_size)
goto fail;
for(j = 0; j < s->l2_size; j++) {
offset = be64_to_cpu(l2_table[j]);
if (offset != 0) {
old_offset = offset;
offset &= ~QCOW_OFLAG_COPIED;
if (offset & QCOW_OFLAG_COMPRESSED) {
nb_csectors = ((offset >> s->csize_shift) &
s->csize_mask) + 1;
if (addend != 0)
update_refcount(bs, (offset & s->cluster_offset_mask) & ~511,
nb_csectors * 512, addend);
/* compressed clusters are never modified */
refcount = 2;
} else {
if (addend != 0) {
refcount = update_cluster_refcount(bs, offset >> s->cluster_bits, addend);
} else {
refcount = get_refcount(bs, offset >> s->cluster_bits);
}
}
if (refcount == 1) {
offset |= QCOW_OFLAG_COPIED;
}
if (offset != old_offset) {
l2_table[j] = cpu_to_be64(offset);
l2_modified = 1;
}
}
}
if (l2_modified) {
if (bdrv_pwrite(s->hd,
l2_offset, l2_table, l2_size) != l2_size)
goto fail;
}
if (addend != 0) {
refcount = update_cluster_refcount(bs, l2_offset >> s->cluster_bits, addend);
} else {
refcount = get_refcount(bs, l2_offset >> s->cluster_bits);
}
if (refcount == 1) {
l2_offset |= QCOW_OFLAG_COPIED;
}
if (l2_offset != old_l2_offset) {
l1_table[i] = l2_offset;
l1_modified = 1;
}
}
}
if (l1_modified) {
for(i = 0; i < l1_size; i++)
cpu_to_be64s(&l1_table[i]);
if (bdrv_pwrite(s->hd, l1_table_offset, l1_table,
l1_size2) != l1_size2)
goto fail;
for(i = 0; i < l1_size; i++)
be64_to_cpus(&l1_table[i]);
}
if (l1_allocated)
qemu_free(l1_table);
qemu_free(l2_table);
cache_refcount_updates = 0;
write_refcount_block(s);
return 0;
fail:
if (l1_allocated)
qemu_free(l1_table);
qemu_free(l2_table);
cache_refcount_updates = 0;
write_refcount_block(s);
return -EIO;
}
/*********************************************************/
/* refcount checking functions */
/*
* Increases the refcount for a range of clusters in a given refcount table.
* This is used to construct a temporary refcount table out of L1 and L2 tables
* which can be compared the the refcount table saved in the image.
*
* Returns the number of errors in the image that were found
*/
static int inc_refcounts(BlockDriverState *bs,
uint16_t *refcount_table,
int refcount_table_size,
int64_t offset, int64_t size)
{
BDRVQcowState *s = bs->opaque;
int64_t start, last, cluster_offset;
int k;
int errors = 0;
if (size <= 0)
return 0;
start = offset & ~(s->cluster_size - 1);
last = (offset + size - 1) & ~(s->cluster_size - 1);
for(cluster_offset = start; cluster_offset <= last;
cluster_offset += s->cluster_size) {
k = cluster_offset >> s->cluster_bits;
if (k < 0 || k >= refcount_table_size) {
fprintf(stderr, "ERROR: invalid cluster offset=0x%" PRIx64 "\n",
cluster_offset);
errors++;
} else {
if (++refcount_table[k] == 0) {
fprintf(stderr, "ERROR: overflow cluster offset=0x%" PRIx64
"\n", cluster_offset);
errors++;
}
}
}
return errors;
}
/*
* Increases the refcount in the given refcount table for the all clusters
* referenced in the L2 table. While doing so, performs some checks on L2
* entries.
*
* Returns the number of errors found by the checks or -errno if an internal
* error occurred.
*/
static int check_refcounts_l2(BlockDriverState *bs,
uint16_t *refcount_table, int refcount_table_size, int64_t l2_offset,
int check_copied)
{
BDRVQcowState *s = bs->opaque;
uint64_t *l2_table, offset;
int i, l2_size, nb_csectors, refcount;
int errors = 0;
/* Read L2 table from disk */
l2_size = s->l2_size * sizeof(uint64_t);
l2_table = qemu_malloc(l2_size);
if (bdrv_pread(s->hd, l2_offset, l2_table, l2_size) != l2_size)
goto fail;
/* Do the actual checks */
for(i = 0; i < s->l2_size; i++) {
offset = be64_to_cpu(l2_table[i]);
if (offset != 0) {
if (offset & QCOW_OFLAG_COMPRESSED) {
/* Compressed clusters don't have QCOW_OFLAG_COPIED */
if (offset & QCOW_OFLAG_COPIED) {
fprintf(stderr, "ERROR: cluster %" PRId64 ": "
"copied flag must never be set for compressed "
"clusters\n", offset >> s->cluster_bits);
offset &= ~QCOW_OFLAG_COPIED;
errors++;
}
/* Mark cluster as used */
nb_csectors = ((offset >> s->csize_shift) &
s->csize_mask) + 1;
offset &= s->cluster_offset_mask;
errors += inc_refcounts(bs, refcount_table,
refcount_table_size,
offset & ~511, nb_csectors * 512);
} else {
/* QCOW_OFLAG_COPIED must be set iff refcount == 1 */
if (check_copied) {
uint64_t entry = offset;
offset &= ~QCOW_OFLAG_COPIED;
refcount = get_refcount(bs, offset >> s->cluster_bits);
if ((refcount == 1) != ((entry & QCOW_OFLAG_COPIED) != 0)) {
fprintf(stderr, "ERROR OFLAG_COPIED: offset=%"
PRIx64 " refcount=%d\n", entry, refcount);
errors++;
}
}
/* Mark cluster as used */
offset &= ~QCOW_OFLAG_COPIED;
errors += inc_refcounts(bs, refcount_table,
refcount_table_size,
offset, s->cluster_size);
/* Correct offsets are cluster aligned */
if (offset & (s->cluster_size - 1)) {
fprintf(stderr, "ERROR offset=%" PRIx64 ": Cluster is not "
"properly aligned; L2 entry corrupted.\n", offset);
errors++;
}
}
}
}
qemu_free(l2_table);
return errors;
fail:
fprintf(stderr, "ERROR: I/O error in check_refcounts_l1\n");
qemu_free(l2_table);
return -EIO;
}
/*
* Increases the refcount for the L1 table, its L2 tables and all referenced
* clusters in the given refcount table. While doing so, performs some checks
* on L1 and L2 entries.
*
* Returns the number of errors found by the checks or -errno if an internal
* error occurred.
*/
static int check_refcounts_l1(BlockDriverState *bs,
uint16_t *refcount_table,
int refcount_table_size,
int64_t l1_table_offset, int l1_size,
int check_copied)
{
BDRVQcowState *s = bs->opaque;
uint64_t *l1_table, l2_offset, l1_size2;
int i, refcount, ret;
int errors = 0;
l1_size2 = l1_size * sizeof(uint64_t);
/* Mark L1 table as used */
errors += inc_refcounts(bs, refcount_table, refcount_table_size,
l1_table_offset, l1_size2);
/* Read L1 table entries from disk */
l1_table = qemu_malloc(l1_size2);
if (bdrv_pread(s->hd, l1_table_offset,
l1_table, l1_size2) != l1_size2)
goto fail;
for(i = 0;i < l1_size; i++)
be64_to_cpus(&l1_table[i]);
/* Do the actual checks */
for(i = 0; i < l1_size; i++) {
l2_offset = l1_table[i];
if (l2_offset) {
/* QCOW_OFLAG_COPIED must be set iff refcount == 1 */
if (check_copied) {
refcount = get_refcount(bs, (l2_offset & ~QCOW_OFLAG_COPIED)
>> s->cluster_bits);
if ((refcount == 1) != ((l2_offset & QCOW_OFLAG_COPIED) != 0)) {
fprintf(stderr, "ERROR OFLAG_COPIED: l2_offset=%" PRIx64
" refcount=%d\n", l2_offset, refcount);
errors++;
}
}
/* Mark L2 table as used */
l2_offset &= ~QCOW_OFLAG_COPIED;
errors += inc_refcounts(bs, refcount_table,
refcount_table_size,
l2_offset,
s->cluster_size);
/* L2 tables are cluster aligned */
if (l2_offset & (s->cluster_size - 1)) {
fprintf(stderr, "ERROR l2_offset=%" PRIx64 ": Table is not "
"cluster aligned; L1 entry corrupted\n", l2_offset);
errors++;
}
/* Process and check L2 entries */
ret = check_refcounts_l2(bs, refcount_table, refcount_table_size,
l2_offset, check_copied);
if (ret < 0) {
goto fail;
}
errors += ret;
}
}
qemu_free(l1_table);
return errors;
fail:
fprintf(stderr, "ERROR: I/O error in check_refcounts_l1\n");
qemu_free(l1_table);
return -EIO;
}
/*
* Checks an image for refcount consistency.
*
* Returns 0 if no errors are found, the number of errors in case the image is
* detected as corrupted, and -errno when an internal error occured.
*/
int qcow2_check_refcounts(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
int64_t size;
int nb_clusters, refcount1, refcount2, i;
QCowSnapshot *sn;
uint16_t *refcount_table;
int ret, errors = 0;
size = bdrv_getlength(s->hd);
nb_clusters = size_to_clusters(s, size);
refcount_table = qemu_mallocz(nb_clusters * sizeof(uint16_t));
/* header */
errors += inc_refcounts(bs, refcount_table, nb_clusters,
0, s->cluster_size);
/* current L1 table */
ret = check_refcounts_l1(bs, refcount_table, nb_clusters,
s->l1_table_offset, s->l1_size, 1);
if (ret < 0) {
return ret;
}
errors += ret;
/* snapshots */
for(i = 0; i < s->nb_snapshots; i++) {
sn = s->snapshots + i;
check_refcounts_l1(bs, refcount_table, nb_clusters,
sn->l1_table_offset, sn->l1_size, 0);
}
errors += inc_refcounts(bs, refcount_table, nb_clusters,
s->snapshots_offset, s->snapshots_size);
/* refcount data */
errors += inc_refcounts(bs, refcount_table, nb_clusters,
s->refcount_table_offset,
s->refcount_table_size * sizeof(uint64_t));
for(i = 0; i < s->refcount_table_size; i++) {
int64_t offset;
offset = s->refcount_table[i];
if (offset != 0) {
errors += inc_refcounts(bs, refcount_table, nb_clusters,
offset, s->cluster_size);
}
}
/* compare ref counts */
for(i = 0; i < nb_clusters; i++) {
refcount1 = get_refcount(bs, i);
refcount2 = refcount_table[i];
if (refcount1 != refcount2) {
fprintf(stderr, "ERROR cluster %d refcount=%d reference=%d\n",
i, refcount1, refcount2);
errors++;
}
}
qemu_free(refcount_table);
return errors;
}

View File

@@ -1,405 +0,0 @@
/*
* Block driver for the QCOW version 2 format
*
* Copyright (c) 2004-2006 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "qemu-common.h"
#include "block_int.h"
#include "block/qcow2.h"
typedef struct __attribute__((packed)) QCowSnapshotHeader {
/* header is 8 byte aligned */
uint64_t l1_table_offset;
uint32_t l1_size;
uint16_t id_str_size;
uint16_t name_size;
uint32_t date_sec;
uint32_t date_nsec;
uint64_t vm_clock_nsec;
uint32_t vm_state_size;
uint32_t extra_data_size; /* for extension */
/* extra data follows */
/* id_str follows */
/* name follows */
} QCowSnapshotHeader;
void qcow2_free_snapshots(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
int i;
for(i = 0; i < s->nb_snapshots; i++) {
qemu_free(s->snapshots[i].name);
qemu_free(s->snapshots[i].id_str);
}
qemu_free(s->snapshots);
s->snapshots = NULL;
s->nb_snapshots = 0;
}
int qcow2_read_snapshots(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
QCowSnapshotHeader h;
QCowSnapshot *sn;
int i, id_str_size, name_size;
int64_t offset;
uint32_t extra_data_size;
if (!s->nb_snapshots) {
s->snapshots = NULL;
s->snapshots_size = 0;
return 0;
}
offset = s->snapshots_offset;
s->snapshots = qemu_mallocz(s->nb_snapshots * sizeof(QCowSnapshot));
for(i = 0; i < s->nb_snapshots; i++) {
offset = align_offset(offset, 8);
if (bdrv_pread(s->hd, offset, &h, sizeof(h)) != sizeof(h))
goto fail;
offset += sizeof(h);
sn = s->snapshots + i;
sn->l1_table_offset = be64_to_cpu(h.l1_table_offset);
sn->l1_size = be32_to_cpu(h.l1_size);
sn->vm_state_size = be32_to_cpu(h.vm_state_size);
sn->date_sec = be32_to_cpu(h.date_sec);
sn->date_nsec = be32_to_cpu(h.date_nsec);
sn->vm_clock_nsec = be64_to_cpu(h.vm_clock_nsec);
extra_data_size = be32_to_cpu(h.extra_data_size);
id_str_size = be16_to_cpu(h.id_str_size);
name_size = be16_to_cpu(h.name_size);
offset += extra_data_size;
sn->id_str = qemu_malloc(id_str_size + 1);
if (bdrv_pread(s->hd, offset, sn->id_str, id_str_size) != id_str_size)
goto fail;
offset += id_str_size;
sn->id_str[id_str_size] = '\0';
sn->name = qemu_malloc(name_size + 1);
if (bdrv_pread(s->hd, offset, sn->name, name_size) != name_size)
goto fail;
offset += name_size;
sn->name[name_size] = '\0';
}
s->snapshots_size = offset - s->snapshots_offset;
return 0;
fail:
qcow2_free_snapshots(bs);
return -1;
}
/* add at the end of the file a new list of snapshots */
static int qcow_write_snapshots(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
QCowSnapshot *sn;
QCowSnapshotHeader h;
int i, name_size, id_str_size, snapshots_size;
uint64_t data64;
uint32_t data32;
int64_t offset, snapshots_offset;
/* compute the size of the snapshots */
offset = 0;
for(i = 0; i < s->nb_snapshots; i++) {
sn = s->snapshots + i;
offset = align_offset(offset, 8);
offset += sizeof(h);
offset += strlen(sn->id_str);
offset += strlen(sn->name);
}
snapshots_size = offset;
snapshots_offset = qcow2_alloc_clusters(bs, snapshots_size);
offset = snapshots_offset;
for(i = 0; i < s->nb_snapshots; i++) {
sn = s->snapshots + i;
memset(&h, 0, sizeof(h));
h.l1_table_offset = cpu_to_be64(sn->l1_table_offset);
h.l1_size = cpu_to_be32(sn->l1_size);
h.vm_state_size = cpu_to_be32(sn->vm_state_size);
h.date_sec = cpu_to_be32(sn->date_sec);
h.date_nsec = cpu_to_be32(sn->date_nsec);
h.vm_clock_nsec = cpu_to_be64(sn->vm_clock_nsec);
id_str_size = strlen(sn->id_str);
name_size = strlen(sn->name);
h.id_str_size = cpu_to_be16(id_str_size);
h.name_size = cpu_to_be16(name_size);
offset = align_offset(offset, 8);
if (bdrv_pwrite(s->hd, offset, &h, sizeof(h)) != sizeof(h))
goto fail;
offset += sizeof(h);
if (bdrv_pwrite(s->hd, offset, sn->id_str, id_str_size) != id_str_size)
goto fail;
offset += id_str_size;
if (bdrv_pwrite(s->hd, offset, sn->name, name_size) != name_size)
goto fail;
offset += name_size;
}
/* update the various header fields */
data64 = cpu_to_be64(snapshots_offset);
if (bdrv_pwrite(s->hd, offsetof(QCowHeader, snapshots_offset),
&data64, sizeof(data64)) != sizeof(data64))
goto fail;
data32 = cpu_to_be32(s->nb_snapshots);
if (bdrv_pwrite(s->hd, offsetof(QCowHeader, nb_snapshots),
&data32, sizeof(data32)) != sizeof(data32))
goto fail;
/* free the old snapshot table */
qcow2_free_clusters(bs, s->snapshots_offset, s->snapshots_size);
s->snapshots_offset = snapshots_offset;
s->snapshots_size = snapshots_size;
return 0;
fail:
return -1;
}
static void find_new_snapshot_id(BlockDriverState *bs,
char *id_str, int id_str_size)
{
BDRVQcowState *s = bs->opaque;
QCowSnapshot *sn;
int i, id, id_max = 0;
for(i = 0; i < s->nb_snapshots; i++) {
sn = s->snapshots + i;
id = strtoul(sn->id_str, NULL, 10);
if (id > id_max)
id_max = id;
}
snprintf(id_str, id_str_size, "%d", id_max + 1);
}
static int find_snapshot_by_id(BlockDriverState *bs, const char *id_str)
{
BDRVQcowState *s = bs->opaque;
int i;
for(i = 0; i < s->nb_snapshots; i++) {
if (!strcmp(s->snapshots[i].id_str, id_str))
return i;
}
return -1;
}
static int find_snapshot_by_id_or_name(BlockDriverState *bs, const char *name)
{
BDRVQcowState *s = bs->opaque;
int i, ret;
ret = find_snapshot_by_id(bs, name);
if (ret >= 0)
return ret;
for(i = 0; i < s->nb_snapshots; i++) {
if (!strcmp(s->snapshots[i].name, name))
return i;
}
return -1;
}
/* if no id is provided, a new one is constructed */
int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
{
BDRVQcowState *s = bs->opaque;
QCowSnapshot *snapshots1, sn1, *sn = &sn1;
int i, ret;
uint64_t *l1_table = NULL;
memset(sn, 0, sizeof(*sn));
if (sn_info->id_str[0] == '\0') {
/* compute a new id */
find_new_snapshot_id(bs, sn_info->id_str, sizeof(sn_info->id_str));
}
/* check that the ID is unique */
if (find_snapshot_by_id(bs, sn_info->id_str) >= 0)
return -ENOENT;
sn->id_str = qemu_strdup(sn_info->id_str);
if (!sn->id_str)
goto fail;
sn->name = qemu_strdup(sn_info->name);
if (!sn->name)
goto fail;
sn->vm_state_size = sn_info->vm_state_size;
sn->date_sec = sn_info->date_sec;
sn->date_nsec = sn_info->date_nsec;
sn->vm_clock_nsec = sn_info->vm_clock_nsec;
ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 1);
if (ret < 0)
goto fail;
/* create the L1 table of the snapshot */
sn->l1_table_offset = qcow2_alloc_clusters(bs, s->l1_size * sizeof(uint64_t));
sn->l1_size = s->l1_size;
l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));
for(i = 0; i < s->l1_size; i++) {
l1_table[i] = cpu_to_be64(s->l1_table[i]);
}
if (bdrv_pwrite(s->hd, sn->l1_table_offset,
l1_table, s->l1_size * sizeof(uint64_t)) !=
(s->l1_size * sizeof(uint64_t)))
goto fail;
qemu_free(l1_table);
l1_table = NULL;
snapshots1 = qemu_malloc((s->nb_snapshots + 1) * sizeof(QCowSnapshot));
if (s->snapshots) {
memcpy(snapshots1, s->snapshots, s->nb_snapshots * sizeof(QCowSnapshot));
qemu_free(s->snapshots);
}
s->snapshots = snapshots1;
s->snapshots[s->nb_snapshots++] = *sn;
if (qcow_write_snapshots(bs) < 0)
goto fail;
#ifdef DEBUG_ALLOC
qcow2_check_refcounts(bs);
#endif
return 0;
fail:
qemu_free(sn->name);
qemu_free(l1_table);
return -1;
}
/* copy the snapshot 'snapshot_name' into the current disk image */
int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
{
BDRVQcowState *s = bs->opaque;
QCowSnapshot *sn;
int i, snapshot_index, l1_size2;
snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id);
if (snapshot_index < 0)
return -ENOENT;
sn = &s->snapshots[snapshot_index];
if (qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, -1) < 0)
goto fail;
if (qcow2_grow_l1_table(bs, sn->l1_size) < 0)
goto fail;
s->l1_size = sn->l1_size;
l1_size2 = s->l1_size * sizeof(uint64_t);
/* copy the snapshot l1 table to the current l1 table */
if (bdrv_pread(s->hd, sn->l1_table_offset,
s->l1_table, l1_size2) != l1_size2)
goto fail;
if (bdrv_pwrite(s->hd, s->l1_table_offset,
s->l1_table, l1_size2) != l1_size2)
goto fail;
for(i = 0;i < s->l1_size; i++) {
be64_to_cpus(&s->l1_table[i]);
}
if (qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 1) < 0)
goto fail;
#ifdef DEBUG_ALLOC
qcow2_check_refcounts(bs);
#endif
return 0;
fail:
return -EIO;
}
int qcow2_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
{
BDRVQcowState *s = bs->opaque;
QCowSnapshot *sn;
int snapshot_index, ret;
snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id);
if (snapshot_index < 0)
return -ENOENT;
sn = &s->snapshots[snapshot_index];
ret = qcow2_update_snapshot_refcount(bs, sn->l1_table_offset, sn->l1_size, -1);
if (ret < 0)
return ret;
/* must update the copied flag on the current cluster offsets */
ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 0);
if (ret < 0)
return ret;
qcow2_free_clusters(bs, sn->l1_table_offset, sn->l1_size * sizeof(uint64_t));
qemu_free(sn->id_str);
qemu_free(sn->name);
memmove(sn, sn + 1, (s->nb_snapshots - snapshot_index - 1) * sizeof(*sn));
s->nb_snapshots--;
ret = qcow_write_snapshots(bs);
if (ret < 0) {
/* XXX: restore snapshot if error ? */
return ret;
}
#ifdef DEBUG_ALLOC
qcow2_check_refcounts(bs);
#endif
return 0;
}
int qcow2_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
{
BDRVQcowState *s = bs->opaque;
QEMUSnapshotInfo *sn_tab, *sn_info;
QCowSnapshot *sn;
int i;
if (!s->nb_snapshots) {
*psn_tab = NULL;
return s->nb_snapshots;
}
sn_tab = qemu_mallocz(s->nb_snapshots * sizeof(QEMUSnapshotInfo));
for(i = 0; i < s->nb_snapshots; i++) {
sn_info = sn_tab + i;
sn = s->snapshots + i;
pstrcpy(sn_info->id_str, sizeof(sn_info->id_str),
sn->id_str);
pstrcpy(sn_info->name, sizeof(sn_info->name),
sn->name);
sn_info->vm_state_size = sn->vm_state_size;
sn_info->date_sec = sn->date_sec;
sn_info->date_nsec = sn->date_nsec;
sn_info->vm_clock_nsec = sn->vm_clock_nsec;
}
*psn_tab = sn_tab;
return s->nb_snapshots;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,207 +0,0 @@
/*
* Block driver for the QCOW version 2 format
*
* Copyright (c) 2004-2006 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef BLOCK_QCOW2_H
#define BLOCK_QCOW2_H
#include "aes.h"
//#define DEBUG_ALLOC
//#define DEBUG_ALLOC2
//#define DEBUG_EXT
#define QCOW_MAGIC (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb)
#define QCOW_VERSION 2
#define QCOW_CRYPT_NONE 0
#define QCOW_CRYPT_AES 1
#define QCOW_MAX_CRYPT_CLUSTERS 32
/* indicate that the refcount of the referenced cluster is exactly one. */
#define QCOW_OFLAG_COPIED (1LL << 63)
/* indicate that the cluster is compressed (they never have the copied flag) */
#define QCOW_OFLAG_COMPRESSED (1LL << 62)
#define REFCOUNT_SHIFT 1 /* refcount size is 2 bytes */
#define MIN_CLUSTER_BITS 9
#define MAX_CLUSTER_BITS 16
#define L2_CACHE_SIZE 16
typedef struct QCowHeader {
uint32_t magic;
uint32_t version;
uint64_t backing_file_offset;
uint32_t backing_file_size;
uint32_t cluster_bits;
uint64_t size; /* in bytes */
uint32_t crypt_method;
uint32_t l1_size; /* XXX: save number of clusters instead ? */
uint64_t l1_table_offset;
uint64_t refcount_table_offset;
uint32_t refcount_table_clusters;
uint32_t nb_snapshots;
uint64_t snapshots_offset;
} QCowHeader;
typedef struct QCowSnapshot {
uint64_t l1_table_offset;
uint32_t l1_size;
char *id_str;
char *name;
uint32_t vm_state_size;
uint32_t date_sec;
uint32_t date_nsec;
uint64_t vm_clock_nsec;
} QCowSnapshot;
typedef struct BDRVQcowState {
BlockDriverState *hd;
int cluster_bits;
int cluster_size;
int cluster_sectors;
int l2_bits;
int l2_size;
int l1_size;
int l1_vm_state_index;
int csize_shift;
int csize_mask;
uint64_t cluster_offset_mask;
uint64_t l1_table_offset;
uint64_t *l1_table;
uint64_t *l2_cache;
uint64_t l2_cache_offsets[L2_CACHE_SIZE];
uint32_t l2_cache_counts[L2_CACHE_SIZE];
uint8_t *cluster_cache;
uint8_t *cluster_data;
uint64_t cluster_cache_offset;
uint64_t *refcount_table;
uint64_t refcount_table_offset;
uint32_t refcount_table_size;
uint64_t refcount_block_cache_offset;
uint16_t *refcount_block_cache;
int64_t free_cluster_index;
int64_t free_byte_offset;
uint32_t crypt_method; /* current crypt method, 0 if no key yet */
uint32_t crypt_method_header;
AES_KEY aes_encrypt_key;
AES_KEY aes_decrypt_key;
uint64_t snapshots_offset;
int snapshots_size;
int nb_snapshots;
QCowSnapshot *snapshots;
} BDRVQcowState;
/* XXX: use std qcow open function ? */
typedef struct QCowCreateState {
int cluster_size;
int cluster_bits;
uint16_t *refcount_block;
uint64_t *refcount_table;
int64_t l1_table_offset;
int64_t refcount_table_offset;
int64_t refcount_block_offset;
} QCowCreateState;
/* XXX This could be private for qcow2-cluster.c */
typedef struct QCowL2Meta
{
uint64_t offset;
int n_start;
int nb_available;
int nb_clusters;
} QCowL2Meta;
static inline int size_to_clusters(BDRVQcowState *s, int64_t size)
{
return (size + (s->cluster_size - 1)) >> s->cluster_bits;
}
static inline int64_t align_offset(int64_t offset, int n)
{
offset = (offset + n - 1) & ~(n - 1);
return offset;
}
// FIXME Need qcow2_ prefix to global functions
/* qcow2.c functions */
int qcow2_backing_read1(BlockDriverState *bs,
int64_t sector_num, uint8_t *buf, int nb_sectors);
/* qcow2-refcount.c functions */
int qcow2_refcount_init(BlockDriverState *bs);
void qcow2_refcount_close(BlockDriverState *bs);
int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size);
int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size);
void qcow2_free_clusters(BlockDriverState *bs,
int64_t offset, int64_t size);
void qcow2_free_any_clusters(BlockDriverState *bs,
uint64_t cluster_offset, int nb_clusters);
void qcow2_create_refcount_update(QCowCreateState *s, int64_t offset,
int64_t size);
int qcow2_update_snapshot_refcount(BlockDriverState *bs,
int64_t l1_table_offset, int l1_size, int addend);
int qcow2_check_refcounts(BlockDriverState *bs);
/* qcow2-cluster.c functions */
int qcow2_grow_l1_table(BlockDriverState *bs, int min_size);
void qcow2_l2_cache_reset(BlockDriverState *bs);
int qcow2_decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset);
void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
uint8_t *out_buf, const uint8_t *in_buf,
int nb_sectors, int enc,
const AES_KEY *key);
uint64_t qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
int *num);
uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs,
uint64_t offset,
int n_start, int n_end,
int *num, QCowL2Meta *m);
uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
uint64_t offset,
int compressed_size);
int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, uint64_t cluster_offset,
QCowL2Meta *m);
/* qcow2-snapshot.c functions */
int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info);
int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id);
int qcow2_snapshot_delete(BlockDriverState *bs, const char *snapshot_id);
int qcow2_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab);
void qcow2_free_snapshots(BlockDriverState *bs);
int qcow2_read_snapshots(BlockDriverState *bs);
#endif

View File

@@ -25,19 +25,11 @@
#define BLOCK_INT_H
#include "block.h"
#include "qemu-option.h"
#define BLOCK_FLAG_ENCRYPT 1
#define BLOCK_FLAG_COMPRESS 2
#define BLOCK_FLAG_COMPAT6 4
#define BLOCK_OPT_SIZE "size"
#define BLOCK_OPT_ENCRYPT "encryption"
#define BLOCK_OPT_COMPAT6 "compat6"
#define BLOCK_OPT_BACKING_FILE "backing_file"
#define BLOCK_OPT_BACKING_FMT "backing_fmt"
#define BLOCK_OPT_CLUSTER_SIZE "cluster_size"
typedef struct AIOPool {
void (*cancel)(BlockDriverAIOCB *acb);
int aiocb_size;
@@ -48,28 +40,34 @@ struct BlockDriver {
const char *format_name;
int instance_size;
int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
int (*bdrv_probe_device)(const char *filename);
int (*bdrv_open)(BlockDriverState *bs, const char *filename, int flags);
int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors);
int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);
void (*bdrv_close)(BlockDriverState *bs);
int (*bdrv_create)(const char *filename, QEMUOptionParameter *options);
int (*bdrv_create)(const char *filename, int64_t total_sectors,
const char *backing_file, int flags);
void (*bdrv_flush)(BlockDriverState *bs);
int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum);
int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
int (*bdrv_make_empty)(BlockDriverState *bs);
/* aio */
BlockDriverAIOCB *(*bdrv_aio_readv)(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverAIOCB *(*bdrv_aio_read)(BlockDriverState *bs,
int64_t sector_num, uint8_t *buf, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);
BlockDriverAIOCB *(*bdrv_aio_writev)(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverAIOCB *(*bdrv_aio_write)(BlockDriverState *bs,
int64_t sector_num, const uint8_t *buf, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);
void (*bdrv_aio_cancel)(BlockDriverAIOCB *acb);
int aiocb_size;
const char *protocol_name;
int (*bdrv_pread)(BlockDriverState *bs, int64_t offset,
uint8_t *buf, int count);
int (*bdrv_pwrite)(BlockDriverState *bs, int64_t offset,
const uint8_t *buf, int count);
int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset);
int64_t (*bdrv_getlength)(BlockDriverState *bs);
int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num,
@@ -84,10 +82,10 @@ struct BlockDriver {
QEMUSnapshotInfo **psn_info);
int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
int (*bdrv_save_vmstate)(BlockDriverState *bs, const uint8_t *buf,
int64_t pos, int size);
int (*bdrv_load_vmstate)(BlockDriverState *bs, uint8_t *buf,
int64_t pos, int size);
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);
@@ -97,17 +95,8 @@ struct BlockDriver {
/* to control generic scsi devices */
int (*bdrv_ioctl)(BlockDriverState *bs, unsigned long int req, void *buf);
BlockDriverAIOCB *(*bdrv_aio_ioctl)(BlockDriverState *bs,
unsigned long int req, void *buf,
BlockDriverCompletionFunc *cb, void *opaque);
/* List of options for creating images, terminated by name == NULL */
QEMUOptionParameter *create_options;
/* Returns number of errors in image, -errno for internal errors */
int (*bdrv_check)(BlockDriverState* bs);
AIOPool aio_pool;
struct BlockDriver *next;
};
@@ -130,7 +119,6 @@ struct BlockDriverState {
char filename[1024];
char backing_file[1024]; /* if non zero, the image is a diff of
this file image */
char backing_format[16]; /* if non-zero and backing_file exists */
int is_temporary;
int media_changed;
@@ -148,9 +136,6 @@ struct BlockDriverState {
/* Whether the disk can expand beyond total_sectors */
int growable;
/* the memory alignment required for the buffers handled by this driver */
int buffer_alignment;
/* NOTE: the following infos are only hints for real hardware
drivers. They are not used by the block driver */
int cyls, heads, secs, translation;
@@ -170,16 +155,15 @@ struct BlockDriverAIOCB {
void get_tmp_filename(char *filename, int size);
void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs,
BlockDriverCompletionFunc *cb, void *opaque);
void qemu_aio_release(void *p);
void aio_pool_init(AIOPool *pool, int aiocb_size,
void (*cancel)(BlockDriverAIOCB *acb));
void *qemu_blockalign(BlockDriverState *bs, size_t size);
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;
#ifdef _WIN32
int is_windows_drive(const char *filename);
#endif
#endif /* BLOCK_INT_H */

View File

@@ -10,7 +10,7 @@
#include "qemu.h"
#define TARGET_NGROUPS 32
#define NGROUPS 32
/* ??? This should really be somewhere else. */
abi_long memcpy_to_target(abi_ulong dest, const void *src,
@@ -31,9 +31,9 @@ static int in_group_p(gid_t g)
/* return TRUE if we're in the specified group, FALSE otherwise */
int ngroup;
int i;
gid_t grouplist[TARGET_NGROUPS];
gid_t grouplist[NGROUPS];
ngroup = getgroups(TARGET_NGROUPS, grouplist);
ngroup = getgroups(NGROUPS, grouplist);
for(i = 0; i < ngroup; i++) {
if(grouplist[i] == g) {
return 1;
@@ -163,7 +163,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
bprm.p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
bprm.page[i] = NULL;
bprm.page[i] = 0;
retval = open(filename, O_RDONLY);
if (retval < 0)
return retval;

View File

@@ -545,6 +545,8 @@ static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
memcpy(to, from, n);
}
extern unsigned long x86_stack_size;
static int load_aout_interp(void * exptr, int interp_fd);
#ifdef BSWAP_NEEDED
@@ -1012,7 +1014,7 @@ static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr)
key.st_value = orig_addr;
sym = bsearch(&key, syms, s->disas_num_syms, sizeof(*syms), symfind);
if (sym != NULL) {
if (sym != 0) {
return s->disas_strtab + sym->st_name;
}
@@ -1293,7 +1295,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
}
if (interp_elf_ex.e_ident[0] != 0x7f ||
strncmp((char *)&interp_elf_ex.e_ident[1], "ELF",3) != 0) {
strncmp(&interp_elf_ex.e_ident[1], "ELF",3) != 0) {
interpreter_type &= ~INTERPRETER_ELF;
}

View File

@@ -1,147 +0,0 @@
/* default linux values for the selectors */
#define __USER_CS (0x23)
#define __USER_DS (0x2B)
struct target_pt_regs {
long ebx;
long ecx;
long edx;
long esi;
long edi;
long ebp;
long eax;
int xds;
int xes;
long orig_eax;
long eip;
int xcs;
long eflags;
long esp;
int xss;
};
/* ioctls */
#define TARGET_LDT_ENTRIES 8192
#define TARGET_LDT_ENTRY_SIZE 8
#define TARGET_GDT_ENTRIES 9
#define TARGET_GDT_ENTRY_TLS_ENTRIES 3
#define TARGET_GDT_ENTRY_TLS_MIN 6
#define TARGET_GDT_ENTRY_TLS_MAX (TARGET_GDT_ENTRY_TLS_MIN + TARGET_GDT_ENTRY_TLS_ENTRIES - 1)
struct target_modify_ldt_ldt_s {
unsigned int entry_number;
abi_ulong base_addr;
unsigned int limit;
unsigned int flags;
};
/* vm86 defines */
#define TARGET_BIOSSEG 0x0f000
#define TARGET_CPU_086 0
#define TARGET_CPU_186 1
#define TARGET_CPU_286 2
#define TARGET_CPU_386 3
#define TARGET_CPU_486 4
#define TARGET_CPU_586 5
#define TARGET_VM86_SIGNAL 0 /* return due to signal */
#define TARGET_VM86_UNKNOWN 1 /* unhandled GP fault - IO-instruction or similar */
#define TARGET_VM86_INTx 2 /* int3/int x instruction (ARG = x) */
#define TARGET_VM86_STI 3 /* sti/popf/iret instruction enabled virtual interrupts */
/*
* Additional return values when invoking new vm86()
*/
#define TARGET_VM86_PICRETURN 4 /* return due to pending PIC request */
#define TARGET_VM86_TRAP 6 /* return due to DOS-debugger request */
/*
* function codes when invoking new vm86()
*/
#define TARGET_VM86_PLUS_INSTALL_CHECK 0
#define TARGET_VM86_ENTER 1
#define TARGET_VM86_ENTER_NO_BYPASS 2
#define TARGET_VM86_REQUEST_IRQ 3
#define TARGET_VM86_FREE_IRQ 4
#define TARGET_VM86_GET_IRQ_BITS 5
#define TARGET_VM86_GET_AND_RESET_IRQ 6
/*
* This is the stack-layout seen by the user space program when we have
* done a translation of "SAVE_ALL" from vm86 mode. The real kernel layout
* is 'kernel_vm86_regs' (see below).
*/
struct target_vm86_regs {
/*
* normal regs, with special meaning for the segment descriptors..
*/
abi_long ebx;
abi_long ecx;
abi_long edx;
abi_long esi;
abi_long edi;
abi_long ebp;
abi_long eax;
abi_long __null_ds;
abi_long __null_es;
abi_long __null_fs;
abi_long __null_gs;
abi_long orig_eax;
abi_long eip;
unsigned short cs, __csh;
abi_long eflags;
abi_long esp;
unsigned short ss, __ssh;
/*
* these are specific to v86 mode:
*/
unsigned short es, __esh;
unsigned short ds, __dsh;
unsigned short fs, __fsh;
unsigned short gs, __gsh;
};
struct target_revectored_struct {
abi_ulong __map[8]; /* 256 bits */
};
struct target_vm86_struct {
struct target_vm86_regs regs;
abi_ulong flags;
abi_ulong screen_bitmap;
abi_ulong cpu_type;
struct target_revectored_struct int_revectored;
struct target_revectored_struct int21_revectored;
};
/*
* flags masks
*/
#define TARGET_VM86_SCREEN_BITMAP 0x0001
struct target_vm86plus_info_struct {
abi_ulong flags;
#define TARGET_force_return_for_pic (1 << 0)
#define TARGET_vm86dbg_active (1 << 1) /* for debugger */
#define TARGET_vm86dbg_TFpendig (1 << 2) /* for debugger */
#define TARGET_is_vm86pus (1 << 31) /* for vm86 internal use */
unsigned char vm86dbg_intxxtab[32]; /* for debugger */
};
struct target_vm86plus_struct {
struct target_vm86_regs regs;
abi_ulong flags;
abi_ulong screen_bitmap;
abi_ulong cpu_type;
struct target_revectored_struct int_revectored;
struct target_revectored_struct int21_revectored;
struct target_vm86plus_info_struct vm86plus;
};
#define UNAME_MACHINE "i386"

View File

@@ -1,20 +0,0 @@
#ifndef TARGET_SIGNAL_H
#define TARGET_SIGNAL_H
#include "cpu.h"
/* this struct defines a stack used during syscall handling */
typedef struct target_sigaltstack {
abi_ulong ss_sp;
abi_long ss_flags;
abi_ulong ss_size;
} target_stack_t;
static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
{
return state->regs[R_ESP];
}
#endif /* TARGET_SIGNAL_H */

View File

@@ -14,7 +14,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <stdlib.h>
#include <stdio.h>
@@ -23,8 +25,6 @@
#include <errno.h>
#include <unistd.h>
#include <machine/trap.h>
#include <sys/types.h>
#include <sys/mman.h>
#include "qemu.h"
#include "qemu-common.h"
@@ -33,8 +33,6 @@
#define DEBUG_LOGFILE "/tmp/qemu.log"
int singlestep;
static const char *interp_prefix = CONFIG_QEMU_PREFIX;
const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
extern char **environ;
@@ -52,270 +50,6 @@ void gemu_log(const char *fmt, ...)
vfprintf(stderr, fmt, ap);
va_end(ap);
}
#if defined(TARGET_I386)
int cpu_get_pic_interrupt(CPUState *env)
{
return -1;
}
#endif
/* These are no-ops because we are not threadsafe. */
static inline void cpu_exec_start(CPUState *env)
{
}
static inline void cpu_exec_end(CPUState *env)
{
}
static inline void start_exclusive(void)
{
}
static inline void end_exclusive(void)
{
}
void fork_start(void)
{
}
void fork_end(int child)
{
if (child) {
gdbserver_fork(thread_env);
}
}
void cpu_list_lock(void)
{
}
void cpu_list_unlock(void)
{
}
#ifdef TARGET_I386
/***********************************************************/
/* CPUX86 core interface */
void cpu_smm_update(CPUState *env)
{
}
uint64_t cpu_get_tsc(CPUX86State *env)
{
return cpu_get_real_ticks();
}
static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
int flags)
{
unsigned int e1, e2;
uint32_t *p;
e1 = (addr << 16) | (limit & 0xffff);
e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
e2 |= flags;
p = ptr;
p[0] = tswap32(e1);
p[1] = tswap32(e2);
}
static uint64_t *idt_table;
#ifdef TARGET_X86_64
static void set_gate64(void *ptr, unsigned int type, unsigned int dpl,
uint64_t addr, unsigned int sel)
{
uint32_t *p, e1, e2;
e1 = (addr & 0xffff) | (sel << 16);
e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
p = ptr;
p[0] = tswap32(e1);
p[1] = tswap32(e2);
p[2] = tswap32(addr >> 32);
p[3] = 0;
}
/* only dpl matters as we do only user space emulation */
static void set_idt(int n, unsigned int dpl)
{
set_gate64(idt_table + n * 2, 0, dpl, 0, 0);
}
#else
static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
uint32_t addr, unsigned int sel)
{
uint32_t *p, e1, e2;
e1 = (addr & 0xffff) | (sel << 16);
e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
p = ptr;
p[0] = tswap32(e1);
p[1] = tswap32(e2);
}
/* only dpl matters as we do only user space emulation */
static void set_idt(int n, unsigned int dpl)
{
set_gate(idt_table + n, 0, dpl, 0, 0);
}
#endif
void cpu_loop(CPUX86State *env, enum BSDType bsd_type)
{
int trapnr;
abi_ulong pc;
//target_siginfo_t info;
for(;;) {
trapnr = cpu_x86_exec(env);
switch(trapnr) {
case 0x80:
/* syscall from int $0x80 */
env->regs[R_EAX] = do_openbsd_syscall(env,
env->regs[R_EAX],
env->regs[R_EBX],
env->regs[R_ECX],
env->regs[R_EDX],
env->regs[R_ESI],
env->regs[R_EDI],
env->regs[R_EBP]);
break;
#ifndef TARGET_ABI32
case EXCP_SYSCALL:
/* linux syscall from syscall intruction */
env->regs[R_EAX] = do_openbsd_syscall(env,
env->regs[R_EAX],
env->regs[R_EDI],
env->regs[R_ESI],
env->regs[R_EDX],
env->regs[10],
env->regs[8],
env->regs[9]);
env->eip = env->exception_next_eip;
break;
#endif
#if 0
case EXCP0B_NOSEG:
case EXCP0C_STACK:
info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = TARGET_SI_KERNEL;
info._sifields._sigfault._addr = 0;
queue_signal(env, info.si_signo, &info);
break;
case EXCP0D_GPF:
/* XXX: potential problem if ABI32 */
#ifndef TARGET_X86_64
if (env->eflags & VM_MASK) {
handle_vm86_fault(env);
} else
#endif
{
info.si_signo = SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SI_KERNEL;
info._sifields._sigfault._addr = 0;
queue_signal(env, info.si_signo, &info);
}
break;
case EXCP0E_PAGE:
info.si_signo = SIGSEGV;
info.si_errno = 0;
if (!(env->error_code & 1))
info.si_code = TARGET_SEGV_MAPERR;
else
info.si_code = TARGET_SEGV_ACCERR;
info._sifields._sigfault._addr = env->cr[2];
queue_signal(env, info.si_signo, &info);
break;
case EXCP00_DIVZ:
#ifndef TARGET_X86_64
if (env->eflags & VM_MASK) {
handle_vm86_trap(env, trapnr);
} else
#endif
{
/* division by zero */
info.si_signo = SIGFPE;
info.si_errno = 0;
info.si_code = TARGET_FPE_INTDIV;
info._sifields._sigfault._addr = env->eip;
queue_signal(env, info.si_signo, &info);
}
break;
case EXCP01_DB:
case EXCP03_INT3:
#ifndef TARGET_X86_64
if (env->eflags & VM_MASK) {
handle_vm86_trap(env, trapnr);
} else
#endif
{
info.si_signo = SIGTRAP;
info.si_errno = 0;
if (trapnr == EXCP01_DB) {
info.si_code = TARGET_TRAP_BRKPT;
info._sifields._sigfault._addr = env->eip;
} else {
info.si_code = TARGET_SI_KERNEL;
info._sifields._sigfault._addr = 0;
}
queue_signal(env, info.si_signo, &info);
}
break;
case EXCP04_INTO:
case EXCP05_BOUND:
#ifndef TARGET_X86_64
if (env->eflags & VM_MASK) {
handle_vm86_trap(env, trapnr);
} else
#endif
{
info.si_signo = SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SI_KERNEL;
info._sifields._sigfault._addr = 0;
queue_signal(env, info.si_signo, &info);
}
break;
case EXCP06_ILLOP:
info.si_signo = SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPN;
info._sifields._sigfault._addr = env->eip;
queue_signal(env, info.si_signo, &info);
break;
#endif
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
#if 0
case EXCP_DEBUG:
{
int sig;
sig = gdb_handlesig (env, TARGET_SIGTRAP);
if (sig)
{
info.si_signo = sig;
info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, &info);
}
}
break;
#endif
default:
pc = env->segs[R_CS].base + env->eip;
fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
(long)pc, trapnr);
abort();
}
process_pending_signals(env);
}
}
#endif
#ifdef TARGET_SPARC
#define SPARC64_STACK_BIAS 2047
@@ -607,7 +341,6 @@ static void usage(void)
"Debug options:\n"
"-d options activate log (logfile=%s)\n"
"-p pagesize set the host page size to 'pagesize'\n"
"-singlestep always run in singlestep mode\n"
"-strace log system calls\n"
"\n"
"Environment variables:\n"
@@ -730,8 +463,6 @@ int main(int argc, char **argv)
usage();
}
optind++;
} else if (!strcmp(r, "singlestep")) {
singlestep = 1;
} else if (!strcmp(r, "strace")) {
do_strace = 1;
} else
@@ -753,13 +484,7 @@ int main(int argc, char **argv)
init_paths(interp_prefix);
if (cpu_model == NULL) {
#if defined(TARGET_I386)
#ifdef TARGET_X86_64
cpu_model = "qemu64";
#else
cpu_model = "qemu32";
#endif
#elif defined(TARGET_SPARC)
#if defined(TARGET_SPARC)
#ifdef TARGET_SPARC64
cpu_model = "TI UltraSparc II";
#else
@@ -834,124 +559,7 @@ int main(int argc, char **argv)
ts->info = info;
env->opaque = ts;
#if defined(TARGET_I386)
cpu_x86_set_cpl(env, 3);
env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
env->hflags |= HF_PE_MASK;
if (env->cpuid_features & CPUID_SSE) {
env->cr[4] |= CR4_OSFXSR_MASK;
env->hflags |= HF_OSFXSR_MASK;
}
#ifndef TARGET_ABI32
/* enable 64 bit mode if possible */
if (!(env->cpuid_ext2_features & CPUID_EXT2_LM)) {
fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
exit(1);
}
env->cr[4] |= CR4_PAE_MASK;
env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
env->hflags |= HF_LMA_MASK;
#endif
/* flags setup : we activate the IRQs by default as in user mode */
env->eflags |= IF_MASK;
/* linux register setup */
#ifndef TARGET_ABI32
env->regs[R_EAX] = regs->rax;
env->regs[R_EBX] = regs->rbx;
env->regs[R_ECX] = regs->rcx;
env->regs[R_EDX] = regs->rdx;
env->regs[R_ESI] = regs->rsi;
env->regs[R_EDI] = regs->rdi;
env->regs[R_EBP] = regs->rbp;
env->regs[R_ESP] = regs->rsp;
env->eip = regs->rip;
#else
env->regs[R_EAX] = regs->eax;
env->regs[R_EBX] = regs->ebx;
env->regs[R_ECX] = regs->ecx;
env->regs[R_EDX] = regs->edx;
env->regs[R_ESI] = regs->esi;
env->regs[R_EDI] = regs->edi;
env->regs[R_EBP] = regs->ebp;
env->regs[R_ESP] = regs->esp;
env->eip = regs->eip;
#endif
/* linux interrupt setup */
#ifndef TARGET_ABI32
env->idt.limit = 511;
#else
env->idt.limit = 255;
#endif
env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
PROT_READ|PROT_WRITE,
MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
idt_table = g2h(env->idt.base);
set_idt(0, 0);
set_idt(1, 0);
set_idt(2, 0);
set_idt(3, 3);
set_idt(4, 3);
set_idt(5, 0);
set_idt(6, 0);
set_idt(7, 0);
set_idt(8, 0);
set_idt(9, 0);
set_idt(10, 0);
set_idt(11, 0);
set_idt(12, 0);
set_idt(13, 0);
set_idt(14, 0);
set_idt(15, 0);
set_idt(16, 0);
set_idt(17, 0);
set_idt(18, 0);
set_idt(19, 0);
set_idt(0x80, 3);
/* linux segment setup */
{
uint64_t *gdt_table;
env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
PROT_READ|PROT_WRITE,
MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
gdt_table = g2h(env->gdt.base);
#ifdef TARGET_ABI32
write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
(3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
#else
/* 64 bit code segment */
write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
DESC_L_MASK |
(3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
#endif
write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
(3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
}
cpu_x86_load_seg(env, R_CS, __USER_CS);
cpu_x86_load_seg(env, R_SS, __USER_DS);
#ifdef TARGET_ABI32
cpu_x86_load_seg(env, R_DS, __USER_DS);
cpu_x86_load_seg(env, R_ES, __USER_DS);
cpu_x86_load_seg(env, R_FS, __USER_DS);
cpu_x86_load_seg(env, R_GS, __USER_DS);
/* This hack makes Wine work... */
env->segs[R_FS].selector = 0;
#else
cpu_x86_load_seg(env, R_DS, 0);
cpu_x86_load_seg(env, R_ES, 0);
cpu_x86_load_seg(env, R_FS, 0);
cpu_x86_load_seg(env, R_GS, 0);
#endif
#elif defined(TARGET_SPARC)
#if defined(TARGET_SPARC)
{
int i;
env->pc = regs->pc;

View File

@@ -14,7 +14,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <stdlib.h>
#include <stdio.h>

View File

@@ -186,16 +186,11 @@ int target_msync(abi_ulong start, abi_ulong len, int flags);
extern unsigned long last_brk;
void mmap_lock(void);
void mmap_unlock(void);
void cpu_list_lock(void);
void cpu_list_unlock(void);
#if defined(USE_NPTL)
void mmap_fork_start(void);
void mmap_fork_end(int child);
#endif
/* main.c */
extern unsigned long x86_stack_size;
/* user access */
#define VERIFY_READ 0

View File

@@ -14,7 +14,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <stdlib.h>
#include <stdio.h>

View File

@@ -14,7 +14,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <stdlib.h>
#include <stdio.h>

View File

@@ -37,6 +37,17 @@ abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len)
return ret;
}
/* XXX: use host strnlen if available ? */
static int qemu_strnlen(const char *s, int max_len)
{
int i;
for(i = 0; i < max_len; i++) {
if (s[i] == '\0')
break;
}
return i;
}
/* Return the length of a string in target memory or -TARGET_EFAULT if
access error */
abi_long target_strlen(abi_ulong guest_addr1)
@@ -51,7 +62,7 @@ abi_long target_strlen(abi_ulong guest_addr1)
ptr = lock_user(VERIFY_READ, guest_addr, max_len, 1);
if (!ptr)
return -TARGET_EFAULT;
len = qemu_strnlen((char *)ptr, max_len);
len = qemu_strnlen(ptr, max_len);
unlock_user(ptr, guest_addr, 0);
guest_addr += len;
/* we don't allow wrapping or integer overflow */

View File

@@ -1,98 +0,0 @@
#define __USER_CS (0x33)
#define __USER_DS (0x2B)
struct target_pt_regs {
abi_ulong r15;
abi_ulong r14;
abi_ulong r13;
abi_ulong r12;
abi_ulong rbp;
abi_ulong rbx;
/* arguments: non interrupts/non tracing syscalls only save upto here*/
abi_ulong r11;
abi_ulong r10;
abi_ulong r9;
abi_ulong r8;
abi_ulong rax;
abi_ulong rcx;
abi_ulong rdx;
abi_ulong rsi;
abi_ulong rdi;
abi_ulong orig_rax;
/* end of arguments */
/* cpu exception frame or undefined */
abi_ulong rip;
abi_ulong cs;
abi_ulong eflags;
abi_ulong rsp;
abi_ulong ss;
/* top of stack page */
};
/* Maximum number of LDT entries supported. */
#define TARGET_LDT_ENTRIES 8192
/* The size of each LDT entry. */
#define TARGET_LDT_ENTRY_SIZE 8
#define TARGET_GDT_ENTRIES 16
#define TARGET_GDT_ENTRY_TLS_ENTRIES 3
#define TARGET_GDT_ENTRY_TLS_MIN 12
#define TARGET_GDT_ENTRY_TLS_MAX 14
#if 0 // Redefine this
struct target_modify_ldt_ldt_s {
unsigned int entry_number;
abi_ulong base_addr;
unsigned int limit;
unsigned int seg_32bit:1;
unsigned int contents:2;
unsigned int read_exec_only:1;
unsigned int limit_in_pages:1;
unsigned int seg_not_present:1;
unsigned int useable:1;
unsigned int lm:1;
};
#else
struct target_modify_ldt_ldt_s {
unsigned int entry_number;
abi_ulong base_addr;
unsigned int limit;
unsigned int flags;
};
#endif
struct target_ipc64_perm
{
int key;
uint32_t uid;
uint32_t gid;
uint32_t cuid;
uint32_t cgid;
unsigned short mode;
unsigned short __pad1;
unsigned short seq;
unsigned short __pad2;
abi_ulong __unused1;
abi_ulong __unused2;
};
struct target_msqid64_ds {
struct target_ipc64_perm msg_perm;
unsigned int msg_stime; /* last msgsnd time */
unsigned int msg_rtime; /* last msgrcv time */
unsigned int msg_ctime; /* last change time */
abi_ulong msg_cbytes; /* current number of bytes on queue */
abi_ulong msg_qnum; /* number of messages in queue */
abi_ulong msg_qbytes; /* max number of bytes on queue */
unsigned int msg_lspid; /* pid of last msgsnd */
unsigned int msg_lrpid; /* last receive pid */
abi_ulong __unused4;
abi_ulong __unused5;
};
#define UNAME_MACHINE "x86_64"
#define TARGET_ARCH_SET_GS 0x1001
#define TARGET_ARCH_SET_FS 0x1002
#define TARGET_ARCH_GET_FS 0x1003
#define TARGET_ARCH_GET_GS 0x1004

View File

@@ -1,19 +0,0 @@
#ifndef TARGET_SIGNAL_H
#define TARGET_SIGNAL_H
#include "cpu.h"
/* this struct defines a stack used during syscall handling */
typedef struct target_sigaltstack {
abi_ulong ss_sp;
abi_long ss_flags;
abi_ulong ss_size;
} target_stack_t;
static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
{
return state->regs[R_ESP];
}
#endif /* TARGET_SIGNAL_H */

View File

@@ -151,7 +151,7 @@ static inline void cpu_to_le16wu(uint16_t *p, uint16_t v)
{
uint8_t *p1 = (uint8_t *)p;
p1[0] = v & 0xff;
p1[0] = v;
p1[1] = v >> 8;
}
@@ -159,7 +159,7 @@ static inline void cpu_to_le32wu(uint32_t *p, uint32_t v)
{
uint8_t *p1 = (uint8_t *)p;
p1[0] = v & 0xff;
p1[0] = v;
p1[1] = v >> 8;
p1[2] = v >> 16;
p1[3] = v >> 24;
@@ -188,7 +188,7 @@ static inline void cpu_to_be16wu(uint16_t *p, uint16_t v)
uint8_t *p1 = (uint8_t *)p;
p1[0] = v >> 8;
p1[1] = v & 0xff;
p1[1] = v;
}
static inline void cpu_to_be32wu(uint32_t *p, uint32_t v)
@@ -198,7 +198,7 @@ static inline void cpu_to_be32wu(uint32_t *p, uint32_t v)
p1[0] = v >> 24;
p1[1] = v >> 16;
p1[2] = v >> 8;
p1[3] = v & 0xff;
p1[3] = v;
}
#endif

View File

@@ -14,14 +14,14 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "qemu-common.h"
#include "qemu-char.h"
#include "sysemu.h"
#include "net.h"
#include "bt-host.h"
#ifndef _WIN32
# include <errno.h>
@@ -52,7 +52,7 @@ static void bt_host_send(struct HCIInfo *hci,
struct iovec iv[2];
int ret;
iv[0].iov_base = (void *)&pkt;
iv[0].iov_base = &pkt;
iv[0].iov_len = 1;
iv[1].iov_base = (void *) data;
iv[1].iov_len = len;
@@ -171,7 +171,7 @@ struct HCIInfo *bt_host_hci(const char *id)
if (fd < 0) {
fprintf(stderr, "qemu: Can't open `%s': %s (%i)\n",
id, strerror(errno), errno);
return NULL;
return 0;
}
# ifdef CONFIG_BLUEZ
@@ -192,7 +192,7 @@ struct HCIInfo *bt_host_hci(const char *id)
s->hci.acl_send = bt_host_acl;
s->hci.bdaddr_set = bt_host_bdaddr_set;
qemu_set_fd_handler2(s->fd, bt_host_read_poll, bt_host_read, NULL, s);
qemu_set_fd_handler2(s->fd, bt_host_read_poll, bt_host_read, 0, s);
return &s->hci;
}

View File

@@ -1,9 +0,0 @@
#ifndef BT_HOST_H
#define BT_HOST_H
struct HCIInfo;
/* bt-host.c */
struct HCIInfo *bt_host_hci(const char *id);
#endif

View File

@@ -14,7 +14,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "qemu-common.h"
@@ -164,5 +165,5 @@ void bt_vhci_init(struct HCIInfo *info)
s->info->evt_recv = vhci_out_hci_packet_event;
s->info->acl_recv = vhci_out_hci_packet_acl;
qemu_set_fd_handler(s->fd, vhci_read, NULL, s);
qemu_set_fd_handler(s->fd, vhci_read, 0, s);
}

View File

@@ -113,7 +113,7 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in
int offset = 0;
ssize_t ret;
dprintf("putting %d bytes at %" PRId64 "\n", size, pos);
dprintf("putting %ld bytes at %Ld\n", size, pos);
if (s->has_error) {
dprintf("flush when error, bailing\n");
@@ -151,7 +151,7 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in
}
if (offset >= 0) {
dprintf("buffering %d bytes\n", size - offset);
dprintf("buffering %ld bytes\n", size - offset);
buffered_append(s, buf + offset, size - offset);
offset = size;
}
@@ -198,19 +198,6 @@ static int buffered_rate_limit(void *opaque)
return 0;
}
static size_t buffered_set_rate_limit(void *opaque, size_t new_rate)
{
QEMUFileBuffered *s = opaque;
if (s->has_error)
goto out;
s->xfer_limit = new_rate / 10;
out:
return s->xfer_limit;
}
static void buffered_rate_tick(void *opaque)
{
QEMUFileBuffered *s = opaque;
@@ -250,8 +237,7 @@ QEMUFile *qemu_fopen_ops_buffered(void *opaque,
s->close = close;
s->file = qemu_fopen_ops(s, buffered_put_buffer, NULL,
buffered_close, buffered_rate_limit,
buffered_set_rate_limit);
buffered_close, buffered_rate_limit);
s->timer = qemu_new_timer(rt_clock, buffered_rate_tick, s);

562
cmd.c
View File

@@ -1,562 +0,0 @@
/*
* Copyright (c) 2003-2005 Silicon Graphics, Inc.
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "cmd.h"
#define _(x) x /* not gettext support yet */
extern int optind;
/* from libxcmd/command.c */
cmdinfo_t *cmdtab;
int ncmds;
static argsfunc_t args_func;
static checkfunc_t check_func;
static int ncmdline;
static char **cmdline;
static int
compare(const void *a, const void *b)
{
return strcmp(((const cmdinfo_t *)a)->name,
((const cmdinfo_t *)b)->name);
}
void
add_command(
const cmdinfo_t *ci)
{
cmdtab = realloc((void *)cmdtab, ++ncmds * sizeof(*cmdtab));
cmdtab[ncmds - 1] = *ci;
qsort(cmdtab, ncmds, sizeof(*cmdtab), compare);
}
static int
check_command(
const cmdinfo_t *ci)
{
if (check_func)
return check_func(ci);
return 1;
}
void
add_check_command(
checkfunc_t cf)
{
check_func = cf;
}
int
command_usage(
const cmdinfo_t *ci)
{
printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
return 0;
}
int
command(
const cmdinfo_t *ct,
int argc,
char **argv)
{
char *cmd = argv[0];
if (!check_command(ct))
return 0;
if (argc-1 < ct->argmin || (ct->argmax != -1 && argc-1 > ct->argmax)) {
if (ct->argmax == -1)
fprintf(stderr,
_("bad argument count %d to %s, expected at least %d arguments\n"),
argc-1, cmd, ct->argmin);
else if (ct->argmin == ct->argmax)
fprintf(stderr,
_("bad argument count %d to %s, expected %d arguments\n"),
argc-1, cmd, ct->argmin);
else
fprintf(stderr,
_("bad argument count %d to %s, expected between %d and %d arguments\n"),
argc-1, cmd, ct->argmin, ct->argmax);
return 0;
}
optind = 0;
return ct->cfunc(argc, argv);
}
const cmdinfo_t *
find_command(
const char *cmd)
{
cmdinfo_t *ct;
for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
if (strcmp(ct->name, cmd) == 0 ||
(ct->altname && strcmp(ct->altname, cmd) == 0))
return (const cmdinfo_t *)ct;
}
return NULL;
}
void
add_user_command(char *optarg)
{
ncmdline++;
cmdline = realloc(cmdline, sizeof(char*) * (ncmdline));
if (!cmdline) {
perror("realloc");
exit(1);
}
cmdline[ncmdline-1] = optarg;
}
static int
args_command(
int index)
{
if (args_func)
return args_func(index);
return 0;
}
void
add_args_command(
argsfunc_t af)
{
args_func = af;
}
void
command_loop(void)
{
int c, i, j = 0, done = 0;
char *input;
char **v;
const cmdinfo_t *ct;
for (i = 0; !done && i < ncmdline; i++) {
input = strdup(cmdline[i]);
if (!input) {
fprintf(stderr,
_("cannot strdup command '%s': %s\n"),
cmdline[i], strerror(errno));
exit(1);
}
v = breakline(input, &c);
if (c) {
ct = find_command(v[0]);
if (ct) {
if (ct->flags & CMD_FLAG_GLOBAL)
done = command(ct, c, v);
else {
j = 0;
while (!done && (j = args_command(j)))
done = command(ct, c, v);
}
} else
fprintf(stderr, _("command \"%s\" not found\n"),
v[0]);
}
doneline(input, v);
}
if (cmdline) {
free(cmdline);
return;
}
while (!done) {
if ((input = fetchline()) == NULL)
break;
v = breakline(input, &c);
if (c) {
ct = find_command(v[0]);
if (ct)
done = command(ct, c, v);
else
fprintf(stderr, _("command \"%s\" not found\n"),
v[0]);
}
doneline(input, v);
}
}
/* from libxcmd/input.c */
#if defined(ENABLE_READLINE)
# include <readline/history.h>
# include <readline/readline.h>
#elif defined(ENABLE_EDITLINE)
# include <histedit.h>
#endif
static char *
get_prompt(void)
{
static char prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ];
if (!prompt[0])
snprintf(prompt, sizeof(prompt), "%s> ", progname);
return prompt;
}
#if defined(ENABLE_READLINE)
char *
fetchline(void)
{
char *line;
line = readline(get_prompt());
if (line && *line)
add_history(line);
return line;
}
#elif defined(ENABLE_EDITLINE)
static char *el_get_prompt(EditLine *e) { return get_prompt(); }
char *
fetchline(void)
{
static EditLine *el;
static History *hist;
HistEvent hevent;
char *line;
int count;
if (!el) {
hist = history_init();
history(hist, &hevent, H_SETSIZE, 100);
el = el_init(progname, stdin, stdout, stderr);
el_source(el, NULL);
el_set(el, EL_SIGNAL, 1);
el_set(el, EL_PROMPT, el_get_prompt);
el_set(el, EL_HIST, history, (const char *)hist);
}
line = strdup(el_gets(el, &count));
if (line) {
if (count > 0)
line[count-1] = '\0';
if (*line)
history(hist, &hevent, H_ENTER, line);
}
return line;
}
#else
# define MAXREADLINESZ 1024
char *
fetchline(void)
{
char *p, *line = malloc(MAXREADLINESZ);
if (!line)
return NULL;
printf("%s", get_prompt());
fflush(stdout);
if (!fgets(line, MAXREADLINESZ, stdin)) {
free(line);
return NULL;
}
p = line + strlen(line);
if (p != line && p[-1] == '\n')
p[-1] = '\0';
return line;
}
#endif
char **
breakline(
char *input,
int *count)
{
int c = 0;
char *p;
char **rval = calloc(sizeof(char *), 1);
while (rval && (p = strsep(&input, " ")) != NULL) {
if (!*p)
continue;
c++;
rval = realloc(rval, sizeof(*rval) * (c + 1));
if (!rval) {
c = 0;
break;
}
rval[c - 1] = p;
rval[c] = NULL;
}
*count = c;
return rval;
}
void
doneline(
char *input,
char **vec)
{
free(input);
free(vec);
}
#define EXABYTES(x) ((long long)(x) << 60)
#define PETABYTES(x) ((long long)(x) << 50)
#define TERABYTES(x) ((long long)(x) << 40)
#define GIGABYTES(x) ((long long)(x) << 30)
#define MEGABYTES(x) ((long long)(x) << 20)
#define KILOBYTES(x) ((long long)(x) << 10)
long long
cvtnum(
char *s)
{
long long i;
char *sp;
int c;
i = strtoll(s, &sp, 0);
if (i == 0 && sp == s)
return -1LL;
if (*sp == '\0')
return i;
if (sp[1] != '\0')
return -1LL;
c = tolower(*sp);
switch (c) {
default:
return i;
case 'k':
return KILOBYTES(i);
case 'm':
return MEGABYTES(i);
case 'g':
return GIGABYTES(i);
case 't':
return TERABYTES(i);
case 'p':
return PETABYTES(i);
case 'e':
return EXABYTES(i);
}
return -1LL;
}
#define TO_EXABYTES(x) ((x) / EXABYTES(1))
#define TO_PETABYTES(x) ((x) / PETABYTES(1))
#define TO_TERABYTES(x) ((x) / TERABYTES(1))
#define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
#define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
#define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
void
cvtstr(
double value,
char *str,
size_t size)
{
const char *fmt;
int precise;
precise = ((double)value * 1000 == (double)(int)value * 1000);
if (value >= EXABYTES(1)) {
fmt = precise ? "%.f EiB" : "%.3f EiB";
snprintf(str, size, fmt, TO_EXABYTES(value));
} else if (value >= PETABYTES(1)) {
fmt = precise ? "%.f PiB" : "%.3f PiB";
snprintf(str, size, fmt, TO_PETABYTES(value));
} else if (value >= TERABYTES(1)) {
fmt = precise ? "%.f TiB" : "%.3f TiB";
snprintf(str, size, fmt, TO_TERABYTES(value));
} else if (value >= GIGABYTES(1)) {
fmt = precise ? "%.f GiB" : "%.3f GiB";
snprintf(str, size, fmt, TO_GIGABYTES(value));
} else if (value >= MEGABYTES(1)) {
fmt = precise ? "%.f MiB" : "%.3f MiB";
snprintf(str, size, fmt, TO_MEGABYTES(value));
} else if (value >= KILOBYTES(1)) {
fmt = precise ? "%.f KiB" : "%.3f KiB";
snprintf(str, size, fmt, TO_KILOBYTES(value));
} else {
snprintf(str, size, "%f bytes", value);
}
}
struct timeval
tsub(struct timeval t1, struct timeval t2)
{
t1.tv_usec -= t2.tv_usec;
if (t1.tv_usec < 0) {
t1.tv_usec += 1000000;
t1.tv_sec--;
}
t1.tv_sec -= t2.tv_sec;
return t1;
}
double
tdiv(double value, struct timeval tv)
{
return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
}
#define HOURS(sec) ((sec) / (60 * 60))
#define MINUTES(sec) (((sec) % (60 * 60)) / 60)
#define SECONDS(sec) ((sec) % 60)
void
timestr(
struct timeval *tv,
char *ts,
size_t size,
int format)
{
double usec = (double)tv->tv_usec / 1000000.0;
if (format & TERSE_FIXED_TIME) {
if (!HOURS(tv->tv_sec)) {
snprintf(ts, size, "%u:%02u.%02u",
(unsigned int) MINUTES(tv->tv_sec),
(unsigned int) SECONDS(tv->tv_sec),
(unsigned int) usec * 100);
return;
}
format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
}
if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
snprintf(ts, size, "%u:%02u:%02u.%02u",
(unsigned int) HOURS(tv->tv_sec),
(unsigned int) MINUTES(tv->tv_sec),
(unsigned int) SECONDS(tv->tv_sec),
(unsigned int) usec * 100);
} else {
snprintf(ts, size, "0.%04u sec", (unsigned int) usec * 10000);
}
}
/* from libxcmd/quit.c */
static cmdinfo_t quit_cmd;
/* ARGSUSED */
static int
quit_f(
int argc,
char **argv)
{
return 1;
}
void
quit_init(void)
{
quit_cmd.name = _("quit");
quit_cmd.altname = _("q");
quit_cmd.cfunc = quit_f;
quit_cmd.argmin = -1;
quit_cmd.argmax = -1;
quit_cmd.flags = CMD_FLAG_GLOBAL;
quit_cmd.oneline = _("exit the program");
add_command(&quit_cmd);
}
/* from libxcmd/help.c */
static cmdinfo_t help_cmd;
static void help_onecmd(const char *cmd, const cmdinfo_t *ct);
static void help_oneline(const char *cmd, const cmdinfo_t *ct);
static void
help_all(void)
{
const cmdinfo_t *ct;
for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++)
help_oneline(ct->name, ct);
printf(_("\nUse 'help commandname' for extended help.\n"));
}
static int
help_f(
int argc,
char **argv)
{
const cmdinfo_t *ct;
if (argc == 1) {
help_all();
return 0;
}
ct = find_command(argv[1]);
if (ct == NULL) {
printf(_("command %s not found\n"), argv[1]);
return 0;
}
help_onecmd(argv[1], ct);
return 0;
}
static void
help_onecmd(
const char *cmd,
const cmdinfo_t *ct)
{
help_oneline(cmd, ct);
if (ct->help)
ct->help();
}
static void
help_oneline(
const char *cmd,
const cmdinfo_t *ct)
{
if (cmd)
printf("%s ", cmd);
else {
printf("%s ", ct->name);
if (ct->altname)
printf("(or %s) ", ct->altname);
}
if (ct->args)
printf("%s ", ct->args);
printf("-- %s\n", ct->oneline);
}
void
help_init(void)
{
help_cmd.name = _("help");
help_cmd.altname = _("?");
help_cmd.cfunc = help_f;
help_cmd.argmin = 0;
help_cmd.argmax = 1;
help_cmd.flags = CMD_FLAG_GLOBAL;
help_cmd.args = _("[command]");
help_cmd.oneline = _("help for one or all commands");
add_command(&help_cmd);
}

79
cmd.h
View File

@@ -1,79 +0,0 @@
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __COMMAND_H__
#define __COMMAND_H__
#define CMD_FLAG_GLOBAL ((int)0x80000000) /* don't iterate "args" */
typedef int (*cfunc_t)(int argc, char **argv);
typedef void (*helpfunc_t)(void);
typedef struct cmdinfo {
const char *name;
const char *altname;
cfunc_t cfunc;
int argmin;
int argmax;
int canpush;
int flags;
const char *args;
const char *oneline;
helpfunc_t help;
} cmdinfo_t;
extern cmdinfo_t *cmdtab;
extern int ncmds;
extern void help_init(void);
extern void quit_init(void);
typedef int (*argsfunc_t)(int index);
typedef int (*checkfunc_t)(const cmdinfo_t *ci);
extern void add_command(const cmdinfo_t *ci);
extern void add_user_command(char *optarg);
extern void add_args_command(argsfunc_t af);
extern void add_check_command(checkfunc_t cf);
extern const cmdinfo_t *find_command(const char *cmd);
extern void command_loop(void);
extern int command_usage(const cmdinfo_t *ci);
extern int command(const cmdinfo_t *ci, int argc, char **argv);
/* from input.h */
extern char **breakline(char *input, int *count);
extern void doneline(char *input, char **vec);
extern char *fetchline(void);
extern long long cvtnum(char *s);
extern void cvtstr(double value, char *str, size_t sz);
extern struct timeval tsub(struct timeval t1, struct timeval t2);
extern double tdiv(double value, struct timeval tv);
enum {
DEFAULT_TIME = 0x0,
TERSE_FIXED_TIME = 0x1,
VERBOSE_FIXED_TIME = 0x2
};
extern void timestr(struct timeval *tv, char *str, size_t sz, int flags);
extern char *progname;
#endif /* __COMMAND_H__ */

1112
configure vendored

File diff suppressed because it is too large Load Diff

View File

@@ -28,6 +28,7 @@
//#define DEBUG_CONSOLE
#define DEFAULT_BACKSCROLL 512
#define MAX_CONSOLES 12
#define DEFAULT_MONITOR_SIZE "800x600"
#define QEMU_RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
#define QEMU_RGB(r, g, b) QEMU_RGBA(r, g, b, 0xff)
@@ -1067,7 +1068,8 @@ void console_select(unsigned int index)
DisplayState *ds = s->ds;
active_console = s;
if (ds_get_bits_per_pixel(s->ds)) {
ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height);
ds->surface = qemu_resize_displaysurface(ds->surface, s->g_width,
s->g_height, 32, 4 * s->g_width);
} else {
s->ds->surface->width = s->width;
s->ds->surface->height = s->height;
@@ -1275,12 +1277,11 @@ DisplayState *graphic_console_init(vga_hw_update_ptr update,
DisplayState *ds;
ds = (DisplayState *) qemu_mallocz(sizeof(DisplayState));
ds->allocator = &default_allocator;
ds->surface = qemu_create_displaysurface(ds, 640, 480);
ds->surface = qemu_create_displaysurface(640, 480, 32, 640 * 4);
s = new_console(ds, GRAPHIC_CONSOLE);
if (s == NULL) {
qemu_free_displaysurface(ds);
qemu_free_displaysurface(ds->surface);
qemu_free(ds);
return NULL;
}
@@ -1326,7 +1327,7 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds, const c
unsigned height;
static int color_inited;
s = new_console(ds, (p == NULL) ? TEXT_CONSOLE : TEXT_CONSOLE_FIXED_SIZE);
s = new_console(ds, (p == 0) ? TEXT_CONSOLE : TEXT_CONSOLE_FIXED_SIZE);
if (!s) {
free(chr);
return;
@@ -1352,7 +1353,7 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds, const c
s->y = 0;
width = ds_get_width(s->ds);
height = ds_get_height(s->ds);
if (p != NULL) {
if (p != 0) {
width = strtoul(p, (char **)&p, 10);
if (*p == 'C') {
p++;
@@ -1428,7 +1429,7 @@ void qemu_console_resize(DisplayState *ds, int width, int height)
s->g_width = width;
s->g_height = height;
if (is_graphic_console()) {
ds->surface = qemu_resize_displaysurface(ds, width, height);
ds->surface = qemu_resize_displaysurface(ds->surface, width, height, 32, 4 * width);
dpy_resize(ds);
}
}
@@ -1551,14 +1552,14 @@ PixelFormat qemu_default_pixelformat(int bpp)
return pf;
}
DisplaySurface* defaultallocator_create_displaysurface(int width, int height)
DisplaySurface* qemu_create_displaysurface(int width, int height, int bpp, int linesize)
{
DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
surface->width = width;
surface->height = height;
surface->linesize = width * 4;
surface->pf = qemu_default_pixelformat(32);
surface->linesize = linesize;
surface->pf = qemu_default_pixelformat(bpp);
#ifdef WORDS_BIGENDIAN
surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
#else
@@ -1569,13 +1570,13 @@ DisplaySurface* defaultallocator_create_displaysurface(int width, int height)
return surface;
}
DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface,
int width, int height)
DisplaySurface* qemu_resize_displaysurface(DisplaySurface *surface,
int width, int height, int bpp, int linesize)
{
surface->width = width;
surface->height = height;
surface->linesize = width * 4;
surface->pf = qemu_default_pixelformat(32);
surface->linesize = linesize;
surface->pf = qemu_default_pixelformat(bpp);
if (surface->flags & QEMU_ALLOCATED_FLAG)
surface->data = (uint8_t*) qemu_realloc(surface->data, surface->linesize * surface->height);
else
@@ -1606,7 +1607,7 @@ DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
return surface;
}
void defaultallocator_free_displaysurface(DisplaySurface *surface)
void qemu_free_displaysurface(DisplaySurface *surface)
{
if (surface == NULL)
return;

View File

@@ -35,7 +35,7 @@ void kbd_put_keycode(int keycode);
void kbd_mouse_event(int dx, int dy, int dz, int buttons_state);
int kbd_mouse_is_absolute(void);
struct MouseTransformInfo {
struct mouse_transform_info_s {
/* Touchscreen resolution */
int x;
int y;
@@ -43,8 +43,8 @@ struct MouseTransformInfo {
int a[7];
};
void do_info_mice(Monitor *mon);
void do_mouse_set(Monitor *mon, int index);
void do_info_mice(void);
void do_mouse_set(int index);
/* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
constants) */
@@ -75,7 +75,6 @@ void kbd_put_keysym(int keysym);
#define QEMU_BIG_ENDIAN_FLAG 0x01
#define QEMU_ALLOCATED_FLAG 0x02
#define QEMU_REALPIXELS_FLAG 0x04
struct PixelFormat {
uint8_t bits_per_pixel;
@@ -114,18 +113,11 @@ struct DisplayChangeListener {
struct DisplayChangeListener *next;
};
struct DisplayAllocator {
DisplaySurface* (*create_displaysurface)(int width, int height);
DisplaySurface* (*resize_displaysurface)(DisplaySurface *surface, int width, int height);
void (*free_displaysurface)(DisplaySurface *surface);
};
struct DisplayState {
struct DisplaySurface *surface;
void *opaque;
struct QEMUTimer *gui_timer;
struct DisplayAllocator* allocator;
struct DisplayChangeListener* listeners;
void (*mouse_set)(int x, int y, int on);
@@ -137,44 +129,18 @@ struct DisplayState {
void register_displaystate(DisplayState *ds);
DisplayState *get_displaystate(void);
DisplaySurface* qemu_create_displaysurface(int width, int height, int bpp, int linesize);
DisplaySurface* qemu_resize_displaysurface(DisplaySurface *surface,
int width, int height, int bpp, int linesize);
DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
int linesize, uint8_t *data);
void qemu_free_displaysurface(DisplaySurface *surface);
PixelFormat qemu_different_endianness_pixelformat(int bpp);
PixelFormat qemu_default_pixelformat(int bpp);
extern struct DisplayAllocator default_allocator;
DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da);
DisplaySurface* defaultallocator_create_displaysurface(int width, int height);
DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface, int width, int height);
void defaultallocator_free_displaysurface(DisplaySurface *surface);
static inline DisplaySurface* qemu_create_displaysurface(DisplayState *ds, int width, int height)
{
return ds->allocator->create_displaysurface(width, height);
}
static inline DisplaySurface* qemu_resize_displaysurface(DisplayState *ds, int width, int height)
{
return ds->allocator->resize_displaysurface(ds->surface, width, height);
}
static inline void qemu_free_displaysurface(DisplayState *ds)
{
ds->allocator->free_displaysurface(ds->surface);
}
static inline int is_surface_bgr(DisplaySurface *surface)
{
if (surface->pf.bits_per_pixel == 32 && surface->pf.rshift == 0)
return 1;
else
return 0;
}
static inline int is_buffer_shared(DisplaySurface *surface)
{
return (!(surface->flags & QEMU_ALLOCATED_FLAG) &&
!(surface->flags & QEMU_REALPIXELS_FLAG));
return (!(surface->flags & QEMU_ALLOCATED_FLAG));
}
static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl)
@@ -321,10 +287,34 @@ void vnc_display_init(DisplayState *ds);
void vnc_display_close(DisplayState *ds);
int vnc_display_open(DisplayState *ds, const char *display);
int vnc_display_password(DisplayState *ds, const char *password);
void do_info_vnc(Monitor *mon);
char *vnc_display_local_addr(DisplayState *ds);
void do_info_vnc(void);
/* curses.c */
void curses_display_init(DisplayState *ds, int full_screen);
/* FIXME: term_printf et al should probably go elsewhere so everything
does not need to include console.h */
/* monitor.c */
void monitor_init(CharDriverState *hd, int show_banner);
void term_puts(const char *str);
void term_vprintf(const char *fmt, va_list ap);
void term_printf(const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
void term_print_filename(const char *filename);
void term_flush(void);
void term_print_help(void);
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);
extern int completion_index;
void add_completion(const char *str);
void readline_handle_byte(int ch);
void readline_find_completion(const char *cmdline);
const char *readline_get_history(unsigned int index);
void readline_start(const char *prompt, int is_password,
ReadLineFunc *readline_func, void *opaque);
#endif

117
cpu-all.h
View File

@@ -14,13 +14,17 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
*/
#ifndef CPU_ALL_H
#define CPU_ALL_H
#include "qemu-common.h"
#include "cpu-common.h"
#if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__)
#define WORDS_ALIGNED
#endif
/* some important defines:
*
@@ -35,6 +39,7 @@
* TARGET_WORDS_BIGENDIAN : same for target cpu
*/
#include "bswap.h"
#include "softfloat.h"
#if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
@@ -734,15 +739,12 @@ extern unsigned long qemu_host_page_mask;
#define PAGE_RESERVED 0x0020
void page_dump(FILE *f);
int walk_memory_regions(void *,
int (*fn)(void *, unsigned long, unsigned long, unsigned long));
int page_get_flags(target_ulong address);
void page_set_flags(target_ulong start, target_ulong end, int flags);
int page_check_range(target_ulong start, target_ulong len, int flags);
void cpu_exec_init_all(unsigned long tb_size);
CPUState *cpu_copy(CPUState *env);
CPUState *qemu_get_cpu(int cpu);
void cpu_dump_state(CPUState *env, FILE *f,
int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
@@ -758,6 +760,7 @@ extern CPUState *cpu_single_env;
extern int64_t qemu_icount;
extern int use_icount;
#define CPU_INTERRUPT_EXIT 0x01 /* wants exit from main loop */
#define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */
#define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */
#define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */
@@ -767,17 +770,10 @@ extern int use_icount;
#define CPU_INTERRUPT_DEBUG 0x80 /* Debug event occured. */
#define CPU_INTERRUPT_VIRQ 0x100 /* virtual interrupt pending. */
#define CPU_INTERRUPT_NMI 0x200 /* NMI pending. */
#define CPU_INTERRUPT_INIT 0x400 /* INIT pending. */
#define CPU_INTERRUPT_SIPI 0x800 /* SIPI pending. */
#define CPU_INTERRUPT_MCE 0x1000 /* (x86 only) MCE pending. */
void cpu_interrupt(CPUState *s, int mask);
void cpu_reset_interrupt(CPUState *env, int mask);
void cpu_exit(CPUState *s);
int qemu_cpu_has_work(CPUState *env);
/* Breakpoint/watchpoint flags */
#define BP_MEM_READ 0x01
#define BP_MEM_WRITE 0x02
@@ -836,14 +832,32 @@ void cpu_set_log_filename(const char *filename);
int cpu_str_to_log_mask(const char *str);
/* IO ports API */
#include "ioport.h"
/* NOTE: as these functions may be even used when there is an isa
brige on non x86 targets, we always defined them */
#ifndef NO_CPU_IO_DEFS
void cpu_outb(CPUState *env, int addr, int val);
void cpu_outw(CPUState *env, int addr, int val);
void cpu_outl(CPUState *env, int addr, int val);
int cpu_inb(CPUState *env, int addr);
int cpu_inw(CPUState *env, int addr);
int cpu_inl(CPUState *env, int addr);
#endif
/* address in the RAM (different from a physical address) */
#ifdef USE_KQEMU
typedef uint32_t ram_addr_t;
#else
typedef unsigned long ram_addr_t;
#endif
/* memory API */
extern ram_addr_t phys_ram_size;
extern int phys_ram_fd;
extern uint8_t *phys_ram_base;
extern uint8_t *phys_ram_dirty;
extern ram_addr_t ram_size;
extern ram_addr_t last_ram_offset;
/* physical memory access */
@@ -851,8 +865,19 @@ extern ram_addr_t last_ram_offset;
3 flags. The ROMD code stores the page ram offset in iotlb entry,
so only a limited number of ids are avaiable. */
#define IO_MEM_SHIFT 3
#define IO_MEM_NB_ENTRIES (1 << (TARGET_PAGE_BITS - IO_MEM_SHIFT))
#define IO_MEM_RAM (0 << IO_MEM_SHIFT) /* hardcoded offset */
#define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */
#define IO_MEM_UNASSIGNED (2 << IO_MEM_SHIFT)
#define IO_MEM_NOTDIRTY (3 << IO_MEM_SHIFT)
/* Acts like a ROM when read and like a device when written. */
#define IO_MEM_ROMD (1)
#define IO_MEM_SUBPAGE (2)
#define IO_MEM_SUBWIDTH (4)
/* Flags stored in the low bits of the TLB virtual address. These are
defined so that fast path ram access is all zeros. */
/* Zero if TLB entry is valid. */
@@ -863,6 +888,64 @@ extern ram_addr_t last_ram_offset;
/* Set if TLB entry is an IO callback. */
#define TLB_MMIO (1 << 5)
typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value);
typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset,
ram_addr_t region_offset);
static inline void cpu_register_physical_memory(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset)
{
cpu_register_physical_memory_offset(start_addr, size, phys_offset, 0);
}
ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr);
ram_addr_t qemu_ram_alloc(ram_addr_t);
void qemu_ram_free(ram_addr_t addr);
int cpu_register_io_memory(int io_index,
CPUReadMemoryFunc **mem_read,
CPUWriteMemoryFunc **mem_write,
void *opaque);
void cpu_unregister_io_memory(int table_address);
CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index);
CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index);
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
int len, int is_write);
static inline void cpu_physical_memory_read(target_phys_addr_t addr,
uint8_t *buf, int len)
{
cpu_physical_memory_rw(addr, buf, len, 0);
}
static inline void cpu_physical_memory_write(target_phys_addr_t addr,
const uint8_t *buf, int len)
{
cpu_physical_memory_rw(addr, (uint8_t *)buf, len, 1);
}
void *cpu_physical_memory_map(target_phys_addr_t addr,
target_phys_addr_t *plen,
int is_write);
void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
int is_write, target_phys_addr_t access_len);
void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque));
void cpu_unregister_map_client(void *cookie);
uint32_t ldub_phys(target_phys_addr_t addr);
uint32_t lduw_phys(target_phys_addr_t addr);
uint32_t ldl_phys(target_phys_addr_t addr);
uint64_t ldq_phys(target_phys_addr_t addr);
void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val);
void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val);
void stb_phys(target_phys_addr_t addr, uint32_t val);
void stw_phys(target_phys_addr_t addr, uint32_t val);
void stl_phys(target_phys_addr_t addr, uint32_t val);
void stq_phys(target_phys_addr_t addr, uint64_t val);
void cpu_physical_memory_write_rom(target_phys_addr_t addr,
const uint8_t *buf, int len);
int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
uint8_t *buf, int len, int is_write);
@@ -896,8 +979,7 @@ int cpu_physical_memory_set_dirty_tracking(int enable);
int cpu_physical_memory_get_dirty_tracking(void);
int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
target_phys_addr_t end_addr);
void cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, target_phys_addr_t end_addr);
void dump_exec_info(FILE *f,
int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
@@ -1061,7 +1143,4 @@ extern int64_t kqemu_ret_excp_count;
extern int64_t kqemu_ret_intr_count;
#endif
void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
uint64_t mcg_status, uint64_t addr, uint64_t misc);
#endif /* CPU_ALL_H */

View File

@@ -1,95 +0,0 @@
#ifndef CPU_COMMON_H
#define CPU_COMMON_H 1
/* CPU interfaces that are target indpendent. */
#if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__)
#define WORDS_ALIGNED
#endif
#include "bswap.h"
/* address in the RAM (different from a physical address) */
#ifdef CONFIG_KQEMU
/* FIXME: This is wrong. */
typedef uint32_t ram_addr_t;
#else
typedef unsigned long ram_addr_t;
#endif
/* memory API */
typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value);
typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset,
ram_addr_t region_offset);
static inline void cpu_register_physical_memory(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset)
{
cpu_register_physical_memory_offset(start_addr, size, phys_offset, 0);
}
ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr);
ram_addr_t qemu_ram_alloc(ram_addr_t);
void qemu_ram_free(ram_addr_t addr);
/* This should only be used for ram local to a device. */
void *qemu_get_ram_ptr(ram_addr_t addr);
/* This should not be used by devices. */
ram_addr_t qemu_ram_addr_from_host(void *ptr);
int cpu_register_io_memory(CPUReadMemoryFunc **mem_read,
CPUWriteMemoryFunc **mem_write,
void *opaque);
void cpu_unregister_io_memory(int table_address);
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
int len, int is_write);
static inline void cpu_physical_memory_read(target_phys_addr_t addr,
uint8_t *buf, int len)
{
cpu_physical_memory_rw(addr, buf, len, 0);
}
static inline void cpu_physical_memory_write(target_phys_addr_t addr,
const uint8_t *buf, int len)
{
cpu_physical_memory_rw(addr, (uint8_t *)buf, len, 1);
}
void *cpu_physical_memory_map(target_phys_addr_t addr,
target_phys_addr_t *plen,
int is_write);
void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
int is_write, target_phys_addr_t access_len);
void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque));
void cpu_unregister_map_client(void *cookie);
uint32_t ldub_phys(target_phys_addr_t addr);
uint32_t lduw_phys(target_phys_addr_t addr);
uint32_t ldl_phys(target_phys_addr_t addr);
uint64_t ldq_phys(target_phys_addr_t addr);
void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val);
void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val);
void stb_phys(target_phys_addr_t addr, uint32_t val);
void stw_phys(target_phys_addr_t addr, uint32_t val);
void stl_phys(target_phys_addr_t addr, uint32_t val);
void stq_phys(target_phys_addr_t addr, uint64_t val);
void cpu_physical_memory_write_rom(target_phys_addr_t addr,
const uint8_t *buf, int len);
#define IO_MEM_SHIFT 3
#define IO_MEM_RAM (0 << IO_MEM_SHIFT) /* hardcoded offset */
#define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */
#define IO_MEM_UNASSIGNED (2 << IO_MEM_SHIFT)
#define IO_MEM_NOTDIRTY (3 << IO_MEM_SHIFT)
/* Acts like a ROM when read and like a device when written. */
#define IO_MEM_ROMD (1)
#define IO_MEM_SUBPAGE (2)
#define IO_MEM_SUBWIDTH (4)
#endif /* !CPU_COMMON_H */

View File

@@ -14,7 +14,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
*/
#ifndef CPU_DEFS_H
#define CPU_DEFS_H
@@ -29,12 +30,19 @@
#include <signal.h>
#include "osdep.h"
#include "sys-queue.h"
#include "targphys.h"
#ifndef TARGET_LONG_BITS
#error TARGET_LONG_BITS must be defined before including this header
#endif
#ifndef TARGET_PHYS_ADDR_BITS
#if TARGET_LONG_BITS >= HOST_LONG_BITS
#define TARGET_PHYS_ADDR_BITS TARGET_LONG_BITS
#else
#define TARGET_PHYS_ADDR_BITS HOST_LONG_BITS
#endif
#endif
#define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8)
/* target_ulong is the type of a virtual address */
@@ -54,6 +62,22 @@ typedef uint64_t target_ulong;
#error TARGET_LONG_SIZE undefined
#endif
/* target_phys_addr_t is the type of a physical address (its size can
be different from 'target_ulong'). We have sizeof(target_phys_addr)
= max(sizeof(unsigned long),
sizeof(size_of_target_physical_address)) because we must pass a
host pointer to memory operations in some cases */
#if TARGET_PHYS_ADDR_BITS == 32
typedef uint32_t target_phys_addr_t;
#define TARGET_FMT_plx "%08x"
#elif TARGET_PHYS_ADDR_BITS == 64
typedef uint64_t target_phys_addr_t;
#define TARGET_FMT_plx "%016" PRIx64
#else
#error TARGET_PHYS_ADDR_BITS undefined
#endif
#define HOST_LONG_SIZE (HOST_LONG_BITS / 8)
#define EXCP_INTERRUPT 0x10000 /* async interruption */
@@ -146,8 +170,6 @@ typedef struct CPUWatchpoint {
target_ulong mem_io_vaddr; /* target virtual addr at which the \
memory was accessed */ \
uint32_t halted; /* Nonzero if the CPU is in suspend state */ \
uint32_t stop; /* Stop request */ \
uint32_t stopped; /* Artificially stopped */ \
uint32_t interrupt_request; \
volatile sig_atomic_t exit_request; \
/* The meaning of the MMU modes is defined in the target code. */ \
@@ -181,17 +203,12 @@ typedef struct CPUWatchpoint {
jmp_buf jmp_env; \
int exception_index; \
\
CPUState *next_cpu; /* next CPU sharing TB cache */ \
void *next_cpu; /* next CPU sharing TB cache */ \
int cpu_index; /* CPU index (informative) */ \
uint32_t host_tid; /* host thread ID */ \
int numa_node; /* NUMA node this cpu is belonging to */ \
int running; /* Nonzero if cpu is currently running(usermode). */ \
/* user data */ \
void *opaque; \
\
uint32_t created; \
struct QemuThread *thread; \
struct QemuCond *halt_cond; \
const char *cpu_model_str; \
struct KVMState *kvm_state; \
struct kvm_run *kvm_run; \

View File

@@ -14,9 +14,11 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
*/
#include "config.h"
#define CPU_NO_GLOBAL_REGS
#include "exec.h"
#include "disas.h"
#include "tcg.h"
@@ -49,11 +51,6 @@ int tb_invalidated_flag;
//#define DEBUG_EXEC
//#define DEBUG_SIGNAL
int qemu_cpu_has_work(CPUState *env)
{
return cpu_has_work(env);
}
void cpu_loop_exit(void)
{
/* NOTE: the register at this point must be saved by hand because
@@ -245,7 +242,6 @@ int cpu_exec(CPUState *env1)
#elif defined(TARGET_ALPHA)
#elif defined(TARGET_ARM)
#elif defined(TARGET_PPC)
#elif defined(TARGET_MICROBLAZE)
#elif defined(TARGET_MIPS)
#elif defined(TARGET_SH4)
#elif defined(TARGET_CRIS)
@@ -258,11 +254,6 @@ int cpu_exec(CPUState *env1)
/* prepare setjmp context for exception handling */
for(;;) {
if (setjmp(env->jmp_env) == 0) {
#if defined(__sparc__) && !defined(HOST_SOLARIS)
#undef env
env = cpu_single_env;
#define env cpu_single_env
#endif
env->current_tb = NULL;
/* if an exception is pending, we execute it here */
if (env->exception_index >= 0) {
@@ -300,8 +291,6 @@ int cpu_exec(CPUState *env1)
env->old_exception = -1;
#elif defined(TARGET_PPC)
do_interrupt(env);
#elif defined(TARGET_MICROBLAZE)
do_interrupt(env);
#elif defined(TARGET_MIPS)
do_interrupt(env);
#elif defined(TARGET_SPARC)
@@ -321,7 +310,7 @@ int cpu_exec(CPUState *env1)
}
env->exception_index = -1;
}
#ifdef CONFIG_KQEMU
#ifdef USE_KQEMU
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);
@@ -369,8 +358,7 @@ int cpu_exec(CPUState *env1)
cpu_loop_exit();
}
#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
defined(TARGET_MICROBLAZE)
defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
if (interrupt_request & CPU_INTERRUPT_HALT) {
env->interrupt_request &= ~CPU_INTERRUPT_HALT;
env->halted = 1;
@@ -379,14 +367,7 @@ int cpu_exec(CPUState *env1)
}
#endif
#if defined(TARGET_I386)
if (interrupt_request & CPU_INTERRUPT_INIT) {
svm_check_intercept(SVM_EXIT_INIT);
do_cpu_init(env);
env->exception_index = EXCP_HALTED;
cpu_loop_exit();
} else if (interrupt_request & CPU_INTERRUPT_SIPI) {
do_cpu_sipi(env);
} else if (env->hflags2 & HF2_GIF_MASK) {
if (env->hflags2 & HF2_GIF_MASK) {
if ((interrupt_request & CPU_INTERRUPT_SMI) &&
!(env->hflags & HF_SMM_MASK)) {
svm_check_intercept(SVM_EXIT_SMI);
@@ -399,10 +380,6 @@ int cpu_exec(CPUState *env1)
env->hflags2 |= HF2_NMI_MASK;
do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
next_tb = 0;
} else if (interrupt_request & CPU_INTERRUPT_MCE) {
env->interrupt_request &= ~CPU_INTERRUPT_MCE;
do_interrupt(EXCP12_MCHK, 0, 0, 0, 0);
next_tb = 0;
} else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
(((env->hflags2 & HF2_VINTR_MASK) &&
(env->hflags2 & HF2_HIF_MASK)) ||
@@ -414,11 +391,6 @@ int cpu_exec(CPUState *env1)
env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
intno = cpu_get_pic_interrupt(env);
qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
#if defined(__sparc__) && !defined(HOST_SOLARIS)
#undef env
env = cpu_single_env;
#define env cpu_single_env
#endif
do_interrupt(intno, 0, 0, 0, 1);
/* ensure that no TB jump will be modified as
the program flow was changed */
@@ -450,15 +422,6 @@ int cpu_exec(CPUState *env1)
env->interrupt_request &= ~CPU_INTERRUPT_HARD;
next_tb = 0;
}
#elif defined(TARGET_MICROBLAZE)
if ((interrupt_request & CPU_INTERRUPT_HARD)
&& (env->sregs[SR_MSR] & MSR_IE)
&& !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
&& !(env->iflags & (D_FLAG | IMM_FLAG))) {
env->exception_index = EXCP_IRQ;
do_interrupt(env);
next_tb = 0;
}
#elif defined(TARGET_MIPS)
if ((interrupt_request & CPU_INTERRUPT_HARD) &&
(env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
@@ -474,7 +437,7 @@ int cpu_exec(CPUState *env1)
}
#elif defined(TARGET_SPARC)
if ((interrupt_request & CPU_INTERRUPT_HARD) &&
cpu_interrupts_enabled(env)) {
(env->psret != 0)) {
int pil = env->interrupt_index & 15;
int type = env->interrupt_index & 0xf0;
@@ -485,7 +448,7 @@ int cpu_exec(CPUState *env1)
env->exception_index = env->interrupt_index;
do_interrupt(env);
env->interrupt_index = 0;
#if !defined(CONFIG_USER_ONLY)
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
cpu_check_irqs(env);
#endif
next_tb = 0;
@@ -588,8 +551,6 @@ int cpu_exec(CPUState *env1)
env->sr = (env->sr & 0xffe0)
| env->cc_dest | (env->cc_x << 4);
log_cpu_state(env, 0);
#elif defined(TARGET_MICROBLAZE)
log_cpu_state(env, 0);
#elif defined(TARGET_MIPS)
log_cpu_state(env, 0);
#elif defined(TARGET_SH4)
@@ -624,7 +585,7 @@ int cpu_exec(CPUState *env1)
jump. */
{
if (next_tb != 0 &&
#ifdef CONFIG_KQEMU
#ifdef USE_KQEMU
(env->kqemu_enabled != 2) &&
#endif
tb->page_addr[1] == -1) {
@@ -681,7 +642,7 @@ int cpu_exec(CPUState *env1)
}
/* reset soft MMU for next block (it can currently
only be set by a memory fault) */
#if defined(CONFIG_KQEMU)
#if defined(USE_KQEMU)
#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
if (kqemu_is_ok(env) &&
(cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
@@ -707,7 +668,6 @@ int cpu_exec(CPUState *env1)
env->cc_op = CC_OP_FLAGS;
env->sr = (env->sr & 0xffe0)
| env->cc_dest | (env->cc_x << 4);
#elif defined(TARGET_MICROBLAZE)
#elif defined(TARGET_MIPS)
#elif defined(TARGET_SH4)
#elif defined(TARGET_ALPHA)
@@ -1054,56 +1014,6 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
return 1;
}
#elif defined (TARGET_MICROBLAZE)
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
int is_write, sigset_t *old_set,
void *puc)
{
TranslationBlock *tb;
int ret;
if (cpu_single_env)
env = cpu_single_env; /* XXX: find a correct solution for multithread */
#if defined(DEBUG_SIGNAL)
printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
pc, address, is_write, *(unsigned long *)old_set);
#endif
/* XXX: locking issue */
if (is_write && page_unprotect(h2g(address), pc, puc)) {
return 1;
}
/* see if it is an MMU fault */
ret = cpu_mb_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
if (ret < 0)
return 0; /* not an MMU fault */
if (ret == 0)
return 1; /* the MMU fault was handled without causing real CPU fault */
/* now we have a real cpu fault */
tb = tb_find_pc(pc);
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
cpu_restore_state(tb, env, pc, puc);
}
if (ret == 1) {
#if 0
printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
env->PC, env->error_code, tb);
#endif
/* we restore the process signal mask as the sigreturn should
do it (XXX: use sigsetjmp) */
sigprocmask(SIG_SETMASK, old_set, NULL);
cpu_loop_exit();
} else {
/* activate soft MMU for this block */
cpu_resume_from_signal(env, puc);
}
/* never comes here */
return 1;
}
#elif defined (TARGET_SH4)
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
int is_write, sigset_t *old_set,
@@ -1246,28 +1156,17 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
# define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
# define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
# define ERROR_sig(context) ((context)->uc_mcontext->es.err)
# define MASK_sig(context) ((context)->uc_sigmask)
#elif defined(__OpenBSD__)
# define EIP_sig(context) ((context)->sc_eip)
# define TRAP_sig(context) ((context)->sc_trapno)
# define ERROR_sig(context) ((context)->sc_err)
# define MASK_sig(context) ((context)->sc_mask)
#else
# define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
# define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
# define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
# define MASK_sig(context) ((context)->uc_sigmask)
#endif
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
#if defined(__OpenBSD__)
struct sigcontext *uc = puc;
#else
struct ucontext *uc = puc;
#endif
unsigned long pc;
int trapno;
@@ -1282,26 +1181,20 @@ int cpu_signal_handler(int host_signum, void *pinfo,
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
trapno == 0xe ?
(ERROR_sig(uc) >> 1) & 1 : 0,
&MASK_sig(uc), puc);
&uc->uc_sigmask, puc);
}
#elif defined(__x86_64__)
#ifdef __NetBSD__
#define PC_sig(context) _UC_MACHINE_PC(context)
#define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
#define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
#define MASK_sig(context) ((context)->uc_sigmask)
#elif defined(__OpenBSD__)
#define PC_sig(context) ((context)->sc_rip)
#define TRAP_sig(context) ((context)->sc_trapno)
#define ERROR_sig(context) ((context)->sc_err)
#define MASK_sig(context) ((context)->sc_mask)
#define REG_ERR _REG_ERR
#define REG_TRAPNO _REG_TRAPNO
#define QEMU_UC_MCONTEXT_GREGS(uc, reg) (uc)->uc_mcontext.__gregs[(reg)]
#define QEMU_UC_MACHINE_PC(uc) _UC_MACHINE_PC(uc)
#else
#define PC_sig(context) ((context)->uc_mcontext.gregs[REG_RIP])
#define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
#define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
#define MASK_sig(context) ((context)->uc_sigmask)
#define QEMU_UC_MCONTEXT_GREGS(uc, reg) (uc)->uc_mcontext.gregs[(reg)]
#define QEMU_UC_MACHINE_PC(uc) QEMU_UC_MCONTEXT_GREGS(uc, REG_RIP)
#endif
int cpu_signal_handler(int host_signum, void *pinfo,
@@ -1311,17 +1204,15 @@ int cpu_signal_handler(int host_signum, void *pinfo,
unsigned long pc;
#ifdef __NetBSD__
ucontext_t *uc = puc;
#elif defined(__OpenBSD__)
struct sigcontext *uc = puc;
#else
struct ucontext *uc = puc;
#endif
pc = PC_sig(uc);
pc = QEMU_UC_MACHINE_PC(uc);
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
TRAP_sig(uc) == 0xe ?
(ERROR_sig(uc) >> 1) & 1 : 0,
&MASK_sig(uc), puc);
QEMU_UC_MCONTEXT_GREGS(uc, REG_TRAPNO) == 0xe ?
(QEMU_UC_MCONTEXT_GREGS(uc, REG_ERR) >> 1) & 1 : 0,
&uc->uc_sigmask, puc);
}
#elif defined(_ARCH_PPC)
@@ -1458,24 +1349,12 @@ int cpu_signal_handler(int host_signum, void *pinfo,
if ((insn >> 30) == 3) {
switch((insn >> 19) & 0x3f) {
case 0x05: // stb
case 0x15: // stba
case 0x06: // sth
case 0x16: // stha
case 0x04: // st
case 0x14: // sta
case 0x07: // std
case 0x17: // stda
case 0x0e: // stx
case 0x1e: // stxa
case 0x24: // stf
case 0x34: // stfa
case 0x27: // stdf
case 0x37: // stdfa
case 0x26: // stqf
case 0x36: // stqfa
case 0x25: // stfsr
case 0x3c: // casa
case 0x3e: // casxa
is_write = 1;
break;
}

View File

@@ -1,55 +0,0 @@
#!/bin/sh
echo "/* Automatically generated by configure - do not modify */"
echo "#include \"../config-host.h\""
while read line; do
case $line in
CONFIG_*=y) # configuration
name=${line%=*}
echo "#define $name 1"
;;
CONFIG_*=*) # configuration
name=${line%=*}
value=${line#*=}
echo "#define $name $value"
;;
TARGET_ARCH=*) # configuration
target_arch=${line#*=}
arch_name=`echo $target_arch | tr '[:lower:]' '[:upper:]'`
echo "#define TARGET_ARCH \"$target_arch\""
echo "#define TARGET_$arch_name 1"
;;
TARGET_BASE_ARCH=*) # configuration
target_base_arch=${line#*=}
if [ "$target_base_arch" != "$target_arch" ]; then
base_arch_name=`echo $target_base_arch | tr '[:lower:]' '[:upper:]'`
echo "#define TARGET_$base_arch_name 1"
fi
;;
TARGET_XML_FILES=*)
# do nothing
;;
TARGET_ABI_DIR=*)
# do nothing
;;
TARGET_ARCH2=*)
# do nothing
;;
TARGET_*=y) # configuration
name=${line%=*}
echo "#define $name 1"
;;
TARGET_*=*) # configuration
name=${line%=*}
value=${line#*=}
echo "#define $name $value"
;;
USE_NPTL=y) # configuration
name=${line%=*}
echo "#define $name 1"
;;
esac
done # read

View File

@@ -16,7 +16,9 @@
more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>. */
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
#include "dis-asm.h"
//#include "sysdep.h"
@@ -49,7 +51,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>. */
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
#ifndef NULL
#define NULL (0)

View File

@@ -21,6 +21,11 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "qemu-common.h"
#include "console.h"
#include "sysemu.h"
#include <curses.h>
#ifndef _WIN32
@@ -33,10 +38,6 @@
#define resize_term resizeterm
#endif
#include "qemu-common.h"
#include "console.h"
#include "sysemu.h"
#define FONT_HEIGHT 16
#define FONT_WIDTH 8
@@ -157,8 +158,9 @@ static void curses_cursor_position(DisplayState *ds, int x, int y)
/* generic keyboard conversion */
#include "curses_keys.h"
#include "keymaps.c"
static kbd_layout_t *kbd_layout = NULL;
static kbd_layout_t *kbd_layout = 0;
static int keycode2keysym[CURSES_KEYS];
static void curses_refresh(DisplayState *ds)
@@ -309,7 +311,7 @@ static void curses_keyboard_setup(void)
keyboard_layout = "en-us";
#endif
if(keyboard_layout) {
kbd_layout = init_keyboard_layout(name2keysym, keyboard_layout);
kbd_layout = init_keyboard_layout(keyboard_layout);
if (!kbd_layout)
exit(1);
}
@@ -364,7 +366,7 @@ void curses_display_init(DisplayState *ds, int full_screen)
dcl->dpy_refresh = curses_refresh;
dcl->dpy_text_cursor = curses_cursor_position;
register_displaychangelistener(ds, dcl);
qemu_free_displaysurface(ds);
qemu_free_displaysurface(ds->surface);
ds->surface = qemu_create_displaysurface_from(640, 400, 0, 0, (uint8_t*) screen);
invalidate = 1;

View File

@@ -21,10 +21,6 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "keymaps.h"
#define KEY_RELEASE 0x80
#define KEY_MASK 0x7f
#define SHIFT_CODE 0x2a
@@ -206,7 +202,7 @@ static const int curses2keycode[CURSES_KEYS] = {
[0x006] = 33 | CNTRL, /* Control + f */
[0x007] = 34 | CNTRL, /* Control + g */
[0x008] = 35 | CNTRL, /* Control + h */
/* Control + j collides with Return */
[0x00a] = 36 | CNTRL, /* Control + j */
[0x00b] = 37 | CNTRL, /* Control + k */
[0x00c] = 38 | CNTRL, /* Control + l */
@@ -243,6 +239,11 @@ static const int curses2keysym[CURSES_KEYS] = {
};
typedef struct {
const char* name;
int keysym;
} name2keysym_t;
static const name2keysym_t name2keysym[] = {
/* Plain ASCII */
{ "space", 0x020 },
@@ -479,5 +480,5 @@ static const name2keysym_t name2keysym[] = {
{ "F20", 0x11c },
{ "Escape", 27 },
{ NULL, 0 },
{ 0, 0 },
};

View File

@@ -83,19 +83,6 @@ int stristart(const char *str, const char *val, const char **ptr)
return 1;
}
/* XXX: use host strnlen if available ? */
int qemu_strnlen(const char *s, int max_len)
{
int i;
for(i = 0; i < max_len; i++) {
if (s[i] == '\0') {
break;
}
}
return i;
}
time_t mktimegm(struct tm *tm)
{
time_t t;
@@ -125,22 +112,8 @@ void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint)
qiov->size = 0;
}
void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov)
{
int i;
qiov->iov = iov;
qiov->niov = niov;
qiov->nalloc = -1;
qiov->size = 0;
for (i = 0; i < niov; i++)
qiov->size += iov[i].iov_len;
}
void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len)
{
assert(qiov->nalloc != -1);
if (qiov->niov == qiov->nalloc) {
qiov->nalloc = 2 * qiov->nalloc + 1;
qiov->iov = qemu_realloc(qiov->iov, qiov->nalloc * sizeof(struct iovec));
@@ -153,15 +126,11 @@ void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len)
void qemu_iovec_destroy(QEMUIOVector *qiov)
{
assert(qiov->nalloc != -1);
qemu_free(qiov->iov);
}
void qemu_iovec_reset(QEMUIOVector *qiov)
{
assert(qiov->nalloc != -1);
qiov->niov = 0;
qiov->size = 0;
}

View File

@@ -14,7 +14,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <fcntl.h>
#include <stdio.h>

View File

@@ -14,7 +14,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
*/
#include <stdio.h>
#include <sys/types.h>

View File

@@ -15,7 +15,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <stdlib.h>
#include <stdio.h>
@@ -39,8 +41,6 @@
#include <mach/mach_init.h>
#include <mach/vm_map.h>
int singlestep;
const char *interp_prefix = "";
asm(".zerofill __STD_PROG_ZONE, __STD_PROG_ZONE, __std_prog_zone, 0x0dfff000");
@@ -70,6 +70,39 @@ void gemu_log(const char *fmt, ...)
va_end(ap);
}
void cpu_outb(CPUState *env, int addr, int val)
{
fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);
}
void cpu_outw(CPUState *env, int addr, int val)
{
fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);
}
void cpu_outl(CPUState *env, int addr, int val)
{
fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);
}
int cpu_inb(CPUState *env, int addr)
{
fprintf(stderr, "inb: port=0x%04x\n", addr);
return 0;
}
int cpu_inw(CPUState *env, int addr)
{
fprintf(stderr, "inw: port=0x%04x\n", addr);
return 0;
}
int cpu_inl(CPUState *env, int addr)
{
fprintf(stderr, "inl: port=0x%04x\n", addr);
return 0;
}
int cpu_get_pic_interrupt(CPUState *env)
{
return -1;
@@ -123,12 +156,12 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
return -1;
}
#define EXCP_DUMP(env, fmt, ...) \
do { \
fprintf(stderr, fmt , ## __VA_ARGS__); \
cpu_dump_state(env, stderr, fprintf, 0); \
qemu_log(fmt, ## __VA_ARGS__); \
log_cpu_state(env, 0); \
#define EXCP_DUMP(env, fmt, args...) \
do { \
fprintf(stderr, fmt , ##args); \
cpu_dump_state(env, stderr, fprintf, 0); \
qemu_log(fmt, ##args); \
log_cpu_state(env, 0); \
} while (0)
void cpu_loop(CPUPPCState *env)
@@ -718,7 +751,6 @@ void usage(void)
"-d options activate log (logfile='%s')\n"
"-g wait for gdb on port 1234\n"
"-p pagesize set the host page size to 'pagesize'\n",
"-singlestep always run in singlestep mode\n"
TARGET_ARCH,
TARGET_ARCH,
interp_prefix,
@@ -810,8 +842,6 @@ int main(int argc, char **argv)
#endif
exit(1);
}
} else if (!strcmp(r, "singlestep")) {
singlestep = 1;
} else
{
usage();

View File

@@ -14,7 +14,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <stdlib.h>
#include <stdio.h>

View File

@@ -14,7 +14,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <stdlib.h>
#include <stdio.h>
@@ -213,7 +215,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
#endif
if (queue_signal(sig, &tinfo) == 1) {
/* interrupt the virtual CPU as soon as possible */
cpu_exit(global_env);
cpu_interrupt(global_env, CPU_INTERRUPT_EXIT);
}
}

View File

@@ -15,7 +15,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <fcntl.h>
#include <stdio.h>
@@ -625,7 +627,7 @@ static inline void byteswap_winsize(struct winsize *w)
tswap16s(&w->ws_ypixel);
}
#define STRUCT(name, ...) STRUCT_ ## name,
#define STRUCT(name, list...) STRUCT_ ## name,
#define STRUCT_SPECIAL(name) STRUCT_ ## name,
enum {
#include "ioctls_types.h"
@@ -633,7 +635,7 @@ enum {
#undef STRUCT
#undef STRUCT_SPECIAL
#define STRUCT(name, ...) const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
#define STRUCT(name, list...) const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
#define STRUCT_SPECIAL(name)
#include "ioctls_types.h"
#undef STRUCT
@@ -654,8 +656,8 @@ typedef struct IOCTLEntry {
#define MAX_STRUCT_SIZE 4096
static IOCTLEntry ioctl_entries[] = {
#define IOCTL(cmd, access, ...) \
{ cmd, cmd, #cmd, access, { __VA_ARGS__ } },
#define IOCTL(cmd, access, types...) \
{ cmd, cmd, #cmd, access, { types } },
#include "ioctls.h"
{ 0, 0, },
};
@@ -896,10 +898,10 @@ typedef long (*syscall_function_t)(void *cpu_env, int num);
#define WRAPPER_CALL_DIRECT_6(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6; return (long)function(arg1, arg2, arg3, arg4, arg5, arg6); }
#define WRAPPER_CALL_DIRECT_7(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6; typeof(_arg7) arg7 = _arg7; return (long)function(arg1, arg2, arg3, arg4, arg5, arg6, arg7); }
#define WRAPPER_CALL_DIRECT_8(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7, _arg8) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6; typeof(_arg7) arg7 = _arg7; typeof(_arg8) arg8 = _arg8; return (long)function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); }
#define WRAPPER_CALL_DIRECT(function, nargs, ...) WRAPPER_CALL_DIRECT_##nargs(function, __VA_ARGS__)
#define WRAPPER_CALL_NOERRNO(function, nargs, ...) WRAPPER_CALL_DIRECT(function, nargs, __VA_ARGS__)
#define WRAPPER_CALL_INDIRECT(function, nargs, ...)
#define ENTRY(name, number, function, nargs, call_type, ...) WRAPPER_##call_type(function, nargs, __VA_ARGS__)
#define WRAPPER_CALL_DIRECT(function, nargs, args...) WRAPPER_CALL_DIRECT_##nargs(function, args)
#define WRAPPER_CALL_NOERRNO(function, nargs, args...) WRAPPER_CALL_DIRECT(function, nargs, args)
#define WRAPPER_CALL_INDIRECT(function, nargs, args...)
#define ENTRY(name, number, function, nargs, call_type, args...) WRAPPER_##call_type(function, nargs, args)
#include "syscalls.h"
@@ -924,7 +926,7 @@ typedef long (*syscall_function_t)(void *cpu_env, int num);
#define ENTRY_CALL_DIRECT(name, number, function, nargs, call_type) _ENTRY(name, number, __qemu_##function, nargs, call_type)
#define ENTRY_CALL_NOERRNO(name, number, function, nargs, call_type) ENTRY_CALL_DIRECT(name, number, function, nargs, call_type)
#define ENTRY_CALL_INDIRECT(name, number, function, nargs, call_type) _ENTRY(name, number, function, nargs, call_type)
#define ENTRY(name, number, function, nargs, call_type, ...) ENTRY_##call_type(name, number, function, nargs, call_type)
#define ENTRY(name, number, function, nargs, call_type, args...) ENTRY_##call_type(name, number, function, nargs, call_type)
#define CALL_DIRECT 1
#define CALL_INDIRECT 2

View File

@@ -25,34 +25,34 @@
#include <libfdt.h>
void *load_device_tree(const char *filename_path, int *sizep)
void *load_device_tree(const char *filename_path, void *load_addr)
{
int dt_size;
int dt_file_size;
int dt_file_load_size;
int new_dt_size;
int ret;
void *fdt = NULL;
void *dt_file = NULL;
void *fdt;
*sizep = 0;
dt_size = get_image_size(filename_path);
if (dt_size < 0) {
dt_file_size = get_image_size(filename_path);
if (dt_file_size < 0) {
printf("Unable to get size of device tree file '%s'\n",
filename_path);
goto fail;
}
/* Expand to 2x size to give enough room for manipulation. */
dt_size *= 2;
/* First allocate space in qemu for device tree */
fdt = qemu_mallocz(dt_size);
dt_file = qemu_mallocz(dt_file_size);
dt_file_load_size = load_image(filename_path, fdt);
if (dt_file_load_size < 0) {
printf("Unable to open device tree file '%s'\n",
filename_path);
goto fail;
}
dt_file_load_size = load_image(filename_path, dt_file);
ret = fdt_open_into(fdt, fdt, dt_size);
/* Second we place new copy of 2x size in guest memory
* This give us enough room for manipulation.
*/
new_dt_size = dt_file_size * 2;
fdt = load_addr;
ret = fdt_open_into(dt_file, fdt, new_dt_size);
if (ret) {
printf("Unable to copy device tree in memory\n");
goto fail;
@@ -64,11 +64,12 @@ void *load_device_tree(const char *filename_path, int *sizep)
filename_path);
goto fail;
}
*sizep = dt_size;
/* free qemu memory with old device tree */
qemu_free(dt_file);
return fdt;
fail:
qemu_free(fdt);
qemu_free(dt_file);
return NULL;
}

View File

@@ -14,7 +14,7 @@
#ifndef __DEVICE_TREE_H__
#define __DEVICE_TREE_H__
void *load_device_tree(const char *filename_path, int *sizep);
void *load_device_tree(const char *filename_path, void *load_addr);
int qemu_devtree_setprop(void *fdt, const char *node_path,
const char *property, uint32_t *val_array, int size);

View File

@@ -218,7 +218,6 @@ enum bfd_architecture
#define bfd_mach_cris_v0_v10 255
#define bfd_mach_cris_v32 32
#define bfd_mach_cris_v10_v32 1032
bfd_arch_microblaze, /* Xilinx MicroBlaze. */
bfd_arch_last
};
#define bfd_mach_s390_31 31
@@ -401,7 +400,6 @@ extern int print_insn_tic30 PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_ppc PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_s390 PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_crisv32 PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_microblaze PARAMS ((bfd_vma, disassemble_info*));
#if 0
/* Fetch the disassembler for a given BFD, if that support is available. */

32
disas.c
View File

@@ -33,7 +33,10 @@ target_read_memory (bfd_vma memaddr,
int length,
struct disassemble_info *info)
{
cpu_memory_rw_debug(cpu_single_env, memaddr, myaddr, length, 0);
int i;
for(i = 0; i < length; i++) {
myaddr[i] = ldub_code(memaddr + i);
}
return 0;
}
@@ -195,9 +198,6 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
#elif defined(TARGET_CRIS)
disasm_info.mach = bfd_mach_cris_v32;
print_insn = print_insn_crisv32;
#elif defined(TARGET_MICROBLAZE)
disasm_info.mach = bfd_arch_microblaze;
print_insn = print_insn_microblaze;
#else
fprintf(out, "0x" TARGET_FMT_lx
": Asm output not supported on this arch\n", code);
@@ -222,13 +222,6 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
fprintf(out, "\n");
if (count < 0)
break;
if (size < count) {
fprintf(out,
"Disassembler disagrees with translator over instruction "
"decoding\n"
"Please report this to qemu-devel@nongnu.org\n");
break;
}
}
}
@@ -315,7 +308,8 @@ const char *lookup_symbol(target_ulong orig_addr)
#if !defined(CONFIG_USER_ONLY)
#include "monitor.h"
void term_vprintf(const char *fmt, va_list ap);
void term_printf(const char *fmt, ...);
static int monitor_disas_is_physical;
static CPUState *monitor_disas_env;
@@ -336,19 +330,19 @@ static int monitor_fprintf(FILE *stream, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
monitor_vprintf((Monitor *)stream, fmt, ap);
term_vprintf(fmt, ap);
va_end(ap);
return 0;
}
void monitor_disas(Monitor *mon, CPUState *env,
void monitor_disas(CPUState *env,
target_ulong pc, int nb_insn, int is_physical, int flags)
{
int count, i;
struct disassemble_info disasm_info;
int (*print_insn)(bfd_vma pc, disassemble_info *info);
INIT_DISASSEMBLE_INFO(disasm_info, (FILE *)mon, monitor_fprintf);
INIT_DISASSEMBLE_INFO(disasm_info, NULL, monitor_fprintf);
monitor_disas_env = env;
monitor_disas_is_physical = is_physical;
@@ -394,15 +388,15 @@ void monitor_disas(Monitor *mon, CPUState *env,
print_insn = print_insn_little_mips;
#endif
#else
monitor_printf(mon, "0x" TARGET_FMT_lx
": Asm output not supported on this arch\n", pc);
term_printf("0x" TARGET_FMT_lx
": Asm output not supported on this arch\n", pc);
return;
#endif
for(i = 0; i < nb_insn; i++) {
monitor_printf(mon, "0x" TARGET_FMT_lx ": ", pc);
term_printf("0x" TARGET_FMT_lx ": ", pc);
count = print_insn(pc, &disasm_info);
monitor_printf(mon, "\n");
term_printf("\n");
if (count < 0)
break;
pc += count;

View File

@@ -1,17 +1,11 @@
#ifndef _QEMU_DISAS_H
#define _QEMU_DISAS_H
#include "qemu-common.h"
/* Disassemble this for me please... (debugging). */
void disas(FILE *out, void *code, unsigned long size);
void target_disas(FILE *out, target_ulong code, target_ulong size, int flags);
/* The usual mess... FIXME: Remove this condition once dyngen-exec.h is gone */
#ifndef __DYNGEN_EXEC_H__
void monitor_disas(Monitor *mon, CPUState *env,
void monitor_disas(CPUState *env,
target_ulong pc, int nb_insn, int is_physical, int flags);
#endif
/* Look up symbol for debugging purpose. Returns "" if unknown. */
const char *lookup_symbol(target_ulong orig_addr);

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));
@@ -79,7 +81,7 @@ static void dma_bdrv_unmap(DMAAIOCB *dbs)
}
}
static void dma_bdrv_cb(void *opaque, int ret)
void dma_bdrv_cb(void *opaque, int ret)
{
DMAAIOCB *dbs = (DMAAIOCB *)opaque;
target_phys_addr_t cur_addr, cur_len;
@@ -130,26 +132,12 @@ static void dma_bdrv_cb(void *opaque, int ret)
}
}
static void dma_aio_cancel(BlockDriverAIOCB *acb)
{
DMAAIOCB *dbs = container_of(acb, DMAAIOCB, common);
if (dbs->acb) {
bdrv_aio_cancel(dbs->acb);
}
}
static AIOPool dma_aio_pool = {
.aiocb_size = sizeof(DMAAIOCB),
.cancel = dma_aio_cancel,
};
static BlockDriverAIOCB *dma_bdrv_io(
BlockDriverState *bs, QEMUSGList *sg, uint64_t sector_num,
BlockDriverCompletionFunc *cb, void *opaque,
int is_write)
{
DMAAIOCB *dbs = qemu_aio_get(&dma_aio_pool, bs, cb, opaque);
DMAAIOCB *dbs = qemu_aio_get_pool(&dma_aio_pool, bs, cb, opaque);
dbs->acb = NULL;
dbs->bs = bs;
@@ -182,3 +170,17 @@ 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);
}

5
dma.h
View File

@@ -11,8 +11,7 @@
#define DMA_H
#include <stdio.h>
//#include "cpu.h"
#include "hw/hw.h"
#include "cpu.h"
#include "block.h"
typedef struct {
@@ -38,4 +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

View File

@@ -14,7 +14,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
*/
#if !defined(__DYNGEN_EXEC_H__)
#define __DYNGEN_EXEC_H__
@@ -30,16 +31,58 @@
point because host CPU registers are used as global variables. Some
host headers do not allow that. */
#include <stddef.h>
#include <stdint.h>
#ifdef __OpenBSD__
#include <sys/types.h>
#else
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
// Linux/Sparc64 defines uint64_t
#if !(defined (__sparc_v9__) && defined(__linux__)) && !(defined(__APPLE__) && defined(__x86_64__))
/* XXX may be done for all 64 bits targets ? */
#if defined (__x86_64__) || defined(__ia64) || defined(__s390x__) || defined(__alpha__) || defined(_ARCH_PPC64)
typedef unsigned long uint64_t;
#else
typedef unsigned long long uint64_t;
#endif
#endif
/* if Solaris/__sun__, don't typedef int8_t, as it will be typedef'd
prior to this and will cause an error in compliation, conflicting
with /usr/include/sys/int_types.h, line 75 */
#ifndef __sun__
typedef signed char int8_t;
#endif
typedef signed short int16_t;
typedef signed int int32_t;
// Linux/Sparc64 defines int64_t
#if !(defined (__sparc_v9__) && defined(__linux__)) && !(defined(__APPLE__) && defined(__x86_64__))
#if defined (__x86_64__) || defined(__ia64) || defined(__s390x__) || defined(__alpha__) || defined(_ARCH_PPC64)
typedef signed long int64_t;
#else
typedef signed long long int64_t;
#endif
#endif
#endif
/* XXX: This may be wrong for 64-bit ILP32 hosts. */
typedef void * host_reg_t;
#ifdef HOST_BSD
#define INT8_MIN (-128)
#define INT16_MIN (-32767-1)
#define INT32_MIN (-2147483647-1)
#define INT64_MIN (-(int64_t)(9223372036854775807)-1)
#define INT8_MAX (127)
#define INT16_MAX (32767)
#define INT32_MAX (2147483647)
#define INT64_MAX ((int64_t)(9223372036854775807))
#define UINT8_MAX (255)
#define UINT16_MAX (65535)
#define UINT32_MAX (4294967295U)
#define UINT64_MAX ((uint64_t)(18446744073709551615))
#ifdef _BSD
typedef struct __sFILE FILE;
#else
typedef struct FILE FILE;
@@ -54,31 +97,57 @@ extern int printf(const char *, ...);
#define AREG0 "ebp"
#define AREG1 "ebx"
#define AREG2 "esi"
#define AREG3 "edi"
#elif defined(__x86_64__)
#define AREG0 "r14"
#define AREG1 "r15"
#define AREG2 "r12"
#define AREG3 "r13"
//#define AREG4 "rbp"
//#define AREG5 "rbx"
#elif defined(_ARCH_PPC)
#define AREG0 "r27"
#define AREG1 "r24"
#define AREG2 "r25"
#define AREG3 "r26"
/* XXX: suppress this hack */
#if defined(CONFIG_USER_ONLY)
#define AREG4 "r16"
#define AREG5 "r17"
#define AREG6 "r18"
#define AREG7 "r19"
#define AREG8 "r20"
#define AREG9 "r21"
#define AREG10 "r22"
#define AREG11 "r23"
#endif
#elif defined(__arm__)
#define AREG0 "r7"
#define AREG1 "r4"
#define AREG2 "r5"
#define AREG3 "r6"
#elif defined(__hppa__)
#define AREG0 "r17"
#define AREG1 "r14"
#define AREG2 "r15"
#define AREG3 "r16"
#elif defined(__mips__)
#define AREG0 "fp"
#define AREG1 "s0"
#define AREG2 "s1"
#define AREG3 "s2"
#define AREG4 "s3"
#define AREG5 "s4"
#define AREG6 "s5"
#define AREG7 "s6"
#define AREG8 "s7"
#elif defined(__sparc__)
#ifdef HOST_SOLARIS
#define AREG0 "g2"
#define AREG1 "g3"
#define AREG2 "g4"
#define AREG3 "g5"
#define AREG4 "g6"
#else
#ifdef __sparc_v9__
#define AREG0 "g5"
@@ -88,26 +157,43 @@ extern int printf(const char *, ...);
#define AREG0 "g6"
#define AREG1 "g1"
#define AREG2 "g2"
#define AREG3 "g3"
#define AREG4 "l0"
#define AREG5 "l1"
#define AREG6 "l2"
#define AREG7 "l3"
#define AREG8 "l4"
#define AREG9 "l5"
#define AREG10 "l6"
#define AREG11 "l7"
#endif
#endif
#elif defined(__s390__)
#define AREG0 "r10"
#define AREG1 "r7"
#define AREG2 "r8"
#define AREG3 "r9"
#elif defined(__alpha__)
/* Note $15 is the frame pointer, so anything in op-i386.c that would
require a frame pointer, like alloca, would probably loose. */
#define AREG0 "$15"
#define AREG1 "$9"
#define AREG2 "$10"
#define AREG3 "$11"
#define AREG4 "$12"
#define AREG5 "$13"
#define AREG6 "$14"
#elif defined(__mc68000)
#define AREG0 "%a5"
#define AREG1 "%a4"
#define AREG2 "%d7"
#define AREG3 "%d6"
#define AREG4 "%d5"
#elif defined(__ia64__)
#define AREG0 "r7"
#define AREG1 "r4"
#define AREG2 "r5"
#define AREG3 "r6"
#else
#error unsupported CPU
#endif

21
elf.h
View File

@@ -119,8 +119,6 @@ typedef int64_t Elf64_Sxword;
*/
#define EM_S390_OLD 0xA390
#define EM_XILINX_MICROBLAZE 0xBAAB
/* This is the info that is needed to parse the dynamic section of the file */
#define DT_NULL 0
#define DT_NEEDED 1
@@ -1081,23 +1079,7 @@ typedef struct elf64_shdr {
#define EI_CLASS 4
#define EI_DATA 5
#define EI_VERSION 6
#define EI_OSABI 7
#define EI_PAD 8
#define ELFOSABI_NONE 0 /* UNIX System V ABI */
#define ELFOSABI_SYSV 0 /* Alias. */
#define ELFOSABI_HPUX 1 /* HP-UX */
#define ELFOSABI_NETBSD 2 /* NetBSD. */
#define ELFOSABI_LINUX 3 /* Linux. */
#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */
#define ELFOSABI_AIX 7 /* IBM AIX. */
#define ELFOSABI_IRIX 8 /* SGI Irix. */
#define ELFOSABI_FREEBSD 9 /* FreeBSD. */
#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */
#define ELFOSABI_MODESTO 11 /* Novell Modesto. */
#define ELFOSABI_OPENBSD 12 /* OpenBSD. */
#define ELFOSABI_ARM 97 /* ARM */
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
#define EI_PAD 7
#define ELFMAG0 0x7f /* EI_MAG */
#define ELFMAG1 'E'
@@ -1124,7 +1106,6 @@ typedef struct elf64_shdr {
#define NT_PRFPREG 2
#define NT_PRPSINFO 3
#define NT_TASKSTRUCT 4
#define NT_AUXV 6
#define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */

View File

@@ -67,7 +67,7 @@ static int glue(symfind, SZ)(const void *s0, const void *s1)
int result = 0;
if (key->st_value < sym->st_value) {
result = -1;
} else if (key->st_value >= sym->st_value + sym->st_size) {
} else if (key->st_value > sym->st_value + sym->st_size) {
result = 1;
}
return result;
@@ -82,7 +82,7 @@ static const char *glue(lookup_symbol, SZ)(struct syminfo *s, target_ulong orig_
key.st_value = orig_addr;
sym = bsearch(&key, syms, s->disas_num_syms, sizeof(*syms), glue(symfind, SZ));
if (sym != NULL) {
if (sym != 0) {
return s->disas_strtab + sym->st_name;
}
@@ -185,7 +185,7 @@ static int glue(load_elf, SZ)(int fd, int64_t address_offset,
struct elf_phdr *phdr = NULL, *ph;
int size, i, total_size;
elf_word mem_size;
uint64_t addr, low = (uint64_t)-1, high = 0;
uint64_t addr, low = 0, high = 0;
uint8_t *data = NULL;
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
@@ -194,21 +194,8 @@ static int glue(load_elf, SZ)(int fd, int64_t address_offset,
glue(bswap_ehdr, SZ)(&ehdr);
}
switch (ELF_MACHINE) {
case EM_PPC64:
if (EM_PPC64 != ehdr.e_machine)
if (EM_PPC != ehdr.e_machine)
goto fail;
break;
case EM_X86_64:
if (EM_X86_64 != ehdr.e_machine)
if (EM_386 != ehdr.e_machine)
goto fail;
break;
default:
if (ELF_MACHINE != ehdr.e_machine)
goto fail;
}
if (ELF_MACHINE != ehdr.e_machine)
goto fail;
if (pentry)
*pentry = (uint64_t)(elf_sword)ehdr.e_entry;
@@ -249,9 +236,9 @@ static int glue(load_elf, SZ)(int fd, int64_t address_offset,
cpu_physical_memory_write_rom(addr, data, mem_size);
total_size += mem_size;
if (addr < low)
if (!low || addr < low)
low = addr;
if ((addr + mem_size) > high)
if (!high || (addr + mem_size) > high)
high = addr + mem_size;
qemu_free(data);

View File

@@ -14,7 +14,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
*/
#ifndef _EXEC_ALL_H_
@@ -315,7 +316,6 @@ static inline target_ulong get_phys_addr_code(CPUState *env1, target_ulong addr)
static inline target_ulong get_phys_addr_code(CPUState *env1, target_ulong addr)
{
int mmu_idx, page_index, pd;
void *p;
page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
mmu_idx = cpu_mmu_index(env1);
@@ -331,9 +331,7 @@ static inline target_ulong get_phys_addr_code(CPUState *env1, target_ulong addr)
cpu_abort(env1, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);
#endif
}
p = (void *)(unsigned long)addr
+ env1->tlb_table[mmu_idx][page_index].addend;
return qemu_ram_addr_from_host(p);
return addr + env1->tlb_table[mmu_idx][page_index].addend - (unsigned long)phys_ram_base;
}
/* Deterministic execution requires that IO only be performed on the last
@@ -351,7 +349,7 @@ static inline int can_do_io(CPUState *env)
}
#endif
#ifdef CONFIG_KQEMU
#ifdef USE_KQEMU
#define KQEMU_MODIFY_PAGE_MASK (0xff & ~(VGA_DIRTY_FLAG | CODE_DIRTY_FLAG))
#define MSR_QPI_COMMBASE 0xfabe0010
@@ -369,9 +367,6 @@ void kqemu_record_dump(void);
extern uint32_t kqemu_comm_base;
extern ram_addr_t kqemu_phys_ram_size;
extern uint8_t *kqemu_phys_ram_base;
static inline int kqemu_is_ok(CPUState *env)
{
return(env->kqemu_enabled &&
@@ -389,8 +384,4 @@ static inline int kqemu_is_ok(CPUState *env)
typedef void (CPUDebugExcpHandler)(CPUState *env);
CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler);
/* vl.c */
extern int singlestep;
#endif

611
exec.c

File diff suppressed because it is too large Load Diff

View File

@@ -17,7 +17,9 @@
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.
output=$1
shift
@@ -72,5 +74,5 @@ for input; do
echo " { \"$basename\", $arrayname }," >> $output
done
echo " { (char *)0, (char *)0 }" >> $output
echo " { 0, 0 }" >> $output
echo "};" >> $output

View File

@@ -590,12 +590,12 @@ static bits32 estimateSqrt32( int16 aExp, bits32 a )
index = ( a>>27 ) & 15;
if ( aExp & 1 ) {
z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ (int)index ];
z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ];
z = ( ( a / z )<<14 ) + ( z<<15 );
a >>= 1;
}
else {
z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ (int)index ];
z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ];
z = a / z + z;
z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 );
if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 );

View File

@@ -2,15 +2,11 @@
context is supported */
#include "softfloat.h"
#include <math.h>
#if defined(HOST_SOLARIS)
#include <fenv.h>
#endif
void set_float_rounding_mode(int val STATUS_PARAM)
{
STATUS(float_rounding_mode) = val;
#if defined(HOST_BSD) && !defined(__APPLE__) || \
(defined(HOST_SOLARIS) && HOST_SOLARIS < 10)
#if defined(_BSD) && !defined(__APPLE__) || (defined(HOST_SOLARIS) && HOST_SOLARIS < 10)
fpsetround(val);
#elif defined(__arm__)
/* nothing to do */
@@ -26,7 +22,7 @@ void set_floatx80_rounding_precision(int val STATUS_PARAM)
}
#endif
#if defined(HOST_BSD) || (defined(HOST_SOLARIS) && HOST_SOLARIS < 10)
#if defined(_BSD) || (defined(HOST_SOLARIS) && HOST_SOLARIS < 10)
#define lrint(d) ((int32_t)rint(d))
#define llrint(d) ((int64_t)rint(d))
#define lrintf(f) ((int32_t)rint(f))

View File

@@ -1,7 +1,7 @@
/* Native implementation of soft float functions */
#include <math.h>
#if (defined(HOST_BSD) && !defined(__APPLE__)) || defined(HOST_SOLARIS)
#if (defined(_BSD) && !defined(__APPLE__)) || defined(HOST_SOLARIS)
#include <ieeefp.h>
#define fabsf(f) ((float)fabs(f))
#else
@@ -20,7 +20,7 @@
* are defined in <iso/math_c99.h> with a compiler directive
*/
#if defined(HOST_SOLARIS) && (( HOST_SOLARIS <= 9 ) || ((HOST_SOLARIS >= 10) \
&& (__GNUC__ < 4))) \
&& (__GNUC__ <= 4))) \
|| (defined(__OpenBSD__) && (OpenBSD < 200811))
/*
* C99 7.12.3 classification macros
@@ -111,7 +111,7 @@ typedef union {
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point rounding mode.
*----------------------------------------------------------------------------*/
#if (defined(HOST_BSD) && !defined(__APPLE__)) || defined(HOST_SOLARIS)
#if (defined(_BSD) && !defined(__APPLE__)) || defined(HOST_SOLARIS)
#if defined(__OpenBSD__)
#define FE_RM FP_RM
#define FE_RP FP_RP

Some files were not shown because too many files have changed in this diff Show More