Compare commits

...
140 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
Anthony Liguori e389e937a7 Update version and changelog for release
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2010-01-14 08:40:19 -06:00
Anthony Liguori 73b48d914f Update SeaBIOS to 0.5.1
- 5da6833 Update version to 0.5.1
 - 669c991 Fix sign error preventing incorrect memory over 4gig calculation.
 - 7e6bd3e Minor - better indent assembler in int1587.
 - 48cf232 Add comment explaining why mptable is in low memory.
 - 643062f Add int1589 support.
 - 085debd Set FDPT in irq table even for small drives.
 - 7c1b186 Reduce #ifs by weeding out some cross-chunk function definitions.
 - f9b25d3 Fix vgahook sign issue; add warning to build to catch future cases.
 - 3862b2d vgabios: Fix compile error due to fixed prototypes.
 - 1ca05b0 Be sure to add "void" to all function prototypes that take no args.
 - b5bb9db mptable: Reset pinmask on new bus or device.
 - 8918989 Detect latest FC12 gcc -combine breakage.
 - c9d3c2d Minor vga binary cleanups.
 - 9a8609f Make MTRR region 0xc0000-0x100000 be cached.
 - fdca418 Force a link error if a function is used from the wrong code chunk.
 - dad41d9 Add __noreturn define for __attribute__((noreturn)).
 - c003148 Implement native 32bit APM support.
 - 5c99b6c Commit compiled dsdt file; misc comment updates.
 - 29f4b91 prevent acpi from rerouting SCI interrupt
 - 4c94b7e enumerate all PCI buses in mptable
 - 871e0a0 Add support for 32bit PCI BIOS entry.
 - eda2c83 Only add "addr32" to memory accesses that require them.
 - 52a300f Introduce MODESEGMENT define; rename VISIBLE32 to VISIBLE32FLAT.
 - fe2c3ee Allocate smbios in temp space and copy into final location.
 - b164d2c Clear user reserved interrupts (0x60-0x66).
 - d9104ff Remove pci_bios_bigmem_addr; set pci_bios_mem_addr=0xe0000000
 - 14021f2 Add initial support for ATA DMA.
 - 8362699 Allocate mptable in temp space and copy into final location.
 - 979862e Also report memory over 4G during init.
 - 928d4df provide correct pci routing information in mptable
 - afc02da Add symbolic definitions for MTRR code.
 - fb214dc Fix yield() so it works from boot code.
 - 2ceeec9 Fix potential build failure due to text16 section being too large.
 - a2195e4 Increase version in preparation for next release.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2010-01-14 08:40:11 -06:00
Milan Plzik 3999bf3244 Qemu's internal TFTP server breaks lock-step-iness of TFTP
According to RFC 1350 and RFC 2347, TFTP server should answer RRQ by
either OACK or DATA packet. Qemu's internal TFTP server answers RRQ with
additional options by sending both OACK and DATA packet, thus breaking
the "lock-step" feature of the protocol, and also confuses client.

  Proposed solution would be to, in case of OACK packet, wait for ACK
from client and just then start sending data. Attached patch implements
this.

Signed-off-by: Thomas Horsten <thomas@horsten.com>
Signed-off-by: Milan Plzik <milan.plzik@gmail.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 1cb1a66aed)
2010-01-13 17:22:57 -06:00
Kevin Wolf a3441a43a6 osdep.c: Fix accept4 fallback
Commit 3a03bfa5 added a fallback in case the Linux kernel running qemu is older
than the kernel of the build system. Unfortunately, v1 was committed instead of
v2, so the code has a bug that was revealed in the review (checking for the
wrong error code).

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 347ed55cd1)
2010-01-13 17:22:33 -06:00
Gerd Hoffmann 49a3aaac4a pc: add rombar to compat properties for pc-0.10 and pc-0.11
So '-M pc-0.10' and '-M pc-0.11' will use the fw_cfg rom load method
by default.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 20a86364c9)
2010-01-12 14:48:35 -06:00
Gerd Hoffmann 027866ce23 pci: allow loading roms via fw_cfg.
This patch adds a pci bus property 'rombar' which specifies whenever
the pci rom should be loaded via pci rom bar (default) or via fw_cfg.
The later can be used for compatibility with older qemu versions where
no pci rom bar is present.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 88169ddf82)
2010-01-12 14:48:27 -06:00
Gerd Hoffmann 04babf6c6f roms: rework rom loading via fw
This patch changes the way rom loading via fw_cfg is handled.
Instead of having pc_init1() call a function which passed all
roms to the firmware config we simply pass a pointer to fw_cfg
to the rom loader.

Advantage: loading roms via firmware works also for devices which
are initialized after pc_init1(), i.e. everyting added via -device.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 8832cb805d)
2010-01-12 14:48:19 -06:00
Gerd Hoffmann d2b8117310 fw_cfg: rom loader tweaks.
Changes:
 - make dir argument mandatory, we allways have one anyway
   (vgaroms or genroms).
 - check for duplicates, skip loading if found.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit de9352bcae)
2010-01-12 14:48:07 -06:00
Gerd Hoffmann 0c4b9aef7b roms: minor fixes and cleanups.
Changes:
  - Drop extra file argument from rom_add_file().
  - Drop fw_dir check in do_info_roms, we allways have a dir name.
  - code style fixes.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit bdb5ee3064)
2010-01-12 14:48:00 -06:00
Gerd Hoffmann 431c829f33 pc: add machine type for 0.12
Add a new machine type for qemu 0.12.

