Compare commits

...
102 Commits
Author SHA1 Message Date
Anthony Liguori b04c3db504 Update for 0.12.4 release
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2010-05-04 09:17:19 -05:00
Juergen Lock d04d7cf158 Workaround for broken OSS_GETVERSION on FreeBSD, part two
Turns out on those versions of FreeBSD (>= 7.x) that know OSS_GETVERSION
the ioctl doesn't actually work yet (except in the Linuxolator), so if
building on FreeBSD assume the sound drivers are new enough if the ioctl
returns the errno it does currently on FreeBSD.

(Rev 2 after private discussion with malc.)

 Signed-off-by: Juergen Lock <nox@jelal.kn-bremen.de>

Signed-off-by: malc <av1474@comtv.ru>
(cherry picked from commit 72ff25e4e9)
2010-04-25 12:20:26 +02:00
malc 2b8bdd5c7f oss: fix fragment setting
Previous patch introduced subtle regression, in cases when
OSS_GETVERSION fails the code wasn't falling back to
SNDCTL_DSP_SETFRAGMENT.

Signed-off-by: malc <av1474@comtv.ru>
(cherry picked from commit 3d709fe73a)
2010-04-25 12:20:10 +02:00
malc 2a44494726 oss: issue OSS_GETVERSION ioctl only when needed
Signed-off-by: malc <av1474@comtv.ru>
(cherry picked from commit 6d246526ce)
2010-04-25 12:20:01 +02:00
malc 8f30db54d9 oss: refactor code around policy setting
This fixes a problem with a previous patch spotted by Juergen Lock,
thanks to him again.

Signed-off-by: malc <av1474@comtv.ru>
(cherry picked from commit 78d9356d3c)
2010-04-25 12:19:48 +02:00
malc b09ac1abe7 oss: workaround for cases when OSS_GETVERSION is not defined
Thanks to Juergen Lock.

Signed-off-by: malc <av1474@comtv.ru>
(cherry picked from commit e726fe7d60)
2010-04-25 12:19:39 +02:00
Stefan Hajnoczi 012d4869c1 block: Free iovec arrays allocated by multiwrite_merge()
A new iovec array is allocated when creating a merged write request.
This patch ensures that the iovec array is deleted in addition to its
qiov owner.

Reported-by: Leszek Urbanski <tygrys@moo.pl>
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 1e1ea48d42)
2010-04-24 12:45:03 +02:00
Gerd Hoffmann 3597c9c1d5 lsi: fix segfault in lsi_command_complete
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 6ac08101f9)
2010-04-18 22:02:30 +02:00
Gerd Hoffmann 3b4bef0696 lsi: pass lsi_request to lsi_reselect
All callers of lsi_reselect have a lsi_request struct at hand anyway.
So just pass it directly instead of having lsi_reselect search for it
using the tag.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit aa4d32c474)
2010-04-18 22:02:03 +02:00
Gerd Hoffmann d899303743 lsi: move dma_len+dma_buf into lsi_request
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit b96a0da06b)
2010-04-18 22:01:55 +02:00
Gerd Hoffmann 5773685183 lsi: move current_dev into lsi_request
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit daa70311e0)
2010-04-18 22:01:47 +02:00
Gerd Hoffmann d40ba77ebf lsi: have lsi_request for the whole life time of the request.
Right now lsi_request is allocated when a request is queued and released
when a request is unqueued.  With this patch applied the lsi_request is
kept for the whole lifetime of the scsi request.

Rationale: We can use it for per-request data then.  The patch does that
already for the request tag.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit af12ac9880)
2010-04-18 22:01:41 +02:00
Gerd Hoffmann a8c46d182c lsi: use QTAILQ for lsi_queue
Replace the funky array logic for queued commands with standard
qemu list functions.  Also rename lsi_queue to lsi_request.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 042ec49dc5)
2010-04-18 22:01:31 +02:00
Stefan Weil d80e20a1c3 tcp/mips: Change TCG_AREG0 (fp -> s0)
Register fp (frame pointer) is a bad choice for compilations
without optimisation, because the compiler makes heavy use
of this register (so the resulting code crashes).

Register s0 had been used for TCG_AREG1 in earlier releases,
but was no longer used and is now free for TCG_AREG0.

The resulting code works for compilations without
optimisation (tested with qemu mips in qemu mips
on x86 host).

Signed-off-by: Stefan Weil <weil@mail.berlios.de>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
2010-04-14 01:02:24 +02:00
Aurelien Jarno 1ce4fad939 sh_pci: fix memory and I/O access
Since commit 8da3ff1809 ("MMIO callback
interface changes"), the addresses passed to the I/O functions are an
offset to the start of the area. As a consequence, there is no need to
correct the address using the value of IOBR. This make possible the use
of the default MMIO functions. Moreover the addresses are now remaped
when the value if IOBR change.

The memory area corresponds to the devices behing the PCI bus, it should
not be mapped by the PCI controller. Remove the corresponding code.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry-picked from commit 5ba9e9522c)
2010-04-14 00:54:38 +02:00
Marcelo Tosatti 9167a242db Fix incoming migration with iothread
Do not allow the vcpus to execute if the vm is stopped.

Fixes -incoming with CONFIG_IOTHREAD enabled.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
(cherry picked from commit c5f32c99c6)
2010-04-14 00:10:24 +02:00
Chris Webb 09e96924ec Fix SIGFPE for vnc display of width/height = 1
During boot, the screen gets resized to height 1 and a mouse click at this
point will cause a division by zero when calculating the absolute pointer
position from the pixel (x, y). Return a click in the middle of the screen
instead in this case.

Signed-off-by: Chris Webb <chris@arachsys.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit cc39a92cbf)
2010-04-11 13:34:43 +02:00
Eduardo Habkost 69ff4e9dbd net: remove broken net_set_boot_mask() boot device validation
There are many problems with net_set_boot_mask():

1) It is broken when using the device model instead of "-net nic". Example:
   $ qemu-system-x86_64 -device rtl8139,vlan=0,id=net0,mac=52:54:00:82:41:fd,bus=pci.0,addr=0x4 -net user,vlan=0,name=hostnet0 -vnc 0.0.0.0:0 -boot n
   Cannot boot from non-existent NIC
   $
2) The mask was previously used to set which boot ROMs were supposed to be
   loaded, but this was changed long time ago. Now all ROM images are loaded,
   and SeaBIOS takes care of jumping to the right boot entry point depending on
   the boot settings.
3) Interpretation and validation of the boot parameter letters is done on
   the machine type code. Examples: PC accepts only a,b,c,d,n as valid boot
   device letters. mac99 accepts only a,b,c,d,e,f.

As a side-effect of this change, qemu-kvm won't abort anymore if using "-boot n"
on a machine with no network devices. Checking if the requested boot device is
valid is now a task for the BIOS or the machine-type code.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Acked-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry-picked from da1fcfda59)
2010-04-11 12:33:21 +02:00
Kevin Wolf 0434349d6a qcow2: Remove request from in-flight list after error
If we complete a request with a failure we need to remove it from the list of
requests that are in flight. If we don't do it, the next time the same AIOCB is
used for a cluster allocation it will create a loop in the list and qemu will
hang in an endless loop.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit c644db3d53)
2010-04-10 01:54:52 +02:00
Kevin Wolf e007221223 qcow2: Don't ignore immediate read/write failures
Returning -EIO is far from optimal, but at least it's an error code.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 171e3d6b99)
2010-04-10 01:51:35 +02:00
Kevin Wolf 4622317288 block: Fix multiwrite memory leak in error case
Previously multiwrite_user_cb was never called if a request in the multiwrite
batch failed right away because it did set mcb->error immediately. Make it look
more like a normal callback to fix this.

Reported-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 7eb58a6c55)
2010-04-10 01:15:54 +02:00
Kevin Wolf ffac613ff9 block: Fix error code in multiwrite for immediate failures
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 0f0b604b00)
2010-04-10 01:15:44 +02:00
Kevin Wolf aba5288247 block: Fix multiwrite error handling
When two requests of the same multiwrite batch fail, the callback of all
requests in that batch were called twice. This could have any kind of nasty
effects, in my case it lead to use after free and eventually a segfault.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit cb6d3ca07b)
2010-04-10 00:36:49 +02:00
Gerd Hoffmann 4f7cb96931 scsi-disk: fix buffer overflow
In case s->version is shorter than 4 bytes we overflow the memcpy src
buffer.  Fix it by clearing the target buffer, then copy only the
amount of bytes we actually have.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from 314b1811c1)

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2010-04-09 18:41:59 +02:00
Kevin Wolf fafc2e4b33 qcow2: Rewrite alloc_refcount_block/grow_refcount_table
The current implementation of alloc_refcount_block and grow_refcount_table has
fundamental problems regarding error handling. There are some places where an
I/O error means that the image is going to be corrupted. I have found that the
only way to fix this is to completely rewrite the thing.

In detail, the problem is that the refcount blocks itself are allocated using
alloc_refcount_noref (to avoid endless recursion when updating the refcount of
the new refcount block, which migh access just the same refcount block but its
allocation is not yet completed...). Only at the end of the refcount allocation
the refcount of the refcount block is increased. If an error happens in
between, the refcount block is in use, but has a refcount of zero and will
likely be overwritten later.

The new approach is explained in comments in the code. The trick is basically
to let new refcount blocks describe their own refcount, so their refcount will
be automatically changed when they are hooked up in the refcount table.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 92dcb59fd4)
2010-04-09 18:41:59 +02:00
Kevin Wolf 83ef70f24a qcow2: Factor next_refcount_table_size out
When the refcount table grows, it doesn't only grow by one entry but reserves
some space for future refcount blocks. The algorithm to calculate the number of
entries stays the same with the fixes, so factor it out before replacing the
rest.

As Juan suggested take the opportunity to simplify the code a bit.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 05121aedc4)
2010-04-09 18:41:59 +02:00
Christoph Hellwig de17c16e1f block: avoid creating too large iovecs in multiwrite_merge
If we go over the maximum number of iovecs support by syscall we get
back EINVAL from the kernel which translate to I/O errors for the guest.

Add a MAX_IOV defintion for platforms that don't have it.  For now we use
the same 1024 define that's used on Linux and various other platforms,
but until the windows block backend implements some kind of vectored I/O
it doesn't matter.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit e2a305fb13)

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2010-04-09 18:41:59 +02:00
Kevin Wolf 9462695b64 json-parser: Fix segfault on malformed input
If the parser fails to parse the key in parse_pair, it will access a NULL
pointer. A simple way to trigger this is sending {foo} via QMP. This patch
turns the segfault into a syntax error reply.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit d758d90fe1)
2010-04-09 18:41:59 +02:00
Aurelien Jarno 5eb089588e linux-user: switch default ppc64 CPU to 970fx from 970
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit f7177937a2)
2010-04-09 18:40:39 +02:00
Aurelien Jarno 2039f70c23 target-sh4: MMU: fix store queue addresses
The store queues are located from 0xe0000000 to 0xe3ffffff.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit b1563142123593581895049568c5526b1e91da7b)
2010-04-09 18:22:38 +02:00
Aurelien Jarno 082a9fc256 target-sh4: MMU: fix ITLB priviledge check
There is an ITLB access violation if SR_MD=0 (user mode) while
the high bit of the protection key is 0 (priviledge mode).

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit bc13ad29e6b7484ccd5e7ee0f5d0f966585eb4c9)
2010-04-09 18:22:06 +02:00
Aurelien Jarno 36a013c956 target-sh4: MMU: fix mem_idx computation
The mem_idx is wrongly computed. As written in target-sh4/cpu.h, mode 0
corresponds to kernel mode (SR_MD = 1), while mode 1 corresponds to user
mode (SR_MD = 0).

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 33b8f5546cc16eaa3d89fe133a9843c794b65d6c)
2010-04-09 18:21:51 +02:00
Aurelien Jarno c4c4b32b81 sh7750: handle MMUCR TI bit
When the MMUCR TI bit is set, all the UTLB and ITLB entries should be
flushed.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit e781d1285fc3b81d689ba25360c6c272116387fa)
2010-04-09 18:21:35 +02:00
Paul Brook 804b6ab08d UHCI spurious interrut fix
Only raise an interrupt if the TD has actually completed.

Signed-off-by: Paul Brook <paul@codesourcery.com>
2010-04-06 07:02:37 +02:00
Aurelien Jarno 81b168a702 tcg/mips: fix branch offset during retranslation
Branch offsets should only be overwritten during relocation, to support
partial retranslation.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 6d8ff4d85c)
2010-03-29 02:11:35 +02:00
Aurelien Jarno 5c6892078a tcg/arm: correctly save/restore registers in prologue/epilogue
Since commit 6113d6d316 QEMU crashes
on ARM hosts. This is not a bug of this commit, but a latent bug
revealed by this commit.

The TCG code is called through a procedure call using the prologue
and epilogue code. This code does not save and restore enough registers.
The "Procedure Call Standard for the ARM Architecture" says:

  A subroutine must preserve the contents of the registers r4-r8, r10,
  r11 and SP (and r9 in PCS variants that designate r9 as v6).

The current code only saves and restores r9 to r11, and misses r4 to
r8. The patch fixes that by saving r4 to r12. Theoretically there is
no need to save and restore r12, but an even number of registers have
to be saved as per EABI.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 4e17eae9f2)
2010-03-19 23:02:37 +01:00
Igor V. Kovalenko 18a21890ff workaround for cmd646 bmdma register access while no dma is active
This is a workaround only, and is a partial revert
of a few changes to BMDMAState which removed pci_dev
field on the way.

- cmd646 pci_from_bm() expects bm->unit value to
correspond with bm data being passed to callback
as opaque pointer. This breaks when write to dma
control register of second channel happens when no
dma operation is in progress, so bm->unit is zero
for second channel, and pci_from_bm() returns garbage
pointer. Crash happens shortly after that while
dereferencing that pointer.

v0->v1: cleaned up dead code from pci_from_bm.

Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit 90228ee395)
2010-03-19 22:54:17 +01:00
Jan Kiszka 6629fa6473 Fix corner case in chardev udp: parameter
The missing '@' broke 'udp::<port>@:<port>' parsing.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 39324ca488)
2010-03-16 08:40:50 +01:00
Jan Kiszka 2a7996ce0e Don't set default monitor when there is a mux'ed one
This fixes eg. "-nographic -serial mon:stdio [-serial ...]".

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 18141ed67f)
2010-03-16 08:40:47 +01:00
Vagrant Cascadian 8ec131fb59 spelling typo (compatibilty) in hw/fw_cfg.c
here's a trivial patch to fix the spelling of "compatibility":

Signed-off-by: Vagrant Cascadian <vagrant@freegeek.org>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit 66c80e7575)
2010-03-14 22:54:26 +01:00
Gerd Hoffmann 30d061750d fdc: fix drive property handling.
Fix the floppy controller init wrappers to set the drive properties
only in case the DriveInfo pointers passed in are non NULL.  This allows
to set the properties using -global.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 995bf0ca57)
2010-03-13 12:16:06 +01:00
TeLeMan c5f5dc5bad target-i386: fix commit c22549204a
The commit c22549204a led movntps &
movntdq to be translated incorrectly.

Signed-off-by: TeLeMan <geleman@gmail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 2e21e7491f)
2010-03-13 11:37:33 +01:00
Aurelien Jarno d2df336c58 target-i386: fix SIB decoding with index = 4
A SIB byte with an index of 4 means "no scaled index", even if the scale
value is not 0. In 64-bit mode, if REX.X is used, an index of 4 selects
%r12. This is correctly handled by the computation of the index variable,
which includes the index bits, and also the REX.X prefix:

    index = ((code >> 3) & 7) | REX_X(s);

Thanks to Avi Kivity, Jamie Lokier and Malc for the analysis of the
problem and the initial patch.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit b16f827bdf)
2010-03-10 08:52:46 +01:00
Ryan Harper b299b12b17 Fix segfault with ram_size > 4095M without kvm
Currently, x86_64-softmmu qemu segfaults when trying to use > 4095M memsize.
This patch adds a simple check and error message (much like the 2047 limit on
32-bit hosts) on ram_size in the control path after we determine we're
not using kvm

Upstream qemu-kvm is affected if using the -no-kvm option; this patch address
the segfault there as well.

Signed-off-by: Ryan Harper <ryanh@us.ibm.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
2010-03-06 22:30:25 +01:00
malc c248df6161 target-i386: Fix long jumps/calls in long mode with REX.W set
Signed-off-by: malc <av1474@comtv.ru>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 41b1e61f51)
2010-03-06 19:40:11 +01:00
Aurelien Jarno 7d5625d5f7 target-i386: fix lddqu SSE instruction
This instruction load data from memory to register and not the reverse.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit c22549204a)
2010-03-06 19:40:06 +01:00
Jan Kiszka cc21d131e3 qemu-char.c: drop debug printfs from qemu_chr_parse_compat
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 5bb599023a)
2010-02-28 14:11:32 +01:00
Paolo Bonzini 41a5bda61f fix undefined shifts by >32
This one is for 0.12 too.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
(cherry picked from commit 0dfbd51446)
2010-02-27 16:36:21 +01:00
Aurelien Jarno 5163f6e864 Fix qemu -net user,hostfwd= example
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit aa37520618)
2010-02-27 11:00:13 +01:00
Anthony Liguori 6173d56bdc Merge remote branch 'qemu-kvm/uq/stable-0.12' into stable-0.12 2010-02-23 14:08:31 -06:00
Anthony Liguori f39942d217 Update version and change for 0.12.3 release
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2010-02-23 14:08:23 -06:00
Kevin Wolf 5dde87088f qcow2: Fix access after end of array
If a write requests crosses a L2 table boundary and all clusters until the
end of the L2 table are usable for the request, we must not look at the next
L2 entry because we already have arrived at the end of the array.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 4805bb6696)
2010-02-23 14:07:58 -06:00
Marcelo Tosatti 3fa017e24b ide save/restore pio/atapi cmd transfer fields and io buffer
Save/restore information necessary to continue in progress PIO/ATAPI CMD
transfers.

This includes the IO buffer.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit ed487bb1d6)
2010-02-23 14:07:58 -06:00
Markus Armbruster 35924dbe8c net: Monitor command set_link finds only VLAN clients, fix
Clients not associated with a VLAN exist since commit d80b9fc6.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 2583ba97ef)
2010-02-23 14:07:58 -06:00
Markus Armbruster 88aa905668 net: info network shows only VLAN clients, fix
Clients not associated with a VLAN exist since commit d80b9fc6.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit a0104e0ec7)
2010-02-23 14:07:58 -06:00
Markus Armbruster b93c5c84c8 net: net_check_clients() checks only VLAN clients, fix
Clients not associated with a VLAN exist since commit d80b9fc6.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit efe32fdde1)
2010-02-23 14:07:58 -06:00
Markus Armbruster f203baee5b net: Fix bogus "Warning: vlan 0 with no nics" with -device
net_check_clients() prints this when an VLAN has host devices, but no
guest devices.  It uses VLANState members nb_guest_devs and
nb_host_devs to keep track of these devices.  However, -device does
not update nb_guest_devs, only net_init_nic() does that, for -net nic.

Check the VLAN clients directly, and remove the counters.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 62112d181c)
2010-02-23 14:07:58 -06:00
Markus Armbruster 5e3be62385 net: net_check_clients() runs too early to see -device, fix
Call it right after -device devices get created.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 668680f75f)
2010-02-23 14:07:58 -06:00
Markus Armbruster b391493bc6 net: Remove unused net_client_uninit()
Unused since commit 9ad4531e.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 7f76abe1c9)
2010-02-23 14:07:58 -06:00
Jim Meyering 57f9f4c9f5 don't dereference NULL after failed strdup
Most of these are obvious NULL-deref bug fixes, for example,
the ones in these files:

  block/curl.c
  net.c
  slirp/misc.c

and the first one in block/vvfat.c.
The others in block/vvfat.c may not lead to an immediate segfault, but I
traced the two schedule_rename(..., strdup(path)) uses, and a failed
strdup would appear to trigger this assertion in handle_renames_and_mkdirs:

	    assert(commit->path);