Also fixup the 0.11 machine type: msi for virtio-blk-pci was enabled
after the 0.11 release, so turn it off in the 0.11 machine type.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 2cae6f5e34)
2010-01-12 14:47:53 -06:00
Aurelien Jarno be7398ec06 loader: more ignores for rom intended to be loaded by the bios
Similarly to what has been done in e405a2ba91,
ignore rom intended to be loaded by the bios in find_rom() and rom_copy().

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit f21a59c224)
2010-01-12 14:44:50 -06:00
Stefano Stabellini be59ce1f48 vnc_refresh: return if vd->timer is NULL
Hi all,
calling vnc_update_client in vnc_refresh might have the unlikely side
effect of setting vd->timer = NULL, if the last vnc client disconnected.
In this case we have to return from vnc_refresh without updating the
timer, otherwise we cause a segfault.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 83755c173f)
2010-01-12 13:34:48 -06:00
Luiz Capitulino eacad66dbe QMP: Don't free async event's 'data'
The monitor_protocol_event() function will free the
event's data, this is wrong as 'data' management is up
to the caller.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 3d72f9a2be)
2010-01-12 13:33:13 -06:00
Thomas Horsten 66dbb62824 Handle TFTP ERROR from client
If a PXE client only wants to find out the size of a file, it will
open the file and then abort the transfer by sending a TFTP ERROR packet.

The ERROR packet should cause qemu to terminate the session. If not,
the sessions will soon run out and cause timeouts in the client.

Also, if a TFTP session already exists with same IP/UDP port, it
should be terminated when a new RRQ is received, instead of creating a
duplicate (which will never be used).

A patch for gPXE to send the ERROR packet is also being submitted to
gPXE. Together they resolve slowness/hanging when booting pxegrub from
qemu's internal TFTP server. The patch from Milan Plzik to return
after sending OACK is also required for a complete fix.

Signed-off-by: Thomas Horsten <thomas@horsten.com>
Signed-off-by: Milan Plzik <milan.plzik@gmail.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit bfe4e17242)
2010-01-12 13:31:51 -06:00
Christoph Hellwig d47d251286 dmg: fix ->open failure
Currently the dmg image format driver simply opens the images as raw
if any kind of failure happens.  This is contrarty to the behaviour
of all other image formats which just return an error and let the
block core deal with it.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 1559ca00bc)
2010-01-12 13:31:21 -06:00
Michael S. Tsirkin 348af56fae virtio-pci: thinko fix
Since patch ed757e140c0ada220f213036e4497315d24ca8bct, virtio will
sometimes clear all status registers on bus master disable, which loses
information such as VIRTIO_CONFIG_S_FAILED bit.  This is a result of
a patch being misapplied: code uses !  instead of ~ for bit
operations as in Yan's original patch.  This obviously does not make
sense.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 49e75cf388)
2010-01-12 13:30:08 -06:00
Stefan Weil 09866b9baa pc-bios: Update README (SeaBIOS)
The PC BIOS no longer comes from Bochs.
This patch updates the related entry.

V2 - Modify SeaBIOS description and URL
     (Thanks to Gleb Natapov for the hint).

Signed-off-by: Stefan Weil <weil@mail.berlios.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit c0ced0f3a7)
2010-01-12 13:29:48 -06:00
Roland Dreier e1daf40e3e vmware_vga: Check cursor dimensions passed from guest to avoid buffer overflow
Check that the cursor dimensions passed from the guest for the
DEFINE_CURSOR command don't overflow the available space in the
cursor.image[] or cursor.mask[] arrays before copying data from the
guest into those arrays.

Signed-off-by: Roland Dreier <rolandd@cisco.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit f2d928d44e)
2010-01-11 10:03:39 -06:00
Gleb Natapov de3ea06d59 remove pending exception on vcpu reset.
Without this qemu can even start on kvm modules with events support
since default value of exception_injected in zero and this is #DE
exception.

Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit e73223a584)
2010-01-11 10:03:30 -06:00
Jiri Denemark fe46a160ce Fix CPU topology initialization
Late initialization of CPU topology in CPUState prevents KVM guests to
actually see the topology.

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 3f7638ec40)
2010-01-11 10:03:18 -06:00
Huang Ying 8033c42abd MCE: Fix bug of IA32_MCG_STATUS after system reset
Now, if we inject a fatal MCE into guest OS, for example Linux, Linux
will go panic and then reboot. But if we inject another MCE now,
system will reset directly instead of go panic firstly, because
MCG_STATUS.MCIP is set to 1 and not cleared after reboot. This is does
not follow the behavior in real hardware.

This patch fixes this via set env->mcg_status to 0 during system reset.

Signed-off-by: Huang Ying <ying.huang@intel.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit af364b418c)
2010-01-11 10:02:55 -06:00
Avi Kivity 4713c69fa2 linuxboot: fix gdt address calculation
The gdt address calculation in linuxboot.bin is broken in two ways: first
it loads %cs into %eax, but that instruction leaves the high bits of %eax
undefined and we did not clear them.  Secondly, we completely ignore the
incorrect %eax, and use the undefined %ebx instead.

With these issues fixed, linuxboot works again.

Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit d0652aa8ac)
2010-01-08 10:01:39 -06:00
Luiz Capitulino d68bf60838 QMP: Drop wrong assert()
Some commands return a QList of QDicts, which is valid,
but will trig the assert().

Just drop it.

Reported-by: Nathan Baum <nathan@parenthephobia.org.uk>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 810f49b56a)
2010-01-08 10:01:26 -06:00
Anthony Liguori 57fa5ca551 vnc: Fix artifacts in hextile decoding
02c2b87 introduced a regression whereas the foreground color in a hextile
update was not being properly invalidated leading to artifacts.