The conversion to use qemu_strdup in envlist_to_environ is not technically
needed, but does avoid a theoretical leak in the caller when strdup fails
for one value, but later succeeds in allocating another buffer(plausible,
if one string length is much larger than the others).  The caller does
not know the length of the returned list, and as such can only free
pointers until it hits the first NULL.  If there are non-NULL pointers
beyond the first, their buffers would be leaked.  This one is admittedly
far-fetched.

The two in linux-user/main.c are worth fixing to ensure that an
OOM error is diagnosed up front, rather than letting it provoke some
harder-to-diagnose secondary error, in case of exec failure, or worse, in
case the exec succeeds but with an invalid list of command line options.
However, considering how unlikely it is to encounter a failed strdup early
in main, this isn't a big deal.  Note that adding the required uses of
qemu_strdup here and in envlist.c induce link failures because qemu_strdup
is not currently in any library they're linked with.  So for now, I've
omitted those changes, as well as the fixes in target-i386/helper.c
and target-sparc/helper.c.

If you'd like to see the above discussion (or anything else)
in the commit log, just let me know and I'll be happy to adjust.

>From 9af42864fd1ea666bd25e2cecfdfae74c20aa8c7 Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering@redhat.com>
Date: Mon, 8 Feb 2010 18:29:29 +0100
Subject: [PATCH] don't dereference NULL after failed strdup

Handle failing strdup by replacing each use with qemu_strdup,
so as not to dereference NULL or trigger a failing assertion.
* block/curl.c (curl_open): s/\bstrdup\b/qemu_strdup/
* block/vvfat.c (init_directories): Likewise.
(get_cluster_count_for_direntry, check_directory_consistency): Likewise.
* net.c (parse_host_src_port): Likewise.
* slirp/misc.c (fork_exec): Likewise.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 6265eb26a3)
2010-02-23 14:07:58 -06:00
Tom Lendacky 7ebc79037c virtio-net: fix network stall under load
Fix a race condition where qemu finds that there are not enough virtio
ring buffers available and the guest make more buffers available before
qemu can enable notifications.

Signed-off-by: Tom Lendacky <toml@us.ibm.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 06b1297017)
2010-02-23 14:07:58 -06:00
Roy Tam ea299062eb json: fix PRId64 on Win32
OK we are fooled by the json lexer and parser. As we use %I64d to
print 'long long' variables in Win32, but lexer and parser only deal
with %lld but not %I64d, this patch add support for %I64d and solve
'info pci', 'powser_reset' and 'power_powerdown' assert failure in
Win32.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 2c0d4b36e7)
2010-02-23 14:07:58 -06:00
Marcelo Tosatti e03dd1a6c2 fix inet_parse typo
qemu_opt_set wants on/off, not yes/no.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 2198a62eb2)
2010-02-23 14:07:58 -06:00
Marcelo Tosatti 535d2eb34a iothread: fix vcpu stop with smp tcg
Round robin vcpus in tcg_cpu_next even if the vm stopped. This
allows all cpus to enter stopped state.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit c37cc7b072)
2010-02-23 14:07:57 -06:00
David S. Ahern beb8eab90c segfault due to buffer overrun in usb-serial
This fixes a segfault due to buffer overrun in the usb-serial device.
The memcpy was incrementing the start location by recv_used yet, the
computation of first_size (how much to write at the end of the buffer
before wrapping to the front) was not accounting for it. This causes the
next element after the receive buffer (recv_ptr) to get overwritten with
random data.

Signed-off-by: David Ahern <daahern@cisco.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 4ab4183d76)
2010-02-23 14:07:57 -06:00
Kevin Wolf 8d67694fbf qcow2: Fix signedness bugs
Checking for return codes < 0 isn't really going to work with unsigned
types. Use signed types instead.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit f4f0d391b2)
2010-02-23 14:07:57 -06:00
Evgeniy Dushistov 02510b2436 Do not ignore error, if open file failed (-serial /dev/tty)
In case, when qemu is executed with option like
-serial /dev/ttyS0, report if there are problems with
opening of devices. At now errors are silently ignoring.

Signed-off-by: Evgeniy Dushistov <dushistov@mail.ru>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit afc535acb5)
2010-02-23 14:07:57 -06:00
Anthony Liguori b57a2297f2 pc-bios: update to newer version of (stable) seabios
- 9fb3f4d Fix PkgLength calculation for the SSDT.
 - 6d75be2 Go back to using 0xf0000000 for PCI memory start.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2010-02-23 14:07:57 -06:00
Jan Kiszka 43fab08210 kvm: Fix eflags corruption in kvm mode
This should explain a lot of the weird breakages of upstream KVM we've
seen recently (actually we should have seen it much earlier):

Stop translating eflags into TCG format when in kvm mode as we never
translate it back and rather sync this broken state into the kernel.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
2010-02-23 14:07:57 -06:00
Aurelien Jarno 915080e6b1 target-mips: fix ROTR and DROTR by zero
Backported from HEAD (cc3f20fee2c9bea3793bf873c531ae6baf68df3a)

Signed-off-by: Nathan Froyd <froydnj@codesourcery.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
2010-02-23 18:31:00 +01:00
Nathan Froyd 9f59ddcc4f target-mips: fix CpU exception for coprocessor 0
When we signal a CpU exception for coprocessor 0, we should indicate
that it's for coprocessor 0 instead of coprocessor 1.

Signed-off-by: Nathan Froyd <froydnj@codesourcery.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 13f160cebd0778113ba8d251aea297286b1666cb)
2010-02-23 18:27:54 +01:00
Jan Kiszka 999ceb2c1d kvm: Fix eflags corruption in kvm mode
This should explain a lot of the weird breakages of upstream KVM we've
seen recently (actually we should have seen it much earlier):

Stop translating eflags into TCG format when in kvm mode as we never
translate it back and rather sync this broken state into the kernel.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
2010-02-21 11:13:19 +02:00
Aurelien Jarno 307331a42a tcg/mips: fix crash in tcg_out_qemu_ld()
The address register is overriden when it corresponds to v0 and the fast
path is taken, which leads to a crash. Fix that by using the a0 register
instead.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit cca1af8c4d)
2010-02-09 23:29:44 +01:00
Aurelien Jarno 6728dd464b target-mips: don't call cpu_loop_exit() from helper.c
In helper.c AREG0 may not correspond do env, so it's not possible to
call cpu_loop_exit() here. Call it from op_helper.c instead.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit c36bbb28ad)
2010-02-06 17:25:15 +01:00
Kevin Wolf bb45bcc8de virtio-blk: Fix error cases which ignored rerror/werror
If an I/O request fails right away instead of getting an error only in the
callback, we still need to consider rerror/werror.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 6c510fbf60)
2010-01-29 10:21:29 -06:00
Kevin Wolf 096109c804 virtio-blk: Fix restart after read error
Current code assumes that only write requests are ever going to be restarted.
This is wrong since rerror=stop exists. Instead of directly starting writes,
use the same request processing as used for new requests.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit f1b5286803)
2010-01-29 10:21:20 -06:00
Kevin Wolf 7ae1fcc88c virtio_blk: Factor virtio_blk_handle_request out
We need a function that handles a single request. Create one by splitting out
code from virtio_blk_handle_output.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit bc6694d43a)
2010-01-29 10:21:11 -06:00
Jan Kiszka 299e0bc52a cirrus: Properly re-register cirrus_linear_io_addr on vram unmap
This fixes CONFIG_FB_CIRRUS for Linux guests and probably much more:

When switching away from linearly mapped vram, we also have to restore
the I/O handlers for the LFB.

This regression was once introduced by commit 2bec46dc97.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 4516e45f82)
2010-01-29 10:21:00 -06:00
Kevin Wolf 74f0529e24 qcow2: Don't ignore qcow2_alloc_clusters return value
Now that qcow2_alloc_clusters can return error codes, we must handle them in
the callers of qcow2_alloc_clusters.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 5d757b563d)
2010-01-27 07:52:50 -06:00
Kevin Wolf 614971158c qcow2: Don't ignore update_refcount return value
update_refcount can return errors that need to be handled by the callers.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit db3a964fb6)
2010-01-27 07:52:40 -06:00
Kevin Wolf afa328b1b2 qcow2: Allow updating no refcounts
There's absolutely no problem with updating the refcounts of 0 clusters.
At least snapshot code is doing this and would fail once the result of
update_refcount isn't ignored any more.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 7322afe7ea)
2010-01-27 07:52:32 -06:00
Kevin Wolf 868dab5dc2 qcow2: Improve error handling in update_refcount
If update_refcount fails, try to undo any changes made so far to avoid
inconsistencies in the image file.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 09508d13f3)
2010-01-27 07:52:22 -06:00
Kevin Wolf 29bb3bf350 qcow2: Fix error handling in grow_refcount_table
Return the appropriate error code instead of -EIO.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit f2b7c8b370)
2010-01-27 07:52:12 -06:00
Kevin Wolf dbf45b44b7 block: Return original error codes in bdrv_pread/write
Don't assume -EIO but return the real error.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 9a8c4cceaf)
2010-01-27 07:51:46 -06:00
Kevin Wolf d0d888bc6d qcow2: Return 0/-errno in qcow2_alloc_cluster_offset
Returning 0/-errno allows it to distingush different errors classes. The
cluster offset of newly allocated clusters is now returned in the QCowL2Meta
struct.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 148da7ea9d)
2010-01-27 07:51:35 -06:00
Kevin Wolf 19abbad0da qcow2: Return 0/-errno in get_cluster_table
Switching to 0/-errno allows it to distinguish different error cases.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 1e3e8f1a43)
2010-01-27 07:51:23 -06:00
Kevin Wolf f48aba6de7 qcow2: Fix error handling in qcow_save_vmstate
Don't assume success but pass the bdrv_pwrite return value on.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 1d36e3aae3)
2010-01-27 07:51:10 -06:00
Kevin Wolf cb2ae96bf6 qcow2: Fix error handling in qcow2_grow_l1_table
Return the appropriate error value instead of always using EIO. Don't free the
L1 table on errors, we still need it.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit fb8fa77ce1)
2010-01-27 07:51:02 -06:00
Herve Poussineau 848f874ca1 win32/sdl: Fix toggle full screen
Toggle full screen on Win32/SDL 1.2.13 was broken by commit
c18a2c360e. Re-add the call to
do_sdl_resize() which was removed in this revision

Signed-off-by: Herve Poussineau <hpoussin@reactos.org>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit a35aed57bf)
2010-01-26 18:09:32 -06:00
Herve Poussineau a1a86bf902 win32: pair qemu_memalign() with qemu_vfree()
Win32 suffers from a very big memory leak when dealing with SCSI devices.
Each read/write request allocates memory with qemu_memalign (ie
VirtualAlloc) but frees it with qemu_free (ie free).
Pair all qemu_memalign() calls with qemu_vfree() to prevent such leaks.

Signed-off-by: Herve Poussineau <hpoussin@reactos.org>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit f8a83245d9)
2010-01-26 18:09:22 -06:00
Stefano Stabellini c727a05459 vnc_refresh: calling vnc_update_client might free vs
Hi all,
this patch fixes another bug in vnc_refresh: calling vnc_update_client
might cause vs to be free()ed, in this case we cannot access vs->next
right after to examine the next item on the list.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 6185c5783c)
2010-01-26 18:09:08 -06:00
Jan Kiszka eb05143e24 Musicpal: Fix descriptor walk in eth_send
Commit 930c86820e introduced a regression to eth_send: eth_tx_desc_put
manipulates the host's tx descriptor copy before writing it back, but
two lines down the descriptor is evaluated again, leaving us with an
invalid next address if host and guest endianness differ. So this was
the actual issue commit 2e87c5b937 tried to paper over.

Signed-off-by: Jan Kiszka <jan.kiszka@web.de>
Signed-off-by: malc <av1474@comtv.ru>
(cherry picked from commit 07b064e9de)

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2010-01-26 16:20:20 -06:00
Jan Kiszka 0c709e6195 Musicpal: Fix wm8750 I2C address
Commit b3a219883e uncovered that we attached the Wolfson with an I2C
address shifted left by one. Fixing this makes sound work again for
the Musicpal.

Signed-off-by: Jan Kiszka <jan.kiszka@web.de>
Signed-off-by: malc <av1474@comtv.ru>
(cherry picked from commit 6425822964)

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2010-01-26 16:20:12 -06:00
Marcelo Tosatti dc88aa49b4 fix savevm command without id or tag
savevm without id or tag segfaults in:

(gdb) bt
#0  0x00007f600a83bf8a in __strcmp_sse42 () from /lib64/libc.so.6
#1  0x00000000004745b6 in bdrv_snapshot_find (bs=<value optimized out>,
    sn_info=0x7fff996be280, name=0x0) at savevm.c:1631
#2  0x0000000000475c80 in del_existing_snapshots (name=<value optimized out>,
    mon=<value optimized out>) at savevm.c:1654
#3  do_savevm (name=<value optimized out>, mon=<value optimized out>)

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit f139a41256)
2010-01-26 15:59:11 -06:00
Gleb Natapov dc2ffbf6d8 reduce number of reinjects on ACK
Windows 7 BSODs under load with HAL_RTC_IRQF_WILL_NOT_CLEAR error.

It happens here:
hal!HalpRtcUnmaskClock:
8281b93a 8bff            mov     edi,edi
8281b93c 56              push    esi
8281b93d 33f6            xor     esi,esi
8281b93f 6a0c            push    0Ch
8281b941 e8b2ffffff      call    hal!CMOS_READ (8281b8f8)
8281b946 84c0            test    al,al
8281b948 7920            jns     hal!HalpRtcUnmaskClock+0x30 (8281b96a)
8281b94a 6a0a            push    0Ah
8281b94c 46              inc     esi
8281b94d e854c8ffff      call    hal!KeStallExecutionProcessor (828181a6)
8281b952 83fe64          cmp     esi,64h
8281b955 72e8            jb      hal!HalpRtcUnmaskClock+0x5 (8281b93f)
8281b957 6a00            push    0
8281b959 6a00            push    0
8281b95b 6a00            push    0
8281b95d 680a010000      push    10Ah
8281b962 6a5c            push    5Ch
8281b964 ff1500c38082    call    dword ptr [hal!_imp__KeBugCheckEx (8280c300)]
8281b96a 5e              pop     esi
8281b96b c3              ret

So it loops for 100(64h) times reading register C before BSOD. Lets
reduce number of immediate reinjection well under this limit.

Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit dd17765b5f)
2010-01-20 08:54:22 -06:00
Luiz Capitulino d3bf9367f2 QMP: Fix asynchronous events delivery
Commit f039a563f2 introduces
a regression as monitor_protocol_event() will return in
the first user Monitor it finds in the QLIST_FOREACH()
loop.

The right thing to do is to only delivery an asynchronous
event if the 'mon' is a QMP Monitor.

The aforementioned commit was an early version, if it was
applied to stable (it should) this one has to be applied
there too.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 23fabed136)
2010-01-20 08:53:24 -06:00
Stefan Weil c502715a74 Documentation: Add missing documentation for qdev related command line options
The command line options -device, -nodefaults, -readconfig,
-writeconfig had entries for command line help, but
documentation for texi and derived formats (man, html, info)
was missing.

This also required moving "@end table" to the end of
qemu-options.hx again.

Signed-off-by: Stefan Weil <weil@mail.berlios.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 3dbf2c7fc5)
2010-01-20 08:53:02 -06:00
Gerd Hoffmann b9a61d2154 pc: add driver version compat properties
This patch adds compat property entries for ide-disk.ver and
scsi-disk.ver to pc-0.10 and pc-0.11.  With this patch applied
the scsi and ide disks report "0.10" and "0.11" as version when
you start qemu with "-M pc-0.10" or "-M pc-0.11".

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 374ef70452)
2010-01-19 16:42:45 -06:00
Gerd Hoffmann 9525204c5d scsi: device version property
This patch adds a new property named 'ver' to scsi-disk which allows to
specify the version which the virtual disk/cdrom should report to the
guest.  By default this is the qemu version (i.e. 0.12).  usage:

  -drive if=none,id=disk,file=...
  -device lsi
  -device scsi-disk,drive=disk,bus=scsi.0,unit=0,ver=42

You can also switch the version for all scsi drives using:

  -global scsi-disk.ver=42

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 383b4d9b79)
2010-01-19 16:42:37 -06:00
Gerd Hoffmann f79d556b4f ide: device version property
This patch adds a new property named 'ver' to ide-drive which allows to
specify the version which the virtual disk/cdrom should report to the
guest.  By default this is the qemu version (i.e. 0.12).  usage:

  -drive if=none,id=disk,file=...
  -device ide-drive,bus=ide.0,unit=0,drive=disk,ver=42

You can also switch the version for all ide drives using:

  -global ide-drive.ver=42

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 47c0634030)
2010-01-19 16:42:25 -06:00
Adam Litke 41ae9ece21 QMP: Emit asynchronous events on all QMP monitors
When using a control/QMP monitor in tandem with a regular monitor, asynchronous
messages can get lost depending on the order of the QEMU program arguments.
QEMU events issued by monitor_protocol_event() always go to cur_mon.  If the
user monitor was specified on the command line first (or it has ,default), the
message will be directed to the user monitor (not the QMP monitor).
Additionally, only one QMP session is currently able to receive async messages.

To avoid this confusion, scan through the list of monitors and emit the message
on each QMP monitor.

Signed-off-by: Adam Litke <agl@us.ibm.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit f039a563f2)
2010-01-19 16:42:15 -06:00
Kevin Wolf 40480d2bf4 Fix QEMU_WARN_UNUSED_RESULT
Since commit 747bbdf7 QEMU_WARN_UNUSED_RESULT is never defined as it is
conditional on a define from config-host.h which is included only later.
Include that file earlier to get the warnings back.

Reactivating it unfortunately leads to some warnings about unused qdev_init
results. These calls are changed to qdev_init_nofail to avoid build failures.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit beb6f0de7a)
2010-01-19 16:42:03 -06:00
72 changed files with 1193 additions and 658 deletions

No files matched your search