It's still necessary to explicitly invalidate the foreground color with a
SubrectColoured tile even though we no longer send a foreground color as
part of the tile.

Reported-by: Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 18cb1d8557)
2010-01-07 07:59:28 -06:00
Anthony Liguori 8610774f79 Merge remote branch 'mst/stable-0.12' into stable-0.12 2010-01-06 09:17:53 -06:00
Aurelien Jarno 76ba04832b target-i386: Fix "call im" on x86_64 when executing 32-bit code
Similarly to what is done in 32938e127f
for "jmp im", trunc the immediate to 32-bit when not running in 64-bit
mode.

Reported-by: Kevin O'Connor <kevin@koconnor.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
2010-01-03 03:16:59 +01:00
Michael Tokarev 644f5de21b Add missing newline at the end of options list
In qemu-kvm this place looks even more "interesting":

 -runas user     Change to user id user just before starting the VM.
 -readconfig <file>
 -writeconfig <file>
                read/write config file-no-kvm         disable KVM hardware virtualization
 -no-kvm-irqchip disable KVM kernel mode PIC/IOAPIC/LAPIC
 -no-kvm-pit     disable KVM kernel mode PIT

Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 19e65b47f6)
2009-12-30 13:46:40 +01:00
Avi Kivity dcc0da8297 Don't load options roms intended to be loaded by the bios in qemu
The first such option rom will load at address 0, which isn't very nice,
and the second will report a conflict and abort, which is horrible.

Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit e405a2ba91)
2009-12-24 19:35:24 +01:00
Scott Tsai 41193c50fa USB: Improve usbdevice error messages
When an non-existent USB device is specified on the command line,
print "qemu: could not add USB device 'X'".
Likewise for the usb_{add,del} monitor commands.

Signed-off-by: Scott Tsai <scottt.tw@gmail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 59d1c1c2d7)
2009-12-23 07:42:38 +01:00
Aurelien Jarno da0266005a cpu-all.h: fix cpu_get_real_ticks() #ifdef
Reported-by: Hervé Poussineau <hpoussin@reactos.org>

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 9706c06d9c)
2009-12-20 21:47:03 +01:00
Blue Swirl eacdccbb3e alpha: fix compile
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
2009-12-20 10:27:44 +00:00
Kirill A. Shutemov 65e8c51928 user_only: compile everything with -fpie
We really need compile _all_ sources for user target with -fpie when
use --enable-user-pie.

It's regression introduced by commit add16157d7.

Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name>
Cc: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
[blauwirbel@gmail.com: combined 299060a0 and 58faa1a6 to avoid breakage]
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
2009-12-20 11:35:57 +02:00
Artyom Tarasenko e470436f19 fdc/sparc32: don't hang on detection under OBP
Stepping through the SS-5's OBP initialization routines
it looks like reading fdc main status register should
clear the fd interrupt.
The patch doesn't fix problems with fdc on sparc platform,
it only fixes fdc detection.

Signed-off-by: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
2009-12-20 11:35:48 +02:00
Artyom Tarasenko b60c2c74f3 scsi-disk: Inquiry with allocation length of CDB < 36 (v4)
According to the SCSI-2 specification,
http://ldkelley.com/SCSI2/SCSI2/SCSI2/SCSI2-08.html#8.2.5 ,
"if the allocation length of the command descriptor block (CDB) is too
small to transfer all of the parameters, the additional length shall
not be adjusted to reflect the truncation."
The 36 mandatory bytes of response are written to outbuf, and then
only the length requested in CDB is transferred.

Signed-off-by: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
2009-12-20 11:35:28 +02:00
Anthony Liguori fe1b69708c Update version and changelog for 0.12.1
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-12-19 19:31:18 -06:00
Kevin Wolf a1678e85db Multiboot support: Fix rom_copy
ROMs need to be loaded if they are anywhere in the requested area, not
only at the very beginning. This fixes Multiboot with ELF kernels that
have more than one program header.

Signed-off-by: Kevin Wolf <mail@kevin-wolf.de>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit 935effc2bb)
2009-12-19 21:51:10 +01:00
Aurelien Jarno 8212d18cf5 roms: allow roms to be loaded at address 0
It was possible to load roms at address 0, but commit
632cf034b4 started to forbid that, which
broke at least ARM versatile.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
(cherry picked from commit f9e69bd9cf)
2009-12-19 19:46:10 +01:00
Michael S. Tsirkin c56651312b e1000: fix init values for command register
Command register for e1000 was initialized to
values out of spec: all of bus master,
io, memory and interrupt disable bits were set.

This breaks the device now that we actually respect
the interrupt disable bit, unless the guest
happens to clear it. Fix, and make the device
more spec compliant, by not touching
the default.

There are implications for migration
from old qemu as well, will be addressed
separately.

Reported-by: Luiz Capitulino <lcapitulino@redhat.com>
Tested-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2009-12-15 13:55:20 +02:00
90 changed files with 1447 additions and 740 deletions

No files matched your search