+102
View File
@@ -1,3 +1,105 @@
version 0.12.4
- Workaround for broken OSS_GETVERSION on FreeBSD, part two (Juergen Lock)
- oss: fix fragment setting (malc)
- oss: issue OSS_GETVERSION ioctl only when needed (malc)
- oss: refactor code around policy setting (malc)
- oss: workaround for cases when OSS_GETVERSION is not defined (malc)
- block: Free iovec arrays allocated by multiwrite_merge() (Stefan Hajnoczi)
- lsi: fix segfault in lsi_command_complete (Gerd Hoffmann)
- lsi: pass lsi_request to lsi_reselect (Gerd Hoffmann)
- lsi: move dma_len+dma_buf into lsi_request (Gerd Hoffmann)
- lsi: move current_dev into lsi_request (Gerd Hoffmann)
- lsi: have lsi_request for the whole life time of the request. (Gerd Hoffmann)
- lsi: use QTAILQ for lsi_queue (Gerd Hoffmann)
- tcp/mips: Change TCG_AREG0 (fp -> s0) (Stefan Weil)
- sh_pci: fix memory and I/O access (Aurelien Jarno)
- Fix incoming migration with iothread (Marcelo Tosatti)
- Fix SIGFPE for vnc display of width/height = 1 (Chris Webb)
- net: remove broken net_set_boot_mask() boot device validation (Eduardo Habkost)
- qcow2: Remove request from in-flight list after error (Kevin Wolf)
- qcow2: Don't ignore immediate read/write failures (Kevin Wolf)
- block: Fix multiwrite memory leak in error case (Kevin Wolf)
- block: Fix error code in multiwrite for immediate failures (Kevin Wolf)
- block: Fix multiwrite error handling (Kevin Wolf)
- scsi-disk: fix buffer overflow (Gerd Hoffmann)
- qcow2: Rewrite alloc_refcount_block/grow_refcount_table (Kevin Wolf)
- qcow2: Factor next_refcount_table_size out (Kevin Wolf)
- block: avoid creating too large iovecs in multiwrite_merge (Christoph Hellwig)
- json-parser: Fix segfault on malformed input (Kevin Wolf)
- linux-user: switch default ppc64 CPU to 970fx from 970 (Aurelien Jarno)
- target-sh4: MMU: fix store queue addresses (Aurelien Jarno)
- target-sh4: MMU: fix ITLB priviledge check (Aurelien Jarno)
- target-sh4: MMU: fix mem_idx computation (Aurelien Jarno)
- sh7750: handle MMUCR TI bit (Aurelien Jarno)
- UHCI spurious interrut fix (Paul Brook)
- tcg/mips: fix branch offset during retranslation (Aurelien Jarno)
- tcg/arm: correctly save/restore registers in prologue/epilogue (Aurelien Jarno)
- workaround for cmd646 bmdma register access while no dma is active (Igor V. Kovalenko)
- Fix corner case in chardev udp: parameter (Jan Kiszka)
- Don't set default monitor when there is a mux'ed one (Jan Kiszka)
- spelling typo (compatibilty) in hw/fw_cfg.c (Vagrant Cascadian)
- fdc: fix drive property handling. (Gerd Hoffmann)
- target-i386: fix commit c22549204a6edc431e8e4358e61bd56386ff6957 (TeLeMan)
- target-i386: fix SIB decoding with index = 4 (Aurelien Jarno)
- Fix segfault with ram_size > 4095M without kvm (Ryan Harper)
- target-i386: Fix long jumps/calls in long mode with REX.W set (malc)
- target-i386: fix lddqu SSE instruction (Aurelien Jarno)
- qemu-char.c: drop debug printfs from qemu_chr_parse_compat (Jan Kiszka)
- fix undefined shifts by >32 (Paolo Bonzini)
- Fix qemu -net user,hostfwd= example (Aurelien Jarno)
version 0.12.3
- kvm: Fix eflags corruption in kvm mode (Jan Kiszka)
- qcow2: Fix access after end of array (Kevin Wolf)
- ide save/restore pio/atapi cmd transfer fields and io buffer (Marcelo Tosatti)
- net: Monitor command set_link finds only VLAN clients, fix (Markus Armbruster)
- net: info network shows only VLAN clients, fix (Markus Armbruster)
- net: net_check_clients() checks only VLAN clients, fix (Markus Armbruster)
- net: Fix bogus "Warning: vlan 0 with no nics" with -device (Markus Armbruster)
- net: net_check_clients() runs too early to see -device, fix (Markus Armbruster)
- net: Remove unused net_client_uninit() (Markus Armbruster)
- don't dereference NULL after failed strdup (Jim Meyering)
- virtio-net: fix network stall under load (Tom Lendacky)
- json: fix PRId64 on Win32 (Roy Tam)
- fix inet_parse typo (Marcelo Tosatti)
- iothread: fix vcpu stop with smp tcg (Marcelo Tosatti)
- segfault due to buffer overrun in usb-serial (David S. Ahern)
- qcow2: Fix signedness bugs (Kevin Wolf)
- Do not ignore error, if open file failed (-serial /dev/tty) (Evgeniy Dushistov)
- pc-bios: update to newer version of (stable) seabios (Anthony Liguori)
- target-mips: fix ROTR and DROTR by zero (Aurelien Jarno)
- target-mips: fix CpU exception for coprocessor 0 (Nathan Froyd)
- tcg/mips: fix crash in tcg_out_qemu_ld() (Aurelien Jarno)
- target-mips: don't call cpu_loop_exit() from helper.c (Aurelien Jarno)
- virtio-blk: Fix error cases which ignored rerror/werror (Kevin Wolf)
- virtio-blk: Fix restart after read error (Kevin Wolf)
- virtio_blk: Factor virtio_blk_handle_request out (Kevin Wolf)
- cirrus: Properly re-register cirrus_linear_io_addr on vram unmap (Jan Kiszka)
- qcow2: Don't ignore qcow2_alloc_clusters return value (Kevin Wolf)
- qcow2: Don't ignore update_refcount return value (Kevin Wolf)
- qcow2: Allow updating no refcounts (Kevin Wolf)
- qcow2: Improve error handling in update_refcount (Kevin Wolf)
- qcow2: Fix error handling in grow_refcount_table (Kevin Wolf)
- block: Return original error codes in bdrv_pread/write (Kevin Wolf)
- qcow2: Return 0/-errno in qcow2_alloc_cluster_offset (Kevin Wolf)
- qcow2: Return 0/-errno in get_cluster_table (Kevin Wolf)
- qcow2: Fix error handling in qcow_save_vmstate (Kevin Wolf)
- qcow2: Fix error handling in qcow2_grow_l1_table (Kevin Wolf)
- win32/sdl: Fix toggle full screen (Herve Poussineau)
- win32: pair qemu_memalign() with qemu_vfree() (Herve Poussineau)
- vnc_refresh: calling vnc_update_client might free vs (Stefano Stabellini)
- Musicpal: Fix descriptor walk in eth_send (Jan Kiszka)
- Musicpal: Fix wm8750 I2C address (Jan Kiszka)
- fix savevm command without id or tag (Marcelo Tosatti)
- reduce number of reinjects on ACK (Gleb Natapov)
- QMP: Fix asynchronous events delivery (Luiz Capitulino)
- Documentation: Add missing documentation for qdev related command line options (Stefan Weil)
- pc: add driver version compat properties (Gerd Hoffmann)
- scsi: device version property (Gerd Hoffmann)
- ide: device version property (Gerd Hoffmann)
- QMP: Emit asynchronous events on all QMP monitors (Adam Litke)
- Fix QEMU_WARN_UNUSED_RESULT (Kevin Wolf)
version 0.12.2:
- Qemu's internal TFTP server breaks lock-step-iness of TFTP (Milan Plzik)
- osdep.c: Fix accept4 fallback (Kevin Wolf)
+1 -1
View File
@@ -1 +1 @@
0.12.2
0.12.4
+50 -18
View File
@@ -38,6 +38,10 @@
#define AUDIO_CAP "oss"
#include "audio_int.h"
#if defined OSS_GETVERSION && defined SNDCTL_DSP_POLICY
#define USE_DSP_POLICY
#endif
typedef struct OSSVoiceOut {
HWVoiceOut hw;
void *pcm_buf;
@@ -236,14 +240,39 @@ static void oss_dump_info (struct oss_params *req, struct oss_params *obt)
}
#endif
#ifdef USE_DSP_POLICY
static int oss_get_version (int fd, int *version, const char *typ)
{
if (ioctl (fd, OSS_GETVERSION, &version)) {
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
/*
* Looks like atm (20100109) FreeBSD knows OSS_GETVERSION
* since 7.x, but currently only on the mixer device (or in
* the Linuxolator), and in the native version that part of
* the code is in fact never reached so the ioctl fails anyway.
* Until this is fixed, just check the errno and if its what
* FreeBSD's sound drivers return atm assume they are new enough.
*/
if (errno == EINVAL) {
*version = 0x040000;
return 0;
}
#endif
oss_logerr2 (errno, typ, "Failed to get OSS version\n");
return -1;
}
return 0;
}
#endif
static int oss_open (int in, struct oss_params *req,
struct oss_params *obt, int *pfd)
{
int fd;
int version;
int oflags = conf.exclusive ? O_EXCL : 0;
audio_buf_info abinfo;
int fmt, freq, nchannels;
int setfragment = 1;
const char *dspname = in ? conf.devpath_in : conf.devpath_out;
const char *typ = in ? "ADC" : "DAC";
@@ -281,27 +310,30 @@ static int oss_open (int in, struct oss_params *req,
goto err;
}
if (ioctl (fd, OSS_GETVERSION, &version)) {
oss_logerr2 (errno, typ, "Failed to get OSS version\n");
version = 0;
}
#ifdef USE_DSP_POLICY
if (conf.policy >= 0) {
int version;
if (conf.debug) {
dolog ("OSS version = %#x\n", version);
}
if (!oss_get_version (fd, &version, typ)) {
if (conf.debug) {
dolog ("OSS version = %#x\n", version);
}
#ifdef SNDCTL_DSP_POLICY
if (conf.policy >= 0 && version >= 0x040000) {
int policy = conf.policy;
if (ioctl (fd, SNDCTL_DSP_POLICY, &policy)) {
oss_logerr2 (errno, typ, "Failed to set timing policy to %d\n",
conf.policy);
goto err;
if (version >= 0x040000) {
int policy = conf.policy;
if (ioctl (fd, SNDCTL_DSP_POLICY, &policy)) {
oss_logerr2 (errno, typ,
"Failed to set timing policy to %d\n",
conf.policy);
goto err;
}
setfragment = 0;
}
}
}
else
#endif
{
if (setfragment) {
int mmmmssss = (req->nfrags << 16) | ctz32 (req->fragsize);
if (ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss)) {
oss_logerr2 (errno, typ, "Failed to set buffer length (%d, %d)\n",
@@ -857,7 +889,7 @@ static struct audio_option oss_options[] = {
.valp = &conf.exclusive,
.descr = "Open device in exclusive mode (vmix wont work)"
},
#ifdef SNDCTL_DSP_POLICY
#ifdef USE_DSP_POLICY
{
.name = "POLICY",
.tag = AUD_OPT_INT,
+30 -20
View File
@@ -691,6 +691,7 @@ int bdrv_pread(BlockDriverState *bs, int64_t offset,
uint8_t tmp_buf[BDRV_SECTOR_SIZE];
int len, nb_sectors, count;
int64_t sector_num;
int ret;
count = count1;
/* first read to align to sector start */
@@ -699,8 +700,8 @@ int bdrv_pread(BlockDriverState *bs, int64_t offset,
len = count;
sector_num = offset >> BDRV_SECTOR_BITS;
if (len > 0) {
if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
return -EIO;
if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
return ret;
memcpy(buf, tmp_buf + (offset & (BDRV_SECTOR_SIZE - 1)), len);
count -= len;
if (count == 0)
@@ -712,8 +713,8 @@ int bdrv_pread(BlockDriverState *bs, int64_t offset,
/* read the sectors "in place" */
nb_sectors = count >> BDRV_SECTOR_BITS;
if (nb_sectors > 0) {
if (bdrv_read(bs, sector_num, buf, nb_sectors) < 0)
return -EIO;
if ((ret = bdrv_read(bs, sector_num, buf, nb_sectors)) < 0)
return ret;
sector_num += nb_sectors;
len = nb_sectors << BDRV_SECTOR_BITS;
buf += len;
@@ -722,8 +723,8 @@ int bdrv_pread(BlockDriverState *bs, int64_t offset,
/* add data from the last sector */
if (count > 0) {
if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
return -EIO;
if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
return ret;
memcpy(buf, tmp_buf, count);
}
return count1;
@@ -735,6 +736,7 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
uint8_t tmp_buf[BDRV_SECTOR_SIZE];
int len, nb_sectors, count;
int64_t sector_num;
int ret;
count = count1;
/* first write to align to sector start */
@@ -743,11 +745,11 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
len = count;
sector_num = offset >> BDRV_SECTOR_BITS;
if (len > 0) {
if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
return -EIO;
if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
return ret;
memcpy(tmp_buf + (offset & (BDRV_SECTOR_SIZE - 1)), buf, len);
if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
return -EIO;
if ((ret = bdrv_write(bs, sector_num, tmp_buf, 1)) < 0)
return ret;
count -= len;
if (count == 0)
return count1;
@@ -758,8 +760,8 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
/* write the sectors "in place" */
nb_sectors = count >> BDRV_SECTOR_BITS;
if (nb_sectors > 0) {
if (bdrv_write(bs, sector_num, buf, nb_sectors) < 0)
return -EIO;
if ((ret = bdrv_write(bs, sector_num, buf, nb_sectors)) < 0)
return ret;
sector_num += nb_sectors;
len = nb_sectors << BDRV_SECTOR_BITS;
buf += len;
@@ -768,11 +770,11 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
/* add data from the last sector */
if (count > 0) {
if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
return -EIO;
if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
return ret;
memcpy(tmp_buf, buf, count);
if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
return -EIO;
if ((ret = bdrv_write(bs, sector_num, tmp_buf, 1)) < 0)
return ret;
}
return count1;
}
@@ -1606,8 +1608,11 @@ static void multiwrite_user_cb(MultiwriteCB *mcb)
for (i = 0; i < mcb->num_callbacks; i++) {
mcb->callbacks[i].cb(mcb->callbacks[i].opaque, mcb->error);
if (mcb->callbacks[i].free_qiov) {
qemu_iovec_destroy(mcb->callbacks[i].free_qiov);
}
qemu_free(mcb->callbacks[i].free_qiov);
qemu_free(mcb->callbacks[i].free_buf);
qemu_vfree(mcb->callbacks[i].free_buf);
}
}
@@ -1615,7 +1620,7 @@ static void multiwrite_cb(void *opaque, int ret)
{
MultiwriteCB *mcb = opaque;
if (ret < 0) {
if (ret < 0 && !mcb->error) {
mcb->error = ret;
multiwrite_user_cb(mcb);
}
@@ -1667,6 +1672,10 @@ static int multiwrite_merge(BlockDriverState *bs, BlockRequest *reqs,
merge = bs->drv->bdrv_merge_requests(bs, &reqs[outidx], &reqs[i]);
}
if (reqs[outidx].qiov->niov + reqs[i].qiov->niov + 1 > IOV_MAX) {
merge = 0;
}
if (merge) {
size_t size;
QEMUIOVector *qiov = qemu_mallocz(sizeof(*qiov));
@@ -1752,10 +1761,11 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
// submitted yet. Otherwise we'll wait for the submitted AIOs to
// complete and report the error in the callback.
if (mcb->num_requests == 0) {
reqs[i].error = EIO;
reqs[i].error = -EIO;
goto fail;
} else {
mcb->error = EIO;
mcb->num_requests++;
multiwrite_cb(mcb, -EIO);
break;
}
} else {
+1 -1
View File
@@ -309,7 +309,7 @@ static int curl_open(BlockDriverState *bs, const char *filename, int flags)
static int inited = 0;
file = strdup(filename);
file = qemu_strdup(filename);
s->readahead_size = READ_AHEAD_SIZE;
/* Parse a trailing ":readahead=#:" param, if present. */
+72 -36
View File
@@ -33,7 +33,7 @@ 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;
int64_t new_l1_table_offset;
uint8_t data[12];
new_l1_size = s->l1_size;
@@ -55,6 +55,10 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
/* write new table (align to cluster) */
new_l1_table_offset = qcow2_alloc_clusters(bs, new_l1_size2);
if (new_l1_table_offset < 0) {
qemu_free(new_l1_table);
return new_l1_table_offset;
}
for(i = 0; i < s->l1_size; i++)
new_l1_table[i] = cpu_to_be64(new_l1_table[i]);
@@ -67,9 +71,10 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
/* 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))
ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_size), data,sizeof(data));
if (ret != 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;
@@ -77,8 +82,9 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
s->l1_size = new_l1_size;
return 0;
fail:
qemu_free(s->l1_table);
return -EIO;
qemu_free(new_l1_table);
qcow2_free_clusters(bs, new_l1_table_offset, new_l1_size2);
return ret < 0 ? ret : -EIO;
}
void qcow2_l2_cache_reset(BlockDriverState *bs)
@@ -213,13 +219,17 @@ 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;
uint64_t *l2_table;
int64_t 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));
if (l2_offset < 0) {
return NULL;
}
/* update the L1 entry */
@@ -479,8 +489,8 @@ out:
* the l2 table offset in the qcow2 file and the cluster index
* in the l2 table are given to the caller.
*
* Returns 0 on success, -errno in failure case
*/
static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
uint64_t **new_l2_table,
uint64_t *new_l2_offset,
@@ -496,8 +506,9 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
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;
if (ret < 0) {
return ret;
}
}
l2_offset = s->l1_table[l1_index];
@@ -507,14 +518,16 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
/* load the l2 table in memory */
l2_offset &= ~QCOW_OFLAG_COPIED;
l2_table = l2_load(bs, l2_offset);
if (l2_table == NULL)
return 0;
if (l2_table == NULL) {
return -EIO;
}
} 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;
if (l2_table == NULL) {
return -EIO;
}
l2_offset = s->l1_table[l1_index] & ~QCOW_OFLAG_COPIED;
}
@@ -526,7 +539,7 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
*new_l2_offset = l2_offset;
*new_l2_index = l2_index;
return 1;
return 0;
}
/*
@@ -548,12 +561,14 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
{
BDRVQcowState *s = bs->opaque;
int l2_index, ret;
uint64_t l2_offset, *l2_table, cluster_offset;
uint64_t l2_offset, *l2_table;
int64_t cluster_offset;
int nb_csectors;
ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index);
if (ret == 0)
if (ret < 0) {
return 0;
}
cluster_offset = be64_to_cpu(l2_table[l2_index]);
if (cluster_offset & QCOW_OFLAG_COPIED)
@@ -563,6 +578,10 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
qcow2_free_any_clusters(bs, cluster_offset, 1);
cluster_offset = qcow2_alloc_bytes(bs, compressed_size);
if (cluster_offset < 0) {
return 0;
}
nb_csectors = ((cluster_offset + compressed_size - 1) >> 9) -
(cluster_offset >> 9);
@@ -605,12 +624,12 @@ static int write_l2_entries(BDRVQcowState *s, uint64_t *l2_table,
return 0;
}
int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, uint64_t cluster_offset,
QCowL2Meta *m)
int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
{
BDRVQcowState *s = bs->opaque;
int i, j = 0, l2_index, ret;
uint64_t *old_cluster, start_sect, l2_offset, *l2_table;
uint64_t cluster_offset = m->cluster_offset;
if (m->nb_clusters == 0)
return 0;
@@ -633,10 +652,11 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, uint64_t cluster_offset,
goto err;
}
ret = -EIO;
/* update L2 table */
if (!get_cluster_table(bs, m->offset, &l2_table, &l2_offset, &l2_index))
ret = get_cluster_table(bs, m->offset, &l2_table, &l2_offset, &l2_index);
if (ret < 0) {
goto err;
}
for (i = 0; i < m->nb_clusters; i++) {
/* if two concurrent writes happen to the same unallocated cluster
@@ -670,30 +690,36 @@ err:
/*
* alloc_cluster_offset
*
* For a given offset of the disk image, return cluster offset in
* qcow2 file.
*
* 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.
* If the cluster was already allocated, m->nb_clusters is set to 0,
* m->depends_on is set to NULL and the other fields in m are meaningless.
*
* If the cluster is newly allocated, m->nb_clusters is set to the number of
* contiguous clusters that have been allocated. This may be 0 if the request
* conflict with another write request in flight; in this case, m->depends_on
* is set and the remaining fields of m are meaningless.
*
* If m->nb_clusters is non-zero, the other fields of m are valid and contain
* information about the first allocated cluster.
*
* Return 0 on success and -errno in error cases
*/
uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs,
uint64_t offset,
int n_start, int n_end,
int *num, QCowL2Meta *m)
int 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;
uint64_t l2_offset, *l2_table;
int64_t cluster_offset;
unsigned int nb_clusters, i = 0;
QCowL2Meta *old_alloc;
ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index);
if (ret == 0)
return 0;
if (ret < 0) {
return ret;
}
nb_clusters = size_to_clusters(s, n_end << 9);
@@ -709,6 +735,7 @@ uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs,
cluster_offset &= ~QCOW_OFLAG_COPIED;
m->nb_clusters = 0;
m->depends_on = NULL;
goto out;
}
@@ -723,12 +750,15 @@ uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs,
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]))
if ((i >= nb_clusters) || be64_to_cpu(l2_table[l2_index + i])) {
break;
}
i += count_contiguous_free_clusters(nb_clusters - i,
&l2_table[l2_index + i]);
if (i >= nb_clusters) {
break;
}
cluster_offset = be64_to_cpu(l2_table[l2_index + i]);
@@ -736,6 +766,7 @@ uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs,
(cluster_offset & QCOW_OFLAG_COMPRESSED))
break;
}
assert(i <= nb_clusters);
nb_clusters = i;
/*
@@ -779,6 +810,10 @@ uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs,
/* allocate a new cluster */
cluster_offset = qcow2_alloc_clusters(bs, nb_clusters * s->cluster_size);
if (cluster_offset < 0) {
QLIST_REMOVE(m, next_in_flight);
return cluster_offset;
}
/* save info needed for meta data update */
m->offset = offset;
@@ -787,10 +822,11 @@ uint64_t qcow2_alloc_cluster_offset(BlockDriverState *bs,
out:
m->nb_available = MIN(nb_clusters << (s->cluster_bits - 9), n_end);
m->cluster_offset = cluster_offset;
*num = m->nb_available - n_start;
return cluster_offset;
return 0;
}
static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
+298 -110
View File
@@ -27,7 +27,7 @@
#include "block/qcow2.h"
static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size);
static int update_refcount(BlockDriverState *bs,
static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
int64_t offset, int64_t length,
int addend);
@@ -123,121 +123,266 @@ static int get_refcount(BlockDriverState *bs, int64_t cluster_index)
return be16_to_cpu(s->refcount_block_cache[block_index]);
}
static int grow_refcount_table(BlockDriverState *bs, int min_size)
/*
* Rounds the refcount table size up to avoid growing the table for each single
* refcount block that is allocated.
*/
static unsigned int next_refcount_table_size(BDRVQcowState *s,
unsigned 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;
unsigned int min_clusters = (min_size >> (s->cluster_bits - 3)) + 1;
unsigned int refcount_table_clusters =
MAX(1, s->refcount_table_size >> (s->cluster_bits - 3));
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;
while (min_clusters > refcount_table_clusters) {
refcount_table_clusters = (refcount_table_clusters * 3 + 1) / 2;
}
#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:
qemu_free(new_table);
return -EIO;
return refcount_table_clusters << (s->cluster_bits - 3);
}
/* Checks if two offsets are described by the same refcount block */
static int in_same_refcount_block(BDRVQcowState *s, uint64_t offset_a,
uint64_t offset_b)
{
uint64_t block_a = offset_a >> (2 * s->cluster_bits - REFCOUNT_SHIFT);
uint64_t block_b = offset_b >> (2 * s->cluster_bits - REFCOUNT_SHIFT);
return (block_a == block_b);
}
/*
* Loads a refcount block. If it doesn't exist yet, it is allocated first
* (including growing the refcount table if needed).
*
* Returns the offset of the refcount block on success or -errno in error case
*/
static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
{
BDRVQcowState *s = bs->opaque;
int64_t offset, refcount_block_offset;
unsigned int refcount_table_index;
int ret;
uint64_t data64;
int cache = cache_refcount_updates;
/* Find L1 index and grow refcount table if needed */
/* Find the refcount block for the given cluster */
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)
if (refcount_table_index < s->refcount_table_size) {
uint64_t refcount_block_offset =
s->refcount_table[refcount_table_index];
/* If it's already there, we're done */
if (refcount_block_offset) {
if (refcount_block_offset != s->refcount_block_cache_offset) {
ret = load_refcount_block(bs, refcount_block_offset);
if (ret < 0) {
return ret;
}
}
return refcount_block_offset;
}
}
/*
* If we came here, we need to allocate something. Something is at least
* a cluster for the new refcount block. It may also include a new refcount
* table if the old refcount table is too small.
*
* Note that allocating clusters here needs some special care:
*
* - We can't use the normal qcow2_alloc_clusters(), it would try to
* increase the refcount and very likely we would end up with an endless
* recursion. Instead we must place the refcount blocks in a way that
* they can describe them themselves.
*
* - We need to consider that at this point we are inside update_refcounts
* and doing the initial refcount increase. This means that some clusters
* have already been allocated by the caller, but their refcount isn't
* accurate yet. free_cluster_index tells us where this allocation ends
* as long as we don't overwrite it by freeing clusters.
*
* - alloc_clusters_noref and qcow2_free_clusters may load a different
* refcount block into the cache
*/
if (cache_refcount_updates) {
ret = write_refcount_block(s);
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;
/* Allocate the refcount block itself and mark it as used */
uint64_t new_block = alloc_clusters_noref(bs, s->cluster_size);
memset(s->refcount_block_cache, 0, s->cluster_size);
s->refcount_block_cache_offset = new_block;
refcount_block_offset = offset;
s->refcount_block_cache_offset = offset;
update_refcount(bs, offset, s->cluster_size, 1);
cache_refcount_updates = cache;
#ifdef DEBUG_ALLOC2
fprintf(stderr, "qcow2: Allocate refcount block %d for %" PRIx64
" at %" PRIx64 "\n",
refcount_table_index, cluster_index << s->cluster_bits, new_block);
#endif
if (in_same_refcount_block(s, new_block, cluster_index << s->cluster_bits)) {
/* The block describes itself, need to update the cache */
int block_index = (new_block >> s->cluster_bits) &
((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);
s->refcount_block_cache[block_index] = cpu_to_be16(1);
} else {
if (refcount_block_offset != s->refcount_block_cache_offset) {
if (load_refcount_block(bs, refcount_block_offset) < 0)
return -EIO;
/* Described somewhere else. This can recurse at most twice before we
* arrive at a block that describes itself. */
ret = update_refcount(bs, new_block, s->cluster_size, 1);
if (ret < 0) {
goto fail_block;
}
}
return refcount_block_offset;
/* Now the new refcount block needs to be written to disk */
ret = bdrv_pwrite(s->hd, new_block, s->refcount_block_cache,
s->cluster_size);
if (ret < 0) {
goto fail_block;
}
/* If the refcount table is big enough, just hook the block up there */
if (refcount_table_index < s->refcount_table_size) {
uint64_t data64 = cpu_to_be64(new_block);
ret = bdrv_pwrite(s->hd,
s->refcount_table_offset + refcount_table_index * sizeof(uint64_t),
&data64, sizeof(data64));
if (ret < 0) {
goto fail_block;
}
s->refcount_table[refcount_table_index] = new_block;
return new_block;
}
/*
* If we come here, we need to grow the refcount table. Again, a new
* refcount table needs some space and we can't simply allocate to avoid
* endless recursion.
*
* Therefore let's grab new refcount blocks at the end of the image, which
* will describe themselves and the new refcount table. This way we can
* reference them only in the new table and do the switch to the new
* refcount table at once without producing an inconsistent state in
* between.
*/
/* Calculate the number of refcount blocks needed so far */
uint64_t refcount_block_clusters = 1 << (s->cluster_bits - REFCOUNT_SHIFT);
uint64_t blocks_used = (s->free_cluster_index +
refcount_block_clusters - 1) / refcount_block_clusters;
/* And now we need at least one block more for the new metadata */
uint64_t table_size = next_refcount_table_size(s, blocks_used + 1);
uint64_t last_table_size;
uint64_t blocks_clusters;
do {
uint64_t table_clusters = size_to_clusters(s, table_size);
blocks_clusters = 1 +
((table_clusters + refcount_block_clusters - 1)
/ refcount_block_clusters);
uint64_t meta_clusters = table_clusters + blocks_clusters;
last_table_size = table_size;
table_size = next_refcount_table_size(s, blocks_used +
((meta_clusters + refcount_block_clusters - 1)
/ refcount_block_clusters));
} while (last_table_size != table_size);
#ifdef DEBUG_ALLOC2
fprintf(stderr, "qcow2: Grow refcount table %" PRId32 " => %" PRId64 "\n",
s->refcount_table_size, table_size);
#endif
/* Create the new refcount table and blocks */
uint64_t meta_offset = (blocks_used * refcount_block_clusters) *
s->cluster_size;
uint64_t table_offset = meta_offset + blocks_clusters * s->cluster_size;
uint16_t *new_blocks = qemu_mallocz(blocks_clusters * s->cluster_size);
uint64_t *new_table = qemu_mallocz(table_size * sizeof(uint64_t));
assert(meta_offset >= (s->free_cluster_index * s->cluster_size));
/* Fill the new refcount table */
memcpy(new_table, s->refcount_table,
s->refcount_table_size * sizeof(uint64_t));
new_table[refcount_table_index] = new_block;
int i;
for (i = 0; i < blocks_clusters; i++) {
new_table[blocks_used + i] = meta_offset + (i * s->cluster_size);
}
/* Fill the refcount blocks */
uint64_t table_clusters = size_to_clusters(s, table_size * sizeof(uint64_t));
int block = 0;
for (i = 0; i < table_clusters + blocks_clusters; i++) {
new_blocks[block++] = cpu_to_be16(1);
}
/* Write refcount blocks to disk */
ret = bdrv_pwrite(s->hd, meta_offset, new_blocks,
blocks_clusters * s->cluster_size);
qemu_free(new_blocks);
if (ret < 0) {
goto fail_table;
}
/* Write refcount table to disk */
for(i = 0; i < table_size; i++) {
cpu_to_be64s(&new_table[i]);
}
ret = bdrv_pwrite(s->hd, table_offset, new_table,
table_size * sizeof(uint64_t));
if (ret < 0) {
goto fail_table;
}
for(i = 0; i < table_size; i++) {
cpu_to_be64s(&new_table[i]);
}
/* Hook up the new refcount table in the qcow2 header */
uint8_t data[12];
cpu_to_be64w((uint64_t*)data, table_offset);
cpu_to_be32w((uint32_t*)(data + 8), table_clusters);
ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_offset),
data, sizeof(data));
if (ret < 0) {
goto fail_table;
}
/* And switch it in memory */
uint64_t old_table_offset = s->refcount_table_offset;
uint64_t old_table_size = s->refcount_table_size;
qemu_free(s->refcount_table);
s->refcount_table = new_table;
s->refcount_table_size = table_size;
s->refcount_table_offset = table_offset;
/* Free old table. Remember, we must not change free_cluster_index */
uint64_t old_free_cluster_index = s->free_cluster_index;
qcow2_free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t));
s->free_cluster_index = old_free_cluster_index;
ret = load_refcount_block(bs, new_block);
if (ret < 0) {
goto fail_block;
}
return new_block;
fail_table:
qemu_free(new_table);
fail_block:
s->refcount_block_cache_offset = 0;
return ret;
}
#define REFCOUNTS_PER_SECTOR (512 >> REFCOUNT_SHIFT)
@@ -266,22 +411,26 @@ static int write_refcount_block_entries(BDRVQcowState *s,
}
/* XXX: cache several refcount block clusters ? */
static int update_refcount(BlockDriverState *bs,
int64_t offset, int64_t length,
int addend)
static int QEMU_WARN_UNUSED_RESULT 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;
int ret;
#ifdef DEBUG_ALLOC2
printf("update_refcount: offset=%" PRId64 " size=%" PRId64 " addend=%d\n",
offset, length, addend);
#endif
if (length <= 0)
if (length < 0) {
return -EINVAL;
} else if (length == 0) {
return 0;
}
start = offset & ~(s->cluster_size - 1);
last = (offset + length - 1) & ~(s->cluster_size - 1);
for(cluster_offset = start; cluster_offset <= last;
@@ -289,6 +438,7 @@ static int update_refcount(BlockDriverState *bs,
{
int block_index, refcount;
int64_t cluster_index = cluster_offset >> s->cluster_bits;
int64_t new_block;
/* Only write refcount block to disk when we are done with it */
old_table_index = table_index;
@@ -306,10 +456,12 @@ static int update_refcount(BlockDriverState *bs,
}
/* 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;
new_block = alloc_refcount_block(bs, cluster_index);
if (new_block < 0) {
ret = new_block;
goto fail;
}
refcount_block_offset = new_block;
/* we can update the count and save it */
block_index = cluster_index &
@@ -323,24 +475,38 @@ static int update_refcount(BlockDriverState *bs,
refcount = be16_to_cpu(s->refcount_block_cache[block_index]);
refcount += addend;
if (refcount < 0 || refcount > 0xffff)
return -EINVAL;
if (refcount < 0 || refcount > 0xffff) {
ret = -EINVAL;
goto fail;
}
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);
}
ret = 0;
fail:
/* 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 ret < 0 ? ret : -EIO;
}
}
return 0;
/*
* Try do undo any updates if an error is returned (This may succeed in
* some cases like ENOSPC for allocating a new refcount block)
*/
if (ret < 0) {
int dummy;
dummy = update_refcount(bs, offset, cluster_offset - offset, -addend);
}
return ret;
}
/* addend must be 1 or -1 */
@@ -390,9 +556,13 @@ retry:
int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size)
{
int64_t offset;
int ret;
offset = alloc_clusters_noref(bs, size);
update_refcount(bs, offset, size, 1);
ret = update_refcount(bs, offset, size, 1);
if (ret < 0) {
return ret;
}
return offset;
}
@@ -407,6 +577,9 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
assert(size > 0 && size <= s->cluster_size);
if (s->free_byte_offset == 0) {
s->free_byte_offset = qcow2_alloc_clusters(bs, s->cluster_size);
if (s->free_byte_offset < 0) {
return s->free_byte_offset;
}
}
redo:
free_in_cluster = s->cluster_size -
@@ -422,6 +595,9 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
update_cluster_refcount(bs, offset >> s->cluster_bits, 1);
} else {
offset = qcow2_alloc_clusters(bs, s->cluster_size);
if (offset < 0) {
return offset;
}
cluster_offset = s->free_byte_offset & ~(s->cluster_size - 1);
if ((cluster_offset + s->cluster_size) == offset) {
/* we are lucky: contiguous data */
@@ -439,7 +615,13 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
void qcow2_free_clusters(BlockDriverState *bs,
int64_t offset, int64_t size)
{
update_refcount(bs, offset, size, -1);
int ret;
ret = update_refcount(bs, offset, size, -1);
if (ret < 0) {
fprintf(stderr, "qcow2_free_clusters failed: %s\n", strerror(-ret));
abort();
}
}
/*
@@ -549,9 +731,15 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
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);
if (addend != 0) {
int ret;
ret = update_refcount(bs,
(offset & s->cluster_offset_mask) & ~511,
nb_csectors * 512, addend);
if (ret < 0) {
goto fail;
}
}
/* compressed clusters are never modified */
refcount = 2;
} else {
+10 -1
View File
@@ -139,6 +139,9 @@ static int qcow_write_snapshots(BlockDriverState *bs)
snapshots_offset = qcow2_alloc_clusters(bs, snapshots_size);
offset = snapshots_offset;
if (offset < 0) {
return offset;
}
for(i = 0; i < s->nb_snapshots; i++) {
sn = s->snapshots + i;
@@ -235,6 +238,7 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
QCowSnapshot *snapshots1, sn1, *sn = &sn1;
int i, ret;
uint64_t *l1_table = NULL;
int64_t l1_table_offset;
memset(sn, 0, sizeof(*sn));
@@ -263,7 +267,12 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
goto fail;
/* create the L1 table of the snapshot */
sn->l1_table_offset = qcow2_alloc_clusters(bs, s->l1_size * sizeof(uint64_t));
l1_table_offset = qcow2_alloc_clusters(bs, s->l1_size * sizeof(uint64_t));
if (l1_table_offset < 0) {
goto fail;
}
sn->l1_table_offset = l1_table_offset;
sn->l1_size = s->l1_size;
if (s->l1_size != 0) {
+33 -22
View File
@@ -467,8 +467,10 @@ static void qcow_aio_read_cb(void *opaque, int ret)
acb->hd_aiocb = bdrv_aio_readv(s->hd,
(acb->cluster_offset >> 9) + index_in_cluster,
&acb->hd_qiov, acb->n, qcow_aio_read_cb, acb);
if (acb->hd_aiocb == NULL)
if (acb->hd_aiocb == NULL) {
ret = -EIO;
goto done;
}
}
return;
@@ -561,7 +563,7 @@ static void qcow_aio_write_cb(void *opaque, int ret)
acb->hd_aiocb = NULL;
if (ret >= 0) {
ret = qcow2_alloc_cluster_link_l2(bs, acb->cluster_offset, &acb->l2meta);
ret = qcow2_alloc_cluster_link_l2(bs, &acb->l2meta);
}
run_dependent_requests(&acb->l2meta);
@@ -585,21 +587,23 @@ static void qcow_aio_write_cb(void *opaque, int ret)
n_end > QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors)
n_end = QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors;
acb->cluster_offset = qcow2_alloc_cluster_offset(bs, acb->sector_num << 9,
index_in_cluster,
n_end, &acb->n, &acb->l2meta);
ret = qcow2_alloc_cluster_offset(bs, acb->sector_num << 9,
index_in_cluster, n_end, &acb->n, &acb->l2meta);
if (ret < 0) {
goto done;
}
acb->cluster_offset = acb->l2meta.cluster_offset;
/* Need to wait for another request? If so, we are done for now. */
if (!acb->cluster_offset && acb->l2meta.depends_on != NULL) {
if (acb->l2meta.nb_clusters == 0 && acb->l2meta.depends_on != NULL) {
QLIST_INSERT_HEAD(&acb->l2meta.depends_on->dependent_requests,
acb, next_depend);
return;
}
if (!acb->cluster_offset || (acb->cluster_offset & 511) != 0) {
ret = -EIO;
goto done;
}
assert((acb->cluster_offset & 511) == 0);
if (s->crypt_method) {
if (!acb->cluster_data) {
acb->cluster_data = qemu_mallocz(QCOW_MAX_CRYPT_CLUSTERS *
@@ -618,11 +622,17 @@ static void qcow_aio_write_cb(void *opaque, int ret)
(acb->cluster_offset >> 9) + index_in_cluster,
&acb->hd_qiov, acb->n,
qcow_aio_write_cb, acb);
if (acb->hd_aiocb == NULL)
goto done;
if (acb->hd_aiocb == NULL) {
ret = -EIO;
goto fail;
}
return;
fail:
if (acb->l2meta.nb_clusters != 0) {
QLIST_REMOVE(&acb->l2meta, next_in_flight);
}
done:
if (acb->qiov->niov > 1)
qemu_vfree(acb->orig_buf);
@@ -683,27 +693,27 @@ static int get_bits_from_size(size_t size)
static int preallocate(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
uint64_t cluster_offset = 0;
uint64_t nb_sectors;
uint64_t offset;
int num;
int ret;
QCowL2Meta meta;
nb_sectors = bdrv_getlength(bs) >> 9;
offset = 0;
QLIST_INIT(&meta.dependent_requests);
meta.cluster_offset = 0;
while (nb_sectors) {
num = MIN(nb_sectors, INT_MAX >> 9);
cluster_offset = qcow2_alloc_cluster_offset(bs, offset, 0, num, &num,
&meta);
ret = qcow2_alloc_cluster_offset(bs, offset, 0, num, &num, &meta);
if (cluster_offset == 0) {
if (ret < 0) {
return -1;
}
if (qcow2_alloc_cluster_link_l2(bs, cluster_offset, &meta) < 0) {
qcow2_free_any_clusters(bs, cluster_offset, meta.nb_clusters);
if (qcow2_alloc_cluster_link_l2(bs, &meta) < 0) {
qcow2_free_any_clusters(bs, meta.cluster_offset, meta.nb_clusters);
return -1;
}
@@ -722,10 +732,10 @@ static int preallocate(BlockDriverState *bs)
* all of the allocated clusters (otherwise we get failing reads after
* EOF). Extend the image to the last allocated sector.
*/
if (cluster_offset != 0) {
if (meta.cluster_offset != 0) {
uint8_t buf[512];
memset(buf, 0, 512);
bdrv_write(s->hd, (cluster_offset >> 9) + num - 1, buf, 1);
bdrv_write(s->hd, (meta.cluster_offset >> 9) + num - 1, buf, 1);
}
return 0;
@@ -1056,12 +1066,13 @@ static int qcow_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
{
BDRVQcowState *s = bs->opaque;
int growable = bs->growable;
int ret;
bs->growable = 1;
bdrv_pwrite(bs, qcow_vm_state_offset(s) + pos, buf, size);
ret = bdrv_pwrite(bs, qcow_vm_state_offset(s) + pos, buf, size);
bs->growable = growable;
return size;
return ret;
}
static int qcow_load_vmstate(BlockDriverState *bs, uint8_t *buf,
+4 -6
View File
@@ -135,6 +135,7 @@ struct QCowAIOCB;
typedef struct QCowL2Meta
{
uint64_t offset;
uint64_t cluster_offset;
int n_start;
int nb_available;
int nb_clusters;
@@ -191,16 +192,13 @@ void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
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);
int 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);
int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m);
/* qcow2-snapshot.c functions */
int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info);
+1 -1
View File
@@ -595,7 +595,7 @@ static void raw_close(BlockDriverState *bs)
close(s->fd);
s->fd = -1;
if (s->aligned_buf != NULL)
qemu_free(s->aligned_buf);
qemu_vfree(s->aligned_buf);
}
}
+5 -5
View File
@@ -882,7 +882,7 @@ static int init_directories(BDRVVVFATState* s,
mapping->dir_index = 0;
mapping->info.dir.parent_mapping_index = -1;
mapping->first_mapping_index = -1;
mapping->path = strdup(dirname);
mapping->path = qemu_strdup(dirname);
i = strlen(mapping->path);
if (i > 0 && mapping->path[i - 1] == '/')
mapping->path[i - 1] = '\0';
@@ -1632,10 +1632,10 @@ static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
/* rename */
if (strcmp(basename, basename2))
schedule_rename(s, cluster_num, strdup(path));
schedule_rename(s, cluster_num, qemu_strdup(path));
} else if (is_file(direntry))
/* new file */
schedule_new_file(s, strdup(path), cluster_num);
schedule_new_file(s, qemu_strdup(path), cluster_num);
else {
assert(0);
return 0;
@@ -1752,10 +1752,10 @@ static int check_directory_consistency(BDRVVVFATState *s,
mapping->mode &= ~MODE_DELETED;
if (strcmp(basename, basename2))
schedule_rename(s, cluster_num, strdup(path));
schedule_rename(s, cluster_num, qemu_strdup(path));
} else
/* new directory */
schedule_mkdir(s, cluster_num, strdup(path));
schedule_mkdir(s, cluster_num, qemu_strdup(path));
lfn_init(&lfn);
do {
+7 -5
View File
@@ -232,11 +232,13 @@ int cpu_exec(CPUState *env1)
env_to_regs();
#if defined(TARGET_I386)
/* put eflags in CPU temporary format */
CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
DF = 1 - (2 * ((env->eflags >> 10) & 1));
CC_OP = CC_OP_EFLAGS;
env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
if (!kvm_enabled()) {
/* put eflags in CPU temporary format */
CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
DF = 1 - (2 * ((env->eflags >> 10) & 1));
CC_OP = CC_OP_EFLAGS;
env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
}
#elif defined(TARGET_SPARC)
#elif defined(TARGET_M68K)
env->cc_op = CC_OP_FLAGS;
+1
View File
@@ -2,3 +2,4 @@
CONFIG_USB_OHCI=y
CONFIG_PTIMER=y
CONFIG_ISA_MMIO=y
+1
View File
@@ -2,3 +2,4 @@
CONFIG_USB_OHCI=y
CONFIG_PTIMER=y
CONFIG_ISA_MMIO=y
+3 -3
View File
@@ -69,9 +69,9 @@ extern int printf(const char *, ...);
#define AREG1 "r14"
#define AREG2 "r15"
#elif defined(__mips__)
#define AREG0 "fp"
#define AREG1 "s0"
#define AREG2 "s1"
#define AREG0 "s0"
#define AREG1 "s1"
#define AREG2 "fp"
#elif defined(__sparc__)
#ifdef CONFIG_SOLARIS
#define AREG0 "g2"
+1 -1
View File
@@ -3307,7 +3307,7 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
if (is_write) {
cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
}
qemu_free(bounce.buffer);
qemu_vfree(bounce.buffer);
bounce.buffer = NULL;
cpu_notify_map_clients();
}
+4 -2
View File
@@ -2585,9 +2585,11 @@ static void map_linear_vram(CirrusVGAState *s)
static void unmap_linear_vram(CirrusVGAState *s)
{
if (s->vga.map_addr && s->vga.lfb_addr && s->vga.lfb_end)
if (s->vga.map_addr && s->vga.lfb_addr && s->vga.lfb_end) {
s->vga.map_addr = s->vga.map_end = 0;
cpu_register_physical_memory(s->vga.lfb_addr, s->vga.vram_size,
s->cirrus_linear_io_addr);
}
cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x20000,
s->vga.vga_io_memory);
}
+15 -5
View File
@@ -1860,8 +1860,12 @@ fdctrl_t *fdctrl_init_isa(DriveInfo **fds)
ISADevice *dev;
dev = isa_create("isa-fdc");
qdev_prop_set_drive(&dev->qdev, "driveA", fds[0]);
qdev_prop_set_drive(&dev->qdev, "driveB", fds[1]);
if (fds[0]) {
qdev_prop_set_drive(&dev->qdev, "driveA", fds[0]);
}
if (fds[1]) {
qdev_prop_set_drive(&dev->qdev, "driveB", fds[1]);
}
if (qdev_init(&dev->qdev) < 0)
return NULL;
return &(DO_UPCAST(fdctrl_isabus_t, busdev, dev)->state);
@@ -1879,8 +1883,12 @@ fdctrl_t *fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
sys = DO_UPCAST(fdctrl_sysbus_t, busdev.qdev, dev);
fdctrl = &sys->state;
fdctrl->dma_chann = dma_chann; /* FIXME */
qdev_prop_set_drive(dev, "driveA", fds[0]);
qdev_prop_set_drive(dev, "driveB", fds[1]);
if (fds[0]) {
qdev_prop_set_drive(dev, "driveA", fds[0]);
}
if (fds[1]) {
qdev_prop_set_drive(dev, "driveB", fds[1]);
}
qdev_init_nofail(dev);
sysbus_connect_irq(&sys->busdev, 0, irq);
sysbus_mmio_map(&sys->busdev, 0, mmio_base);
@@ -1896,7 +1904,9 @@ fdctrl_t *sun4m_fdctrl_init (qemu_irq irq, target_phys_addr_t io_base,
fdctrl_t *fdctrl;
dev = qdev_create(NULL, "SUNW,fdtwo");
qdev_prop_set_drive(dev, "drive", fds[0]);
if (fds[0]) {
qdev_prop_set_drive(dev, "drive", fds[0]);
}
qdev_init_nofail(dev);
sys = DO_UPCAST(fdctrl_sysbus_t, busdev.qdev, dev);
fdctrl = &sys->state;
+1 -1
View File
@@ -179,7 +179,7 @@ static int get_uint32_as_uint16(QEMUFile *f, void *pv, size_t size)
static void put_unused(QEMUFile *f, void *pv, size_t size)
{
fprintf(stderr, "uint32_as_uint16 is only used for backward compatibilty.\n");
fprintf(stderr, "uint32_as_uint16 is only used for backward compatibility.\n");
fprintf(stderr, "This functions shouldn't be called.\n");
}
+2 -5
View File
@@ -70,11 +70,7 @@ static void ide_map(PCIDevice *pci_dev, int region_num,
static PCIIDEState *pci_from_bm(BMDMAState *bm)
{
if (bm->unit == 0) {
return container_of(bm, PCIIDEState, bmdma[0]);
} else {
return container_of(bm, PCIIDEState, bmdma[1]);
}
return bm->pci_dev;
}
static uint32_t bmdma_readb(void *opaque, uint32_t addr)
@@ -145,6 +141,7 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num,
BMDMAState *bm = &d->bmdma[i];
d->bus[i].bmdma = bm;
bm->bus = d->bus+i;
bm->pci_dev = d;
qemu_add_vm_change_state_handler(ide_dma_restart_cb, bm);
register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm);
+69 -9
View File
@@ -115,7 +115,7 @@ static void ide_identify(IDEState *s)
put_le16(p + 20, 3); /* XXX: retired, remove ? */
put_le16(p + 21, 512); /* cache size in sectors */
put_le16(p + 22, 4); /* ecc bytes */
padstr((char *)(p + 23), QEMU_VERSION, 8); /* firmware version */
padstr((char *)(p + 23), s->version, 8); /* firmware version */
padstr((char *)(p + 27), "QEMU HARDDISK", 40); /* model */
#if MAX_MULT_SECTORS > 1
put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);
@@ -186,7 +186,7 @@ static void ide_atapi_identify(IDEState *s)
put_le16(p + 20, 3); /* buffer type */
put_le16(p + 21, 512); /* cache size in sectors */
put_le16(p + 22, 4); /* ecc bytes */
padstr((char *)(p + 23), QEMU_VERSION, 8); /* firmware version */
padstr((char *)(p + 23), s->version, 8); /* firmware version */
padstr((char *)(p + 27), "QEMU DVD-ROM", 40); /* model */
put_le16(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */
#ifdef USE_DMA_CDROM
@@ -238,7 +238,7 @@ static void ide_cfata_identify(IDEState *s)
put_le16(p + 8, s->nb_sectors); /* Sectors per card */
padstr((char *)(p + 10), s->drive_serial_str, 20); /* serial number */
put_le16(p + 22, 0x0004); /* ECC bytes */
padstr((char *) (p + 23), QEMU_VERSION, 8); /* Firmware Revision */
padstr((char *) (p + 23), s->version, 8); /* Firmware Revision */
padstr((char *) (p + 27), "QEMU MICRODRIVE", 40);/* Model number */
#if MAX_MULT_SECTORS > 1
put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);
@@ -1591,7 +1591,7 @@ static void ide_atapi_cmd(IDEState *s)
buf[7] = 0; /* reserved */
padstr8(buf + 8, 8, "QEMU");
padstr8(buf + 16, 16, "QEMU DVD-ROM");
padstr8(buf + 32, 4, QEMU_VERSION);
padstr8(buf + 32, 4, s->version);
ide_atapi_cmd_reply(s, 36, max_len);
break;
case GPCMD_GET_CONFIGURATION:
@@ -2590,7 +2590,7 @@ void ide_bus_reset(IDEBus *bus)
ide_clear_hob(bus);
}
void ide_init_drive(IDEState *s, DriveInfo *dinfo)
void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version)
{
int cylinders, heads, secs;
uint64_t nb_sectors;
@@ -2619,6 +2619,11 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo)
if (strlen(s->drive_serial_str) == 0)
snprintf(s->drive_serial_str, sizeof(s->drive_serial_str),
"QM%05d", s->drive_serial);
if (version) {
pstrcpy(s->version, sizeof(s->version), version);
} else {
pstrcpy(s->version, sizeof(s->version), QEMU_VERSION);
}
ide_reset(s);
}
@@ -2635,13 +2640,14 @@ void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
s->unit = i;
s->drive_serial = drive_serial++;
s->io_buffer = qemu_blockalign(s->bs, IDE_DMA_BUF_SECTORS*512 + 4);
s->io_buffer_total_len = IDE_DMA_BUF_SECTORS*512 + 4;
s->smart_selftest_data = qemu_blockalign(s->bs, 512);
s->sector_write_timer = qemu_new_timer(vm_clock,
ide_sector_write_timer_cb, s);
if (i == 0)
ide_init_drive(s, hd0);
ide_init_drive(s, hd0, NULL);
if (i == 1)
ide_init_drive(s, hd1);
ide_init_drive(s, hd1, NULL);
}
bus->irq = irq;
}
@@ -2669,6 +2675,25 @@ static bool is_identify_set(void *opaque, int version_id)
return s->identify_set != 0;
}
static EndTransferFunc* transfer_end_table[] = {
ide_sector_read,
ide_sector_write,
ide_transfer_stop,
ide_atapi_cmd_reply_end,
ide_atapi_cmd,
};
static int transfer_end_table_idx(EndTransferFunc *fn)
{
int i;
for (i = 0; i < ARRAY_SIZE(transfer_end_table); i++)
if (transfer_end_table[i] == fn)
return i;
return -1;
}
static int ide_drive_post_load(void *opaque, int version_id)
{
IDEState *s = opaque;
@@ -2679,14 +2704,42 @@ static int ide_drive_post_load(void *opaque, int version_id)
s->cdrom_changed = 1;
}
}
if (s->cur_io_buffer_len) {
s->end_transfer_func = transfer_end_table[s->end_transfer_fn_idx];
s->data_ptr = s->io_buffer + s->cur_io_buffer_offset;
s->data_end = s->data_ptr + s->cur_io_buffer_len;
}
return 0;
}
static void ide_drive_pre_save(void *opaque)
{
IDEState *s = opaque;
s->cur_io_buffer_len = 0;
if (!(s->status & DRQ_STAT))
return;
s->cur_io_buffer_offset = s->data_ptr - s->io_buffer;
s->cur_io_buffer_len = s->data_end - s->data_ptr;
s->end_transfer_fn_idx = transfer_end_table_idx(s->end_transfer_func);
if (s->end_transfer_fn_idx == -1) {
fprintf(stderr, "%s: invalid end_transfer_func for DRQ_STAT\n",
__func__);
s->end_transfer_fn_idx = 2;
}
}
const VMStateDescription vmstate_ide_drive = {
.name = "ide_drive",
.version_id = 3,
.version_id = 4,
.minimum_version_id = 0,
.minimum_version_id_old = 0,
.pre_save = ide_drive_pre_save,
.post_load = ide_drive_post_load,
.fields = (VMStateField []) {
VMSTATE_INT32(mult_sectors, IDEState),
@@ -2709,7 +2762,14 @@ const VMStateDescription vmstate_ide_drive = {
VMSTATE_UINT8(sense_key, IDEState),
VMSTATE_UINT8(asc, IDEState),
VMSTATE_UINT8_V(cdrom_changed, IDEState, 3),
/* XXX: if a transfer is pending, we do not save it yet */
VMSTATE_INT32_V(req_nb_sectors, IDEState, 4),
VMSTATE_VARRAY_INT32(io_buffer, IDEState, io_buffer_total_len, 4,
vmstate_info_uint8, uint8_t),
VMSTATE_INT32_V(cur_io_buffer_offset, IDEState, 4),
VMSTATE_INT32_V(cur_io_buffer_len, IDEState, 4),
VMSTATE_UINT8_V(end_transfer_fn_idx, IDEState, 4),
VMSTATE_INT32_V(elementary_transfer_size, IDEState, 4),
VMSTATE_INT32_V(packet_transfer_size, IDEState, 4),
VMSTATE_END_OF_LIST()
}
};
+9 -1
View File
@@ -397,6 +397,7 @@ struct IDEState {
/* set for lba48 access */
uint8_t lba48;
BlockDriverState *bs;
char version[9];
/* ATAPI specific */
uint8_t sense_key;
uint8_t asc;
@@ -416,6 +417,11 @@ struct IDEState {
uint8_t *data_ptr;
uint8_t *data_end;
uint8_t *io_buffer;
/* PIO save/restore */
int32_t io_buffer_total_len;
int cur_io_buffer_offset;
int cur_io_buffer_len;
uint8_t end_transfer_fn_idx;
QEMUTimer *sector_write_timer; /* only used for win2k install hack */
uint32_t irq_count; /* counts IRQs when using win2k install hack */
/* CF-ATA extended error */
@@ -449,6 +455,7 @@ struct IDEDevice {
DeviceState qdev;
uint32_t unit;
DriveInfo *dinfo;
char *version;
};
typedef int (*ide_qdev_initfn)(IDEDevice *dev);
@@ -474,6 +481,7 @@ struct BMDMAState {
uint8_t status;
uint32_t addr;
struct PCIIDEState *pci_dev;
IDEBus *bus;
/* current transfer state */
uint32_t cur_addr;
@@ -548,7 +556,7 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr);
void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
uint32_t ide_data_readl(void *opaque, uint32_t addr);
void ide_init_drive(IDEState *s, DriveInfo *dinfo);
void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version);
void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
qemu_irq irq);
void ide_init_ioport(IDEBus *bus, int iobase, int iobase2);
+1
View File
@@ -78,6 +78,7 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num,
BMDMAState *bm = &d->bmdma[i];
d->bus[i].bmdma = bm;
bm->bus = d->bus+i;
bm->pci_dev = d;
qemu_add_vm_change_state_handler(ide_dma_restart_cb, bm);
register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm);
+2 -1
View File
@@ -99,7 +99,7 @@ typedef struct IDEDrive {
static int ide_drive_initfn(IDEDevice *dev)
{
IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
ide_init_drive(bus->ifs + dev->unit, dev->dinfo);
ide_init_drive(bus->ifs + dev->unit, dev->dinfo, dev->version);
return 0;
}
@@ -110,6 +110,7 @@ static IDEDeviceInfo ide_drive_info = {
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("unit", IDEDrive, dev.unit, -1),
DEFINE_PROP_DRIVE("drive", IDEDrive, dev.dinfo),
DEFINE_PROP_STRING("ver", IDEDrive, dev.version),
DEFINE_PROP_END_OF_LIST(),
}
};
+84 -92
View File
@@ -173,11 +173,15 @@ do { fprintf(stderr, "lsi_scsi: error: " fmt , ## __VA_ARGS__);} while (0)
/* Flag set if this is a tagged command. */
#define LSI_TAG_VALID (1 << 16)
typedef struct {
typedef struct lsi_request {
uint32_t tag;
SCSIDevice *dev;
uint32_t dma_len;
uint8_t *dma_buf;
uint32_t pending;
int out;
} lsi_queue;
QTAILQ_ENTRY(lsi_request) next;
} lsi_request;
typedef struct {
PCIDevice dev;
@@ -198,16 +202,13 @@ typedef struct {
* 3 if a DMA operation is in progress. */
int waiting;
SCSIBus bus;
SCSIDevice *current_dev;
SCSIDevice *select_dev;
int current_lun;
/* The tag is a combination of the device ID and the SCSI tag. */
uint32_t current_tag;
uint32_t current_dma_len;
uint32_t select_tag;
int command_complete;
uint8_t *dma_buf;
lsi_queue *queue;
int queue_len;
int active_commands;
QTAILQ_HEAD(, lsi_request) queue;
lsi_request *current;
uint32_t dsa;
uint32_t temp;
@@ -370,7 +371,7 @@ static int lsi_dma_64bit(LSIState *s)
static uint8_t lsi_reg_readb(LSIState *s, int offset);
static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val);
static void lsi_execute_script(LSIState *s);
static void lsi_reselect(LSIState *s, uint32_t tag);
static void lsi_reselect(LSIState *s, lsi_request *p);
static inline uint32_t read_dword(LSIState *s, uint32_t addr)
{
@@ -391,9 +392,9 @@ static void lsi_stop_script(LSIState *s)
static void lsi_update_irq(LSIState *s)
{
int i;
int level;
static int last_level;
lsi_request *p;
/* It's unclear whether the DIP/SIP bits should be cleared when the
Interrupt Status Registers are cleared or when istat0 is read.
@@ -427,9 +428,9 @@ static void lsi_update_irq(LSIState *s)
if (!level && lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON)) {
DPRINTF("Handled IRQs & disconnected, looking for pending "
"processes\n");
for (i = 0; i < s->active_commands; i++) {
if (s->queue[i].pending) {
lsi_reselect(s, s->queue[i].tag);
QTAILQ_FOREACH(p, &s->queue, next) {
if (p->pending) {
lsi_reselect(s, p);
break;
}
}
@@ -508,15 +509,16 @@ static void lsi_do_dma(LSIState *s, int out)
uint32_t count;
target_phys_addr_t addr;
if (!s->current_dma_len) {
assert(s->current);
if (!s->current->dma_len) {
/* Wait until data is available. */
DPRINTF("DMA no data available\n");
return;
}
count = s->dbc;
if (count > s->current_dma_len)
count = s->current_dma_len;
if (count > s->current->dma_len)
count = s->current->dma_len;
addr = s->dnad;
/* both 40 and Table Indirect 64-bit DMAs store upper bits in dnad64 */
@@ -532,29 +534,29 @@ static void lsi_do_dma(LSIState *s, int out)
s->dnad += count;
s->dbc -= count;
if (s->dma_buf == NULL) {
s->dma_buf = s->current_dev->info->get_buf(s->current_dev,
s->current_tag);
if (s->current->dma_buf == NULL) {
s->current->dma_buf = s->current->dev->info->get_buf(s->current->dev,
s->current->tag);
}
/* ??? Set SFBR to first data byte. */
if (out) {
cpu_physical_memory_read(addr, s->dma_buf, count);
cpu_physical_memory_read(addr, s->current->dma_buf, count);
} else {
cpu_physical_memory_write(addr, s->dma_buf, count);
cpu_physical_memory_write(addr, s->current->dma_buf, count);
}
s->current_dma_len -= count;
if (s->current_dma_len == 0) {
s->dma_buf = NULL;
s->current->dma_len -= count;
if (s->current->dma_len == 0) {
s->current->dma_buf = NULL;
if (out) {
/* Write the data. */
s->current_dev->info->write_data(s->current_dev, s->current_tag);
s->current->dev->info->write_data(s->current->dev, s->current->tag);
} else {
/* Request any remaining data. */
s->current_dev->info->read_data(s->current_dev, s->current_tag);
s->current->dev->info->read_data(s->current->dev, s->current->tag);
}
} else {
s->dma_buf += count;
s->current->dma_buf += count;
lsi_resume_script(s);
}
}
@@ -563,15 +565,14 @@ static void lsi_do_dma(LSIState *s, int out)
/* Add a command to the queue. */
static void lsi_queue_command(LSIState *s)
{
lsi_queue *p;
lsi_request *p = s->current;
DPRINTF("Queueing tag=0x%x\n", s->current_tag);
if (s->queue_len == s->active_commands) {
s->queue_len++;
s->queue = qemu_realloc(s->queue, s->queue_len * sizeof(lsi_queue));
}
p = &s->queue[s->active_commands++];
p->tag = s->current_tag;
assert(s->current != NULL);
assert(s->current->dma_len == 0);
QTAILQ_INSERT_TAIL(&s->queue, s->current, next);
s->current = NULL;
p->pending = 0;
p->out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
}
@@ -588,45 +589,29 @@ static void lsi_add_msg_byte(LSIState *s, uint8_t data)
}
/* Perform reselection to continue a command. */
static void lsi_reselect(LSIState *s, uint32_t tag)
static void lsi_reselect(LSIState *s, lsi_request *p)
{
lsi_queue *p;
int n;
int id;
p = NULL;
for (n = 0; n < s->active_commands; n++) {
p = &s->queue[n];
if (p->tag == tag)
break;
}
if (n == s->active_commands) {
BADF("Reselected non-existant command tag=0x%x\n", tag);
return;
}
id = (tag >> 8) & 0xf;
assert(s->current == NULL);
QTAILQ_REMOVE(&s->queue, p, next);
s->current = p;
id = (p->tag >> 8) & 0xf;
s->ssid = id | 0x80;
/* LSI53C700 Family Compatibility, see LSI53C895A 4-73 */
if (!s->dcntl & LSI_DCNTL_COM) {
s->sfbr = 1 << (id & 0x7);
}
DPRINTF("Reselected target %d\n", id);
s->current_dev = s->bus.devs[id];
s->current_tag = tag;
s->scntl1 |= LSI_SCNTL1_CON;
lsi_set_phase(s, PHASE_MI);
s->msg_action = p->out ? 2 : 3;
s->current_dma_len = p->pending;
s->dma_buf = NULL;
s->current->dma_len = p->pending;
lsi_add_msg_byte(s, 0x80);
if (s->current_tag & LSI_TAG_VALID) {
if (s->current->tag & LSI_TAG_VALID) {
lsi_add_msg_byte(s, 0x20);
lsi_add_msg_byte(s, tag & 0xff);
}
s->active_commands--;
if (n != s->active_commands) {
s->queue[n] = s->queue[s->active_commands];
lsi_add_msg_byte(s, p->tag & 0xff);
}
if (lsi_irq_on_rsl(s)) {
@@ -638,10 +623,9 @@ static void lsi_reselect(LSIState *s, uint32_t tag)
the device was reselected, nonzero if the IO is deferred. */
static int lsi_queue_tag(LSIState *s, uint32_t tag, uint32_t arg)
{
lsi_queue *p;
int i;
for (i = 0; i < s->active_commands; i++) {
p = &s->queue[i];
lsi_request *p;
QTAILQ_FOREACH(p, &s->queue, next) {
if (p->tag == tag) {
if (p->pending) {
BADF("Multiple IO pending for tag %d\n", tag);
@@ -656,10 +640,10 @@ static int lsi_queue_tag(LSIState *s, uint32_t tag, uint32_t arg)
(lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON) &&
!(s->istat0 & (LSI_ISTAT0_SIP | LSI_ISTAT0_DIP)))) {
/* Reselect device. */
lsi_reselect(s, tag);
lsi_reselect(s, p);
return 0;
} else {
DPRINTF("Queueing IO tag=0x%x\n", tag);
DPRINTF("Queueing IO tag=0x%x\n", tag);
p->pending = arg;
return 1;
}
@@ -687,11 +671,15 @@ static void lsi_command_complete(SCSIBus *bus, int reason, uint32_t tag,
} else {
lsi_set_phase(s, PHASE_ST);
}
qemu_free(s->current);
s->current = NULL;
lsi_resume_script(s);
return;
}
if (s->waiting == 1 || tag != s->current_tag ||
if (s->waiting == 1 || !s->current || tag != s->current->tag ||
(lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON))) {
if (lsi_queue_tag(s, tag, arg))
return;
@@ -699,7 +687,7 @@ static void lsi_command_complete(SCSIBus *bus, int reason, uint32_t tag,
/* host adapter (re)connected */
DPRINTF("Data ready tag=0x%x len=%d\n", tag, arg);
s->current_dma_len = arg;
s->current->dma_len = arg;
s->command_complete = 1;
if (!s->waiting)
return;
@@ -721,14 +709,20 @@ static void lsi_do_command(LSIState *s)
cpu_physical_memory_read(s->dnad, buf, s->dbc);
s->sfbr = buf[0];
s->command_complete = 0;
n = s->current_dev->info->send_command(s->current_dev, s->current_tag, buf,
s->current_lun);
assert(s->current == NULL);
s->current = qemu_mallocz(sizeof(lsi_request));
s->current->tag = s->select_tag;
s->current->dev = s->select_dev;
n = s->current->dev->info->send_command(s->current->dev, s->current->tag, buf,
s->current_lun);
if (n > 0) {
lsi_set_phase(s, PHASE_DI);
s->current_dev->info->read_data(s->current_dev, s->current_tag);
s->current->dev->info->read_data(s->current->dev, s->current->tag);
} else if (n < 0) {
lsi_set_phase(s, PHASE_DO);
s->current_dev->info->write_data(s->current_dev, s->current_tag);
s->current->dev->info->write_data(s->current->dev, s->current->tag);
}
if (!s->command_complete) {
@@ -851,16 +845,16 @@ static void lsi_do_msgout(LSIState *s)
}
break;
case 0x20: /* SIMPLE queue */
s->current_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
s->select_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
DPRINTF("SIMPLE queue tag=0x%x\n", s->current_tag & 0xff);
break;
case 0x21: /* HEAD of queue */
BADF("HEAD queue not implemented\n");
s->current_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
s->select_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
break;
case 0x22: /* ORDERED queue */
BADF("ORDERED queue not implemented\n");
s->current_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
s->select_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID;
break;
default:
if ((msg & 0x80) == 0) {
@@ -905,17 +899,17 @@ static void lsi_memcpy(LSIState *s, uint32_t dest, uint32_t src, int count)
static void lsi_wait_reselect(LSIState *s)
{
int i;
lsi_request *p;
DPRINTF("Wait Reselect\n");
if (s->current_dma_len)
BADF("Reselect with pending DMA\n");
for (i = 0; i < s->active_commands; i++) {
if (s->queue[i].pending) {
lsi_reselect(s, s->queue[i].tag);
QTAILQ_FOREACH(p, &s->queue, next) {
if (p->pending) {
lsi_reselect(s, p);
break;
}
}
if (s->current_dma_len == 0) {
if (s->current == NULL) {
s->waiting = 1;
}
}
@@ -1093,8 +1087,8 @@ again:
/* ??? Linux drivers compain when this is set. Maybe
it only applies in low-level mode (unimplemented).
lsi_script_scsi_interrupt(s, LSI_SIST0_CMP, 0); */
s->current_dev = s->bus.devs[id];
s->current_tag = id << 8;
s->select_dev = s->bus.devs[id];
s->select_tag = id << 8;
s->scntl1 |= LSI_SCNTL1_CON;
if (insn & (1 << 3)) {
s->socl |= LSI_SOCL_ATN;
@@ -2006,9 +2000,11 @@ static void lsi_pre_save(void *opaque)
{
LSIState *s = opaque;
assert(s->dma_buf == NULL);
assert(s->current_dma_len == 0);
assert(s->active_commands == 0);
if (s->current) {
assert(s->current->dma_buf == NULL);
assert(s->current->dma_len == 0);
}
assert(QTAILQ_EMPTY(&s->queue));
}
static const VMStateDescription vmstate_lsi_scsi = {
@@ -2101,8 +2097,6 @@ static int lsi_scsi_uninit(PCIDevice *d)
cpu_unregister_io_memory(s->mmio_io_addr);
cpu_unregister_io_memory(s->ram_io_addr);
qemu_free(s->queue);
return 0;
}
@@ -2138,9 +2132,7 @@ static int lsi_scsi_init(PCIDevice *dev)
PCI_BASE_ADDRESS_SPACE_MEMORY, lsi_mmio_mapfunc);
pci_register_bar((struct PCIDevice *)s, 2, 0x2000,
PCI_BASE_ADDRESS_SPACE_MEMORY, lsi_ram_mapfunc);
s->queue = qemu_malloc(sizeof(lsi_queue));
s->queue_len = 1;
s->active_commands = 0;
QTAILQ_INIT(&s->queue);
lsi_soft_reset(s);
+1 -1
View File
@@ -30,7 +30,7 @@
//#define DEBUG_CMOS
#define RTC_REINJECT_ON_ACK_COUNT 1000
#define RTC_REINJECT_ON_ACK_COUNT 20
#define RTC_SECONDS 0
#define RTC_SECONDS_ALARM 1
+4 -5
View File
@@ -67,7 +67,7 @@
#define MP_AUDIO_IRQ 30
/* Wolfson 8750 I2C address */
#define MP_WM_ADDR 0x34
#define MP_WM_ADDR 0x1A
/* Ethernet register offsets */
#define MP_ETH_SMIR 0x010
@@ -238,14 +238,13 @@ static void eth_send(mv88w8618_eth_state *s, int queue_index)
{
uint32_t desc_addr = s->tx_queue[queue_index];
mv88w8618_tx_desc desc;
uint32_t next_desc;
uint8_t buf[2048];
int len;
if (!desc_addr) {
return;
}
do {
eth_tx_desc_get(desc_addr, &desc);
next_desc = desc.next;
if (desc.cmdstat & MP_ETH_TX_OWN) {
len = desc.bytes;
if (len < 2048) {
@@ -256,7 +255,7 @@ static void eth_send(mv88w8618_eth_state *s, int queue_index)
s->icr |= 1 << (MP_ETH_IRQ_TXLO_BIT - queue_index);
eth_tx_desc_put(desc_addr, &desc);
}
desc_addr = desc.next;
desc_addr = next_desc;
} while (desc_addr != s->tx_queue[queue_index]);
}
+16
View File
@@ -1306,6 +1306,14 @@ static QEMUMachine pc_machine_v0_11 = {
.driver = "virtio-blk-pci",
.property = "vectors",
.value = stringify(0),
},{
.driver = "ide-drive",
.property = "ver",
.value = "0.11",
},{
.driver = "scsi-disk",
.property = "ver",
.value = "0.11",
},{
.driver = "PCI",
.property = "rombar",
@@ -1337,6 +1345,14 @@ static QEMUMachine pc_machine_v0_10 = {
.driver = "virtio-blk-pci",
.property = "vectors",
.value = stringify(0),
},{
.driver = "ide-drive",
.property = "ver",
.value = "0.10",
},{
.driver = "scsi-disk",
.property = "ver",
.value = "0.10",
},{
.driver = "PCI",
.property = "rombar",
+7 -2
View File
@@ -65,6 +65,7 @@ struct SCSIDiskState
int cluster_size;
uint64_t max_lba;
QEMUBH *bh;
char *version;
};
static SCSIDiskReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
@@ -80,7 +81,7 @@ static SCSIDiskReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
static void scsi_remove_request(SCSIDiskReq *r)
{
qemu_free(r->iov.iov_base);
qemu_vfree(r->iov.iov_base);
scsi_req_free(&r->req);
}
@@ -315,6 +316,7 @@ static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
{
BlockDriverState *bdrv = req->dev->dinfo->bdrv;
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
int buflen = 0;
if (req->cmd.buf[1] & 0x2) {
@@ -432,7 +434,9 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
memcpy(&outbuf[16], "QEMU HARDDISK ", 16);
}
memcpy(&outbuf[8], "QEMU ", 8);
memcpy(&outbuf[32], QEMU_VERSION, 4);
memset(&outbuf[32], 0, 4);
memcpy(&outbuf[32], s->version ? s->version : QEMU_VERSION,
MIN(4, strlen(s->version ? s->version : QEMU_VERSION)));
/* Identify device as SCSI-3 rev 1.
Some later commands are also implemented. */
outbuf[2] = 3;
@@ -1029,6 +1033,7 @@ static SCSIDeviceInfo scsi_disk_info = {
.get_buf = scsi_get_buf,
.qdev.props = (Property[]) {
DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.dinfo),
DEFINE_PROP_STRING("ver", SCSIDiskState, version),
DEFINE_PROP_END_OF_LIST(),
},
};
+5 -2
View File
@@ -396,8 +396,11 @@ static void sh7750_mem_writel(void *opaque, target_phys_addr_t addr,
portb_changed(s, temp);
return;
case SH7750_MMUCR_A7:
s->cpu->mmucr = mem_value;
return;
if (mem_value & MMUCR_TI) {
cpu_sh4_invalidate_tlb(s->cpu);
}
s->cpu->mmucr = mem_value & ~MMUCR_TI;
return;
case SH7750_PTEH_A7:
/* If asid changes, clear all registered tlb entries. */
if ((s->cpu->pteh & 0xff) != (mem_value & 0xff))
+15 -96
View File
@@ -47,10 +47,15 @@ static void sh_pci_reg_write (void *p, target_phys_addr_t addr, uint32_t val)
pcic->par = val;
break;
case 0x1c4:
pcic->mbr = val;
pcic->mbr = val & 0xff000001;
break;
case 0x1c8:
pcic->iobr = val;
if ((val & 0xfffc0000) != (pcic->iobr & 0xfffc0000)) {
cpu_register_physical_memory(pcic->iobr & 0xfffc0000, 0x40000,
IO_MEM_UNASSIGNED);
pcic->iobr = val & 0xfffc0001;
isa_mmio_init(pcic->iobr & 0xfffc0000, 0x40000);
}
break;
case 0x220:
pci_data_write(pcic->bus, pcic->par, val, 4);
@@ -66,89 +71,16 @@ static uint32_t sh_pci_reg_read (void *p, target_phys_addr_t addr)
return le32_to_cpup((uint32_t*)(pcic->dev->config + addr));
case 0x1c0:
return pcic->par;
case 0x1c4:
return pcic->mbr;
case 0x1c8:
return pcic->iobr;
case 0x220:
return pci_data_read(pcic->bus, pcic->par, 4);
}
return 0;
}
static void sh_pci_data_write (SHPCIC *pcic, target_phys_addr_t addr,
uint32_t val, int size)
{
pci_data_write(pcic->bus, addr + pcic->mbr, val, size);
}
static uint32_t sh_pci_mem_read (SHPCIC *pcic, target_phys_addr_t addr,
int size)
{
return pci_data_read(pcic->bus, addr + pcic->mbr, size);
}
static void sh_pci_writeb (void *p, target_phys_addr_t addr, uint32_t val)
{
sh_pci_data_write(p, addr, val, 1);
}
static void sh_pci_writew (void *p, target_phys_addr_t addr, uint32_t val)
{
sh_pci_data_write(p, addr, val, 2);
}
static void sh_pci_writel (void *p, target_phys_addr_t addr, uint32_t val)
{
sh_pci_data_write(p, addr, val, 4);
}
static uint32_t sh_pci_readb (void *p, target_phys_addr_t addr)
{
return sh_pci_mem_read(p, addr, 1);
}
static uint32_t sh_pci_readw (void *p, target_phys_addr_t addr)
{
return sh_pci_mem_read(p, addr, 2);
}
static uint32_t sh_pci_readl (void *p, target_phys_addr_t addr)
{
return sh_pci_mem_read(p, addr, 4);
}
static int sh_pci_addr2port(SHPCIC *pcic, target_phys_addr_t addr)
{
return addr + pcic->iobr;
}
static void sh_pci_outb (void *p, target_phys_addr_t addr, uint32_t val)
{
cpu_outb(sh_pci_addr2port(p, addr), val);
}
static void sh_pci_outw (void *p, target_phys_addr_t addr, uint32_t val)
{
cpu_outw(sh_pci_addr2port(p, addr), val);
}
static void sh_pci_outl (void *p, target_phys_addr_t addr, uint32_t val)
{
cpu_outl(sh_pci_addr2port(p, addr), val);
}
static uint32_t sh_pci_inb (void *p, target_phys_addr_t addr)
{
return cpu_inb(sh_pci_addr2port(p, addr));
}
static uint32_t sh_pci_inw (void *p, target_phys_addr_t addr)
{
return cpu_inw(sh_pci_addr2port(p, addr));
}
static uint32_t sh_pci_inl (void *p, target_phys_addr_t addr)
{
return cpu_inl(sh_pci_addr2port(p, addr));
}
typedef struct {
CPUReadMemoryFunc * const r[3];
CPUWriteMemoryFunc * const w[3];
@@ -159,21 +91,11 @@ static MemOp sh_pci_reg = {
{ NULL, NULL, sh_pci_reg_write },
};
static MemOp sh_pci_mem = {
{ sh_pci_readb, sh_pci_readw, sh_pci_readl },
{ sh_pci_writeb, sh_pci_writew, sh_pci_writel },
};
static MemOp sh_pci_iop = {
{ sh_pci_inb, sh_pci_inw, sh_pci_inl },
{ sh_pci_outb, sh_pci_outw, sh_pci_outl },
};
PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
void *opaque, int devfn_min, int nirq)
{
SHPCIC *p;
int mem, reg, iop;
int reg;
p = qemu_mallocz(sizeof(SHPCIC));
p->bus = pci_register_bus(NULL, "pci",
@@ -182,14 +104,11 @@ PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
p->dev = pci_register_device(p->bus, "SH PCIC", sizeof(PCIDevice),
-1, NULL, NULL);
reg = cpu_register_io_memory(sh_pci_reg.r, sh_pci_reg.w, p);
iop = cpu_register_io_memory(sh_pci_iop.r, sh_pci_iop.w, p);
mem = cpu_register_io_memory(sh_pci_mem.r, sh_pci_mem.w, p);
cpu_register_physical_memory(0x1e200000, 0x224, reg);
cpu_register_physical_memory(0x1e240000, 0x40000, iop);
cpu_register_physical_memory(0x1d000000, 0x1000000, mem);
cpu_register_physical_memory(0xfe200000, 0x224, reg);
cpu_register_physical_memory(0xfe240000, 0x40000, iop);
cpu_register_physical_memory(0xfd000000, 0x1000000, mem);
p->iobr = 0xfe240000;
isa_mmio_init(p->iobr, 0x40000);
pci_config_set_vendor_id(p->dev->config, PCI_VENDOR_ID_HITACHI);
pci_config_set_device_id(p->dev->config, PCI_DEVICE_ID_HITACHI_SH7751R);
+1 -1
View File
@@ -1492,7 +1492,7 @@ static USBDevice *usb_net_init(const char *cmdline)
dev = usb_create(NULL /* FIXME */, "usb-net");
qdev_set_nic_properties(&dev->qdev, &nd_table[idx]);
qdev_init(&dev->qdev);
qdev_init_nofail(&dev->qdev);
return dev;
}
+24 -8
View File
@@ -497,12 +497,28 @@ static int usb_serial_can_read(void *opaque)
static void usb_serial_read(void *opaque, const uint8_t *buf, int size)
{
USBSerialState *s = opaque;
int first_size = RECV_BUF - s->recv_ptr;
if (first_size > size)
first_size = size;
memcpy(s->recv_buf + s->recv_ptr + s->recv_used, buf, first_size);
if (size > first_size)
memcpy(s->recv_buf, buf + first_size, size - first_size);
int first_size, start;
/* room in the buffer? */
if (size > (RECV_BUF - s->recv_used))
size = RECV_BUF - s->recv_used;
start = s->recv_ptr + s->recv_used;
if (start < RECV_BUF) {
/* copy data to end of buffer */
first_size = RECV_BUF - start;
if (first_size > size)
first_size = size;
memcpy(s->recv_buf + start, buf, first_size);
/* wrap around to front if needed */
if (size > first_size)
memcpy(s->recv_buf, buf + first_size, size - first_size);
} else {
start -= RECV_BUF;
memcpy(s->recv_buf + start, buf, size);
}
s->recv_used += size;
}
@@ -583,7 +599,7 @@ static USBDevice *usb_serial_init(const char *filename)
qdev_prop_set_uint16(&dev->qdev, "vendorid", vendorid);
if (productid)
qdev_prop_set_uint16(&dev->qdev, "productid", productid);
qdev_init(&dev->qdev);
qdev_init_nofail(&dev->qdev);
return dev;
}
@@ -599,7 +615,7 @@ static USBDevice *usb_braille_init(const char *unused)
dev = usb_create(NULL /* FIXME */, "usb-braille");
qdev_prop_set_chr(&dev->qdev, "chardev", cdrv);
qdev_init(&dev->qdev);
qdev_init_nofail(&dev->qdev);
return dev;
}
+4 -3
View File
@@ -677,9 +677,6 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_
ret = async->packet.len;
if (td->ctrl & TD_CTRL_IOC)
*int_mask |= 0x01;
if (td->ctrl & TD_CTRL_IOS)
td->ctrl &= ~TD_CTRL_ACTIVE;
@@ -693,6 +690,8 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_
here. The docs are somewhat unclear, but win2k relies on this
behavior. */
td->ctrl &= ~(TD_CTRL_ACTIVE | TD_CTRL_NAK);
if (td->ctrl & TD_CTRL_IOC)
*int_mask |= 0x01;
if (pid == USB_TOKEN_IN) {
if (len > max_len) {
@@ -750,6 +749,8 @@ out:
if (err == 0) {
td->ctrl &= ~TD_CTRL_ACTIVE;
s->status |= UHCI_STS_USBERR;
if (td->ctrl & TD_CTRL_IOC)
*int_mask |= 0x01;
uhci_update_irq(s);
}
}
+57 -36
View File
@@ -272,7 +272,7 @@ static void do_multiwrite(BlockDriverState *bs, BlockRequest *blkreq,
if (ret != 0) {
for (i = 0; i < num_writes; i++) {
if (blkreq[i].error) {
virtio_blk_req_complete(blkreq[i].opaque, VIRTIO_BLK_S_IOERR);
virtio_blk_rw_complete(blkreq[i].opaque, -EIO);
}
}
}
@@ -316,7 +316,46 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
acb = bdrv_aio_readv(req->dev->bs, req->out->sector, &req->qiov,
req->qiov.size / 512, virtio_blk_rw_complete, req);
if (!acb) {
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
virtio_blk_rw_complete(req, -EIO);
}
}
typedef struct MultiReqBuffer {
BlockRequest blkreq[32];
int num_writes;
BlockDriverState *old_bs;
} MultiReqBuffer;
static void virtio_blk_handle_request(VirtIOBlockReq *req,
MultiReqBuffer *mrb)
{
if (req->elem.out_num < 1 || req->elem.in_num < 1) {
fprintf(stderr, "virtio-blk missing headers\n");
exit(1);
}
if (req->elem.out_sg[0].iov_len < sizeof(*req->out) ||
req->elem.in_sg[req->elem.in_num - 1].iov_len < sizeof(*req->in)) {
fprintf(stderr, "virtio-blk header not in correct element\n");
exit(1);
}
req->out = (void *)req->elem.out_sg[0].iov_base;
req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base;
if (req->out->type & VIRTIO_BLK_T_FLUSH) {
virtio_blk_handle_flush(req);
} else if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) {
virtio_blk_handle_scsi(req);
} else if (req->out->type & VIRTIO_BLK_T_OUT) {
qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1],
req->elem.out_num - 1);
virtio_blk_handle_write(mrb->blkreq, &mrb->num_writes,
req, &mrb->old_bs);
} else {
qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0],
req->elem.in_num - 1);
virtio_blk_handle_read(req);
}
}
@@ -324,42 +363,17 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
{
VirtIOBlock *s = to_virtio_blk(vdev);
VirtIOBlockReq *req;
BlockRequest blkreq[32];
int num_writes = 0;
BlockDriverState *old_bs = NULL;
MultiReqBuffer mrb = {
.num_writes = 0,
.old_bs = NULL,
};
while ((req = virtio_blk_get_request(s))) {
if (req->elem.out_num < 1 || req->elem.in_num < 1) {
fprintf(stderr, "virtio-blk missing headers\n");
exit(1);
}
if (req->elem.out_sg[0].iov_len < sizeof(*req->out) ||
req->elem.in_sg[req->elem.in_num - 1].iov_len < sizeof(*req->in)) {
fprintf(stderr, "virtio-blk header not in correct element\n");
exit(1);
}
req->out = (void *)req->elem.out_sg[0].iov_base;
req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base;
if (req->out->type & VIRTIO_BLK_T_FLUSH) {
virtio_blk_handle_flush(req);
} else if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) {
virtio_blk_handle_scsi(req);
} else if (req->out->type & VIRTIO_BLK_T_OUT) {
qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1],
req->elem.out_num - 1);
virtio_blk_handle_write(blkreq, &num_writes, req, &old_bs);
} else {
qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0],
req->elem.in_num - 1);
virtio_blk_handle_read(req);
}
virtio_blk_handle_request(req, &mrb);
}
if (num_writes > 0) {
do_multiwrite(old_bs, blkreq, num_writes);
if (mrb.num_writes > 0) {
do_multiwrite(mrb.old_bs, mrb.blkreq, mrb.num_writes);
}
/*
@@ -373,6 +387,10 @@ static void virtio_blk_dma_restart_bh(void *opaque)
{
VirtIOBlock *s = opaque;
VirtIOBlockReq *req = s->rq;
MultiReqBuffer mrb = {
.num_writes = 0,
.old_bs = NULL,
};
qemu_bh_delete(s->bh);
s->bh = NULL;
@@ -380,10 +398,13 @@ static void virtio_blk_dma_restart_bh(void *opaque)
s->rq = NULL;
while (req) {
bdrv_aio_writev(req->dev->bs, req->out->sector, &req->qiov,
req->qiov.size / 512, virtio_blk_rw_complete, req);
virtio_blk_handle_request(req, &mrb);
req = req->next;
}
if (mrb.num_writes > 0) {
do_multiwrite(mrb.old_bs, mrb.blkreq, mrb.num_writes);
}
}
static void virtio_blk_dma_restart_cb(void *opaque, int running, int reason)
+9 -1
View File
@@ -384,7 +384,15 @@ static int virtio_net_has_buffers(VirtIONet *n, int bufsize)
(n->mergeable_rx_bufs &&
!virtqueue_avail_bytes(n->rx_vq, bufsize, 0))) {
virtio_queue_set_notification(n->rx_vq, 1);
return 0;
/* To avoid a race condition where the guest has made some buffers
* available after the above check but before notification was
* enabled, check for available buffers again.
*/
if (virtio_queue_empty(n->rx_vq) ||
(n->mergeable_rx_bufs &&
!virtqueue_avail_bytes(n->rx_vq, bufsize, 0)))
return 0;
}
virtio_queue_set_notification(n->rx_vq, 0);
+16
View File
@@ -54,6 +54,9 @@ enum json_lexer_state {
IN_ESCAPE,
IN_ESCAPE_L,
IN_ESCAPE_LL,
IN_ESCAPE_I,
IN_ESCAPE_I6,
IN_ESCAPE_I64,
IN_ESCAPE_DONE,
IN_WHITESPACE,
IN_OPERATOR_DONE,
@@ -223,6 +226,18 @@ static const uint8_t json_lexer[][256] = {
['l'] = IN_ESCAPE_LL,
},
[IN_ESCAPE_I64] = {
['d'] = IN_ESCAPE_DONE,
},
[IN_ESCAPE_I6] = {
['4'] = IN_ESCAPE_I64,
},
[IN_ESCAPE_I] = {
['6'] = IN_ESCAPE_I6,
},
[IN_ESCAPE] = {
['d'] = IN_ESCAPE_DONE,
['i'] = IN_ESCAPE_DONE,
@@ -230,6 +245,7 @@ static const uint8_t json_lexer[][256] = {
['s'] = IN_ESCAPE_DONE,
['f'] = IN_ESCAPE_DONE,
['l'] = IN_ESCAPE_L,
['I'] = IN_ESCAPE_I,
},
/* top level rule */
+3 -2
View File
@@ -266,7 +266,7 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict, QList **tokens, va_l
peek = qlist_peek(working);
key = parse_value(ctxt, &working, ap);
if (qobject_type(key) != QTYPE_QSTRING) {
if (!key || qobject_type(key) != QTYPE_QSTRING) {
parse_error(ctxt, peek, "key is not a string in object");
goto out;
}
@@ -476,7 +476,8 @@ static QObject *parse_escape(JSONParserContext *ctxt, QList **tokens, va_list *a
obj = QOBJECT(qint_from_int(va_arg(*ap, int)));
} else if (token_is_escape(token, "%ld")) {
obj = QOBJECT(qint_from_int(va_arg(*ap, long)));
} else if (token_is_escape(token, "%lld")) {
} else if (token_is_escape(token, "%lld") ||
token_is_escape(token, "%I64d")) {
obj = QOBJECT(qint_from_int(va_arg(*ap, long long)));
} else if (token_is_escape(token, "%s")) {
obj = QOBJECT(qstring_from_str(va_arg(*ap, const char *)));
+1 -1
View File
@@ -2684,7 +2684,7 @@ int main(int argc, char **argv, char **envp)
#endif
#elif defined(TARGET_PPC)
#ifdef TARGET_PPC64
cpu_model = "970";
cpu_model = "970fx";
#else
cpu_model = "750";
#endif
+6 -5
View File
@@ -334,13 +334,10 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
{
QDict *qmp;
const char *event_name;
Monitor *mon = cur_mon;
Monitor *mon;
assert(event < QEVENT_MAX);
if (!monitor_ctrl_mode(mon))
return;
switch (event) {
case QEVENT_DEBUG:
event_name = "DEBUG";
@@ -370,7 +367,11 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
qdict_put_obj(qmp, "data", data);
}
monitor_json_emitter(mon, QOBJECT(qmp));
QLIST_FOREACH(mon, &mon_list, entry) {
if (monitor_ctrl_mode(mon)) {
monitor_json_emitter(mon, QOBJECT(qmp));
}
}
QDECREF(qmp);
}
+37 -47
View File
@@ -96,7 +96,7 @@ int parse_host_src_port(struct sockaddr_in *haddr,
struct sockaddr_in *saddr,
const char *input_str)
{
char *str = strdup(input_str);
char *str = qemu_strdup(input_str);
char *host_str = str;
char *src_str;
const char *src_str2;
@@ -812,9 +812,6 @@ static int net_init_nic(QemuOpts *opts,
}
nd->used = 1;
if (vlan) {
nd->vlan->nb_guest_devs++;
}
nb_nics++;
return idx;
@@ -1128,20 +1125,6 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
return -1;
}
void net_client_uninit(NICInfo *nd)
{
if (nd->vlan) {
nd->vlan->nb_guest_devs--;
}
nb_nics--;
qemu_free(nd->model);
qemu_free(nd->name);
qemu_free(nd->devaddr);
nd->used = 0;
}
static int net_host_check_device(const char *device)
{
int i;
@@ -1204,39 +1187,26 @@ void net_host_device_remove(Monitor *mon, const QDict *qdict)
qemu_del_vlan_client(vc);
}
void net_set_boot_mask(int net_boot_mask)
{
int i;
/* Only the first four NICs may be bootable */
net_boot_mask = net_boot_mask & 0xF;
for (i = 0; i < nb_nics; i++) {
if (net_boot_mask & (1 << i)) {
nd_table[i].bootable = 1;
net_boot_mask &= ~(1 << i);
}
}
if (net_boot_mask) {
fprintf(stderr, "Cannot boot from non-existent NIC\n");
exit(1);
}
}
void do_info_network(Monitor *mon)
{
VLANState *vlan;
VLANClientState *vc;
QTAILQ_FOREACH(vlan, &vlans, next) {
VLANClientState *vc;
monitor_printf(mon, "VLAN %d devices:\n", vlan->id);
QTAILQ_FOREACH(vc, &vlan->clients, next) {
monitor_printf(mon, " %s: %s\n", vc->name, vc->info_str);
}
}
monitor_printf(mon, "Devices not on any VLAN:\n");
QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
monitor_printf(mon, " %s: %s", vc->name, vc->info_str);
if (vc->peer) {
monitor_printf(mon, " peer=%s", vc->peer->name);
}
monitor_printf(mon, "\n");
}
}
void do_set_link(Monitor *mon, const QDict *qdict)
@@ -1253,6 +1223,7 @@ void do_set_link(Monitor *mon, const QDict *qdict)
}
}
}
vc = qemu_find_netdev(name);
done:
if (!vc) {
@@ -1289,20 +1260,41 @@ void net_cleanup(void)
}
}
static void net_check_clients(void)
void net_check_clients(void)
{
VLANState *vlan;
VLANClientState *vc;
int has_nic, has_host_dev;
QTAILQ_FOREACH(vlan, &vlans, next) {
if (vlan->nb_guest_devs == 0 && vlan->nb_host_devs == 0)
continue;
if (vlan->nb_guest_devs == 0)
QTAILQ_FOREACH(vc, &vlan->clients, next) {
switch (vc->info->type) {
case NET_CLIENT_TYPE_NIC:
has_nic = 1;
break;
case NET_CLIENT_TYPE_SLIRP:
case NET_CLIENT_TYPE_TAP:
case NET_CLIENT_TYPE_SOCKET:
case NET_CLIENT_TYPE_VDE:
has_host_dev = 1;
break;
default: ;
}
}
if (has_host_dev && !has_nic)
fprintf(stderr, "Warning: vlan %d with no nics\n", vlan->id);
if (vlan->nb_host_devs == 0)
if (has_nic && !has_host_dev)
fprintf(stderr,
"Warning: vlan %d is not connected to host network\n",
vlan->id);
}
QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
if (!vc->peer) {
fprintf(stderr, "Warning: %s %s has no peer\n",
vc->info->type == NET_CLIENT_TYPE_NIC ? "nic" : "netdev",
vc->name);
}
}
}
static int net_init_client(QemuOpts *opts, void *dummy)
@@ -1337,8 +1329,6 @@ int net_init_clients(void)
return -1;
}
net_check_clients();
return 0;
}
+1 -3
View File
@@ -76,7 +76,6 @@ struct VLANState {
int id;
QTAILQ_HEAD(, VLANClientState) clients;
QTAILQ_ENTRY(VLANState) next;
unsigned int nb_guest_devs, nb_host_devs;
NetQueue *send_queue;
};
@@ -160,11 +159,10 @@ extern const char *legacy_tftp_prefix;
extern const char *legacy_bootp_filename;
int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev);
void net_client_uninit(NICInfo *nd);
int net_client_parse(QemuOptsList *opts_list, const char *str);
int net_init_clients(void);
void net_check_clients(void);
void net_cleanup(void);
void net_set_boot_mask(int boot_mask);
void net_host_device_add(Monitor *mon, const QDict *qdict);
void net_host_device_remove(Monitor *mon, const QDict *qdict);
-4
View File
@@ -728,10 +728,6 @@ int net_init_slirp(QemuOpts *opts,
qemu_free(config);
}
if (ret != -1 && vlan) {
vlan->nb_host_devs++;
}
qemu_free(vnet);
return ret;
-4
View File
@@ -569,9 +569,5 @@ int net_init_socket(QemuOpts *opts,
return -1;
}
if (vlan) {
vlan->nb_host_devs++;
}
return 0;
}
-4
View File
@@ -714,10 +714,6 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
return -1;
}
if (vlan) {
vlan->nb_host_devs++;
}
return 0;
}
-4
View File
@@ -441,9 +441,5 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
}
}
if (vlan) {
vlan->nb_host_devs++;
}
return 0;
}
-4
View File
@@ -127,9 +127,5 @@ int net_init_vde(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
return -1;
}
if (vlan) {
vlan->nb_host_devs++;
}
return 0;
}
BIN
View File
Binary file not shown.
+4 -4
View File
@@ -1180,6 +1180,9 @@ static CharDriverState *qemu_chr_open_tty(QemuOpts *opts)
int fd;
TFR(fd = open(filename, O_RDWR | O_NONBLOCK));
if (fd < 0) {
return NULL;
}
tty_serial_init(fd, 115200, 'N', 8, 1);
chr = qemu_chr_open_fd(fd, fd);
if (!chr) {
@@ -2314,8 +2317,7 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
qemu_opt_set(opts, "backend", "udp");
if (sscanf(p, "%64[^:]:%32[^@,]%n", host, port, &pos) < 2) {
host[0] = 0;
if (sscanf(p, ":%32[^,]%n", port, &pos) < 1) {
fprintf(stderr, "udp #1\n");
if (sscanf(p, ":%32[^@,]%n", port, &pos) < 1) {
goto fail;
}
}
@@ -2326,7 +2328,6 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
if (sscanf(p, "%64[^:]:%32[^,]%n", host, port, &pos) < 2) {
host[0] = 0;
if (sscanf(p, ":%32[^,]%n", port, &pos) < 1) {
fprintf(stderr, "udp #2\n");
goto fail;
}
}
@@ -2354,7 +2355,6 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
}
fail:
fprintf(stderr, "%s: fail on \"%s\"\n", __FUNCTION__, filename);
qemu_opts_del(opts);
return NULL;
}
+6 -1
View File
@@ -2,6 +2,8 @@
#ifndef QEMU_COMMON_H
#define QEMU_COMMON_H
#include "config-host.h"
#define QEMU_NORETURN __attribute__ ((__noreturn__))
#ifdef CONFIG_GCC_ATTRIBUTE_WARN_UNUSED_RESULT
#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
@@ -29,7 +31,6 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <assert.h>
#include "config-host.h"
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
@@ -53,6 +54,10 @@ struct iovec {
void *iov_base;
size_t iov_len;
};
/*
* Use the same value as Linux for now.
*/
#define IOV_MAX 1024
#else
#include <sys/uio.h>
#endif
+1 -1
View File
@@ -467,7 +467,7 @@ int main(int argc, char **argv)
}
}
} while (persistent || nb_fds > 1);
qemu_free(data);
qemu_vfree(data);
close(sharing_fds[0]);
bdrv_close(bs);
+22 -5
View File
@@ -404,6 +404,12 @@ ETEXI
DEF("device", HAS_ARG, QEMU_OPTION_device,
"-device driver[,options] add device\n")
STEXI
@item -device @var{driver}[,@var{option}[,...]]
Add device @var{driver}. Depending on the device type,
@var{option} (typically @var{key}=@var{value}) may be useful.
ETEXI
DEF("name", HAS_ARG, QEMU_OPTION_name,
"-name string1[,process=string2] set the name of the guest\n"
" string1 sets the window title and string2 the process name (on Linux)\n")
@@ -962,7 +968,7 @@ the guest, use the following:
@example
# on the host
qemu -net user,hostfwd=tcp:5555::23 [...]
qemu -net user,hostfwd=tcp::5555-:23 [...]
telnet localhost 5555
@end example
@@ -1893,6 +1899,8 @@ ETEXI
DEF("nodefaults", 0, QEMU_OPTION_nodefaults, \
"-nodefaults don't create default devices.\n")
STEXI
@item -nodefaults
Don't create default devices.
ETEXI
#ifndef _WIN32
@@ -1915,10 +1923,6 @@ Immediately before starting guest execution, drop root privileges, switching
to the specified user.
ETEXI
STEXI
@end table
ETEXI
#if defined(TARGET_SPARC) || defined(TARGET_PPC)
DEF("prom-env", HAS_ARG, QEMU_OPTION_prom_env,
"-prom-env variable=value\n"
@@ -1934,6 +1938,19 @@ DEF("old-param", 0, QEMU_OPTION_old_param,
#endif
DEF("readconfig", HAS_ARG, QEMU_OPTION_readconfig,
"-readconfig <file>\n")
STEXI
@item -readconfig @var{file}
Read device configuration from @var{file}.
ETEXI
DEF("writeconfig", HAS_ARG, QEMU_OPTION_writeconfig,
"-writeconfig <file>\n"
" read/write config file\n")
STEXI
@item -writeconfig @var{file}
Write device configuration to @var{file}.
ETEXI
HXCOMM This is the last statement. Insert new options before this line!
STEXI
@end table
ETEXI
+4 -4
View File
@@ -424,7 +424,7 @@ static int inet_parse(QemuOpts *opts, const char *str)
__FUNCTION__, str);
return -1;
}
qemu_opt_set(opts, "ipv6", "yes");
qemu_opt_set(opts, "ipv6", "on");
} else if (qemu_isdigit(str[0])) {
/* IPv4 addr */
if (2 != sscanf(str,"%64[0-9.]:%32[^,]%n",addr,port,&pos)) {
@@ -432,7 +432,7 @@ static int inet_parse(QemuOpts *opts, const char *str)
__FUNCTION__, str);
return -1;
}
qemu_opt_set(opts, "ipv4", "yes");
qemu_opt_set(opts, "ipv4", "on");
} else {
/* hostname */
if (2 != sscanf(str,"%64[^:]:%32[^,]%n",addr,port,&pos)) {
@@ -450,9 +450,9 @@ static int inet_parse(QemuOpts *opts, const char *str)
if (h)
qemu_opt_set(opts, "to", h+4);
if (strstr(optstr, ",ipv4"))
qemu_opt_set(opts, "ipv4", "yes");
qemu_opt_set(opts, "ipv4", "on");
if (strstr(optstr, ",ipv6"))
qemu_opt_set(opts, "ipv6", "yes");
qemu_opt_set(opts, "ipv6", "on");
return 0;
}
+1 -1
View File
@@ -1696,7 +1696,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)
sn->vm_clock_nsec = qemu_get_clock(vm_clock);
/* Delete old snapshots of the same name */
if (del_existing_snapshots(mon, name) < 0) {
if (name && del_existing_snapshots(mon, name) < 0) {
goto the_end;
}
+1
View File
@@ -525,6 +525,7 @@ static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state
static void toggle_full_screen(DisplayState *ds)
{
gui_fullscreen = !gui_fullscreen;
do_sdl_resize(real_screen->w, real_screen->h, real_screen->format->BitsPerPixel);
if (gui_fullscreen) {
scaling_active = 0;
gui_saved_grab = gui_grab;
+1 -1
View File
@@ -179,7 +179,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
close(s);
i = 0;
bptr = strdup(ex); /* No need to free() this */
bptr = qemu_strdup(ex); /* No need to free() this */
if (do_pty == 1) {
/* Setup "slirp.telnetd -x" */
argv[i++] = "slirp.telnetd";
+9 -6
View File
@@ -2047,8 +2047,8 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
gen_op_movl_A0_im(disp);
}
}
/* XXX: index == 4 is always invalid */
if (havesib && (index != 4 || scale != 0)) {
/* index == 4 means no index */
if (havesib && (index != 4)) {
#ifdef TARGET_X86_64
if (s->aflag == 2) {
gen_op_addq_A0_reg_sN(scale, index);
@@ -3165,12 +3165,17 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
case 0x1e7: /* movntdq */
case 0x02b: /* movntps */
case 0x12b: /* movntps */
case 0x3f0: /* lddqu */
if (mod == 3)
goto illegal_op;
gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
gen_sto_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
break;
case 0x3f0: /* lddqu */
if (mod == 3)
goto illegal_op;
gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
gen_ldo_env_A0(s->mem_index, offsetof(CPUX86State,xmm_regs[reg]));
break;
case 0x22b: /* movntss */
case 0x32b: /* movntsd */
if (mod == 3)
@@ -4591,9 +4596,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
/* operand size for jumps is 64 bit */
ot = OT_QUAD;
} else if (op == 3 || op == 5) {
/* for call calls, the operand is 16 or 32 bit, even
in long mode */
ot = dflag ? OT_LONG : OT_WORD;
ot = dflag ? OT_LONG + (rex_w == 1) : OT_WORD;
} else if (op == 6) {
/* default push size is 64 bit */
ot = dflag ? OT_QUAD : OT_WORD;
+2 -2
View File
@@ -590,8 +590,8 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
#define cpu_handle_mmu_fault cpu_mips_handle_mmu_fault
void do_interrupt (CPUState *env);
void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra);
target_phys_addr_t do_translate_address (CPUState *env, target_ulong address,
int rw);
target_phys_addr_t cpu_mips_translate_address (CPUState *env, target_ulong address,
int rw);
static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
{
+4 -4
View File
@@ -311,7 +311,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
}
#if !defined(CONFIG_USER_ONLY)
target_phys_addr_t do_translate_address(CPUState *env, target_ulong address, int rw)
target_phys_addr_t cpu_mips_translate_address(CPUState *env, target_ulong address, int rw)
{
target_phys_addr_t physical;
int prot;
@@ -326,10 +326,10 @@ target_phys_addr_t do_translate_address(CPUState *env, target_ulong address, int
address, rw, access_type);
if (ret != TLBRET_MATCH) {
raise_mmu_exception(env, address, rw, ret);
cpu_loop_exit();
return -1LL;
} else {
return physical;
}
return physical;
}
#endif
+16 -2
View File
@@ -276,10 +276,24 @@ void helper_dmultu (target_ulong arg1, target_ulong arg2)
#endif
#ifndef CONFIG_USER_ONLY
static inline target_phys_addr_t do_translate_address(target_ulong address, int rw)
{
target_phys_addr_t lladdr;
lladdr = cpu_mips_translate_address(env, address, rw);
if (lladdr == -1LL) {
cpu_loop_exit();
} else {
return lladdr;
}
}
#define HELPER_LD_ATOMIC(name, insn) \
target_ulong helper_##name(target_ulong arg, int mem_idx) \
{ \
env->lladdr = do_translate_address(env, arg, 0); \
env->lladdr = do_translate_address(arg, 0); \
env->llval = do_##insn(arg, mem_idx); \
return env->llval; \
}
@@ -298,7 +312,7 @@ target_ulong helper_##name(target_ulong arg1, target_ulong arg2, int mem_idx) \
env->CP0_BadVAddr = arg2; \
helper_raise_exception(EXCP_AdES); \
} \
if (do_translate_address(env, arg2, 1) == env->lladdr) { \
if (do_translate_address(arg2, 1) == env->lladdr) { \
tmp = do_##ld_insn(arg2, mem_idx); \
if (tmp == env->llval) { \
do_##st_insn(arg2, arg1, mem_idx); \
+5 -1
View File
@@ -821,7 +821,7 @@ static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv
static inline void check_cp0_enabled(DisasContext *ctx)
{
if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
generate_exception_err(ctx, EXCP_CpU, 1);
generate_exception_err(ctx, EXCP_CpU, 0);
}
static inline void check_cp1_enabled(DisasContext *ctx)
@@ -1451,6 +1451,8 @@ static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
tcg_gen_rotri_i32(t1, t1, uimm);
tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
tcg_temp_free_i32(t1);
} else {
tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
}
opn = "rotr";
} else {
@@ -1489,6 +1491,8 @@ static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
if (env->insn_flags & ISA_MIPS32R2) {
if (uimm != 0) {
tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
} else {
tcg_gen_mov_tl(cpu_gpr[rt], t0);
}
opn = "drotr";
} else {
+2
View File
@@ -167,6 +167,7 @@ int cpu_sh4_handle_mmu_fault(CPUSH4State * env, target_ulong address, int rw,
void do_interrupt(CPUSH4State * env);
void sh4_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
void cpu_sh4_invalidate_tlb(CPUSH4State *s);
void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr,
uint32_t mem_value);
@@ -222,6 +223,7 @@ enum {
/* MMU control register */
#define MMUCR 0x1F000010
#define MMUCR_AT (1<<0)
#define MMUCR_TI (1<<2)
#define MMUCR_SV (1<<8)
#define MMUCR_URC_BITS (6)
#define MMUCR_URC_OFFSET (10)
+20 -2
View File
@@ -377,7 +377,7 @@ static int get_mmu_address(CPUState * env, target_ulong * physical,
n = find_itlb_entry(env, address, use_asid, 1);
if (n >= 0) {
matching = &env->itlb[n];
if ((env->sr & SR_MD) & !(matching->pr & 2))
if (!(env->sr & SR_MD) && !(matching->pr & 2))
n = MMU_ITLB_VIOLATION;
else
*prot = PAGE_READ;
@@ -430,7 +430,7 @@ static int get_physical_address(CPUState * env, target_ulong * physical,
if ((address >= 0x80000000 && address < 0xc0000000) ||
address >= 0xe0000000) {
if (!(env->sr & SR_MD)
&& (address < 0xe0000000 || address > 0xe4000000)) {
&& (address < 0xe0000000 || address >= 0xe4000000)) {
/* Unauthorized access in user mode (only store queues are available) */
fprintf(stderr, "Unauthorized access\n");
if (rw == 0)
@@ -574,6 +574,24 @@ void cpu_load_tlb(CPUSH4State * env)
entry->tc = (uint8_t)cpu_ptea_tc(env->ptea);
}
void cpu_sh4_invalidate_tlb(CPUSH4State *s)
{
int i;
/* UTLB */
for (i = 0; i < UTLB_SIZE; i++) {
tlb_t * entry = &s->utlb[i];
entry->v = 0;
}
/* ITLB */
for (i = 0; i < UTLB_SIZE; i++) {
tlb_t * entry = &s->utlb[i];
entry->v = 0;
}
tlb_flush(s, 1);
}
void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr,
uint32_t mem_value)
{
+1 -1
View File
@@ -1905,7 +1905,7 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
ctx.bstate = BS_NONE;
ctx.sr = env->sr;
ctx.fpscr = env->fpscr;
ctx.memidx = (env->sr & SR_MD) ? 1 : 0;
ctx.memidx = (env->sr & SR_MD) == 0 ? 1 : 0;
/* We don't know if the delayed pc came from a dynamic or static branch,
so assume it is a dynamic branch. */
ctx.delayed_pc = -1; /* use delayed pc from env pointer */
+7 -4
View File
@@ -1697,12 +1697,15 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type,
void tcg_target_qemu_prologue(TCGContext *s)
{
/* stmdb sp!, { r9 - r11, lr } */
tcg_out32(s, (COND_AL << 28) | 0x092d4e00);
/* Theoretically there is no need to save r12, but an
even number of registers to be saved as per EABI */
/* stmdb sp!, { r4 - r12, lr } */
tcg_out32(s, (COND_AL << 28) | 0x092d5ff0);
tcg_out_bx(s, COND_AL, TCG_REG_R0);
tb_ret_addr = s->code_ptr;
/* ldmia sp!, { r9 - r11, pc } */
tcg_out32(s, (COND_AL << 28) | 0x08bd8e00);
/* ldmia sp!, { r4 - r12, pc } */
tcg_out32(s, (COND_AL << 28) | 0x08bd9ff0);
}
+35 -23
View File
@@ -339,6 +339,17 @@ static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int i
tcg_out32(s, inst);
}
/*
* Type branch
*/
static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs)
{
/* We need to keep the offset unchanged for retranslation */
uint16_t offset = (uint16_t)(*(uint32_t *) &s->code_ptr);
tcg_out_opc_imm(s, opc, rt, rs, offset);
}
/*
* Type sa
*/
@@ -469,42 +480,42 @@ static void tcg_out_brcond(TCGContext *s, int cond, int arg1,
switch (cond) {
case TCG_COND_EQ:
tcg_out_opc_imm(s, OPC_BEQ, arg1, arg2, 0);
tcg_out_opc_br(s, OPC_BEQ, arg1, arg2);
break;
case TCG_COND_NE:
tcg_out_opc_imm(s, OPC_BNE, arg1, arg2, 0);
tcg_out_opc_br(s, OPC_BNE, arg1, arg2);
break;
case TCG_COND_LT:
tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
break;
case TCG_COND_LTU:
tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
break;
case TCG_COND_GE:
tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
break;
case TCG_COND_GEU:
tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
break;
case TCG_COND_LE:
tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
break;
case TCG_COND_LEU:
tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
break;
case TCG_COND_GT:
tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
break;
case TCG_COND_GTU:
tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
break;
default:
tcg_abort();
@@ -553,7 +564,7 @@ static void tcg_out_brcond2(TCGContext *s, int cond, int arg1,
}
label_ptr = s->code_ptr;
tcg_out_opc_imm(s, OPC_BNE, arg2, arg4, 0);
tcg_out_opc_br(s, OPC_BNE, arg2, arg4);
tcg_out_nop(s);
switch(cond) {
@@ -670,20 +681,20 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
# if TARGET_LONG_BITS == 64
label3_ptr = s->code_ptr;
tcg_out_opc_imm(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT, 0);
tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
tcg_out_nop(s);
tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_memh);
label1_ptr = s->code_ptr;
tcg_out_opc_imm(s, OPC_BEQ, addr_regh, TCG_REG_AT, 0);
tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
tcg_out_nop(s);
reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
# else
label1_ptr = s->code_ptr;
tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT, 0);
tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
tcg_out_nop(s);
# endif
@@ -725,15 +736,15 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
}
label2_ptr = s->code_ptr;
tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, 0);
tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
tcg_out_nop(s);
/* label1: fast path */
reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
tcg_out_opc_imm(s, OPC_LW, TCG_REG_V0, TCG_REG_A0,
tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
offsetof(CPUState, tlb_table[mem_index][0].addend) + addr_meml);
tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_V0, addr_regl);
tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_A0, addr_regl);
addr_reg1 = TCG_REG_V0;
#endif
@@ -857,20 +868,20 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
# if TARGET_LONG_BITS == 64
label3_ptr = s->code_ptr;
tcg_out_opc_imm(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT, 0);
tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
tcg_out_nop(s);
tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_memh);
label1_ptr = s->code_ptr;
tcg_out_opc_imm(s, OPC_BEQ, addr_regh, TCG_REG_AT, 0);
tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
tcg_out_nop(s);
reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
# else
label1_ptr = s->code_ptr;
tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT, 0);
tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
tcg_out_nop(s);
# endif
@@ -911,7 +922,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out_nop(s);
label2_ptr = s->code_ptr;
tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, 0);
tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
tcg_out_nop(s);
/* label1: fast path */
@@ -1262,7 +1273,9 @@ static const TCGTargetOpDef mips_op_defs[] = {
};
static int tcg_target_callee_save_regs[] = {
#if 0 /* used for the global env (TCG_AREG0), so no need to save */
TCG_REG_S0,
#endif
TCG_REG_S1,
TCG_REG_S2,
TCG_REG_S3,
@@ -1271,8 +1284,7 @@ static int tcg_target_callee_save_regs[] = {
TCG_REG_S6,
TCG_REG_S7,
TCG_REG_GP,
/* TCG_REG_FP, */ /* currently used for the global env, so np
need to save */
TCG_REG_FP,
TCG_REG_RA, /* should be last for ABI compliance */
};
+3 -3
View File
@@ -92,9 +92,9 @@ enum {
#undef TCG_TARGET_HAS_ext16u_i32 /* andi rt, rs, 0xffff */
/* Note: must be synced with dyngen-exec.h */
#define TCG_AREG0 TCG_REG_FP
#define TCG_AREG1 TCG_REG_S0
#define TCG_AREG2 TCG_REG_S1
#define TCG_AREG0 TCG_REG_S0
#define TCG_AREG1 TCG_REG_S1
#define TCG_AREG2 TCG_REG_FP
#include <sys/cachectl.h>
+1 -1
View File
@@ -1036,7 +1036,7 @@ USBDevice *usb_host_device_open(const char *devname)
qdev_prop_set_uint32(&dev->qdev, "hostaddr", filter.addr);
qdev_prop_set_uint32(&dev->qdev, "vendorid", filter.vendor_id);
qdev_prop_set_uint32(&dev->qdev, "productid", filter.product_id);
qdev_init(&dev->qdev);
qdev_init_nofail(&dev->qdev);
return dev;
fail:
+25 -8
View File
@@ -2573,9 +2573,9 @@ static void numa_add(const char *optarg)
fprintf(stderr,
"only 63 CPUs in NUMA mode supported.\n");
}
value = (1 << (endvalue + 1)) - (1 << value);
value = (2ULL << endvalue) - (1ULL << value);
} else {
value = 1 << value;
value = 1ULL << value;
}
}
node_cpumask[nodenr] = value;
@@ -3471,6 +3471,8 @@ static int cpu_can_run(CPUState *env)
return 0;
if (env->stopped)
return 0;
if (!vm_running)
return 0;
return 1;
}
@@ -4042,14 +4044,15 @@ static void tcg_cpu_exec(void)
for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) {
CPUState *env = cur_cpu = next_cpu;
if (!vm_running)
break;
if (timer_alarm_pending) {
timer_alarm_pending = 0;
break;
}
if (cpu_can_run(env))
ret = qemu_cpu_exec(env);
else if (env->stop)
break;
if (ret == EXCP_DEBUG) {
gdb_set_stop_cpu(env);
debug_requested = 1;
@@ -4850,7 +4853,7 @@ int main(int argc, char **argv, char **envp)
const char *gdbstub_dev = NULL;
uint32_t boot_devices_bitmap = 0;
int i;
int snapshot, linux_boot, net_boot;
int snapshot, linux_boot;
const char *initrd_filename;
const char *kernel_filename, *kernel_cmdline;
char boot_devices[33] = "cad"; /* default to HD->floppy->CD-ROM */
@@ -5367,6 +5370,9 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_serial:
add_device_config(DEV_SERIAL, optarg);
default_serial = 0;
if (strncmp(optarg, "mon:", 4) == 0) {
default_monitor = 0;
}
break;
case QEMU_OPTION_watchdog:
if (watchdog) {
@@ -5385,10 +5391,16 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_virtiocon:
add_device_config(DEV_VIRTCON, optarg);
default_virtcon = 0;
if (strncmp(optarg, "mon:", 4) == 0) {
default_monitor = 0;
}
break;
case QEMU_OPTION_parallel:
add_device_config(DEV_PARALLEL, optarg);
default_parallel = 0;
if (strncmp(optarg, "mon:", 4) == 0) {
default_monitor = 0;
}
break;
case QEMU_OPTION_loadvm:
loadvm = optarg;
@@ -5791,6 +5803,12 @@ int main(int argc, char **argv, char **envp)
fprintf(stderr, "failed to initialize KVM\n");
exit(1);
}
} else {
/* without kvm enabled, we can only support 4095 MB RAM */
if (ram_size > (4095UL << 20)) {
fprintf(stderr, "qemu: without kvm support at most 4095 MB RAM can be simulated\n");
exit(1);
}
}
if (qemu_init_main_loop()) {
@@ -5834,9 +5852,6 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
net_boot = (boot_devices_bitmap >> ('n' - 'a')) & 0xF;
net_set_boot_mask(net_boot);
/* init the bluetooth world */
if (foreach_device_config(DEV_BT, bt_parse))
exit(1);
@@ -5968,6 +5983,8 @@ int main(int argc, char **argv, char **envp)
if (qemu_opts_foreach(&qemu_device_opts, device_init_func, NULL, 1) != 0)
exit(1);
net_check_clients();
if (!display_state)
dumb_display_init();
/* just use the first displaystate for the moment */
+8 -4
View File
@@ -1421,8 +1421,10 @@ static void pointer_event(VncState *vs, int button_mask, int x, int y)
dz = 1;
if (vs->absolute) {
kbd_mouse_event(x * 0x7FFF / (ds_get_width(vs->ds) - 1),
y * 0x7FFF / (ds_get_height(vs->ds) - 1),
kbd_mouse_event(ds_get_width(vs->ds) > 1 ?
x * 0x7FFF / (ds_get_width(vs->ds) - 1) : 0x4000,
ds_get_height(vs->ds) > 1 ?
y * 0x7FFF / (ds_get_height(vs->ds) - 1) : 0x4000,
dz, buttons);
} else if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE)) {
x -= 0x7FFF;
@@ -2293,7 +2295,7 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
static void vnc_refresh(void *opaque)
{
VncDisplay *vd = opaque;
VncState *vs = NULL;
VncState *vs = NULL, *vn = NULL;
int has_dirty = 0, rects = 0;
vga_hw_update();
@@ -2302,8 +2304,10 @@ static void vnc_refresh(void *opaque)
vs = vd->clients;
while (vs != NULL) {
vn = vs->next;
rects += vnc_update_client(vs, has_dirty);
vs = vs->next;
/* vs might be free()ed here */
vs = vn;
}
/* vd->timer could be NULL now if the last client disconnected,
* in this case don't update the timer */