+140
View File
@@ -1,3 +1,143 @@
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)
- pc: add rombar to compat properties for pc-0.10 and pc-0.11 (Gerd Hoffmann)
- pci: allow loading roms via fw_cfg. (Gerd Hoffmann)
- roms: rework rom loading via fw (Gerd Hoffmann)
- fw_cfg: rom loader tweaks. (Gerd Hoffmann)
- roms: minor fixes and cleanups. (Gerd Hoffmann)
- pc: add machine type for 0.12 (Gerd Hoffmann)
- loader: more ignores for rom intended to be loaded by the bios (Aurelien Jarno)
- vnc_refresh: return if vd->timer is NULL (Stefano Stabellini)
- QMP: Don't free async event's 'data' (Luiz Capitulino)
- Handle TFTP ERROR from client (Thomas Horsten)
- dmg: fix ->open failure (Christoph Hellwig)
- virtio-pci: thinko fix (Michael S. Tsirkin)
- pc-bios: Update README (SeaBIOS) (Stefan Weil)
- vmware_vga: Check cursor dimensions passed from guest to avoid buffer overflow (Roland Dreier)
- remove pending exception on vcpu reset. (Gleb Natapov)
- Fix CPU topology initialization (Jiri Denemark)
- MCE: Fix bug of IA32_MCG_STATUS after system reset (Huang Ying)
- linuxboot: fix gdt address calculation (Avi Kivity)
- QMP: Drop wrong assert() (Luiz Capitulino)
- vnc: Fix artifacts in hextile decoding (Anthony Liguori)
- target-i386: Fix "call im" on x86_64 when executing 32-bit code (Aurelien Jarno)
- Add missing newline at the end of options list (Michael Tokarev)
- Don't load options roms intended to be loaded by the bios in qemu (Avi Kivity)
- USB: Improve usbdevice error messages (Scott Tsai)
- cpu-all.h: fix cpu_get_real_ticks() #ifdef (Aurelien Jarno)
- alpha: fix compile (Blue Swirl)
- user_only: compile everything with -fpie (Kirill A. Shutemov)
- fdc/sparc32: don't hang on detection under OBP (Artyom Tarasenko)
- scsi-disk: Inquiry with allocation length of CDB < 36 (v4) (Artyom Tarasenko)
- e1000: fix init values for command register (Michael S. Tsirkin)
version 0.12.1:
- loader: fix rom loading at address 0 (fixes target-arm) (Aurelien Jarno)
- loader: fix rom_copy (fixes multiboot) (Kevin Wolf)
version 0.12.0:
- Update to SeaBIOS 0.5.0
+6 -1
View File
@@ -2,10 +2,15 @@
include ../config-host.mak
include $(SRC_PATH)/rules.mak
-include config.mak
.PHONY: all
VPATH=$(SRC_PATH)
# Do not take %.o from $(SRC_PATH), only %.c and %.h
# All %.o for user targets should be built with -fpie, when
# configured with --enable-user-pie, so we don't want to
# take %.o from $(SRC_PATH), since they built without -fpie
vpath %.c %.h $(SRC_PATH)
QEMU_CFLAGS+=-I..
+1 -1
View File
@@ -1 +1 @@
0.12.0
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. */
+14 -14
View File
@@ -90,24 +90,21 @@ static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
/* read offset of info blocks */
if(lseek(s->fd,-0x1d8,SEEK_END)<0) {
dmg_close:
close(s->fd);
/* open raw instead */
bs->drv=bdrv_find_format("raw");
return bs->drv->bdrv_open(bs, filename, flags);
goto fail;
}
info_begin=read_off(s->fd);
if(info_begin==0)
goto dmg_close;
goto fail;
if(lseek(s->fd,info_begin,SEEK_SET)<0)
goto dmg_close;
goto fail;
if(read_uint32(s->fd)!=0x100)
goto dmg_close;
goto fail;
if((count = read_uint32(s->fd))==0)
goto dmg_close;
goto fail;
info_end = info_begin+count;
if(lseek(s->fd,0xf8,SEEK_CUR)<0)
goto dmg_close;
goto fail;
/* read offsets */
last_in_offset = last_out_offset = 0;
@@ -116,14 +113,14 @@ dmg_close:
count = read_uint32(s->fd);
if(count==0)
goto dmg_close;
goto fail;
type = read_uint32(s->fd);
if(type!=0x6d697368 || count<244)
lseek(s->fd,count-4,SEEK_CUR);
else {
int new_size, chunk_count;
if(lseek(s->fd,200,SEEK_CUR)<0)
goto dmg_close;
goto fail;
chunk_count = (count-204)/40;
new_size = sizeof(uint64_t) * (s->n_chunks + chunk_count);
s->types = qemu_realloc(s->types, new_size/2);
@@ -142,7 +139,7 @@ dmg_close:
chunk_count--;
i--;
if(lseek(s->fd,36,SEEK_CUR)<0)
goto dmg_close;
goto fail;
continue;
}
read_uint32(s->fd);
@@ -163,11 +160,14 @@ dmg_close:
s->compressed_chunk = qemu_malloc(max_compressed_size+1);
s->uncompressed_chunk = qemu_malloc(512*max_sectors_per_chunk);
if(inflateInit(&s->zstream) != Z_OK)
goto dmg_close;
goto fail;
s->current_chunk = s->n_chunks;
return 0;
fail:
close(s->fd);
return -1;
}
static inline int is_sector_in_chunk(BDRVDMGState* s,
+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 {
Vendored
+3
View File
@@ -2652,3 +2652,6 @@ d=libuser
mkdir -p $d
rm -f $d/Makefile
ln -s $source_path/Makefile.user $d/Makefile
if test "$static" = "no" -a "$user_pie" = "yes" ; then
echo "QEMU_CFLAGS+=-fpie" > $d/config.mak
fi
+2 -1
View File
@@ -1017,7 +1017,8 @@ static inline int64_t cpu_get_real_ticks (void)
#endif
}
#elif (defined(__mips_isa_rev) && __mips_isa_rev >= 2) || defined(__linux__)
#elif defined(__mips__) && \
((defined(__mips_isa_rev) && __mips_isa_rev >= 2) || defined(__linux__))
/*
* binutils wants to use rdhwr only on mips32r2
* but as linux kernel emulate it, it's fine
+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);
}
+21 -5
View File
@@ -935,6 +935,12 @@ static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl)
fdctrl->dsr &= ~FD_DSR_PWRDOWN;
fdctrl->dor |= FD_DOR_nRESET;
/* Sparc mutation */
if (fdctrl->sun4m) {
retval |= FD_MSR_DIO;
fdctrl_reset_irq(fdctrl);
};
FLOPPY_DPRINTF("main status register: 0x%02x\n", retval);
return retval;
@@ -1854,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);
@@ -1873,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);
@@ -1890,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;
+12 -8
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");
}
@@ -278,7 +278,7 @@ int fw_cfg_add_file(FWCfgState *s, const char *dir, const char *filename,
uint8_t *data, uint32_t len)
{
const char *basename;
int index;
int i, index;
if (!s->files) {
int dsize = sizeof(uint32_t) + sizeof(FWCfgFile) * FW_CFG_FILE_SLOTS;
@@ -300,13 +300,17 @@ int fw_cfg_add_file(FWCfgState *s, const char *dir, const char *filename,
} else {
basename = filename;
}
if (dir) {
snprintf(s->files->f[index].name, sizeof(s->files->f[index].name),
"%s/%s", dir, basename);
} else {
snprintf(s->files->f[index].name, sizeof(s->files->f[index].name),
"%s", basename);
snprintf(s->files->f[index].name, sizeof(s->files->f[index].name),
"%s/%s", dir, basename);
for (i = 0; i < index; i++) {
if (strcmp(s->files->f[index].name, s->files->f[i].name) == 0) {
FW_CFG_DPRINTF("%s: skip duplicate: %s\n", __FUNCTION__,
s->files->f[index].name);
return 1;
}
}
s->files->f[index].size = cpu_to_be32(len);
s->files->f[index].select = cpu_to_be16(FW_CFG_FILE_FIRST + index);
FW_CFG_DPRINTF("%s: #%d: %s (%d bytes)\n", __FUNCTION__,
+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(),
}
};
+40 -30
View File
@@ -535,6 +535,7 @@ struct Rom {
QTAILQ_ENTRY(Rom) next;
};
static FWCfgState *fw_cfg;
static QTAILQ_HEAD(, Rom) roms = QTAILQ_HEAD_INITIALIZER(roms);
int rom_enable_driver_roms;
@@ -556,7 +557,7 @@ static void rom_insert(Rom *rom)
QTAILQ_INSERT_TAIL(&roms, rom, next);
}
int rom_add_file(const char *file, const char *fw_dir, const char *fw_file,
int rom_add_file(const char *file, const char *fw_dir,
target_phys_addr_t addr)
{
Rom *rom;
@@ -576,8 +577,10 @@ int rom_add_file(const char *file, const char *fw_dir, const char *fw_file,
goto err;
}
rom->fw_dir = fw_dir ? qemu_strdup(fw_dir) : NULL;
rom->fw_file = fw_file ? qemu_strdup(fw_file) : NULL;
if (fw_dir) {
rom->fw_dir = qemu_strdup(fw_dir);
rom->fw_file = qemu_strdup(file);
}
rom->addr = addr;
rom->romsize = lseek(fd, 0, SEEK_END);
rom->data = qemu_mallocz(rom->romsize);
@@ -590,6 +593,8 @@ int rom_add_file(const char *file, const char *fw_dir, const char *fw_file,
}
close(fd);
rom_insert(rom);
if (rom->fw_file && fw_cfg)
fw_cfg_add_file(fw_cfg, rom->fw_dir, rom->fw_file, rom->data, rom->romsize);
return 0;
err:
@@ -621,14 +626,14 @@ int rom_add_vga(const char *file)
{
if (!rom_enable_driver_roms)
return 0;
return rom_add_file(file, "vgaroms", file, 0);
return rom_add_file(file, "vgaroms", 0);
}
int rom_add_option(const char *file)
{
if (!rom_enable_driver_roms)
return 0;
return rom_add_file(file, "genroms", file, 0);
return rom_add_file(file, "genroms", 0);
}
static void rom_reset(void *unused)
@@ -636,10 +641,12 @@ static void rom_reset(void *unused)
Rom *rom;
QTAILQ_FOREACH(rom, &roms, next) {
if (rom->addr == 0)
if (rom->fw_file) {
continue;
if (rom->data == NULL)
}
if (rom->data == NULL) {
continue;
}
cpu_physical_memory_write_rom(rom->addr, rom->data, rom->romsize);
if (rom->isrom) {
/* rom needs to be written only once */
@@ -656,8 +663,9 @@ int rom_load_all(void)
Rom *rom;
QTAILQ_FOREACH(rom, &roms, next) {
if (rom->addr == 0)
if (rom->fw_file) {
continue;
}
if (addr > rom->addr) {
fprintf(stderr, "rom: requested regions overlap "
"(rom %s. free=0x" TARGET_FMT_plx
@@ -676,16 +684,9 @@ int rom_load_all(void)
return 0;
}
int rom_load_fw(void *fw_cfg)
void rom_set_fw(void *f)
{
Rom *rom;
QTAILQ_FOREACH(rom, &roms, next) {
if (!rom->fw_file)
continue;
fw_cfg_add_file(fw_cfg, rom->fw_dir, rom->fw_file, rom->data, rom->romsize);
}
return 0;
fw_cfg = f;
}
static Rom *find_rom(target_phys_addr_t addr)
@@ -693,17 +694,25 @@ static Rom *find_rom(target_phys_addr_t addr)
Rom *rom;
QTAILQ_FOREACH(rom, &roms, next) {
if (rom->addr == 0)
if (rom->fw_file) {
continue;
if (rom->addr > addr)
}
if (rom->addr > addr) {
continue;
if (rom->addr + rom->romsize < addr)
}
if (rom->addr + rom->romsize < addr) {
continue;
}
return rom;
}
return NULL;
}
/*
* Copies memory from registered ROMs to dest. Any memory that is contained in
* a ROM between addr and addr + size is copied. Note that this can involve
* multiple ROMs, which need not start at addr and need not end at addr + size.
*/
int rom_copy(uint8_t *dest, target_phys_addr_t addr, size_t size)
{
target_phys_addr_t end = addr + size;
@@ -712,16 +721,18 @@ int rom_copy(uint8_t *dest, target_phys_addr_t addr, size_t size)
Rom *rom;
QTAILQ_FOREACH(rom, &roms, next) {
if (rom->addr == 0)
if (rom->fw_file) {
continue;
if (rom->addr > addr)
}
if (rom->addr + rom->romsize < addr) {
continue;
if (rom->addr + rom->romsize < addr)
continue;
if (rom->addr > end)
}
if (rom->addr > end) {
break;
if (!rom->data)
}
if (!rom->data) {
continue;
}
d = dest + (rom->addr - addr);
s = rom->data;
@@ -757,17 +768,16 @@ void do_info_roms(Monitor *mon)
Rom *rom;
QTAILQ_FOREACH(rom, &roms, next) {
if (rom->addr) {
if (!rom->fw_file) {
monitor_printf(mon, "addr=" TARGET_FMT_plx
" size=0x%06zx mem=%s name=\"%s\" \n",
rom->addr, rom->romsize,
rom->isrom ? "rom" : "ram",
rom->name);
} else {
monitor_printf(mon, "fw=%s%s%s"
monitor_printf(mon, "fw=%s/%s"
" size=0x%06zx name=\"%s\" \n",
rom->fw_dir ? rom->fw_dir : "",
rom->fw_dir ? "/" : "",
rom->fw_dir,
rom->fw_file,
rom->romsize,
rom->name);
+4 -3
View File
@@ -19,18 +19,19 @@ void pstrcpy_targphys(const char *name,
target_phys_addr_t dest, int buf_size,
const char *source);
int rom_add_file(const char *file, const char *fw_dir, const char *fw_file,
int rom_add_file(const char *file, const char *fw_dir,
target_phys_addr_t addr);
int rom_add_blob(const char *name, const void *blob, size_t len,
target_phys_addr_t addr);
int rom_load_all(void);
int rom_load_fw(void *fw_cfg);
void rom_set_fw(void *f);
int rom_copy(uint8_t *dest, target_phys_addr_t addr, size_t size);
void *rom_ptr(target_phys_addr_t addr);
void do_info_roms(Monitor *mon);
#define rom_add_file_fixed(_f, _a) \
rom_add_file(_f, NULL, NULL, _a)
rom_add_file(_f, NULL, _a)
#define rom_add_blob_fixed(_f, _b, _l, _a) \
rom_add_blob(_f, _b, _l, _a)
+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]);
}
+42 -3
View File
@@ -1090,6 +1090,7 @@ static void pc_init1(ram_addr_t ram_size,
bios_size, bios_offset | IO_MEM_ROM);
fw_cfg = bochs_bios_init();
rom_set_fw(fw_cfg);
if (linux_boot) {
load_linux(fw_cfg, kernel_filename, initrd_filename, kernel_cmdline, below_4g_mem_size);
@@ -1250,8 +1251,6 @@ static void pc_init1(ram_addr_t ram_size,
}
}
}
rom_load_fw(fw_cfg);
}
static void pc_init_pci(ram_addr_t ram_size,
@@ -1289,7 +1288,7 @@ void cmos_set_s3_resume(void)
}
static QEMUMachine pc_machine = {
.name = "pc-0.11",
.name = "pc-0.12",
.alias = "pc",
.desc = "Standard PC",
.init = pc_init_pci,
@@ -1297,6 +1296,33 @@ static QEMUMachine pc_machine = {
.is_default = 1,
};
static QEMUMachine pc_machine_v0_11 = {
.name = "pc-0.11",
.desc = "Standard PC, qemu 0.11",
.init = pc_init_pci,
.max_cpus = 255,
.compat_props = (GlobalProperty[]) {
{
.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",
.value = stringify(0),
},
{ /* end of list */ }
}
};
static QEMUMachine pc_machine_v0_10 = {
.name = "pc-0.10",
.desc = "Standard PC, qemu 0.10",
@@ -1319,6 +1345,18 @@ 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",
.value = stringify(0),
},
{ /* end of list */ }
},
@@ -1334,6 +1372,7 @@ static QEMUMachine isapc_machine = {
static void pc_machine_init(void)
{
qemu_register_machine(&pc_machine);
qemu_register_machine(&pc_machine_v0_11);
qemu_register_machine(&pc_machine_v0_10);
qemu_register_machine(&isapc_machine);
}
+15
View File
@@ -64,6 +64,7 @@ static struct BusInfo pci_bus_info = {
.props = (Property[]) {
DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
DEFINE_PROP_UINT32("rombar", PCIDevice, rom_bar, 1),
DEFINE_PROP_END_OF_LIST()
}
};
@@ -1464,6 +1465,20 @@ static int pci_add_option_rom(PCIDevice *pdev)
if (strlen(pdev->romfile) == 0)
return 0;
if (!pdev->rom_bar) {
/*
* Load rom via fw_cfg instead of creating a rom bar,
* for 0.11 compatibility.
*/
int class = pci_get_word(pdev->config + PCI_CLASS_DEVICE);
if (class == 0x0300) {
rom_add_vga(pdev->romfile);
} else {
rom_add_option(pdev->romfile);
}
return 0;
}
path = qemu_find_file(QEMU_FILE_TYPE_BIOS, pdev->romfile);
if (path == NULL) {
path = qemu_strdup(pdev->romfile);
+1
View File
@@ -246,6 +246,7 @@ struct PCIDevice {
/* Location of option rom */
char *romfile;
ram_addr_t rom_offset;
uint32_t rom_bar;
};
PCIDevice *pci_register_device(PCIBus *bus, const char *name,
+22 -8
View File
@@ -5,6 +5,12 @@
* Based on code by Fabrice Bellard
*
* Written by Paul Brook
* Modifications:
* 2009-Dec-12 Artyom Tarasenko : implemented stamdard inquiry for the case
* when the allocation length of CDB is smaller
* than 36.
* 2009-Oct-13 Artyom Tarasenko : implemented the block descriptor in the
* MODE SENSE response.
*
* This code is licenced under the LGPL.
*
@@ -59,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)
@@ -74,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);
}
@@ -309,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) {
@@ -406,11 +414,6 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
return -1;
}
if (req->cmd.xfer < 36) {
BADF("Error: Inquiry (STANDARD) buffer size %zd "
"is less than 36 (TODO: only 5 required)\n", req->cmd.xfer);
}
buflen = req->cmd.xfer;
if (buflen > SCSI_MAX_INQUIRY_LEN)
buflen = SCSI_MAX_INQUIRY_LEN;
@@ -431,12 +434,22 @@ 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;
outbuf[3] = 2; /* Format 2 */
outbuf[4] = buflen - 5; /* Additional Length = (Len - 1) - 4 */
if (buflen > 36) {
outbuf[4] = buflen - 5; /* Additional Length = (Len - 1) - 4 */
} else {
/* If the allocation length of CDB is too small,
the additional length is not adjusted */
outbuf[4] = 36 - 5;
}
/* Sync data transfer and TCQ. */
outbuf[7] = 0x10 | (req->bus->tcq ? 0x02 : 0);
return buflen;
@@ -1020,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);
+1 -1
View File
@@ -372,7 +372,7 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
if (PCI_COMMAND == address) {
if (!(val & PCI_COMMAND_MASTER)) {
proxy->vdev->status &= !VIRTIO_CONFIG_S_DRIVER_OK;
proxy->vdev->status &= ~VIRTIO_CONFIG_S_DRIVER_OK;
}
}
+7
View File
@@ -562,6 +562,13 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
cursor.height = y = vmsvga_fifo_read(s);
vmsvga_fifo_read(s);
cursor.bpp = vmsvga_fifo_read(s);
if (SVGA_BITMAP_SIZE(x, y) > sizeof cursor.mask ||
SVGA_PIXMAP_SIZE(x, y, cursor.bpp) > sizeof cursor.image) {
args = SVGA_BITMAP_SIZE(x, y) + SVGA_PIXMAP_SIZE(x, y, cursor.bpp);
goto badcmd;
}
for (args = 0; args < SVGA_BITMAP_SIZE(x, y); args ++)
cursor.mask[args] = vmsvga_fifo_read_raw(s);
for (args = 0; args < SVGA_PIXMAP_SIZE(x, y, cursor.bpp); args ++)
+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
+9 -7
View File
@@ -283,7 +283,6 @@ static void monitor_protocol_emitter(Monitor *mon, QObject *data)
if (!monitor_has_error(mon)) {
/* success response */
if (data) {
assert(qobject_type(data) == QTYPE_QDICT);
qobject_incref(data);
qdict_put_obj(qmp, "return", data);
} else {
@@ -335,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";
@@ -366,10 +362,16 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
qmp = qdict_new();
timestamp_put(qmp);
qdict_put(qmp, "event", qstring_from_str(event_name));
if (data)
if (data) {
qobject_incref(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;
}
+1 -1
View File
@@ -306,7 +306,7 @@ int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
#ifdef CONFIG_ACCEPT4
ret = accept4(s, addr, addrlen, SOCK_CLOEXEC);
if (ret != -1 || errno != EINVAL) {
if (ret != -1 || errno != ENOSYS) {
return ret;
}
#endif
+2 -1
View File
@@ -1,4 +1,5 @@
- The PC BIOS comes from the Bochs project (http://bochs.sourceforge.net/).
- SeaBIOS (bios.bin) is the successor of pc bios.
See http://www.seabios.org/ for more information.
- The VGA BIOS and the Cirrus VGA BIOS come from the LGPL VGA bios
project (http://www.nongnu.org/vgabios/).
BIN
View File
Binary file not shown.
+3 -2
View File
@@ -86,9 +86,10 @@ copy_kernel:
/* Now create the GDT descriptor */
movw $((3 * 8) - 1), -16(%bp)
mov %cs, %eax
movzwl %ax, %eax
shl $4, %eax
addl $gdt, %ebx
movl %ebx, -14(%bp)
addl $gdt, %eax
movl %eax, -14(%bp)
/* And load the GDT */
data32 lgdt -16(%bp)
+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);
+23 -6
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")
" 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";
+24
View File
@@ -264,6 +264,12 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
size_t prefix_len;
char *req_fname;
/* check if a session already exists and if so terminate it */
s = tftp_session_find(slirp, tp);
if (s >= 0) {
tftp_session_terminate(&slirp->tftp_sessions[s]);
}
s = tftp_session_allocate(slirp, tp);
if (s < 0) {
@@ -362,6 +368,7 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
}
tftp_send_oack(spt, "tsize", tsize, tp);
return;
}
}
@@ -385,6 +392,19 @@ static void tftp_handle_ack(Slirp *slirp, struct tftp_t *tp, int pktlen)
}
}
static void tftp_handle_error(Slirp *slirp, struct tftp_t *tp, int pktlen)
{
int s;
s = tftp_session_find(slirp, tp);
if (s < 0) {
return;
}
tftp_session_terminate(&slirp->tftp_sessions[s]);
}
void tftp_input(struct mbuf *m)
{
struct tftp_t *tp = (struct tftp_t *)m->m_data;
@@ -397,5 +417,9 @@ void tftp_input(struct mbuf *m)
case TFTP_ACK:
tftp_handle_ack(m->slirp, tp, m->m_len);
break;
case TFTP_ERROR:
tftp_handle_error(m->slirp, tp, m->m_len);
break;
}
}
+2 -2
View File
@@ -46,10 +46,10 @@ uint64_t helper_load_fpcr (void)
{
uint64_t ret = 0;
#ifdef CONFIG_SOFTFLOAT
ret |= env->fp_status.float_exception_flags << 52;
ret |= (uint64_t)env->fp_status.float_exception_flags << 52;
if (env->fp_status.float_exception_flags)
ret |= 1ULL << 63;
env->ipr[IPR_EXC_SUM] &= ~0x3E:
env->ipr[IPR_EXC_SUM] &= ~0x3E;
env->ipr[IPR_EXC_SUM] |= env->fp_status.float_exception_flags << 1;
#endif
switch (env->fp_status.float_rounding_mode) {
+2
View File
@@ -617,6 +617,8 @@ void cpu_reset(CPUX86State *env)
env->dr[7] = DR7_FIXED_1;
cpu_breakpoint_remove_all(env, BP_CPU);
cpu_watchpoint_remove_all(env, BP_CPU);
env->mcg_status = 0;
}
void cpu_x86_close(CPUX86State *env)
+1
View File
@@ -227,6 +227,7 @@ int kvm_arch_init_vcpu(CPUState *env)
void kvm_arch_reset_vcpu(CPUState *env)
{
env->exception_injected = -1;
env->interrupt_injected = -1;
env->nmi_injected = 0;
env->nmi_pending = 0;
+11 -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;
@@ -6259,6 +6262,8 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
tval += next_eip;
if (s->dflag == 0)
tval &= 0xffff;
else if(!CODE64(s))
tval &= 0xffffffff;
gen_movtl_T0_im(next_eip);
gen_push_T0(s);
gen_jmp(s, tval);
+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:
+43 -15
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;
@@ -2689,17 +2689,28 @@ static int usb_device_del(const char *devname)
static int usb_parse(const char *cmdline)
{
return usb_device_add(cmdline, 0);
int r;
r = usb_device_add(cmdline, 0);
if (r < 0) {
fprintf(stderr, "qemu: could not add USB device '%s'\n", cmdline);
}
return r;
}
void do_usb_add(Monitor *mon, const QDict *qdict)
{
usb_device_add(qdict_get_str(qdict, "devname"), 1);
const char *devname = qdict_get_str(qdict, "devname");
if (usb_device_add(devname, 1) < 0) {
qemu_error("could not add USB device '%s'\n", devname);
}
}
void do_usb_del(Monitor *mon, const QDict *qdict)
{
usb_device_del(qdict_get_str(qdict, "devname"));
const char *devname = qdict_get_str(qdict, "devname");
if (usb_device_del(devname) < 0) {
qemu_error("could not delete USB device '%s'\n", devname);
}
}
/***********************************************************/
@@ -3460,6 +3471,8 @@ static int cpu_can_run(CPUState *env)
return 0;
if (env->stopped)
return 0;
if (!vm_running)
return 0;
return 1;
}
@@ -3473,10 +3486,10 @@ void qemu_init_vcpu(void *_env)
{
CPUState *env = _env;
if (kvm_enabled())
kvm_init_vcpu(env);
env->nr_cores = smp_cores;
env->nr_threads = smp_threads;
if (kvm_enabled())
kvm_init_vcpu(env);
return;
}
@@ -3802,12 +3815,12 @@ void qemu_init_vcpu(void *_env)
{
CPUState *env = _env;
env->nr_cores = smp_cores;
env->nr_threads = smp_threads;
if (kvm_enabled())
kvm_start_vcpu(env);
else
tcg_init_vcpu(env);
env->nr_cores = smp_cores;
env->nr_threads = smp_threads;
}
void qemu_notify_event(void)
@@ -4031,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;
@@ -4839,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 */
@@ -5356,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) {
@@ -5374,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;
@@ -5780,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()) {
@@ -5823,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);
@@ -5957,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 */
+12 -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,9 +2304,15 @@ 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 */
if (vd->timer == NULL)
return;
if (has_dirty && rects) {
vd->timer_interval /= 2;
+2
View File
@@ -165,6 +165,8 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
irow += ds_get_linesize(vs->ds) / sizeof(pixel_t);
}
/* A SubrectsColoured subtile invalidates the foreground color */
*has_fg = 0;
if (n_data > (w * h * sizeof(pixel_t))) {
n_colors = 4;
flags = 0x01;