Compare commits

...

140 Commits

Author SHA1 Message Date
Gerd Hoffmann
840a178c94 usb: mtp filesharing
Implementation of a USB Media Transfer Device device for easy
filesharing.  Read-only.  No access control inside qemu, it will
happily export any file it is able to open to the guest, i.e.
standard unix access rights for the qemu process apply.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-04-23 10:28:14 +02:00
Gerd Hoffmann
409951f552 usb: add CompatibleID support to msos
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-04-22 12:40:57 +02:00
Peter Maydell
2d03b49c3f Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20140417-1' into staging
target-arm queue:
 * AArch64 system mode support; this is all the CPU emulation code
   but not the virt board support
 * cadence_ttc match register bugfix
 * Allwinner A10 PIC, PIT and ethernet fixes
   [with update to avoid duplicate typedef]
 * zynq-slcr rewrite
 * cadence_gem bugfix
 * fix for SMLALD/SMLSLD insn in A32
 * fix for SQXTUN in A64

# gpg: Signature made Thu 17 Apr 2014 21:35:57 BST using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"

* remotes/pmaydell/tags/pull-target-arm-20140417-1: (51 commits)
  target-arm: A64: fix unallocated test of scalar SQXTUN
  arm: translate.c: Fix smlald Instruction
  net: cadence_gem: Make phy respond to broadcast
  misc: zynq_slcr: Make DB_PRINTs always compile
  misc: zynq_slcr: Convert SBD::init to object init
  misc: zynq-slcr: Rewrite
  allwinner-emac: update irq status after writes to interrupt registers
  allwinner-emac: set autonegotiation complete bit on link up
  allwinner-a10-pit: implement prescaler and source selection
  allwinner-a10-pit: use level triggered interrupts
  allwinner-a10-pit: avoid generation of spurious interrupts
  allwinner-a10-pic: fix behaviour of pending register
  allwinner-a10-pic: set vector address when an interrupt is pending
  timer: cadence_ttc: Fix match register write logic
  target-arm/gdbstub64.c: remove useless 'break' statement.
  target-arm: Dump 32-bit CPU state if 64 bit CPU is in AArch32
  target-arm: Handle the CPU being in AArch32 mode in the AArch64 set_pc
  target-arm: Make Cortex-A15 CBAR read-only
  target-arm: Implement CBAR for Cortex-A57
  target-arm: Implement Cortex-A57 implementation-defined system registers
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-17 21:37:26 +01:00
Alex Bennée
e44a90c596 target-arm: A64: fix unallocated test of scalar SQXTUN
The test for the U bit was incorrectly inverted in the scalar case of SQXTUN.
This doesn't affect the vector case as the U bit is used to select XTN(2).

Reported-by: Hao Liu <hao.liu@arm.com>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Cc: qemu-stable@nongnu.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-17 21:34:07 +01:00
Peter Crosthwaite
33bbd75a7c arm: translate.c: Fix smlald Instruction
The smlald (and probably smlsld) instruction was doing incorrect sign
extensions of the operands amongst 64bit result calculation. The
instruction psuedo-code is:

 operand2 = if m_swap then ROR(R[m],16) else R[m];
 product1 = SInt(R[n]<15:0>) * SInt(operand2<15:0>);
 product2 = SInt(R[n]<31:16>) * SInt(operand2<31:16>);
 result = product1 + product2 + SInt(R[dHi]:R[dLo]);
 R[dHi] = result<63:32>;
 R[dLo] = result<31:0>;

The result calculation should be done in 64 bit arithmetic, and hence
product1 and product2 should be sign extended to 64b before calculation.

The current implementation was adding product1 and product2 together
then sign-extending the intermediate result leading to false negatives.

E.G. if product1 = product2 = 0x4000000, their sum = 0x80000000, which
will be incorrectly interpreted as -ve on sign extension.

We fix by doing the 64b extensions on both product1 and product2 before
any addition/subtraction happens.

We also fix where we were possibly incorrectly setting the Q saturation
flag for SMLSLD, which the ARM ARM specifically says is not set.

Reported-by: Christina Smith <christina.smith@xilinx.com>
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 2cddb6f5a15be4ab8d2160f3499d128ae93d304d.1397704570.git.peter.crosthwaite@xilinx.com
Cc: qemu-stable@nongnu.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-17 21:34:07 +01:00
Peter Crosthwaite
5538937368 net: cadence_gem: Make phy respond to broadcast
Phys must respond to address 0 by specification. Implement.

Signed-off-by: Nathan Rossi <nathan.rossi@xilinx.com>
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Message-id: 6f4d53b04ddbfb19895bfb61a595e69f1c08859a.1396594056.git.peter.crosthwaite@xilinx.com
Reviewed-by: Beniamino Galvani <b.galvani@gmail.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-17 21:34:07 +01:00
Peter Crosthwaite
6954a1cd97 misc: zynq_slcr: Make DB_PRINTs always compile
Change the DB_PRINT macro over to a regular if() rather than
conditional compilation to give constant compile testing of formats.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Message-id: 942477847353c5cff5f45a228cc88c633dc012f3.1396503037.git.peter.crosthwaite@xilinx.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-17 21:34:07 +01:00
Peter Crosthwaite
15e3611e1c misc: zynq_slcr: Convert SBD::init to object init
To bring it up to date with styling guidelines.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Message-id: 2e837af80a18216c21e73241032e048f39d78b99.1396503037.git.peter.crosthwaite@xilinx.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-17 21:34:07 +01:00
Peter Crosthwaite
db302f8f93 misc: zynq-slcr: Rewrite
Near total rewrite of this device model. It is stylistically
obsolete, has numerous coverity fails and is not up to date with latest
Xilinx documentation. Fix.

The registers are flattened into a single array. This greatly simplifies
the MMIO accessor functions.

We take the oppurtunity to update the register Macro definitions to
match the latest TRM. Xilinx has de-documented some regs hence there are
some straight deletions. We only do this however in the case or a stock
read-as-written reset-zero register. Non-zero resets are always
preserved. New register definitions are added as needed.

This all comes with a VMSD version break as the union layout from before
was a bit strange and we are better off without it.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Message-id: 3aa016167b352ed224666909217137285fd3351d.1396503037.git.peter.crosthwaite@xilinx.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-17 21:34:06 +01:00
Beniamino Galvani
6619bc5c55 allwinner-emac: update irq status after writes to interrupt registers
The irq line status must be updated after writes to the INT_CTL and
INT_STA registers.

Signed-off-by: Beniamino Galvani <b.galvani@gmail.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Message-id: 1395771730-16882-8-git-send-email-b.galvani@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-17 21:34:06 +01:00
Beniamino Galvani
103db49a10 allwinner-emac: set autonegotiation complete bit on link up
Signed-off-by: Beniamino Galvani <b.galvani@gmail.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Message-id: 1395771730-16882-7-git-send-email-b.galvani@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-17 21:34:06 +01:00
Beniamino Galvani
286226a479 allwinner-a10-pit: implement prescaler and source selection
This implements the prescaler and source fields of the timer control
register. The source for each timer can be selected among 4 clock
inputs whose frequencies are set through model properties.

Signed-off-by: Beniamino Galvani <b.galvani@gmail.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Message-id: 1395771730-16882-6-git-send-email-b.galvani@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-17 21:34:06 +01:00
Beniamino Galvani
a63f9f85e3 allwinner-a10-pit: use level triggered interrupts
Convert the interrupt generation logic to the use of level triggered
interrupts.

Signed-off-by: Beniamino Galvani <b.galvani@gmail.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Message-id: 1395771730-16882-5-git-send-email-b.galvani@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-17 21:34:06 +01:00
Beniamino Galvani
323a8771cf allwinner-a10-pit: avoid generation of spurious interrupts
The model was generating interrupts for all enabled timers after the
expiration of one of them. Avoid this by passing explicitly the timer
index to the callback function.

Signed-off-by: Beniamino Galvani <b.galvani@gmail.com>
Reviewed-by: Li Guang <lig.fnst@cn.fujitsu.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Message-id: 1395771730-16882-4-git-send-email-b.galvani@gmail.com
[PMM: avoid duplicate typedef of AwA10PITState]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-17 21:34:06 +01:00
Beniamino Galvani
2237094d96 allwinner-a10-pic: fix behaviour of pending register
The pending register is read-only and the value returned upon a read
reflects the state of irq input pins (interrupts are level triggered).
This patch implements such behaviour.

Signed-off-by: Beniamino Galvani <b.galvani@gmail.com>
Reviewed-by: Li Guang <lig.fnst@cn.fujitsu.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Message-id: 1395771730-16882-3-git-send-email-b.galvani@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-17 21:34:06 +01:00
Beniamino Galvani
1c70aa6264 allwinner-a10-pic: set vector address when an interrupt is pending
This patch implements proper updating of the vector register which
should hold, according to the A10 user manual, the vector address for
the interrupt currently active on the CPU IRQ input.

Interrupt priority is not implemented at the moment and thus the first
pending interrupt is returned.

Signed-off-by: Beniamino Galvani <b.galvani@gmail.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Li Guang <lig.fnst@cn.fujitsu.com>
Message-id: 1395771730-16882-2-git-send-email-b.galvani@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-17 21:34:06 +01:00
Peter Crosthwaite
f727d0e621 timer: cadence_ttc: Fix match register write logic
This switch logic should not fall through. Fix.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Message-id: 74147b4c017c904364955cc73107f90e6ac8ba74.1396326389.git.peter.crosthwaite@xilinx.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-17 21:34:06 +01:00
Chen Gang
b5cde1da0a target-arm/gdbstub64.c: remove useless 'break' statement.
Clean up useless 'break' statement after 'return' statement.

Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-17 21:34:06 +01:00
Peter Maydell
177311157c target-arm: Dump 32-bit CPU state if 64 bit CPU is in AArch32
For system mode, we may have a 64 bit CPU which is currently executing
in AArch32 state; if we're dumping CPU state to the logs we should
therefore show the correct state for the current execution state,
rather than hardwiring it based on the type of the CPU. For consistency
with how we handle translation, we leave the 32 bit dump function
as the default, and have it hand off control to the 64 bit dump code
if we're in AArch64 mode.

Reported-by: Rob Herring <rob.herring@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-17 21:34:06 +01:00
Peter Maydell
7633378d5f target-arm: Handle the CPU being in AArch32 mode in the AArch64 set_pc
The AArch64 implementation of the set_pc method needs to be updated to
handle the possibility that the CPU is in AArch32 mode; otherwise there
are weird crashes when doing interprocessing in system emulation mode
when an interrupt occurs and we fail to resynchronize the 32-bit PC
with the TB we need to execute next.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:06 +01:00
Peter Maydell
c29f9a0a29 target-arm: Make Cortex-A15 CBAR read-only
The Cortex-A15's CBAR register is actually read-only (unlike that
of the Cortex-A9). Correct our model to match the hardware.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:06 +01:00
Peter Maydell
f318cec6ad target-arm: Implement CBAR for Cortex-A57
The Cortex-A57, like most of the other ARM cores, has a CBAR
register which defines the base address of the per-CPU
peripherals. However it has a 64-bit view as well as a
32-bit view; expand the QOM reset-cbar property from UINT32
to UINT64 so this can be specified, and implement the
32-bit and 64-bit views of a 64-bit CBAR.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:06 +01:00
Peter Maydell
377a44ec8f target-arm: Implement Cortex-A57 implementation-defined system registers
Implement a subset of the Cortex-A57's implementation defined system
registers. We provide RAZ/WI or reads-as-constant/writes-ignored
implementations of the various control and syndrome reigsters.
We do not implement registers which provide direct access to and
manipulation of the L1 cache, since QEMU doesn't implement caches.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Acked-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:06 +01:00
Peter Maydell
3933443e38 target-arm: Implement RVBAR register
Implement the AArch64 RVBAR register, which indicates the reset
address. Since the reset address is implementation defined and
usually configurable by setting config signals in hardware, we
also provide a QOM property so it can be set at board level if
necessary.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:06 +01:00
Peter Maydell
19525524a7 target-arm: Implement AArch64 address translation operations
Implement the AArch64 address translation operations.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:06 +01:00
Peter Maydell
f32cdad55d target-arm: Implement auxiliary fault status registers
Implement the auxiliary fault status registers AFSR0_EL1 and
AFSR1_EL1. These are present on v7 and later, and have IMPDEF
behaviour; we choose to RAZ/WI for all cores.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:05 +01:00
Peter Maydell
9449fdf61f target-arm: Replace wildcarded cpreg definitions with precise ones for ARMv8
Many of the reginfo definitions in cp_reginfo[] use CP_ANY wildcards.
This is for a combination of reasons:
 * early ARM implementations really did underdecode
 * earlier versions of QEMU underdecoded and we can't tighten
   this up because we don't know if guests really require this or not
 * implementation convenience

For ARMv8 the architecture has tightened things up and system and
coprocessor registers are always specifically decoded. We take
advantage of this opportunity for a clean break by restricting
our CP_ANY wildcarded reginfo to pre-v8 CPUs, and providing
specifically decoded versions where necessary for v8 CPUs.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Acked-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:05 +01:00
Peter Maydell
00a29f3ddc target-arm: Don't expose wildcard ID register definitions for ARMv8
In ARMv8 the 32 bit coprocessor ID register space is tidied up to
remove the wildcarded aliases of the MIDR and the RAZ behaviour
for the unassigned space where crm = 3..7. Make sure we don't
expose thes wildcards for v8 cores. This means we need to have
a specific implementation for REVIDR, an IMPDEF register which
may be the same as the MIDR (and which we always implement as such).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:05 +01:00
Peter Maydell
85acfa9c38 target-arm: Remove THUMB2EE feature from AArch64 'any' CPU
The AArch64 usermode 'any' CPU type was accidentally specified
with the ARM_FEATURE_THUMB2EE bit set. This is incorrect since
ARMv8 removes Thumb2EE completely. Since we never implemented
Thumb2EE anyway having the feature bit set was fairly harmless
for user-mode, but the correct thing is to not set it at all.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:05 +01:00
Peter Maydell
1090b9c6cc target-arm: Implement ISR_EL1 register
Implement the ISR_EL1 register. This is actually present in
ARMv7 as well but was previously unimplemented. It is a
read-only register that indicates whether interrupts are
currently pending.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:05 +01:00
Peter Maydell
2eef0bf821 target-arm: Implement AArch64 view of ACTLR
Implement the AArch64 view of the ACTLR (auxiliary control
register). Note that QEMU internally tends to call this
AUXCR for historical reasons.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:05 +01:00
Peter Maydell
014406b510 target-arm: Implement AArch64 view of CONTEXTIDR
Implement AArch64 view of the CONTEXTIDR register.
We tighten up the condition when we flush the TLB on a CONTEXTIDR
write to avoid needlessly flushing the TLB every time on a 64
bit system (and also on a 32 bit system using LPAE, as a bonus).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:05 +01:00
Peter Maydell
0ff644a786 target-arm: Implement AArch64 views of AArch32 ID registers
All the AArch32 ID registers are visible from AArch64
(in addition to the AArch64-specific ID_AA64* registers).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:05 +01:00
Peter Maydell
cb1fa941c1 target-arm: Add Cortex-A57 processor
Add Cortex-A57 processor.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Acked-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:05 +01:00
Peter Maydell
a50c0f5133 target-arm: Implement ARMv8 MVFR registers
For ARMv8 there are two changes to the MVFR media feature registers:
 * there is a new MVFR2 which is accessible from 32 bit code
 * 64 bit code accesses these via the usual sysreg instructions
   rather than with a floating-point specific instruction

Implement this.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:04 +01:00
Rob Herring
52e60cdd34 target-arm: Implement AArch64 EL1 exception handling
Implement exception handling for AArch64 EL1. Exceptions from AArch64 or
AArch32 EL0 are supported.

Signed-off-by: Rob Herring <rob.herring@linaro.org>
[PMM: fixed minor style nits; updated to match changes in
 previous patches; added some of the simpler cases of
 illegal-exception-return support]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:04 +01:00
Peter Maydell
2f2a00aec9 target-arm: Move arm_log_exception() into internals.h
Move arm_log_exception() into internals.h so we can use it from
helper-a64.c for the AArch64 exception entry code.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:04 +01:00
Peter Maydell
a65f1de982 target-arm: Implement AArch64 SPSR_EL1
Implement the AArch64 SPSR_EL1. For compatibility with how KVM
handles SPSRs and with the architectural mapping between AArch32
and AArch64, we put this in the banked_spsr[] array in the slot
that is used for SVC in AArch32. This means we need to extend the
array from uint32_t to uint64_t, which requires some reworking
of the 32 bit KVM save/restore code.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Acked-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:04 +01:00
Peter Maydell
f502cfc207 target-arm: Implement SP_EL0, SP_EL1
Implement handling for the AArch64 SP_EL0 system register.
This holds the EL0 stack pointer, and is only accessible when
it's not being used as the stack pointer, ie when we're in EL1
and EL1 is using its own stack pointer. We also provide a
definition of the SP_EL1 register; this isn't guest visible
as a system register for an implementation like QEMU which
doesn't provide EL2 or EL3; however it is useful for ensuring
the underlying state is migrated.

We need to update the state fields in the CPU state whenever
we switch stack pointers; this happens when we take an exception
and also when SPSEL is used to change the bit in PSTATE which
indicates which stack pointer EL1 should use.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:04 +01:00
Peter Maydell
a0618a1990 target-arm: Add AArch64 ELR_EL1 register.
Add the AArch64 ELR_EL1 register.

Note that this does not live in env->cp15: for KVM migration
compatibility we need to migrate it separately rather than
as part of the system registers, because the KVM-to-userspace
interface puts it in the struct kvm_regs rather than making
them visible via the ONE_REG ioctls.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:04 +01:00
Rob Herring
6cd8a2649a target-arm: Implement AArch64 views of fault status and data registers
Implement AArch64 views of ESR_EL1 and FAR_EL1, and make the 32 bit
DFSR, DFAR, IFAR share state with them as architecturally specified.
The IFSR doesn't share state with any AArch64 register visible at EL1,
so just rename the state field without widening it to 64 bits.

Signed-off-by: Rob Herring <rob.herring@linaro.org>
[PMM: Minor tweaks; fix some bugs involving inconsistencies between
 use of offsetof() or offsetoflow32() and struct field width]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:04 +01:00
Peter Maydell
7e09797c29 target-arm: Use dedicated CPU state fields for ARM946 access bit registers
The ARM946 model currently uses the c5_data and c5_insn fields in the CPU
state struct to store the contents of its access permission registers.
This is confusing and a good source of bugs because for all the MMU-based
CPUs those fields are fault status and fault address registers, which
behave completely differently; they just happen to use the same cpreg
encoding. Split them out to use their own fields instead.

These registers are only present in PMSAv5 MPU systems (of which the
ARM946 is our only current example); PMSAv6 and PMSAv7 (which we have
no implementations of) handle access permissions differently. We name
the new state fields accordingly.

Note that this change fixes a bug where a data abort or prefetch abort
on the ARM946 would accidentally corrupt the access permission registers
because the interrupt handling code assumed the c5_data and c5_insn
fields were always fault status registers.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:04 +01:00
Peter Maydell
aca3f40b37 target-arm: A64: Implement DC ZVA
Implement the DC ZVA instruction, which clears a block of memory.
The fast path obtains a pointer to the underlying RAM via the TCG TLB
data structure so we can do a direct memset(), with fallback to a
simple byte-store loop in the slow path.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Acked-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:04 +01:00
Peter Maydell
9225d739e7 target-arm: Don't mention PMU in debug feature register
Suppress the ID_AA64DFR0_EL1 PMUVer field, even if the CPU specific
value claims that it exists. QEMU doesn't currently implement it,
and not advertising it prevents the guest from trying to use it
and getting UNDEFs on unimplemented registers.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
This is arguably a hack, but otherwise Linux tries to prod
half a dozen PMU sysregs.
2014-04-17 21:34:04 +01:00
Rob Herring
2c8dd31863 target-arm: Add v8 mmu translation support
Add support for v8 page table walks. This supports stage 1 translations
for 4KB, 16KB and 64KB page sizes starting with 0 or 1 level.

Signed-off-by: Rob Herring <rob.herring@linaro.org>
[PMM: fix style nits, fold in 16/64K page support patch, use
 arm_el_is_aa64() to decide whether to do 64 bit page table walk]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:04 +01:00
Peter Maydell
2c7ffc414d target-arm: Fix VFP enables for AArch32 EL0 under AArch64 EL1
The current A32/T32 decoder bases its "is VFP/Neon enabled?" check
on the FPSCR.EN bit. This is correct if EL1 is AArch32, but for
an AArch64 EL1 the logic is different: it must act as if FPSCR.EN
is always set. Instead, trapping must happen according to CPACR
bits for cp10/cp11; these cover all of FP/Neon, including the
FPSCR/FPSID/MVFR register accesses which FPSCR.EN does not affect.
Add support for CPACR checks (which are also required for ARMv7,
but were unimplemented because Linux happens not to use them)
and make sure they generate exceptions with the correct syndrome.

We actually return incorrect syndrome information for cases
where FP is disabled but the specific instruction bit pattern
is unallocated: strictly these should be the Uncategorized
exception, not a "SIMD disabled" exception. This should be
mostly harmless, and the structure of the A32/T32 VFP/Neon
decoder makes it painful to put the 'FP disabled?' checks in
the right places.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:03 +01:00
Peter Maydell
90e496386f target-arm: A64: Add assertion that FP access was checked
Because unallocated encodings generate different exception syndrome
information from traps due to FP being disabled, we can't do a single
"is fp access disabled" check at a high level in the decode tree.
To help in catching bugs where the access check was forgotten in some
code path, we set this flag when the access check is done, and assert
that it is set at the point where we actually touch the FP regs.

This requires us to pass the DisasContext to the vec_reg_offset
and fp_reg_offset functions.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:03 +01:00
Peter Maydell
8c6afa6ab1 target-arm: A64: Correctly fault FP/Neon if CPACR.FPEN set
For the A64 instruction set, the only FP/Neon disable trap
is the CPACR FPEN bits, which may indicate "enabled", "disabled"
or "disabled for EL0". Add a bit to the AArch64 tb flags indicating
whether FP/Neon access is currently enabled and make the decoder
emit code to raise exceptions on use of FP/Neon insns if it is not.

We use a new flag in DisasContext rather than borrowing the
existing vfp_enabled flag because the A32/T32 decoder is going
to need both.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Acked-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
I'm aware this is a rather hard to review patch; sorry.
I have done an exhaustive check that we have fp access checks
in all code paths with the aid of the assertions added in the
next patch plus the code-coverage hack patch I posted to the
list earlier.

This patch is correct as of
09e037354 target-arm: A64: Add saturating accumulate ops (USQADD/SUQADD)
which was the last of the Neon insns to be added, so assuming
no refactoring of the code it should be fine.
2014-04-17 21:34:03 +01:00
Rob Herring
00892383c9 target-arm: Provide syndrome information for MMU faults
Set up the required syndrome information when we detect an MMU fault.

Signed-off-by: Rob Herring <rob.herring@linaro.org>
[PMM: split out from exception handling patch, tweaked to bring
 in line with how we create other kinds of syndrome information]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:03 +01:00
Peter Maydell
d4a2dc675b target-arm: Add support for generating exceptions with syndrome information
Add new helpers exception_with_syndrome (for generating an exception
with syndrome information) and exception_uncategorized (for generating
an exception with "Unknown or Uncategorized Reason", which have a syndrome
register value of zero), and use them to generate the correct syndrome
information for exceptions which are raised directly from generated code.

This patch includes moving the A32/T32 gen_exception_insn functions
further up in the source file; they will be needed for "VFP/Neon disabled"
exception generation later.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:03 +01:00
Peter Maydell
8bcbf37caa target-arm: Provide correct syndrome information for cpreg access traps
For exceptions taken to AArch64, if a coprocessor/system register
access fails due to a trap or enable bit then the syndrome information
must include details of the failing instruction (crn/crm/opc1/opc2
fields, etc). Make the decoder construct the syndrome information
at translate time so it can be passed at runtime to the access-check
helper function and used as required.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:03 +01:00
Peter Maydell
abf1172fc6 target-arm: Define exception record for AArch64 exceptions
For AArch32 exceptions, the only information provided about
the cause of an exception is the individual exception type (data
abort, undef, etc), which we store in cs->exception_index. For
AArch64, the CPU provides much more detail about the cause of
the exception, which can be found in the syndrome register.
Create a set of fields in CPUARMState which must be filled in
whenever an exception is raised, so that exception entry can
correctly fill in the syndrome register for the guest.
This includes the information which in AArch32 appears in
the DFAR and IFAR (fault address registers) and the DFSR
and IFSR (fault status registers) for data aborts and
prefetch aborts, since if we end up taking the MMU fault
to AArch64 rather than AArch32 this will need to end up
in different system registers.

This patch does a refactoring which moves the setting of the
AArch32 DFAR/DFSR/IFAR/IFSR from the point where the exception
is raised to the point where it is taken. (This is no change
for cores with an MMU, retains the existing clearly incorrect
behaviour for ARM946 of trashing the MP access permissions
registers which share the c5_data and c5_insn state fields,
and has no effect for v7M because we don't implement its
MPU fault status or address registers.)

As a side effect of the cleanup we fix a bug in the AArch64
linux-user mode code where we were passing a 64 bit fault
address through the 32 bit c6_data/c6_insn fields: it now
goes via the always-64-bit exception.vaddress.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:03 +01:00
Peter Maydell
c2b820fe58 target-arm: Implement AArch64 DAIF system register
Implement the DAIF system register which is a view of the
DAIF bits in PSTATE. To avoid needing a readfn, we widen
the daif field in CPUARMState to uint64_t.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:03 +01:00
Peter Maydell
ccd380876b target-arm: Split out private-to-target functions into internals.h
Currently cpu.h defines a mixture of functions and types needed by
the rest of QEMU and those needed only by files within target-arm/.
Split the latter out into a new header so they aren't needlessly
exposed further than required.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
2014-04-17 21:34:03 +01:00
Peter Maydell
c6138aabfb Merge remote-tracking branch 'remotes/rth/tcg-aarch-6-5' into staging
* remotes/rth/tcg-aarch-6-5: (25 commits)
  tcg-aarch64: Use tcg_out_mov in preference to tcg_out_movr
  tcg-aarch64: Prefer unsigned offsets before signed offsets for ldst
  tcg-aarch64: Introduce tcg_out_insn_3312, _3310, _3313
  tcg-aarch64: Merge aarch64_ldst_get_data/type into tcg_out_op
  tcg-aarch64: Introduce tcg_out_insn_3507
  tcg-aarch64: Support stores of zero
  tcg-aarch64: Implement TCG_TARGET_HAS_new_ldst
  tcg-aarch64: Pass qemu_ld/st arguments directly
  tcg-aarch64: Use TCGMemOp in qemu_ld/st
  tcg-aarch64: Use ADR to pass the return address to the ld/st helpers
  tcg-aarch64: Use tcg_out_call for qemu_ld/st
  tcg-aarch64: Avoid add with zero in tlb load
  tcg-aarch64: Implement tcg_register_jit
  tcg-aarch64: Introduce tcg_out_insn_3314
  tcg-aarch64: Reuse LR in translated code
  tcg-aarch64: Use CBZ and CBNZ
  tcg-aarch64: Create tcg_out_brcond
  tcg-aarch64: Use symbolic names for branches
  tcg-aarch64: Use adrp in tcg_out_movi
  tcg-aarch64: Special case small constants in tcg_out_movi
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-17 20:54:38 +01:00
Peter Maydell
5149e557d7 Open 2.1 development tree
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-17 20:39:32 +01:00
Peter Maydell
a9e8aeb375 Update version for v2.0.0 release
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-17 13:41:45 +01:00
Richard Henderson
b825025f08 tcg-aarch64: Use tcg_out_mov in preference to tcg_out_movr
It's the more canonical interface.

Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:13:02 -04:00
Richard Henderson
a056c9faa4 tcg-aarch64: Prefer unsigned offsets before signed offsets for ldst
The assembler seems to prefer them, perhaps we should too.

Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:13:01 -04:00
Richard Henderson
3d4299f425 tcg-aarch64: Introduce tcg_out_insn_3312, _3310, _3313
Replace aarch64_ldst_op_data with AArch64LdstType, as it wasn't encoded
for the proper shift for the field and was confusing.

Merge aarch64_ldst_op_data, AArch64LdstType, and a few stray opcode bits
into a single I3312_* argument, eliminating some magic numbers from the
helper functions.

Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:13:01 -04:00
Richard Henderson
dc73dfd4bc tcg-aarch64: Merge aarch64_ldst_get_data/type into tcg_out_op
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:13:01 -04:00
Richard Henderson
edd8824cd4 tcg-aarch64: Introduce tcg_out_insn_3507
Cleaning up the implementation of REV and REV16 at the same time.

Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:13:01 -04:00
Richard Henderson
e81864a109 tcg-aarch64: Support stores of zero
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:13:01 -04:00
Richard Henderson
de61d14fa7 tcg-aarch64: Implement TCG_TARGET_HAS_new_ldst
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:13:01 -04:00
Richard Henderson
667b1cdd4e tcg-aarch64: Pass qemu_ld/st arguments directly
Instead of passing them the "args" array.

Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:13:00 -04:00
Richard Henderson
9e4177ad6d tcg-aarch64: Use TCGMemOp in qemu_ld/st
Making the bswap conditional on the memop instead of a compile-time test.

Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:13:00 -04:00
Richard Henderson
dc0c8aaf2c tcg-aarch64: Use ADR to pass the return address to the ld/st helpers
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:13:00 -04:00
Richard Henderson
ae7ab46aa8 tcg-aarch64: Use tcg_out_call for qemu_ld/st
In some cases, a direct branch will be in range.

Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:13:00 -04:00
Richard Henderson
6f4724672c tcg-aarch64: Avoid add with zero in tlb load
Some guest env are small enough to reach the tlb with only a 12-bit addition.

Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:13:00 -04:00
Richard Henderson
38d195aa05 tcg-aarch64: Implement tcg_register_jit
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:13:00 -04:00
Richard Henderson
95f72aa90a tcg-aarch64: Introduce tcg_out_insn_3314
Combines 4 other inline functions and tidies the prologue.

Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:12:59 -04:00
Richard Henderson
d82b78e48b tcg-aarch64: Reuse LR in translated code
It's obviously call-clobbered, but is otherwise unused.
Repurpose it as the TCG temporary.

Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:12:59 -04:00
Richard Henderson
3d9e69a238 tcg-aarch64: Use CBZ and CBNZ
A compare and branch against zero happens at the start of
every single TB.

Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:12:59 -04:00
Richard Henderson
cae1f6f3e6 tcg-aarch64: Create tcg_out_brcond
Rearrange code to put the compare and branch in the same place.

Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:12:59 -04:00
Richard Henderson
81d8a5ee19 tcg-aarch64: Use symbolic names for branches
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:12:59 -04:00
Richard Henderson
c6e310d938 tcg-aarch64: Use adrp in tcg_out_movi
Loading an qemu pointer as an immediate happens often.  E.g.

- exit_tb $0x7fa8140013
+ exit_tb $0x7f81ee0013
...
- :  d2800260        mov     x0, #0x13
- :  f2b50280        movk    x0, #0xa814, lsl #16
- :  f2c00fe0        movk    x0, #0x7f, lsl #32
+ :  90ff1000        adrp    x0, 0x7f81ee0000
+ :  91004c00        add     x0, x0, #0x13

Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:12:58 -04:00
Richard Henderson
d8918df577 tcg-aarch64: Special case small constants in tcg_out_movi
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:12:58 -04:00
Richard Henderson
4ec4f0bd56 tcg-aarch64: Use ORRI in tcg_out_movi
The subset of logical immediates that we support is quite quick to test,
and such constants are quite common to want to load.

Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:12:58 -04:00
Richard Henderson
dfeb5fe770 tcg-aarch64: Use MOVN in tcg_out_movi
When profitable, initialize the register with MOVN instead of MOVZ,
before setting the remaining lanes with MOVK.

Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:12:58 -04:00
Richard Henderson
929f8b5550 tcg-aarch64: Use TCGType and TCGMemOp constants
Rather than raw constants that could mean anything.

Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:12:58 -04:00
Richard Henderson
8bf56493f1 tcg-aarch64: Use intptr_t apropriately
As opposed to tcg_target_long.

Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:12:58 -04:00
Richard Henderson
661f7fa4b0 tcg-aarch64: Properly detect SIGSEGV writes
Since the kernel doesn't pass any info on the reason for the fault,
disassemble the instruction to detect a store.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-16 12:12:32 -04:00
Peter Maydell
851627352c Update version for v2.0.0-rc3 release
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-14 17:45:11 +01:00
Michael Tokarev
50212d6346 Revert "fix return check for KVM_GET_DIRTY_LOG ioctl"
This reverts commit b533f658a9.

The original code was wrong, because effectively it ignored errors
from kernel, because kernel does not return -1 on error case but
returns -errno, and does not return -EPERM for this particular ioctl.
But in some cases kernel actually returned unsuccessful result,
namely, when the dirty bitmap in requested slot does not exist
it returns -ENOENT.  With new code this condition becomes an
error when it shouldn't be.

Revert that patch instead of fixing it properly this late in the
release process.  I disagree with this approach, but let's make
things move _somewhere_, instead of arguing endlessly whch of
the 2 proposed fixes is better.

Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Message-id: 1397477644-902-1-git-send-email-mjt@msgid.tls.msk.ru
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-14 15:40:02 +01:00
Peter Maydell
c2b9af1d6c Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
acpi: SSDT update

This has a fix by Igor for a regression introduced by
bridge hotplug code.
Expected test files were updated accordingly.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Mon 14 Apr 2014 13:13:35 BST using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"

* remotes/mst/tags/for_upstream:
  acpi-test: update expected files
  acpi: fix incorrect encoding for 0x{F-1}FFFF

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-14 14:02:12 +01:00
Benoît Canet
940973ae0b ide: Correct improper smart self test counter reset in ide core.
The SMART self test counter was incorrectly being reset to zero,
not 1. This had the effect that on every 21st SMART EXECUTE OFFLINE:
 * We would write off the beginning of a dynamically allocated buffer
 * We forgot the SMART history
Fix this.

Signed-off-by: Benoit Canet <benoit@irqsave.net>
Message-id: 1397336390-24664-1-git-send-email-benoit.canet@irqsave.net
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Cc: qemu-stable@nongnu.org
Acked-by: Kevin Wolf <kwolf@redhat.com>
[PMM: tweaked commit message as per suggestions from Markus]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-14 13:23:53 +01:00
Michael S. Tsirkin
8611224a7b acpi-test: update expected files
commit 58b035c7354afc0c5351ea62264c01d74196ec26
    acpi: fix incorrect encoding for 0x{F-1}FFFF
changes the SSDT, update expected files accordingly.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2014-04-14 15:13:27 +03:00
Igor Mammedov
482f38b948 acpi: fix incorrect encoding for 0x{F-1}FFFF
Fix typo in build_append_int() which causes integer
truncation when it's in range 0x{F-1}FFFF by packing it
as WordConst instead of required DWordConst.

In partucular this fixes a regression: hotplug in slots 16,17,18 and 19
didn't work, since SSDT had code like this:

                If (And (Arg0, 0x0000))
                {
                    Notify (S80, Arg1)
                }

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Stefan Weil <sw@weilnetz.de>
2014-04-14 15:13:27 +03:00
Peter Maydell
590e5dd98f configure: Make stack-protector test check both compile and link
Since we use the -fstack-protector argument at both compile and
link time in the build, we must check that it works with both
a compile and a link:
 * MacOSX only fails in the compile step, not linking
 * some gcc cross environments only fail at the link stage (if they
   require a libssp and it's not present for some reason)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1397232832-32301-1-git-send-email-peter.maydell@linaro.org
Tested-by: Alexey Kardashevskiy <aik@ozlabs.ru>
2014-04-14 12:11:18 +01:00
Dmitry Fleytman
f12d048a52 vmxnet3: validate queues configuration read on migration
CVE-2013-4544

Signed-off-by: Dmitry Fleytman <dmitry@daynix.com>
Reported-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Message-id: 1396604722-11902-5-git-send-email-dmitry@daynix.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-14 11:50:56 +01:00
Dmitry Fleytman
3c99afc779 vmxnet3: validate interrupt indices read on migration
CVE-2013-4544

Signed-off-by: Dmitry Fleytman <dmitry@daynix.com>
Reported-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Message-id: 1396604722-11902-4-git-send-email-dmitry@daynix.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-14 11:50:49 +01:00
Dmitry Fleytman
9878d173f5 vmxnet3: validate queues configuration coming from guest
CVE-2013-4544

Signed-off-by: Dmitry Fleytman <dmitry@daynix.com>
Reported-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Message-id: 1396604722-11902-3-git-send-email-dmitry@daynix.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-14 11:50:22 +01:00
Dmitry Fleytman
8c6c047899 vmxnet3: validate interrupt indices coming from guest
CVE-2013-4544

Signed-off-by: Dmitry Fleytman <dmitry@daynix.com>
Reported-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Message-id: 1396604722-11902-2-git-send-email-dmitry@daynix.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-14 11:33:18 +01:00
Cole Robinson
92b3eeadd9 qom: Fix crash with qom-list and link properties
Commit 9561fda8d9 changed the type of
'opaque' for link properties, but missed updating this call site.
Reproducer:

./x86_64-softmmu/qemu-system-x86_64 -qmp unix:./qmp.sock,server &
./scripts/qmp/qmp-shell ./qmp.sock
(QEMU) qom-list path=//machine/i440fx/pci.0/child[2]

Reported-by: Marcin Gibuła <m.gibula@beyond.pl>
Signed-off-by: Cole Robinson <crobinso@redhat.com>
Message-id: 2f8f007ce2152ac3b65f0811199662799c509225.1397155389.git.crobinso@redhat.com
Acked-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-11 17:57:36 +01:00
Michael S. Tsirkin
edc2438512 virtio-net: fix guest-triggerable buffer overrun
When VM guest programs multicast addresses for
a virtio net card, it supplies a 32 bit
entries counter for the number of addresses.
These addresses are read into tail portion of
a fixed macs array which has size MAC_TABLE_ENTRIES,
at offset equal to in_use.

To avoid overflow of this array by guest, qemu attempts
to test the size as follows:
-    if (in_use + mac_data.entries <= MAC_TABLE_ENTRIES) {

however, as mac_data.entries is uint32_t, this sum
can overflow, e.g. if in_use is 1 and mac_data.entries
is 0xffffffff then in_use + mac_data.entries will be 0.

Qemu will then read guest supplied buffer into this
memory, overflowing buffer on heap.

CVE-2014-0150

Cc: qemu-stable@nongnu.org
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-id: 1397218574-25058-1-git-send-email-mst@redhat.com
Reviewed-by: Michael Tokarev <mjt@tls.msk.ru>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-11 16:02:23 +01:00
Peter Maydell
21e2db7260 Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block patches for 2.0.0-rc3

# gpg: Signature made Fri 11 Apr 2014 13:37:34 BST using RSA key ID C88F2FD6
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>"

* remotes/kevin/tags/for-upstream:
  block-commit: speed is an optional parameter
  iscsi: Remember to set ret for iscsi_open in error case
  bochs: Fix catalog size check
  bochs: Fix memory leak in bochs_open() error path

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-11 14:07:24 +01:00
Peter Maydell
80fc7b1755 Merge remote-tracking branch 'remotes/kraxel/tags/pull-sdl-1' into staging
sdl2 relative mouse mode fixes.

# gpg: Signature made Fri 11 Apr 2014 11:36:46 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/kraxel/tags/pull-sdl-1:
  input: sdl2: Fix relative mode to match SDL1 behavior
  input: sdl2: Fix guest_cursor logic

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-11 13:51:16 +01:00
Max Reitz
5450466394 block-commit: speed is an optional parameter
As speed is an optional parameter for the QMP block-commit command, it
should be set to 0 if not given (as it is undefined if has_speed is
false), that is, the speed should not be limited.

Cc: qemu-stable@nongnu.org
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-11 13:59:49 +02:00
Fam Zheng
cd82b6fb4d iscsi: Remember to set ret for iscsi_open in error case
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-11 13:59:49 +02:00
Kevin Wolf
715c3f60ef bochs: Fix catalog size check
The old check was off by a factor of 512 and didn't consider cases where
we don't get an exact division. This could lead to an out-of-bounds
array access in seek_to_sector().

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
2014-04-11 13:59:49 +02:00
Kevin Wolf
28ec11bc88 bochs: Fix memory leak in bochs_open() error path
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
2014-04-11 13:59:49 +02:00
Cole Robinson
2d968ffbae input: sdl2: Fix relative mode to match SDL1 behavior
Right now relative mode accelerates too fast, and has the 'invisible wall'
problem. SDL2 added an explicit API to handle this use case, so let's use
it.

Signed-off-by: Cole Robinson <crobinso@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-04-11 12:19:16 +02:00
Cole Robinson
afbc0dd649 input: sdl2: Fix guest_cursor logic
Unbreaks relative mouse mode with sdl2, just like was done with sdl.c
in c3aa84b6.

Signed-off-by: Cole Robinson <crobinso@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-04-11 12:19:16 +02:00
Peter Maydell
f516a5cc05 Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
acpi: DSDT update

Two fixes here:
- Test fix to avoid warning with make check.
- Hex file update so people building QEMU
  without installing iasl get exactly the same ACPI
  as with.

Both should help avoid user confusion.

As it's very easy to check that the produced ACPI
binary didn't change, I think these are very low risk.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Thu 10 Apr 2014 17:09:43 BST using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"

* remotes/mst/tags/for_upstream:
  acpi: update generated hex files
  tests/acpi: update expected DSDT files

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-10 23:07:56 +01:00
Peter Maydell
0a9077ea14 configure: use do_cc when checking for -fstack-protector support
MacOSX clang silently swallows unrecognized -f options when doing a link
with '-framework' also on the command line, so to detect support for
the various -fstack-protector options we must do a plain .c to .o compile,
not a complete compile-and-link.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-id: 1397041487-28477-1-git-send-email-peter.maydell@linaro.org
2014-04-10 22:17:47 +01:00
Michael S. Tsirkin
775478418a acpi: update generated hex files
commit f2ccc311df
    dsdt: tweak ACPI ID for hotplug resource device
changes the DSDT, update hex files to match

Otherwise the fix is only effective if QEMU is built
with iasl.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2014-04-10 19:03:18 +03:00
Michael S. Tsirkin
50329d3418 tests/acpi: update expected DSDT files
commit f2ccc311df
    dsdt: tweak ACPI ID for hotplug resource device
changes the DSDT, update test expected files to match

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reported-by: Igor Mammedov <imammedo@redhat.com>
2014-04-09 17:52:08 +03:00
Peter Maydell
efcc87d9ae Update version for v2.0.0-rc2 release
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-08 18:52:06 +01:00
Peter Maydell
7dc176bce4 hw/pci-host/prep: Don't reverse IO accesses on bigendian hosts
The raven_io_read() and raven_io_write() functions pass and
return values in little-endian format (since the IO op struct
is marked DEVICE_LITTLE_ENDIAN); however they were storing the
values in the buffer to pass to address_space_read/write()
in host-endian order, which meant that on big-endian hosts
the values were inadvertently reversed. Use the *_le_p()
accessors instead so that we are consistent regardless of
host endianness.

Strictly speaking the byte order of the buffer for
address_space_rw() is target byte order (which for PPC
will be BE) but it doesn't actually matter as long as we
are consistent about the marking on the IO op struct and
which stl_*_p().

This bug was probably introduced due to confusion caused by
the two different versions of ldl_p() and friends:
 bswap.h defines versions meaning "host endianness access"
 cpu-all.h defines versions meaning "target endianness access"
As a target-independent source file prep.c gets the bswap.h
versions; the very similar looking code in ioport.c is
compiled per-target and gets the cpu-all.h versions.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1396972271-22660-1-git-send-email-peter.maydell@linaro.org
Reviewed-by: Richard Henderson <rth@twiddle.net>
2014-04-08 18:37:45 +01:00
Peter Maydell
9bc1a1d817 Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
acpi bug fix

Here is a single last minute fix for 2.0

This changes the HID of the container used to claim
resources for CPU hotplug.
As a result, windows XP SP3 no longer brings up
an annoying "found new hardware" wizard on boot.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Tue 08 Apr 2014 13:23:30 BST using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"

* remotes/mst/tags/for_upstream:
  dsdt: tweak ACPI ID for hotplug resource device

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-08 13:59:28 +01:00
Michael S. Tsirkin
f2ccc311df dsdt: tweak ACPI ID for hotplug resource device
ACPI0004 seems too new:
Windows XP complains about an unrecognized device.
This is a regression since 1.7.
Use PNP0A06 instead - Generic Container Device.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-By: Igor Mammedov <imammedo@redhat.com>
2014-04-08 15:22:59 +03:00
Peter Maydell
093de72b9c Merge remote-tracking branch 'remotes/kraxel/tags/pull-gtk-5' into staging
gtk: Implement grab-on-click behavior in relative mode

# gpg: Signature made Tue 08 Apr 2014 12:58:49 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/kraxel/tags/pull-gtk-5:
  gtk: Implement grab-on-click behavior in relative mode

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-08 13:05:25 +01:00
Takashi Iwai
800b0e814b gtk: Implement grab-on-click behavior in relative mode
This patch changes the behavior in the relative mode to be compatible
with other UIs, namely, grabbing the input at the first left click.
It improves the usability a lot; otherwise you have to press ctl-alt-G
or select from menu at each time you want to move the pointer.  Also,
the input grab is cleared when the current mode is switched to the
absolute mode.

The automatic reset of the implicit grabbing is needed since the
switching to the absolute mode happens always after the click even on
Gtk.  That is, we cannot check whether the absolute mode is already
available at the first click time even though it should have been
switched in X11 input driver side.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-04-08 13:57:34 +02:00
Peter Maydell
9a4fb6aa19 Merge remote-tracking branch 'remotes/agraf/tags/signed-ppc-for-upstream' into staging
Patch queue for ppc - 2014-04-08

This is the final queue for 2.0! It fixes a lot of bugs people have
seen during testing:

  - Fix e500 SMP
  - Fix book3s_64 DEC
  - Fix VSX (new feature in 2.0) for LE hosts
  - Fix PR KVM on top of pHyp (SLOF update)

# gpg: Signature made Tue 08 Apr 2014 10:24:18 BST using RSA key ID 03FEDC60
# gpg: Can't check signature: public key not found

* remotes/agraf/tags/signed-ppc-for-upstream:
  PPC: Add l1 cache sizes for 970 and above systems
  ppce500_spin: Initialize struct properly
  PPC: Only enter MSR_POW when no interrupts pending
  PPC: Clean up DECR implementation
  target-ppc: Correct VSX Integer to FP Conversion
  target-ppc: Correct VSX FP to Integer Conversion
  target-ppc: Correct VSX FP to FP Conversions
  target-ppc: Correct VSX Scalar Compares
  target-ppc: Correct Simple VSR LE Host Inversions
  target-ppc: Correct LE Host Inversion of Lower VSRs
  target-ppc: Define Endian-Correct Accessors for VSR Field Access
  target-ppc: Bug: VSX Convert to Integer Should Truncate
  softfloat: Introduce float32_to_uint64_round_to_zero
  pseries: Update SLOF firmware image to qemu-slof-20140404
  PPC: E500: Set PIR default reset value rather than SPR value

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-08 10:58:31 +01:00
Peter Maydell
e792933ce1 Merge remote-tracking branch 'remotes/mdroth/qga-pull-2014-4-7' into staging
* remotes/mdroth/qga-pull-2014-4-7:
  vss-win32: Fix build with mingw64-headers-3.1.0
  Makefile: add qga-vss-dll-obj-y to nested variables

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-08 10:41:30 +01:00
Alexander Graf
06f6e12491 PPC: Add l1 cache sizes for 970 and above systems
Book3s_64 guests expect the L1 cache size in device tree, so let's give
them proper values for all CPU types we support.

This fixes a "not compliant" warning with sles11 guests on -M pseries for me.

Signed-off-by: Alexander Graf <agraf@suse.de>
2014-04-08 11:20:06 +02:00
Alexander Graf
6a2b3d89fa ppce500_spin: Initialize struct properly
The spinning struct is in guest endianness, so we need to initialize
its variables in guest endianness too.

This fixes booting e500 guests with SMP on x86 for me.

Signed-off-by: Alexander Graf <agraf@suse.de>
2014-04-08 11:20:05 +02:00
Alexander Graf
05edc26c61 PPC: Only enter MSR_POW when no interrupts pending
We were entering the power saving state even when interrupts (like an
external interrupt or a decrementer interrupt) were still in flight.

In case we find a pending interrupt, don't enter power saving state.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Tom Musta <tmusta@gmail.com>
2014-04-08 11:20:05 +02:00
Alexander Graf
e81a982aa5 PPC: Clean up DECR implementation
There are 3 different variants of the decrementor for BookE and BookS.

The BookE variant sets TSR[DIS] to 1 when the DEC value becomes 1 or 0. TSR[DIS]
is then the indicator whether the decrementor interrupt line is asserted or not.

The old BookS variant treats DEC as an edge interrupt that gets triggered when
the DEC value's top bit turns 1 from 0.

The new BookS variant maintains the assertion bit inside DEC itself. Whenever
the DEC value becomes negative (top bit set) the DEC interrupt line is asserted.

So far we implemented mostly the old BookS variant. Let's do them all properly.

This fixes booting pseries ppc64 guest images in TCG mode for me.

Signed-off-by: Alexander Graf <agraf@suse.de>
2014-04-08 11:20:04 +02:00
Tom Musta
6cd7db3d92 target-ppc: Correct VSX Integer to FP Conversion
This patch corrects the VSX integer to floating point conversion instructions
by using the endian correct accessors.  The auxiliary "j" index used by the
existing macros is now obsolete and is removed.  The JOFFSET preprocessor
macro is also obsolete and removed.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Tested-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-04-08 11:20:04 +02:00
Tom Musta
d1dec5ef55 target-ppc: Correct VSX FP to Integer Conversion
This patch corrects the VSX floating point to integer conversion
instructions by using the endian correct accessors.  The auxiliary
"j" index used by the existing macros is now obsolete and is removed.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Tested-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-04-08 11:20:03 +02:00
Tom Musta
6bbad7a91e target-ppc: Correct VSX FP to FP Conversions
This change corrects the VSX double precision to single precision and
single precision to double precisions conversion routines.  The endian
correct accessors are now used.  The auxiliary "j" index is no longer
necessary and is eliminated.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Tested-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-04-08 11:20:03 +02:00
Tom Musta
50fc89e7b1 target-ppc: Correct VSX Scalar Compares
This change fixes the VSX scalar compare instructions.  The existing usage of "x.f64[0]"
is changed to "x.VsrD(0)".

Signed-off-by: Tom Musta <tommusta@gmail.com>
Tested-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-04-08 11:20:03 +02:00
Tom Musta
bcb7652e8d target-ppc: Correct Simple VSR LE Host Inversions
A common pattern in the VSX helper code macros is the use of "x.fld[i]" where
"x" is a VSR and "fld" is an argument to a macro ("f64" or "f32" is passed).
This is not always correct on LE hosts.

This change addresses all instances of this pattern to be "x.fld" where "fld" is:

  - "VsrD(0)" for scalar instructions accessing 64-bit numbers
  - "VsrD(i)" for vector instructions accessing 64-bit numbers
  - "VsrW(i)" for vector instructions accessing 32-bit numbers

Note that there are no instances of this pattern where a scalar instruction
accesses a 32-bit number.

Note also that it would be correct to use "VsrD(i)" for scalar instructions since
the loop index is only ever "0".  I have choosen to use "VsrD(0)" instead ... it
seems a little clearer.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Tested-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-04-08 11:20:02 +02:00
Tom Musta
d359db00e6 target-ppc: Correct LE Host Inversion of Lower VSRs
This change properly orders the doublewords of the VSRs 0-31.  Because these
registers are constructed from separate doublewords, they must be inverted
on Little Endian hosts.  The inversion is performed both when the VSR is read
and when it is written.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Tested-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-04-08 11:20:02 +02:00
Tom Musta
80189035de target-ppc: Define Endian-Correct Accessors for VSR Field Access
This change defines accessors for VSR doubleword and word fields that
are correct from a host Endian perspective.  This allows code to
use the Power ISA indexing numbers in code.

For example, the xscvdpsxws instruction has a target VSR that looks
like this:

  0           32       64                    127
  +-----------+--------+-----------+-----------+
  | undefined | SW     | undefined | undefined |
  +-----------+--------+-----------+-----------+

VSX helper code will use VsrW(1) to access this field.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Tested-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-04-08 11:20:01 +02:00
Tom Musta
0453099b7d target-ppc: Bug: VSX Convert to Integer Should Truncate
The various VSX Convert to Integer instructions should truncate the
floating point number to an integer value, which is equivalent to
a round-to-zero rounding mode.  The existing VSX floating point to
integer conversion helpers are erroneously using the rounding mode set
int the PowerPC Floating Point Status and Control Register (FPSCR).
This change corrects this defect by using the appropriate
float*_to_*_round_to_zero() routines fro the softfloat library.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Tested-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-04-08 11:20:01 +02:00
Tom Musta
a13d448968 softfloat: Introduce float32_to_uint64_round_to_zero
This change adds the float32_to_uint64_round_to_zero function to the softfloat
library.  This function fills out the complement of float32 to INT round-to-zero
conversion rountines, where INT is {int32_t, uint32_t, int64_t, uint64_t}.

This contribution can be licensed under either the softfloat-2a or -2b
license.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Tested-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-04-08 11:20:00 +02:00
Alexey Kardashevskiy
3636226ae4 pseries: Update SLOF firmware image to qemu-slof-20140404
The change log is:
  > Isolate sc 1 detection logic
  > build: auto-detect ppc64 architecture
  > cas: increase hcall buffer size to accomodate 256 cpus
  > usb: change device tree naming
  > usb-core: adjust port numbers in set_address
  > virtio-scsi: correct srplun comment
  > Fix kernel loading
  > Workaround to make grub2 assign server ip from dhcp ack packet only
  > ELF: Enter LE binary in LE mode
  > ELF loading should fail for virt != phys

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Alexander Graf <agraf@suse.de>
2014-04-08 11:20:00 +02:00
Alexander Graf
6a450df9b8 PPC: E500: Set PIR default reset value rather than SPR value
We now reset SPRs to their reset values on CPU reset. So if we want
to have an SPR persistently changed, we need to change its default
reset value rather than the value itself manually.

Do this for SPR_BOOKE_PIR, fixing e500v2 SMP boot.

Reported-by: Frederic Konrad <fred.konrad@greensocs.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Tested-by: KONRAD Frederic <fred.konrad@greensocs.com>
2014-04-08 11:19:59 +02:00
Tomoki Sekiyama
9854202b57 vss-win32: Fix build with mingw64-headers-3.1.0
In mingw64-headers-3.1.0, definition of _com_issue_error() is added, which
conflicts with definition in install.cpp. This adds version checking for
mingw headers to disable the definition when the headers>=3.1 is used.

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-04-07 14:39:19 -05:00
Tomoki Sekiyama
577a67234d Makefile: add qga-vss-dll-obj-y to nested variables
The build rule for qga/vss-win32/qga-vss.dll is broken by commit
ba1183da9a, because it misses
qga-vss-dll-obj-y in the list of nested variables.
This fixes build of qga-vss.dll by adding qga-vss-dll-obj-y to the list.

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-04-07 14:39:19 -05:00
Peter Maydell
55519a4b24 Merge remote-tracking branch 'remotes/afaerber/tags/qom-devices-for-2.0' into staging
QOM/QTest infrastructure fixes

* Relicensing of FWPathProvider interface
* Clean up all targets' qtests

# gpg: Signature made Mon 07 Apr 2014 17:56:13 BST using RSA key ID 3E7E013F
# gpg: Good signature from "Andreas Färber <afaerber@suse.de>"
# gpg:                 aka "Andreas Färber <afaerber@suse.com>"

* remotes/afaerber/tags/qom-devices-for-2.0:
  tests: Update check-clean rule
  fw-path-provider: Change GPL version to 2+

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-07 17:57:23 +01:00
Andreas Färber
f85e3457ce tests: Update check-clean rule
Only i386, x86_64, sparc and sparc64 qtests were cleaned up.
Make this more generic to not miss any newly tested targets.

Reported-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-04-07 18:33:22 +02:00
Michael Tokarev
9c269f6d7b Makefile: remove bashism
When installing modules (when --enable-modules is specified for
./configure), Makefile uses the following construct to replace all
slashes with dashes in module name:

 ${s//\//-}

This is a bash-specific substitution mechanism.  POSIX does not
have it, and some operating systems (for example Debian) does not
implement this construct in default shell (for example dash).

Use more traditional way to perform the substitution: use `tr' tool.

Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Message-id: 1396707946-21351-1-git-send-email-mjt@msgid.tls.msk.ru
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-07 15:19:16 +01:00
Don Slutz
dffacd4654 char/serial: Fix emptyness handling
The commit 88c1ee73d3
char/serial: Fix emptyness check

Still causes extra NULL byte(s) to be sent.

So if the fifo is empty, do not send an extra NULL byte.

Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Don Slutz <dslutz@verizon.com>
Message-id: 1395160174-16006-1-git-send-email-dslutz@verizon.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-07 14:51:32 +01:00
Alexey Kardashevskiy
20c50a955f fw-path-provider: Change GPL version to 2+
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-04-07 15:36:07 +02:00
Peter Maydell
bd7ce902ab Merge remote-tracking branch 'remotes/spice/tags/pull-spice-6' into staging
spice: monitors_config: check pointer before dereferencing

# gpg: Signature made Mon 07 Apr 2014 11:19:19 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/spice/tags/pull-spice-6:
  spice: monitors_config: check pointer before dereferencing

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-07 12:48:34 +01:00
Peter Maydell
e20c016e32 Merge remote-tracking branch 'remotes/kraxel/tags/pull-gtk-4' into staging
gtk: pointer fixes from Takashi Iwai.

# gpg: Signature made Mon 07 Apr 2014 09:51:52 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/kraxel/tags/pull-gtk-4:
  ui: Update MAINTAINERS entry.
  gtk: Remember the last grabbed pointer position
  gtk: Fix the relative pointer tracking mode
  gtk: Use gtk generic event signal instead of motion-notify-event

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-07 12:27:10 +01:00
Gerd Hoffmann
dc491cfc14 spice: monitors_config: check pointer before dereferencing
Reported-by: Fabio Fantoni <fabio.fantoni@m2r.biz>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-04-07 12:18:43 +02:00
79 changed files with 4698 additions and 1722 deletions

View File

@@ -133,6 +133,7 @@ dummy := $(call unnest-vars,, \
stub-obj-y \
util-obj-y \
qga-obj-y \
qga-vss-dll-obj-y \
block-obj-y \
block-obj-m \
common-obj-y \
@@ -376,7 +377,7 @@ endif
ifneq ($(CONFIG_MODULES),)
$(INSTALL_DIR) "$(DESTDIR)$(qemu_moddir)"
for s in $(patsubst %.mo,%$(DSOSUF),$(modules-m)); do \
$(INSTALL_PROG) $(STRIP_OPT) $$s "$(DESTDIR)$(qemu_moddir)/$${s//\//-}"; \
$(INSTALL_PROG) $(STRIP_OPT) $$s "$(DESTDIR)$(qemu_moddir)/$$(echo $$s | tr / -)"; \
done
endif
ifneq ($(HELPERS-y),)

View File

@@ -1 +1 @@
1.7.91
2.0.50

View File

@@ -148,16 +148,26 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
s->extent_blocks = 1 + (le32_to_cpu(bochs.extent) - 1) / 512;
s->extent_size = le32_to_cpu(bochs.extent);
if (s->extent_size == 0) {
error_setg(errp, "Extent size may not be zero");
return -EINVAL;
if (s->extent_size < BDRV_SECTOR_SIZE) {
/* bximage actually never creates extents smaller than 4k */
error_setg(errp, "Extent size must be at least 512");
ret = -EINVAL;
goto fail;
} else if (!is_power_of_2(s->extent_size)) {
error_setg(errp, "Extent size %" PRIu32 " is not a power of two",
s->extent_size);
ret = -EINVAL;
goto fail;
} else if (s->extent_size > 0x800000) {
error_setg(errp, "Extent size %" PRIu32 " is too large",
s->extent_size);
return -EINVAL;
ret = -EINVAL;
goto fail;
}
if (s->catalog_size < bs->total_sectors / s->extent_size) {
if (s->catalog_size < DIV_ROUND_UP(bs->total_sectors,
s->extent_size / BDRV_SECTOR_SIZE))
{
error_setg(errp, "Catalog size is too small for this disk size");
ret = -EINVAL;
goto fail;

View File

@@ -1233,6 +1233,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
iscsi_readcapacity_sync(iscsilun, &local_err);
if (local_err != NULL) {
error_propagate(errp, local_err);
ret = -EINVAL;
goto out;
}
bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun);

View File

@@ -1876,6 +1876,10 @@ void qmp_block_commit(const char *device,
*/
BlockdevOnError on_error = BLOCKDEV_ON_ERROR_REPORT;
if (!has_speed) {
speed = 0;
}
/* drain all i/o before commits */
bdrv_drain_all();

5
configure vendored
View File

@@ -1448,7 +1448,10 @@ done
if test "$stack_protector" != "no" ; then
gcc_flags="-fstack-protector-strong -fstack-protector-all"
for flag in $gcc_flags; do
if compile_prog "-Werror $flag" "" ; then
# We need to check both a compile and a link, since some compiler
# setups fail only on a .c->.o compile and some only at link time
if do_cc $QEMU_CFLAGS -Werror $flag -c -o $TMPO $TMPC &&
compile_prog "-Werror $flag" ""; then
QEMU_CFLAGS="$QEMU_CFLAGS $flag"
LIBTOOLFLAGS="$LIBTOOLFLAGS -Wc,$flag"
break

View File

@@ -1,6 +1,7 @@
CONFIG_USB_TABLET_WACOM=y
CONFIG_USB_STORAGE_BOT=y
CONFIG_USB_STORAGE_UAS=y
CONFIG_USB_STORAGE_MTP=y
CONFIG_USB_SMARTCARD=y
CONFIG_USB_AUDIO=y
CONFIG_USB_SERIAL=y

View File

@@ -1626,6 +1626,26 @@ uint64 float32_to_uint64(float32 a STATUS_PARAM)
return roundAndPackUint64(aSign, aSig64, aSigExtra STATUS_VAR);
}
/*----------------------------------------------------------------------------
| Returns the result of converting the single-precision floating-point value
| `a' to the 64-bit unsigned integer format. The conversion is
| performed according to the IEC/IEEE Standard for Binary Floating-Point
| Arithmetic, except that the conversion is always rounded toward zero. If
| `a' is a NaN, the largest unsigned integer is returned. Otherwise, if the
| conversion overflows, the largest unsigned integer is returned. If the
| 'a' is negative, the result is rounded and zero is returned; values that do
| not round to zero will raise the inexact flag.
*----------------------------------------------------------------------------*/
uint64 float32_to_uint64_round_to_zero(float32 a STATUS_PARAM)
{
signed char current_rounding_mode = STATUS(float_rounding_mode);
set_float_rounding_mode(float_round_to_zero STATUS_VAR);
int64_t v = float32_to_uint64(a STATUS_VAR);
set_float_rounding_mode(current_rounding_mode STATUS_VAR);
return v;
}
/*----------------------------------------------------------------------------
| Returns the result of converting the single-precision floating-point value
| `a' to the 64-bit two's complement integer format. The conversion is

View File

@@ -43,6 +43,19 @@ static void cubieboard_init(QEMUMachineInitArgs *args)
exit(1);
}
object_property_set_int(OBJECT(&s->a10->timer), 32768, "clk0-freq", &err);
if (err != NULL) {
error_report("Couldn't set clk0 frequency: %s", error_get_pretty(err));
exit(1);
}
object_property_set_int(OBJECT(&s->a10->timer), 24000000, "clk1-freq",
&err);
if (err != NULL) {
error_report("Couldn't set clk1 frequency: %s", error_get_pretty(err));
exit(1);
}
object_property_set_bool(OBJECT(s->a10), true, "realized", &err);
if (err != NULL) {
error_report("Couldn't realize Allwinner A10: %s",

View File

@@ -225,8 +225,10 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
if (s->tsr_retry <= 0) {
if (s->fcr & UART_FCR_FE) {
s->tsr = fifo8_is_empty(&s->xmit_fifo) ?
0 : fifo8_pop(&s->xmit_fifo);
if (fifo8_is_empty(&s->xmit_fifo)) {
return FALSE;
}
s->tsr = fifo8_pop(&s->xmit_fifo);
if (!s->xmit_fifo.num) {
s->lsr |= UART_LSR_THRE;
}

View File

@@ -3,7 +3,8 @@
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; under version 2 of the License.
* the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of

View File

@@ -391,7 +391,7 @@ static void build_append_int(GArray *table, uint32_t value)
build_append_byte(table, 0x01); /* OneOp */
} else if (value <= 0xFF) {
build_append_value(table, value, 1);
} else if (value <= 0xFFFFF) {
} else if (value <= 0xFFFF) {
build_append_value(table, value, 2);
} else {
build_append_value(table, value, 4);

View File

@@ -93,7 +93,7 @@ Scope(\_SB) {
}
Device(CPU_HOTPLUG_RESOURCE_DEVICE) {
Name(_HID, "ACPI0004")
Name(_HID, EisaId("PNP0A06"))
Name(_CRS, ResourceTemplate() {
IO(Decode16, CPU_STATUS_BASE, CPU_STATUS_BASE, 0, CPU_STATUS_LEN)

View File

@@ -3,12 +3,12 @@ static unsigned char AcpiDsdtAmlCode[] = {
0x53,
0x44,
0x54,
0x85,
0x80,
0x11,
0x0,
0x0,
0x1,
0x8b,
0x60,
0x42,
0x58,
0x50,
@@ -31,8 +31,8 @@ static unsigned char AcpiDsdtAmlCode[] = {
0x4e,
0x54,
0x4c,
0x23,
0x8,
0x15,
0x11,
0x13,
0x20,
0x10,
@@ -4010,7 +4010,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
0x53,
0x1,
0x10,
0x47,
0x42,
0x11,
0x5f,
0x53,
@@ -4243,7 +4243,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
0x60,
0x5b,
0x82,
0x2e,
0x29,
0x50,
0x52,
0x45,
@@ -4253,16 +4253,11 @@ static unsigned char AcpiDsdtAmlCode[] = {
0x48,
0x49,
0x44,
0xd,
0xc,
0x41,
0x43,
0x50,
0x49,
0x30,
0x30,
0x30,
0x34,
0x0,
0xd0,
0xa,
0x6,
0x8,
0x5f,
0x43,

View File

@@ -3,12 +3,12 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
0x53,
0x44,
0x54,
0xd7,
0xd2,
0x1c,
0x0,
0x0,
0x1,
0x3e,
0x13,
0x42,
0x58,
0x50,
@@ -31,8 +31,8 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
0x4e,
0x54,
0x4c,
0x23,
0x8,
0x15,
0x11,
0x13,
0x20,
0x10,
@@ -6959,7 +6959,7 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
0x53,
0x1,
0x10,
0x47,
0x42,
0x11,
0x5f,
0x53,
@@ -7192,7 +7192,7 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
0x60,
0x5b,
0x82,
0x2e,
0x29,
0x50,
0x52,
0x45,
@@ -7202,16 +7202,11 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
0x48,
0x49,
0x44,
0xd,
0xc,
0x41,
0x43,
0x50,
0x49,
0x30,
0x30,
0x30,
0x34,
0x0,
0xd0,
0xa,
0x6,
0x8,
0x5f,
0x43,

View File

@@ -1602,7 +1602,7 @@ static bool cmd_smart(IDEState *s, uint8_t cmd)
case 2: /* extended self test */
s->smart_selftest_count++;
if (s->smart_selftest_count > 21) {
s->smart_selftest_count = 0;
s->smart_selftest_count = 1;
}
n = 2 + (s->smart_selftest_count - 1) * 24;
s->smart_selftest_data[n] = s->sector;

View File

@@ -23,11 +23,20 @@
static void aw_a10_pic_update(AwA10PICState *s)
{
uint8_t i;
int irq = 0, fiq = 0;
int irq = 0, fiq = 0, pending;
s->vector = 0;
for (i = 0; i < AW_A10_PIC_REG_NUM; i++) {
irq |= s->irq_pending[i] & ~s->mask[i];
fiq |= s->select[i] & s->irq_pending[i] & ~s->mask[i];
if (!s->vector) {
pending = ffs(s->irq_pending[i] & ~s->mask[i]);
if (pending) {
s->vector = (i * 32 + pending - 1) * 4;
}
}
}
qemu_set_irq(s->parent_irq, !!irq);
@@ -40,6 +49,8 @@ static void aw_a10_pic_set_irq(void *opaque, int irq, int level)
if (level) {
set_bit(irq % 32, (void *)&s->irq_pending[irq / 32]);
} else {
clear_bit(irq % 32, (void *)&s->irq_pending[irq / 32]);
}
aw_a10_pic_update(s);
}
@@ -84,9 +95,6 @@ static void aw_a10_pic_write(void *opaque, hwaddr offset, uint64_t value,
uint8_t index = (offset & 0xc) / 4;
switch (offset) {
case AW_A10_PIC_VECTOR:
s->vector = value & ~0x3;
break;
case AW_A10_PIC_BASE_ADDR:
s->base_addr = value & ~0x3;
case AW_A10_PIC_PROTECT:
@@ -96,7 +104,11 @@ static void aw_a10_pic_write(void *opaque, hwaddr offset, uint64_t value,
s->nmi = value;
break;
case AW_A10_PIC_IRQ_PENDING ... AW_A10_PIC_IRQ_PENDING + 8:
s->irq_pending[index] &= ~value;
/*
* The register is read-only; nevertheless, Linux (including
* the version originally shipped by Allwinner) pretends to
* write to the register. Just ignore it.
*/
break;
case AW_A10_PIC_FIQ_PENDING ... AW_A10_PIC_FIQ_PENDING + 8:
s->fiq_pending[index] &= ~value;

View File

@@ -19,102 +19,155 @@
#include "hw/sysbus.h"
#include "sysemu/sysemu.h"
#ifdef ZYNQ_ARM_SLCR_ERR_DEBUG
#define DB_PRINT(...) do { \
fprintf(stderr, ": %s: ", __func__); \
fprintf(stderr, ## __VA_ARGS__); \
} while (0);
#else
#define DB_PRINT(...)
#ifndef ZYNQ_SLCR_ERR_DEBUG
#define ZYNQ_SLCR_ERR_DEBUG 0
#endif
#define DB_PRINT(...) do { \
if (ZYNQ_SLCR_ERR_DEBUG) { \
fprintf(stderr, ": %s: ", __func__); \
fprintf(stderr, ## __VA_ARGS__); \
} \
} while (0);
#define XILINX_LOCK_KEY 0x767b
#define XILINX_UNLOCK_KEY 0xdf0d
#define R_PSS_RST_CTRL_SOFT_RST 0x1
typedef enum {
ARM_PLL_CTRL,
DDR_PLL_CTRL,
IO_PLL_CTRL,
PLL_STATUS,
ARM_PPL_CFG,
DDR_PLL_CFG,
IO_PLL_CFG,
PLL_BG_CTRL,
PLL_MAX
} PLLValues;
enum {
SCL = 0x000 / 4,
LOCK,
UNLOCK,
LOCKSTA,
typedef enum {
ARM_CLK_CTRL,
DDR_CLK_CTRL,
DCI_CLK_CTRL,
APER_CLK_CTRL,
USB0_CLK_CTRL,
USB1_CLK_CTRL,
GEM0_RCLK_CTRL,
GEM1_RCLK_CTRL,
GEM0_CLK_CTRL,
GEM1_CLK_CTRL,
SMC_CLK_CTRL,
LQSPI_CLK_CTRL,
SDIO_CLK_CTRL,
UART_CLK_CTRL,
SPI_CLK_CTRL,
CAN_CLK_CTRL,
CAN_MIOCLK_CTRL,
DBG_CLK_CTRL,
PCAP_CLK_CTRL,
TOPSW_CLK_CTRL,
CLK_MAX
} ClkValues;
ARM_PLL_CTRL = 0x100 / 4,
DDR_PLL_CTRL,
IO_PLL_CTRL,
PLL_STATUS,
ARM_PLL_CFG,
DDR_PLL_CFG,
IO_PLL_CFG,
typedef enum {
CLK_CTRL,
THR_CTRL,
THR_CNT,
THR_STA,
FPGA_MAX
} FPGAValues;
ARM_CLK_CTRL = 0x120 / 4,
DDR_CLK_CTRL,
DCI_CLK_CTRL,
APER_CLK_CTRL,
USB0_CLK_CTRL,
USB1_CLK_CTRL,
GEM0_RCLK_CTRL,
GEM1_RCLK_CTRL,
GEM0_CLK_CTRL,
GEM1_CLK_CTRL,
SMC_CLK_CTRL,
LQSPI_CLK_CTRL,
SDIO_CLK_CTRL,
UART_CLK_CTRL,
SPI_CLK_CTRL,
CAN_CLK_CTRL,
CAN_MIOCLK_CTRL,
DBG_CLK_CTRL,
PCAP_CLK_CTRL,
TOPSW_CLK_CTRL,
typedef enum {
SYNC_CTRL,
SYNC_STATUS,
BANDGAP_TRIP,
CC_TEST,
PLL_PREDIVISOR,
CLK_621_TRUE,
PICTURE_DBG,
PICTURE_DBG_UCNT,
PICTURE_DBG_LCNT,
MISC_MAX
} MiscValues;
#define FPGA_CTRL_REGS(n, start) \
FPGA ## n ## _CLK_CTRL = (start) / 4, \
FPGA ## n ## _THR_CTRL, \
FPGA ## n ## _THR_CNT, \
FPGA ## n ## _THR_STA,
FPGA_CTRL_REGS(0, 0x170)
FPGA_CTRL_REGS(1, 0x180)
FPGA_CTRL_REGS(2, 0x190)
FPGA_CTRL_REGS(3, 0x1a0)
typedef enum {
PSS,
DDDR,
DMAC = 3,
USB,
GEM,
SDIO,
SPI,
CAN,
I2C,
UART,
GPIO,
LQSPI,
SMC,
OCM,
DEVCI,
FPGA,
A9_CPU,
RS_AWDT,
RST_REASON,
RST_REASON_CLR,
REBOOT_STATUS,
BOOT_MODE,
RESET_MAX
} ResetValues;
BANDGAP_TRIP = 0x1b8 / 4,
PLL_PREDIVISOR = 0x1c0 / 4,
CLK_621_TRUE,
PSS_RST_CTRL = 0x200 / 4,
DDR_RST_CTRL,
TOPSW_RESET_CTRL,
DMAC_RST_CTRL,
USB_RST_CTRL,
GEM_RST_CTRL,
SDIO_RST_CTRL,
SPI_RST_CTRL,
CAN_RST_CTRL,
I2C_RST_CTRL,
UART_RST_CTRL,
GPIO_RST_CTRL,
LQSPI_RST_CTRL,
SMC_RST_CTRL,
OCM_RST_CTRL,
FPGA_RST_CTRL = 0x240 / 4,
A9_CPU_RST_CTRL,
RS_AWDT_CTRL = 0x24c / 4,
RST_REASON,
REBOOT_STATUS = 0x258 / 4,
BOOT_MODE,
APU_CTRL = 0x300 / 4,
WDT_CLK_SEL,
TZ_DMA_NS = 0x440 / 4,
TZ_DMA_IRQ_NS,
TZ_DMA_PERIPH_NS,
PSS_IDCODE = 0x530 / 4,
DDR_URGENT = 0x600 / 4,
DDR_CAL_START = 0x60c / 4,
DDR_REF_START = 0x614 / 4,
DDR_CMD_STA,
DDR_URGENT_SEL,
DDR_DFI_STATUS,
MIO = 0x700 / 4,
#define MIO_LENGTH 54
MIO_LOOPBACK = 0x804 / 4,
MIO_MST_TRI0,
MIO_MST_TRI1,
SD0_WP_CD_SEL = 0x830 / 4,
SD1_WP_CD_SEL,
LVL_SHFTR_EN = 0x900 / 4,
OCM_CFG = 0x910 / 4,
CPU_RAM = 0xa00 / 4,
IOU = 0xa30 / 4,
DMAC_RAM = 0xa50 / 4,
AFI0 = 0xa60 / 4,
AFI1 = AFI0 + 3,
AFI2 = AFI1 + 3,
AFI3 = AFI2 + 3,
#define AFI_LENGTH 3
OCM = 0xa90 / 4,
DEVCI_RAM = 0xaa0 / 4,
CSG_RAM = 0xab0 / 4,
GPIOB_CTRL = 0xb00 / 4,
GPIOB_CFG_CMOS18,
GPIOB_CFG_CMOS25,
GPIOB_CFG_CMOS33,
GPIOB_CFG_HSTL = 0xb14 / 4,
GPIOB_DRVR_BIAS_CTRL,
DDRIOB = 0xb40 / 4,
#define DDRIOB_LENGTH 14
};
#define ZYNQ_SLCR_MMIO_SIZE 0x1000
#define ZYNQ_SLCR_NUM_REGS (ZYNQ_SLCR_MMIO_SIZE / 4)
#define TYPE_ZYNQ_SLCR "xilinx,zynq_slcr"
#define ZYNQ_SLCR(obj) OBJECT_CHECK(ZynqSLCRState, (obj), TYPE_ZYNQ_SLCR)
@@ -124,42 +177,7 @@ typedef struct ZynqSLCRState {
MemoryRegion iomem;
union {
struct {
uint16_t scl;
uint16_t lockval;
uint32_t pll[PLL_MAX]; /* 0x100 - 0x11C */
uint32_t clk[CLK_MAX]; /* 0x120 - 0x16C */
uint32_t fpga[4][FPGA_MAX]; /* 0x170 - 0x1AC */
uint32_t misc[MISC_MAX]; /* 0x1B0 - 0x1D8 */
uint32_t reset[RESET_MAX]; /* 0x200 - 0x25C */
uint32_t apu_ctrl; /* 0x300 */
uint32_t wdt_clk_sel; /* 0x304 */
uint32_t tz_ocm[3]; /* 0x400 - 0x408 */
uint32_t tz_ddr; /* 0x430 */
uint32_t tz_dma[3]; /* 0x440 - 0x448 */
uint32_t tz_misc[3]; /* 0x450 - 0x458 */
uint32_t tz_fpga[2]; /* 0x484 - 0x488 */
uint32_t dbg_ctrl; /* 0x500 */
uint32_t pss_idcode; /* 0x530 */
uint32_t ddr[8]; /* 0x600 - 0x620 - 0x604-missing */
uint32_t mio[54]; /* 0x700 - 0x7D4 */
uint32_t mio_func[4]; /* 0x800 - 0x810 */
uint32_t sd[2]; /* 0x830 - 0x834 */
uint32_t lvl_shftr_en; /* 0x900 */
uint32_t ocm_cfg; /* 0x910 */
uint32_t cpu_ram[8]; /* 0xA00 - 0xA1C */
uint32_t iou[7]; /* 0xA30 - 0xA48 */
uint32_t dmac_ram; /* 0xA50 */
uint32_t afi[4][3]; /* 0xA60 - 0xA8C */
uint32_t ocm[3]; /* 0xA90 - 0xA98 */
uint32_t devci_ram; /* 0xAA0 */
uint32_t csg_ram; /* 0xAB0 */
uint32_t gpiob[12]; /* 0xB00 - 0xB2C */
uint32_t ddriob[14]; /* 0xB40 - 0xB74 */
};
uint8_t data[0x1000];
};
uint32_t regs[ZYNQ_SLCR_NUM_REGS];
} ZynqSLCRState;
static void zynq_slcr_reset(DeviceState *d)
@@ -169,177 +187,169 @@ static void zynq_slcr_reset(DeviceState *d)
DB_PRINT("RESET\n");
s->lockval = 1;
s->regs[LOCKSTA] = 1;
/* 0x100 - 0x11C */
s->pll[ARM_PLL_CTRL] = 0x0001A008;
s->pll[DDR_PLL_CTRL] = 0x0001A008;
s->pll[IO_PLL_CTRL] = 0x0001A008;
s->pll[PLL_STATUS] = 0x0000003F;
s->pll[ARM_PPL_CFG] = 0x00014000;
s->pll[DDR_PLL_CFG] = 0x00014000;
s->pll[IO_PLL_CFG] = 0x00014000;
s->regs[ARM_PLL_CTRL] = 0x0001A008;
s->regs[DDR_PLL_CTRL] = 0x0001A008;
s->regs[IO_PLL_CTRL] = 0x0001A008;
s->regs[PLL_STATUS] = 0x0000003F;
s->regs[ARM_PLL_CFG] = 0x00014000;
s->regs[DDR_PLL_CFG] = 0x00014000;
s->regs[IO_PLL_CFG] = 0x00014000;
/* 0x120 - 0x16C */
s->clk[ARM_CLK_CTRL] = 0x1F000400;
s->clk[DDR_CLK_CTRL] = 0x18400003;
s->clk[DCI_CLK_CTRL] = 0x01E03201;
s->clk[APER_CLK_CTRL] = 0x01FFCCCD;
s->clk[USB0_CLK_CTRL] = s->clk[USB1_CLK_CTRL] = 0x00101941;
s->clk[GEM0_RCLK_CTRL] = s->clk[GEM1_RCLK_CTRL] = 0x00000001;
s->clk[GEM0_CLK_CTRL] = s->clk[GEM1_CLK_CTRL] = 0x00003C01;
s->clk[SMC_CLK_CTRL] = 0x00003C01;
s->clk[LQSPI_CLK_CTRL] = 0x00002821;
s->clk[SDIO_CLK_CTRL] = 0x00001E03;
s->clk[UART_CLK_CTRL] = 0x00003F03;
s->clk[SPI_CLK_CTRL] = 0x00003F03;
s->clk[CAN_CLK_CTRL] = 0x00501903;
s->clk[DBG_CLK_CTRL] = 0x00000F03;
s->clk[PCAP_CLK_CTRL] = 0x00000F01;
s->regs[ARM_CLK_CTRL] = 0x1F000400;
s->regs[DDR_CLK_CTRL] = 0x18400003;
s->regs[DCI_CLK_CTRL] = 0x01E03201;
s->regs[APER_CLK_CTRL] = 0x01FFCCCD;
s->regs[USB0_CLK_CTRL] = s->regs[USB1_CLK_CTRL] = 0x00101941;
s->regs[GEM0_RCLK_CTRL] = s->regs[GEM1_RCLK_CTRL] = 0x00000001;
s->regs[GEM0_CLK_CTRL] = s->regs[GEM1_CLK_CTRL] = 0x00003C01;
s->regs[SMC_CLK_CTRL] = 0x00003C01;
s->regs[LQSPI_CLK_CTRL] = 0x00002821;
s->regs[SDIO_CLK_CTRL] = 0x00001E03;
s->regs[UART_CLK_CTRL] = 0x00003F03;
s->regs[SPI_CLK_CTRL] = 0x00003F03;
s->regs[CAN_CLK_CTRL] = 0x00501903;
s->regs[DBG_CLK_CTRL] = 0x00000F03;
s->regs[PCAP_CLK_CTRL] = 0x00000F01;
/* 0x170 - 0x1AC */
s->fpga[0][CLK_CTRL] = s->fpga[1][CLK_CTRL] = s->fpga[2][CLK_CTRL] =
s->fpga[3][CLK_CTRL] = 0x00101800;
s->fpga[0][THR_STA] = s->fpga[1][THR_STA] = s->fpga[2][THR_STA] =
s->fpga[3][THR_STA] = 0x00010000;
s->regs[FPGA0_CLK_CTRL] = s->regs[FPGA1_CLK_CTRL] = s->regs[FPGA2_CLK_CTRL]
= s->regs[FPGA3_CLK_CTRL] = 0x00101800;
s->regs[FPGA0_THR_STA] = s->regs[FPGA1_THR_STA] = s->regs[FPGA2_THR_STA]
= s->regs[FPGA3_THR_STA] = 0x00010000;
/* 0x1B0 - 0x1D8 */
s->misc[BANDGAP_TRIP] = 0x0000001F;
s->misc[PLL_PREDIVISOR] = 0x00000001;
s->misc[CLK_621_TRUE] = 0x00000001;
s->regs[BANDGAP_TRIP] = 0x0000001F;
s->regs[PLL_PREDIVISOR] = 0x00000001;
s->regs[CLK_621_TRUE] = 0x00000001;
/* 0x200 - 0x25C */
s->reset[FPGA] = 0x01F33F0F;
s->reset[RST_REASON] = 0x00000040;
s->regs[FPGA_RST_CTRL] = 0x01F33F0F;
s->regs[RST_REASON] = 0x00000040;
s->regs[BOOT_MODE] = 0x00000001;
/* 0x700 - 0x7D4 */
for (i = 0; i < 54; i++) {
s->mio[i] = 0x00001601;
s->regs[MIO + i] = 0x00001601;
}
for (i = 2; i <= 8; i++) {
s->mio[i] = 0x00000601;
s->regs[MIO + i] = 0x00000601;
}
/* MIO_MST_TRI0, MIO_MST_TRI1 */
s->mio_func[2] = s->mio_func[3] = 0xFFFFFFFF;
s->regs[MIO_MST_TRI0] = s->regs[MIO_MST_TRI1] = 0xFFFFFFFF;
s->cpu_ram[0] = s->cpu_ram[1] = s->cpu_ram[3] =
s->cpu_ram[4] = s->cpu_ram[7] = 0x00010101;
s->cpu_ram[2] = s->cpu_ram[5] = 0x01010101;
s->cpu_ram[6] = 0x00000001;
s->regs[CPU_RAM + 0] = s->regs[CPU_RAM + 1] = s->regs[CPU_RAM + 3]
= s->regs[CPU_RAM + 4] = s->regs[CPU_RAM + 7]
= 0x00010101;
s->regs[CPU_RAM + 2] = s->regs[CPU_RAM + 5] = 0x01010101;
s->regs[CPU_RAM + 6] = 0x00000001;
s->iou[0] = s->iou[1] = s->iou[2] = s->iou[3] = 0x09090909;
s->iou[4] = s->iou[5] = 0x00090909;
s->iou[6] = 0x00000909;
s->regs[IOU + 0] = s->regs[IOU + 1] = s->regs[IOU + 2] = s->regs[IOU + 3]
= 0x09090909;
s->regs[IOU + 4] = s->regs[IOU + 5] = 0x00090909;
s->regs[IOU + 6] = 0x00000909;
s->dmac_ram = 0x00000009;
s->regs[DMAC_RAM] = 0x00000009;
s->afi[0][0] = s->afi[0][1] = 0x09090909;
s->afi[1][0] = s->afi[1][1] = 0x09090909;
s->afi[2][0] = s->afi[2][1] = 0x09090909;
s->afi[3][0] = s->afi[3][1] = 0x09090909;
s->afi[0][2] = s->afi[1][2] = s->afi[2][2] = s->afi[3][2] = 0x00000909;
s->regs[AFI0 + 0] = s->regs[AFI0 + 1] = 0x09090909;
s->regs[AFI1 + 0] = s->regs[AFI1 + 1] = 0x09090909;
s->regs[AFI2 + 0] = s->regs[AFI2 + 1] = 0x09090909;
s->regs[AFI3 + 0] = s->regs[AFI3 + 1] = 0x09090909;
s->regs[AFI0 + 2] = s->regs[AFI1 + 2] = s->regs[AFI2 + 2]
= s->regs[AFI3 + 2] = 0x00000909;
s->ocm[0] = 0x01010101;
s->ocm[1] = s->ocm[2] = 0x09090909;
s->regs[OCM + 0] = 0x01010101;
s->regs[OCM + 1] = s->regs[OCM + 2] = 0x09090909;
s->devci_ram = 0x00000909;
s->csg_ram = 0x00000001;
s->regs[DEVCI_RAM] = 0x00000909;
s->regs[CSG_RAM] = 0x00000001;
s->ddriob[0] = s->ddriob[1] = s->ddriob[2] = s->ddriob[3] = 0x00000e00;
s->ddriob[4] = s->ddriob[5] = s->ddriob[6] = 0x00000e00;
s->ddriob[12] = 0x00000021;
s->regs[DDRIOB + 0] = s->regs[DDRIOB + 1] = s->regs[DDRIOB + 2]
= s->regs[DDRIOB + 3] = 0x00000e00;
s->regs[DDRIOB + 4] = s->regs[DDRIOB + 5] = s->regs[DDRIOB + 6]
= 0x00000e00;
s->regs[DDRIOB + 12] = 0x00000021;
}
static inline uint32_t zynq_slcr_read_imp(void *opaque,
hwaddr offset)
{
ZynqSLCRState *s = (ZynqSLCRState *)opaque;
static bool zynq_slcr_check_offset(hwaddr offset, bool rnw)
{
switch (offset) {
case 0x0: /* SCL */
return s->scl;
case 0x4: /* LOCK */
case 0x8: /* UNLOCK */
DB_PRINT("Reading SCLR_LOCK/UNLOCK is not enabled\n");
return 0;
case 0x0C: /* LOCKSTA */
return s->lockval;
case 0x100 ... 0x11C:
return s->pll[(offset - 0x100) / 4];
case 0x120 ... 0x16C:
return s->clk[(offset - 0x120) / 4];
case 0x170 ... 0x1AC:
return s->fpga[0][(offset - 0x170) / 4];
case 0x1B0 ... 0x1D8:
return s->misc[(offset - 0x1B0) / 4];
case 0x200 ... 0x258:
return s->reset[(offset - 0x200) / 4];
case 0x25c:
return 1;
case 0x300:
return s->apu_ctrl;
case 0x304:
return s->wdt_clk_sel;
case 0x400 ... 0x408:
return s->tz_ocm[(offset - 0x400) / 4];
case 0x430:
return s->tz_ddr;
case 0x440 ... 0x448:
return s->tz_dma[(offset - 0x440) / 4];
case 0x450 ... 0x458:
return s->tz_misc[(offset - 0x450) / 4];
case 0x484 ... 0x488:
return s->tz_fpga[(offset - 0x484) / 4];
case 0x500:
return s->dbg_ctrl;
case 0x530:
return s->pss_idcode;
case 0x600 ... 0x620:
if (offset == 0x604) {
goto bad_reg;
}
return s->ddr[(offset - 0x600) / 4];
case 0x700 ... 0x7D4:
return s->mio[(offset - 0x700) / 4];
case 0x800 ... 0x810:
return s->mio_func[(offset - 0x800) / 4];
case 0x830 ... 0x834:
return s->sd[(offset - 0x830) / 4];
case 0x900:
return s->lvl_shftr_en;
case 0x910:
return s->ocm_cfg;
case 0xA00 ... 0xA1C:
return s->cpu_ram[(offset - 0xA00) / 4];
case 0xA30 ... 0xA48:
return s->iou[(offset - 0xA30) / 4];
case 0xA50:
return s->dmac_ram;
case 0xA60 ... 0xA8C:
return s->afi[0][(offset - 0xA60) / 4];
case 0xA90 ... 0xA98:
return s->ocm[(offset - 0xA90) / 4];
case 0xAA0:
return s->devci_ram;
case 0xAB0:
return s->csg_ram;
case 0xB00 ... 0xB2C:
return s->gpiob[(offset - 0xB00) / 4];
case 0xB40 ... 0xB74:
return s->ddriob[(offset - 0xB40) / 4];
case LOCK:
case UNLOCK:
case DDR_CAL_START:
case DDR_REF_START:
return !rnw; /* Write only */
case LOCKSTA:
case FPGA0_THR_STA:
case FPGA1_THR_STA:
case FPGA2_THR_STA:
case FPGA3_THR_STA:
case BOOT_MODE:
case PSS_IDCODE:
case DDR_CMD_STA:
case DDR_DFI_STATUS:
case PLL_STATUS:
return rnw;/* read only */
case SCL:
case ARM_PLL_CTRL ... IO_PLL_CTRL:
case ARM_PLL_CFG ... IO_PLL_CFG:
case ARM_CLK_CTRL ... TOPSW_CLK_CTRL:
case FPGA0_CLK_CTRL ... FPGA0_THR_CNT:
case FPGA1_CLK_CTRL ... FPGA1_THR_CNT:
case FPGA2_CLK_CTRL ... FPGA2_THR_CNT:
case FPGA3_CLK_CTRL ... FPGA3_THR_CNT:
case BANDGAP_TRIP:
case PLL_PREDIVISOR:
case CLK_621_TRUE:
case PSS_RST_CTRL ... A9_CPU_RST_CTRL:
case RS_AWDT_CTRL:
case RST_REASON:
case REBOOT_STATUS:
case APU_CTRL:
case WDT_CLK_SEL:
case TZ_DMA_NS ... TZ_DMA_PERIPH_NS:
case DDR_URGENT:
case DDR_URGENT_SEL:
case MIO ... MIO + MIO_LENGTH - 1:
case MIO_LOOPBACK ... MIO_MST_TRI1:
case SD0_WP_CD_SEL:
case SD1_WP_CD_SEL:
case LVL_SHFTR_EN:
case OCM_CFG:
case CPU_RAM:
case IOU:
case DMAC_RAM:
case AFI0 ... AFI3 + AFI_LENGTH - 1:
case OCM:
case DEVCI_RAM:
case CSG_RAM:
case GPIOB_CTRL ... GPIOB_CFG_CMOS33:
case GPIOB_CFG_HSTL:
case GPIOB_DRVR_BIAS_CTRL:
case DDRIOB ... DDRIOB + DDRIOB_LENGTH - 1:
return true;
default:
bad_reg:
DB_PRINT("Bad register offset 0x%x\n", (int)offset);
return 0;
return false;
}
}
static uint64_t zynq_slcr_read(void *opaque, hwaddr offset,
unsigned size)
{
uint32_t ret = zynq_slcr_read_imp(opaque, offset);
ZynqSLCRState *s = opaque;
offset /= 4;
uint32_t ret = s->regs[offset];
DB_PRINT("addr: %08x data: %08x\n", (unsigned)offset, (unsigned)ret);
if (!zynq_slcr_check_offset(offset, true)) {
qemu_log_mask(LOG_GUEST_ERROR, "zynq_slcr: Invalid read access to "
" addr %" HWADDR_PRIx "\n", offset * 4);
}
DB_PRINT("addr: %08" HWADDR_PRIx " data: %08" PRIx32 "\n", offset * 4, ret);
return ret;
}
@@ -347,148 +357,55 @@ static void zynq_slcr_write(void *opaque, hwaddr offset,
uint64_t val, unsigned size)
{
ZynqSLCRState *s = (ZynqSLCRState *)opaque;
offset /= 4;
DB_PRINT("offset: %08x data: %08x\n", (unsigned)offset, (unsigned)val);
DB_PRINT("addr: %08" HWADDR_PRIx " data: %08" PRIx64 "\n", offset * 4, val);
if (!zynq_slcr_check_offset(offset, false)) {
qemu_log_mask(LOG_GUEST_ERROR, "zynq_slcr: Invalid write access to "
"addr %" HWADDR_PRIx "\n", offset * 4);
return;
}
switch (offset) {
case 0x00: /* SCL */
s->scl = val & 0x1;
return;
case 0x4: /* SLCR_LOCK */
case SCL:
s->regs[SCL] = val & 0x1;
return;
case LOCK:
if ((val & 0xFFFF) == XILINX_LOCK_KEY) {
DB_PRINT("XILINX LOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
(unsigned)val & 0xFFFF);
s->lockval = 1;
s->regs[LOCKSTA] = 1;
} else {
DB_PRINT("WRONG XILINX LOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
(int)offset, (unsigned)val & 0xFFFF);
}
return;
case 0x8: /* SLCR_UNLOCK */
case UNLOCK:
if ((val & 0xFFFF) == XILINX_UNLOCK_KEY) {
DB_PRINT("XILINX UNLOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
(unsigned)val & 0xFFFF);
s->lockval = 0;
s->regs[LOCKSTA] = 0;
} else {
DB_PRINT("WRONG XILINX UNLOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
(int)offset, (unsigned)val & 0xFFFF);
}
return;
case 0xc: /* LOCKSTA */
DB_PRINT("Writing SCLR_LOCKSTA is not enabled\n");
}
if (!s->regs[LOCKSTA]) {
s->regs[offset / 4] = val;
} else {
DB_PRINT("SCLR registers are locked. Unlock them first\n");
return;
}
if (!s->lockval) {
switch (offset) {
case 0x100 ... 0x11C:
if (offset == 0x10C) {
goto bad_reg;
}
s->pll[(offset - 0x100) / 4] = val;
break;
case 0x120 ... 0x16C:
s->clk[(offset - 0x120) / 4] = val;
break;
case 0x170 ... 0x1AC:
s->fpga[0][(offset - 0x170) / 4] = val;
break;
case 0x1B0 ... 0x1D8:
s->misc[(offset - 0x1B0) / 4] = val;
break;
case 0x200 ... 0x25C:
if (offset == 0x250) {
goto bad_reg;
}
s->reset[(offset - 0x200) / 4] = val;
if (offset == 0x200 && (val & R_PSS_RST_CTRL_SOFT_RST)) {
qemu_system_reset_request();
}
break;
case 0x300:
s->apu_ctrl = val;
break;
case 0x304:
s->wdt_clk_sel = val;
break;
case 0x400 ... 0x408:
s->tz_ocm[(offset - 0x400) / 4] = val;
break;
case 0x430:
s->tz_ddr = val;
break;
case 0x440 ... 0x448:
s->tz_dma[(offset - 0x440) / 4] = val;
break;
case 0x450 ... 0x458:
s->tz_misc[(offset - 0x450) / 4] = val;
break;
case 0x484 ... 0x488:
s->tz_fpga[(offset - 0x484) / 4] = val;
break;
case 0x500:
s->dbg_ctrl = val;
break;
case 0x530:
s->pss_idcode = val;
break;
case 0x600 ... 0x620:
if (offset == 0x604) {
goto bad_reg;
}
s->ddr[(offset - 0x600) / 4] = val;
break;
case 0x700 ... 0x7D4:
s->mio[(offset - 0x700) / 4] = val;
break;
case 0x800 ... 0x810:
s->mio_func[(offset - 0x800) / 4] = val;
break;
case 0x830 ... 0x834:
s->sd[(offset - 0x830) / 4] = val;
break;
case 0x900:
s->lvl_shftr_en = val;
break;
case 0x910:
break;
case 0xA00 ... 0xA1C:
s->cpu_ram[(offset - 0xA00) / 4] = val;
break;
case 0xA30 ... 0xA48:
s->iou[(offset - 0xA30) / 4] = val;
break;
case 0xA50:
s->dmac_ram = val;
break;
case 0xA60 ... 0xA8C:
s->afi[0][(offset - 0xA60) / 4] = val;
break;
case 0xA90:
s->ocm[0] = val;
break;
case 0xAA0:
s->devci_ram = val;
break;
case 0xAB0:
s->csg_ram = val;
break;
case 0xB00 ... 0xB2C:
if (offset == 0xB20 || offset == 0xB2C) {
goto bad_reg;
}
s->gpiob[(offset - 0xB00) / 4] = val;
break;
case 0xB40 ... 0xB74:
s->ddriob[(offset - 0xB40) / 4] = val;
break;
default:
bad_reg:
DB_PRINT("Bad register write %x <= %08x\n", (int)offset,
(unsigned)val);
switch (offset) {
case PSS_RST_CTRL:
if (val & R_PSS_RST_CTRL_SOFT_RST) {
qemu_system_reset_request();
}
} else {
DB_PRINT("SCLR registers are locked. Unlock them first\n");
break;
}
}
@@ -498,23 +415,22 @@ static const MemoryRegionOps slcr_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
static int zynq_slcr_init(SysBusDevice *dev)
static void zynq_slcr_init(Object *obj)
{
ZynqSLCRState *s = ZYNQ_SLCR(dev);
ZynqSLCRState *s = ZYNQ_SLCR(obj);
memory_region_init_io(&s->iomem, OBJECT(s), &slcr_ops, s, "slcr", 0x1000);
sysbus_init_mmio(dev, &s->iomem);
return 0;
memory_region_init_io(&s->iomem, obj, &slcr_ops, s, "slcr",
ZYNQ_SLCR_MMIO_SIZE);
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
}
static const VMStateDescription vmstate_zynq_slcr = {
.name = "zynq_slcr",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.version_id = 2,
.minimum_version_id = 2,
.minimum_version_id_old = 2,
.fields = (VMStateField[]) {
VMSTATE_UINT8_ARRAY(data, ZynqSLCRState, 0x1000),
VMSTATE_UINT32_ARRAY(regs, ZynqSLCRState, ZYNQ_SLCR_NUM_REGS),
VMSTATE_END_OF_LIST()
}
};
@@ -522,9 +438,7 @@ static const VMStateDescription vmstate_zynq_slcr = {
static void zynq_slcr_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
sdc->init = zynq_slcr_init;
dc->vmsd = &vmstate_zynq_slcr;
dc->reset = zynq_slcr_reset;
}
@@ -534,6 +448,7 @@ static const TypeInfo zynq_slcr_info = {
.name = TYPE_ZYNQ_SLCR,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ZynqSLCRState),
.instance_init = zynq_slcr_init,
};
static void zynq_slcr_register_types(void)

View File

@@ -27,11 +27,11 @@ static uint8_t padding[60];
static void mii_set_link(RTL8201CPState *mii, bool link_ok)
{
if (link_ok) {
mii->bmsr |= MII_BMSR_LINK_ST;
mii->bmsr |= MII_BMSR_LINK_ST | MII_BMSR_AN_COMP;
mii->anlpar |= MII_ANAR_TXFD | MII_ANAR_10FD | MII_ANAR_10 |
MII_ANAR_CSMACD;
} else {
mii->bmsr &= ~MII_BMSR_LINK_ST;
mii->bmsr &= ~(MII_BMSR_LINK_ST | MII_BMSR_AN_COMP);
mii->anlpar = MII_ANAR_TX;
}
}
@@ -391,9 +391,11 @@ static void aw_emac_write(void *opaque, hwaddr offset, uint64_t value,
break;
case EMAC_INT_CTL_REG:
s->int_ctl = value;
aw_emac_update_irq(s);
break;
case EMAC_INT_STA_REG:
s->int_sta &= ~value;
aw_emac_update_irq(s);
break;
case EMAC_MAC_MADR_REG:
s->phy_target = value;

View File

@@ -1093,7 +1093,7 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size)
uint32_t phy_addr, reg_num;
phy_addr = (retval & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT;
if (phy_addr == BOARD_PHY_ADDRESS) {
if (phy_addr == BOARD_PHY_ADDRESS || phy_addr == 0) {
reg_num = (retval & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;
retval &= 0xFFFF0000;
retval |= gem_phy_read(s, reg_num);
@@ -1193,7 +1193,7 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
uint32_t phy_addr, reg_num;
phy_addr = (val & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT;
if (phy_addr == BOARD_PHY_ADDRESS) {
if (phy_addr == BOARD_PHY_ADDRESS || phy_addr == 0) {
reg_num = (val & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;
gem_phy_write(s, reg_num, val);
}

View File

@@ -677,7 +677,7 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
goto error;
}
if (in_use + mac_data.entries <= MAC_TABLE_ENTRIES) {
if (mac_data.entries <= MAC_TABLE_ENTRIES - in_use) {
s = iov_to_buf(iov, iov_cnt, 0, &macs[in_use * ETH_ALEN],
mac_data.entries * ETH_ALEN);
if (s != mac_data.entries * ETH_ALEN) {

View File

@@ -52,6 +52,9 @@
#define VMXNET3_DEVICE_VERSION 0x1
#define VMXNET3_DEVICE_REVISION 0x1
/* Number of interrupt vectors for non-MSIx modes */
#define VMXNET3_MAX_NMSIX_INTRS (1)
/* Macros for rings descriptors access */
#define VMXNET3_READ_TX_QUEUE_DESCR8(dpa, field) \
(vmw_shmem_ld8(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field)))
@@ -1305,6 +1308,51 @@ static bool vmxnet3_verify_intx(VMXNET3State *s, int intx)
(pci_get_byte(s->parent_obj.config + PCI_INTERRUPT_PIN) - 1));
}
static void vmxnet3_validate_interrupt_idx(bool is_msix, int idx)
{
int max_ints = is_msix ? VMXNET3_MAX_INTRS : VMXNET3_MAX_NMSIX_INTRS;
if (idx >= max_ints) {
hw_error("Bad interrupt index: %d\n", idx);
}
}
static void vmxnet3_validate_interrupts(VMXNET3State *s)
{
int i;
VMW_CFPRN("Verifying event interrupt index (%d)", s->event_int_idx);
vmxnet3_validate_interrupt_idx(s->msix_used, s->event_int_idx);
for (i = 0; i < s->txq_num; i++) {
int idx = s->txq_descr[i].intr_idx;
VMW_CFPRN("Verifying TX queue %d interrupt index (%d)", i, idx);
vmxnet3_validate_interrupt_idx(s->msix_used, idx);
}
for (i = 0; i < s->rxq_num; i++) {
int idx = s->rxq_descr[i].intr_idx;
VMW_CFPRN("Verifying RX queue %d interrupt index (%d)", i, idx);
vmxnet3_validate_interrupt_idx(s->msix_used, idx);
}
}
static void vmxnet3_validate_queues(VMXNET3State *s)
{
/*
* txq_num and rxq_num are total number of queues
* configured by guest. These numbers must not
* exceed corresponding maximal values.
*/
if (s->txq_num > VMXNET3_DEVICE_MAX_TX_QUEUES) {
hw_error("Bad TX queues number: %d\n", s->txq_num);
}
if (s->rxq_num > VMXNET3_DEVICE_MAX_RX_QUEUES) {
hw_error("Bad RX queues number: %d\n", s->rxq_num);
}
}
static void vmxnet3_activate_device(VMXNET3State *s)
{
int i;
@@ -1351,7 +1399,7 @@ static void vmxnet3_activate_device(VMXNET3State *s)
VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.misc.numRxQueues);
VMW_CFPRN("Number of TX/RX queues %u/%u", s->txq_num, s->rxq_num);
assert(s->txq_num <= VMXNET3_DEVICE_MAX_TX_QUEUES);
vmxnet3_validate_queues(s);
qdescr_table_pa =
VMXNET3_READ_DRV_SHARED64(s->drv_shmem, devRead.misc.queueDescPA);
@@ -1447,6 +1495,8 @@ static void vmxnet3_activate_device(VMXNET3State *s)
sizeof(s->rxq_descr[i].rxq_stats));
}
vmxnet3_validate_interrupts(s);
/* Make sure everything is in place before device activation */
smp_wmb();
@@ -2005,7 +2055,6 @@ vmxnet3_cleanup_msix(VMXNET3State *s)
}
}
#define VMXNET3_MSI_NUM_VECTORS (1)
#define VMXNET3_MSI_OFFSET (0x50)
#define VMXNET3_USE_64BIT (true)
#define VMXNET3_PER_VECTOR_MASK (false)
@@ -2016,7 +2065,7 @@ vmxnet3_init_msi(VMXNET3State *s)
PCIDevice *d = PCI_DEVICE(s);
int res;
res = msi_init(d, VMXNET3_MSI_OFFSET, VMXNET3_MSI_NUM_VECTORS,
res = msi_init(d, VMXNET3_MSI_OFFSET, VMXNET3_MAX_NMSIX_INTRS,
VMXNET3_USE_64BIT, VMXNET3_PER_VECTOR_MASK);
if (0 > res) {
VMW_WRPRN("Failed to initialize MSI, error %d", res);
@@ -2342,6 +2391,9 @@ static int vmxnet3_post_load(void *opaque, int version_id)
}
}
vmxnet3_validate_queues(s);
vmxnet3_validate_interrupts(s);
return 0;
}

View File

@@ -145,9 +145,9 @@ static uint64_t raven_io_read(void *opaque, hwaddr addr,
if (size == 1) {
return buf[0];
} else if (size == 2) {
return lduw_p(buf);
return lduw_le_p(buf);
} else if (size == 4) {
return ldl_p(buf);
return ldl_le_p(buf);
} else {
g_assert_not_reached();
}
@@ -164,9 +164,9 @@ static void raven_io_write(void *opaque, hwaddr addr,
if (size == 1) {
buf[0] = val;
} else if (size == 2) {
stw_p(buf, val);
stw_le_p(buf, val);
} else if (size == 4) {
stl_p(buf, val);
stl_le_p(buf, val);
} else {
g_assert_not_reached();
}

View File

@@ -649,7 +649,7 @@ void ppce500_init(QEMUMachineInitArgs *args, PPCE500Params *params)
input = (qemu_irq *)env->irq_inputs;
irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
env->spr[SPR_BOOKE_PIR] = cs->cpu_index = i;
env->spr_cb[SPR_BOOKE_PIR].default_value = cs->cpu_index = i;
env->mpic_iack = MPC8544_CCSRBAR_BASE +
MPC8544_MPIC_REGS_OFFSET + 0xa0;

View File

@@ -620,6 +620,13 @@ static void cpu_ppc_tb_start (CPUPPCState *env)
}
}
bool ppc_decr_clear_on_delivery(CPUPPCState *env)
{
ppc_tb_t *tb_env = env->tb_env;
int flags = PPC_DECR_UNDERFLOW_TRIGGERED | PPC_DECR_UNDERFLOW_LEVEL;
return ((tb_env->flags & flags) == PPC_DECR_UNDERFLOW_TRIGGERED);
}
static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
{
ppc_tb_t *tb_env = env->tb_env;
@@ -677,6 +684,11 @@ static inline void cpu_ppc_decr_excp(PowerPCCPU *cpu)
ppc_set_irq(cpu, PPC_INTERRUPT_DECR, 1);
}
static inline void cpu_ppc_decr_lower(PowerPCCPU *cpu)
{
ppc_set_irq(cpu, PPC_INTERRUPT_DECR, 0);
}
static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu)
{
/* Raise it */
@@ -684,11 +696,16 @@ static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu)
ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
}
static inline void cpu_ppc_hdecr_lower(PowerPCCPU *cpu)
{
ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 0);
}
static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
QEMUTimer *timer,
void (*raise_excp)(PowerPCCPU *),
uint32_t decr, uint32_t value,
int is_excp)
void (*raise_excp)(void *),
void (*lower_excp)(PowerPCCPU *),
uint32_t decr, uint32_t value)
{
CPUPPCState *env = &cpu->env;
ppc_tb_t *tb_env = env->tb_env;
@@ -702,59 +719,74 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
return;
}
/*
* Going from 2 -> 1, 1 -> 0 or 0 -> -1 is the event to generate a DEC
* interrupt.
*
* If we get a really small DEC value, we can assume that by the time we
* handled it we should inject an interrupt already.
*
* On MSB level based DEC implementations the MSB always means the interrupt
* is pending, so raise it on those.
*
* On MSB edge based DEC implementations the MSB going from 0 -> 1 triggers
* an edge interrupt, so raise it here too.
*/
if ((value < 3) ||
((tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL) && (value & 0x80000000)) ||
((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED) && (value & 0x80000000)
&& !(decr & 0x80000000))) {
(*raise_excp)(cpu);
return;
}
/* On MSB level based systems a 0 for the MSB stops interrupt delivery */
if (!(value & 0x80000000) && (tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL)) {
(*lower_excp)(cpu);
}
/* Calculate the next timer event */
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
next = now + muldiv64(value, get_ticks_per_sec(), tb_env->decr_freq);
if (is_excp) {
next += *nextp - now;
}
if (next == now) {
next++;
}
*nextp = next;
/* Adjust timer */
timer_mod(timer, next);
/* If we set a negative value and the decrementer was positive, raise an
* exception.
*/
if ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED)
&& (value & 0x80000000)
&& !(decr & 0x80000000)) {
(*raise_excp)(cpu);
}
}
static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, uint32_t decr,
uint32_t value, int is_excp)
uint32_t value)
{
ppc_tb_t *tb_env = cpu->env.tb_env;
__cpu_ppc_store_decr(cpu, &tb_env->decr_next, tb_env->decr_timer,
&cpu_ppc_decr_excp, decr, value, is_excp);
tb_env->decr_timer->cb, &cpu_ppc_decr_lower, decr,
value);
}
void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value)
{
PowerPCCPU *cpu = ppc_env_get_cpu(env);
_cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value, 0);
_cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value);
}
static void cpu_ppc_decr_cb(void *opaque)
{
PowerPCCPU *cpu = opaque;
_cpu_ppc_store_decr(cpu, 0x00000000, 0xFFFFFFFF, 1);
cpu_ppc_decr_excp(cpu);
}
static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, uint32_t hdecr,
uint32_t value, int is_excp)
uint32_t value)
{
ppc_tb_t *tb_env = cpu->env.tb_env;
if (tb_env->hdecr_timer != NULL) {
__cpu_ppc_store_decr(cpu, &tb_env->hdecr_next, tb_env->hdecr_timer,
&cpu_ppc_hdecr_excp, hdecr, value, is_excp);
tb_env->hdecr_timer->cb, &cpu_ppc_hdecr_lower,
hdecr, value);
}
}
@@ -762,14 +794,14 @@ void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value)
{
PowerPCCPU *cpu = ppc_env_get_cpu(env);
_cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value, 0);
_cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value);
}
static void cpu_ppc_hdecr_cb(void *opaque)
{
PowerPCCPU *cpu = opaque;
_cpu_ppc_store_hdecr(cpu, 0x00000000, 0xFFFFFFFF, 1);
cpu_ppc_hdecr_excp(cpu);
}
static void cpu_ppc_store_purr(PowerPCCPU *cpu, uint64_t value)
@@ -792,8 +824,8 @@ static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
* if a decrementer exception is pending when it enables msr_ee at startup,
* it's not ready to handle it...
*/
_cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0);
_cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0);
_cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF);
_cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF);
cpu_ppc_store_purr(cpu, 0x0000000000000000ULL);
}
@@ -806,6 +838,10 @@ clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
tb_env = g_malloc0(sizeof(ppc_tb_t));
env->tb_env = tb_env;
tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
if (env->insns_flags & PPC_SEGMENT_64B) {
/* All Book3S 64bit CPUs implement level based DEC logic */
tb_env->flags |= PPC_DECR_UNDERFLOW_LEVEL;
}
/* Create new timer */
tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_ppc_decr_cb, cpu);
if (0) {

View File

@@ -65,9 +65,9 @@ static void spin_reset(void *opaque)
for (i = 0; i < MAX_CPUS; i++) {
SpinInfo *info = &s->spin[i];
info->pir = i;
info->r3 = i;
info->addr = 1;
stl_p(&info->pir, i);
stq_p(&info->r3, i);
stq_p(&info->addr, 1);
}
}

View File

@@ -19,6 +19,15 @@
#include "sysemu/sysemu.h"
#include "hw/timer/allwinner-a10-pit.h"
static void a10_pit_update_irq(AwA10PITState *s)
{
int i;
for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
qemu_set_irq(s->irq[i], !!(s->irq_status & s->irq_enable & (1 << i)));
}
}
static uint64_t a10_pit_read(void *opaque, hwaddr offset, unsigned size)
{
AwA10PITState *s = AW_A10_PIT(opaque);
@@ -65,6 +74,22 @@ static uint64_t a10_pit_read(void *opaque, hwaddr offset, unsigned size)
return 0;
}
static void a10_pit_set_freq(AwA10PITState *s, int index)
{
uint32_t prescaler, source, source_freq;
prescaler = 1 << extract32(s->control[index], 4, 3);
source = extract32(s->control[index], 2, 2);
source_freq = s->clk_freq[source];
if (source_freq) {
ptimer_set_freq(s->timer[index], source_freq / prescaler);
} else {
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid clock source %u\n",
__func__, source);
}
}
static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
unsigned size)
{
@@ -74,9 +99,11 @@ static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
switch (offset) {
case AW_A10_PIT_TIMER_IRQ_EN:
s->irq_enable = value;
a10_pit_update_irq(s);
break;
case AW_A10_PIT_TIMER_IRQ_ST:
s->irq_status &= ~value;
a10_pit_update_irq(s);
break;
case AW_A10_PIT_TIMER_BASE ... AW_A10_PIT_TIMER_BASE_END:
index = offset & 0xf0;
@@ -85,6 +112,7 @@ static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
switch (offset & 0x0f) {
case AW_A10_PIT_TIMER_CONTROL:
s->control[index] = value;
a10_pit_set_freq(s, index);
if (s->control[index] & AW_A10_PIT_TIMER_RELOAD) {
ptimer_set_count(s->timer[index], s->interval[index]);
}
@@ -150,6 +178,14 @@ static const MemoryRegionOps a10_pit_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
static Property a10_pit_properties[] = {
DEFINE_PROP_UINT32("clk0-freq", AwA10PITState, clk_freq[0], 0),
DEFINE_PROP_UINT32("clk1-freq", AwA10PITState, clk_freq[1], 0),
DEFINE_PROP_UINT32("clk2-freq", AwA10PITState, clk_freq[2], 0),
DEFINE_PROP_UINT32("clk3-freq", AwA10PITState, clk_freq[3], 0),
DEFINE_PROP_END_OF_LIST(),
};
static const VMStateDescription vmstate_a10_pit = {
.name = "a10.pit",
.version_id = 1,
@@ -178,11 +214,14 @@ static void a10_pit_reset(DeviceState *dev)
s->irq_enable = 0;
s->irq_status = 0;
a10_pit_update_irq(s);
for (i = 0; i < 6; i++) {
s->control[i] = AW_A10_PIT_DEFAULT_CLOCK;
s->interval[i] = 0;
s->count[i] = 0;
ptimer_stop(s->timer[i]);
a10_pit_set_freq(s, i);
}
s->watch_dog_mode = 0;
s->watch_dog_control = 0;
@@ -193,18 +232,17 @@ static void a10_pit_reset(DeviceState *dev)
static void a10_pit_timer_cb(void *opaque)
{
AwA10PITState *s = AW_A10_PIT(opaque);
uint8_t i;
AwA10TimerContext *tc = opaque;
AwA10PITState *s = tc->container;
uint8_t i = tc->index;
for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
if (s->control[i] & AW_A10_PIT_TIMER_EN) {
s->irq_status |= 1 << i;
if (s->control[i] & AW_A10_PIT_TIMER_MODE) {
ptimer_stop(s->timer[i]);
s->control[i] &= ~AW_A10_PIT_TIMER_EN;
}
qemu_irq_pulse(s->irq[i]);
if (s->control[i] & AW_A10_PIT_TIMER_EN) {
s->irq_status |= 1 << i;
if (s->control[i] & AW_A10_PIT_TIMER_MODE) {
ptimer_stop(s->timer[i]);
s->control[i] &= ~AW_A10_PIT_TIMER_EN;
}
a10_pit_update_irq(s);
}
}
@@ -223,9 +261,12 @@ static void a10_pit_init(Object *obj)
sysbus_init_mmio(sbd, &s->iomem);
for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
bh[i] = qemu_bh_new(a10_pit_timer_cb, s);
AwA10TimerContext *tc = &s->timer_context[i];
tc->container = s;
tc->index = i;
bh[i] = qemu_bh_new(a10_pit_timer_cb, tc);
s->timer[i] = ptimer_init(bh[i]);
ptimer_set_freq(s->timer[i], 240000);
}
}
@@ -234,6 +275,7 @@ static void a10_pit_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->reset = a10_pit_reset;
dc->props = a10_pit_properties;
dc->desc = "allwinner a10 timer";
dc->vmsd = &vmstate_a10_pit;
}

View File

@@ -346,11 +346,13 @@ static void cadence_ttc_write(void *opaque, hwaddr offset,
case 0x34:
case 0x38:
s->reg_match[0] = value & 0xffff;
break;
case 0x3c: /* match register */
case 0x40:
case 0x44:
s->reg_match[1] = value & 0xffff;
break;
case 0x48: /* match register */
case 0x4c:

View File

@@ -26,6 +26,10 @@ common-obj-y += ccid-card-passthru.o
common-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
endif
ifeq ($(CONFIG_POSIX),y)
common-obj-$(CONFIG_USB_STORAGE_MTP) += dev-mtp.o
endif
# usb redirection
common-obj-$(CONFIG_USB_REDIR) += redirect.o quirks.o

View File

@@ -44,7 +44,7 @@ typedef struct msos_compat_hdr {
typedef struct msos_compat_func {
uint8_t bFirstInterfaceNumber;
uint8_t reserved_1;
uint8_t compatibleId[8];
char compatibleId[8];
uint8_t subCompatibleId[8];
uint8_t reserved_2[6];
} QEMU_PACKED msos_compat_func;
@@ -59,6 +59,10 @@ static int usb_desc_msos_compat(const USBDesc *desc, uint8_t *dest)
func = (void *)(dest + length);
func->bFirstInterfaceNumber = 0;
func->reserved_1 = 0x01;
if (desc->msos->CompatibleID) {
snprintf(func->compatibleId, sizeof(func->compatibleId),
"%s", desc->msos->CompatibleID);
}
length += sizeof(*func);
count++;

View File

@@ -184,6 +184,7 @@ struct USBDescOther {
};
struct USBDescMSOS {
const char *CompatibleID;
const wchar_t *Label;
bool SelectiveSuspendEnabled;
};

1103
hw/usb/dev-mtp.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -162,3 +162,55 @@
#define stw(p, v) stw_data(p, v)
#define stl(p, v) stl_data(p, v)
#define stq(p, v) stq_data(p, v)
/**
* tlb_vaddr_to_host:
* @env: CPUArchState
* @addr: guest virtual address to look up
* @access_type: 0 for read, 1 for write, 2 for execute
* @mmu_idx: MMU index to use for lookup
*
* Look up the specified guest virtual index in the TCG softmmu TLB.
* If the TLB contains a host virtual address suitable for direct RAM
* access, then return it. Otherwise (TLB miss, TLB entry is for an
* I/O access, etc) return NULL.
*
* This is the equivalent of the initial fast-path code used by
* TCG backends for guest load and store accesses.
*/
static inline void *tlb_vaddr_to_host(CPUArchState *env, target_ulong addr,
int access_type, int mmu_idx)
{
int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
CPUTLBEntry *tlbentry = &env->tlb_table[mmu_idx][index];
target_ulong tlb_addr;
uintptr_t haddr;
switch (access_type) {
case 0:
tlb_addr = tlbentry->addr_read;
break;
case 1:
tlb_addr = tlbentry->addr_write;
break;
case 2:
tlb_addr = tlbentry->addr_code;
break;
default:
g_assert_not_reached();
}
if ((addr & TARGET_PAGE_MASK)
!= (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
/* TLB entry is for a different page */
return NULL;
}
if (tlb_addr & ~TARGET_PAGE_MASK) {
/* IO access */
return NULL;
}
haddr = addr + env->tlb_table[mmu_idx][index].addend;
return (void *)haddr;
}

View File

@@ -342,6 +342,7 @@ uint32 float32_to_uint32( float32 STATUS_PARAM );
uint32 float32_to_uint32_round_to_zero( float32 STATUS_PARAM );
int64 float32_to_int64( float32 STATUS_PARAM );
uint64 float32_to_uint64(float32 STATUS_PARAM);
uint64 float32_to_uint64_round_to_zero(float32 STATUS_PARAM);
int64 float32_to_int64_round_to_zero( float32 STATUS_PARAM );
float64 float32_to_float64( float32 STATUS_PARAM );
floatx80 float32_to_floatx80( float32 STATUS_PARAM );

View File

@@ -3,7 +3,8 @@
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; under version 2 of the License.
* the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of

View File

@@ -144,6 +144,7 @@
#define MII_BMSR_10T_FD (1 << 12)
#define MII_BMSR_10T_HD (1 << 11)
#define MII_BMSR_MFPS (1 << 6)
#define MII_BMSR_AN_COMP (1 << 5)
#define MII_BMSR_AUTONEG (1 << 3)
#define MII_BMSR_LINK_ST (1 << 2)

View File

@@ -44,6 +44,9 @@ struct ppc_tb_t {
#define PPC_DECR_ZERO_TRIGGERED (1 << 3) /* Decr interrupt triggered when
* the decrementer reaches zero.
*/
#define PPC_DECR_UNDERFLOW_LEVEL (1 << 4) /* Decr interrupt active when
* the most significant bit is 1.
*/
uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset);
clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq);

View File

@@ -35,13 +35,22 @@
#define AW_A10_PIT_DEFAULT_CLOCK 0x4
typedef struct AwA10PITState {
typedef struct AwA10PITState AwA10PITState;
typedef struct AwA10TimerContext {
AwA10PITState *container;
int index;
} AwA10TimerContext;
struct AwA10PITState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
qemu_irq irq[AW_A10_PIT_TIMER_NR];
ptimer_state * timer[AW_A10_PIT_TIMER_NR];
AwA10TimerContext timer_context[AW_A10_PIT_TIMER_NR];
MemoryRegion iomem;
uint32_t clk_freq[4];
uint32_t irq_enable;
uint32_t irq_status;
@@ -53,6 +62,6 @@ typedef struct AwA10PITState {
uint32_t count_lo;
uint32_t count_hi;
uint32_t count_ctl;
} AwA10PITState;
};
#endif

View File

@@ -441,7 +441,7 @@ static int kvm_physical_sync_dirty_bitmap(MemoryRegionSection *section)
d.slot = mem->slot;
if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) < 0) {
if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) {
DPRINTF("ioctl failed %d\n", errno);
ret = -1;
break;

View File

@@ -483,17 +483,17 @@ static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
addr = env->regs[2];
if (get_user_u64(oldval, env->regs[0])) {
env->cp15.c6_data = env->regs[0];
env->exception.vaddress = env->regs[0];
goto segv;
};
if (get_user_u64(newval, env->regs[1])) {
env->cp15.c6_data = env->regs[1];
env->exception.vaddress = env->regs[1];
goto segv;
};
if (get_user_u64(val, addr)) {
env->cp15.c6_data = addr;
env->exception.vaddress = addr;
goto segv;
}
@@ -501,7 +501,7 @@ static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
val = newval;
if (put_user_u64(val, addr)) {
env->cp15.c6_data = addr;
env->exception.vaddress = addr;
goto segv;
};
@@ -523,7 +523,7 @@ segv:
info.si_errno = 0;
/* XXX: check env->error_code */
info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = env->cp15.c6_data;
info._sifields._sigfault._addr = env->exception.vaddress;
queue_signal(env, info.si_signo, &info);
end_exclusive();
@@ -620,14 +620,14 @@ static int do_strex(CPUARMState *env)
abort();
}
if (segv) {
env->cp15.c6_data = addr;
env->exception.vaddress = addr;
goto done;
}
if (size == 3) {
uint32_t valhi;
segv = get_user_u32(valhi, addr + 4);
if (segv) {
env->cp15.c6_data = addr + 4;
env->exception.vaddress = addr + 4;
goto done;
}
val = deposit64(val, 32, 32, valhi);
@@ -650,14 +650,14 @@ static int do_strex(CPUARMState *env)
break;
}
if (segv) {
env->cp15.c6_data = addr;
env->exception.vaddress = addr;
goto done;
}
if (size == 3) {
val = env->regs[(env->exclusive_info >> 12) & 0xf];
segv = put_user_u32(val, addr + 4);
if (segv) {
env->cp15.c6_data = addr + 4;
env->exception.vaddress = addr + 4;
goto done;
}
}
@@ -832,12 +832,14 @@ void cpu_loop(CPUARMState *env)
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
case EXCP_STREX:
if (!do_strex(env)) {
break;
}
/* fall through for segv */
case EXCP_PREFETCH_ABORT:
addr = env->cp15.c6_insn;
goto do_segv;
case EXCP_DATA_ABORT:
addr = env->cp15.c6_data;
do_segv:
addr = env->exception.vaddress;
{
info.si_signo = SIGSEGV;
info.si_errno = 0;
@@ -865,12 +867,6 @@ void cpu_loop(CPUARMState *env)
if (do_kernel_trap(env))
goto error;
break;
case EXCP_STREX:
if (do_strex(env)) {
addr = env->cp15.c6_data;
goto do_segv;
}
break;
default:
error:
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
@@ -933,7 +929,7 @@ static int do_strex_a64(CPUARMState *env)
abort();
}
if (segv) {
env->cp15.c6_data = addr;
env->exception.vaddress = addr;
goto error;
}
if (val != env->exclusive_val) {
@@ -946,7 +942,7 @@ static int do_strex_a64(CPUARMState *env)
segv = get_user_u64(val, addr + 8);
}
if (segv) {
env->cp15.c6_data = addr + (size == 2 ? 4 : 8);
env->exception.vaddress = addr + (size == 2 ? 4 : 8);
goto error;
}
if (val != env->exclusive_high) {
@@ -981,7 +977,7 @@ static int do_strex_a64(CPUARMState *env)
segv = put_user_u64(val, addr + 8);
}
if (segv) {
env->cp15.c6_data = addr + (size == 2 ? 4 : 8);
env->exception.vaddress = addr + (size == 2 ? 4 : 8);
goto error;
}
}
@@ -1037,12 +1033,14 @@ void cpu_loop(CPUARMState *env)
info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, &info);
break;
case EXCP_STREX:
if (!do_strex_a64(env)) {
break;
}
/* fall through for segv */
case EXCP_PREFETCH_ABORT:
addr = env->cp15.c6_insn;
goto do_segv;
case EXCP_DATA_ABORT:
addr = env->cp15.c6_data;
do_segv:
addr = env->exception.vaddress;
info.si_signo = SIGSEGV;
info.si_errno = 0;
/* XXX: check env->error_code */
@@ -1060,12 +1058,6 @@ void cpu_loop(CPUARMState *env)
queue_signal(env, info.si_signo, &info);
}
break;
case EXCP_STREX:
if (do_strex_a64(env)) {
addr = env->cp15.c6_data;
goto do_segv;
}
break;
default:
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr);

View File

@@ -17,7 +17,7 @@
- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
implementation for certain IBM POWER hardware. The sources are at
https://github.com/aik/SLOF, and the image currently in qemu is
built from git tag qemu-slof-20140304.
built from git tag qemu-slof-20140404.
- sgabios (the Serial Graphics Adapter option ROM) provides a means for
legacy x86 software to communicate with an attached serial console as

Binary file not shown.

View File

@@ -75,10 +75,13 @@ static void errmsg_dialog(DWORD err, const char *text, const char *opt = "")
#define chk(status) _chk(hr, status, "Failed to " #status, out)
#if !defined(__MINGW64_VERSION_MAJOR) || !defined(__MINGW64_VERSION_MINOR) || \
__MINGW64_VERSION_MAJOR * 100 + __MINGW64_VERSION_MINOR < 301
void __stdcall _com_issue_error(HRESULT hr)
{
errmsg(hr, "Unexpected error in COM");
}
#endif
template<class T>
HRESULT put_Value(ICatalogObject *pObj, LPCWSTR name, T val)

View File

@@ -1225,7 +1225,8 @@ Object *object_resolve_path_component(Object *parent, const gchar *part)
}
if (object_property_is_link(prop)) {
return *(Object **)prop->opaque;
LinkProperty *lprop = prop->opaque;
return *lprop->child;
} else if (object_property_is_child(prop)) {
return prop->opaque;
} else {

View File

@@ -116,6 +116,7 @@ typedef struct ARMCPU {
uint32_t reset_fpsid;
uint32_t mvfr0;
uint32_t mvfr1;
uint32_t mvfr2;
uint32_t ctr;
uint32_t reset_sctlr;
uint32_t id_pfr0;
@@ -147,9 +148,12 @@ typedef struct ARMCPU {
* in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
*/
uint32_t ccsidr[16];
uint32_t reset_cbar;
uint64_t reset_cbar;
uint32_t reset_auxcr;
bool reset_hivecs;
/* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */
uint32_t dcz_blocksize;
uint64_t rvbar;
} ARMCPU;
#define TYPE_AARCH64_CPU "aarch64-cpu"
@@ -196,10 +200,10 @@ void arm_gt_ptimer_cb(void *opaque);
void arm_gt_vtimer_cb(void *opaque);
#ifdef TARGET_AARCH64
void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
fprintf_function cpu_fprintf, int flags);
int aarch64_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void aarch64_cpu_do_interrupt(CPUState *cs);
#endif
#endif

View File

@@ -19,6 +19,7 @@
*/
#include "cpu.h"
#include "internals.h"
#include "qemu-common.h"
#include "hw/qdev-properties.h"
#include "qapi/qmp/qerror.h"
@@ -87,6 +88,7 @@ static void arm_cpu_reset(CPUState *s)
env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid;
env->vfp.xregs[ARM_VFP_MVFR0] = cpu->mvfr0;
env->vfp.xregs[ARM_VFP_MVFR1] = cpu->mvfr1;
env->vfp.xregs[ARM_VFP_MVFR2] = cpu->mvfr2;
if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q';
@@ -99,8 +101,16 @@ static void arm_cpu_reset(CPUState *s)
env->pstate = PSTATE_MODE_EL0t;
/* Userspace expects access to CTL_EL0 and the cache ops */
env->cp15.c1_sys |= SCTLR_UCT | SCTLR_UCI;
/* and to the FP/Neon instructions */
env->cp15.c1_coproc = deposit64(env->cp15.c1_coproc, 20, 2, 3);
#else
env->pstate = PSTATE_MODE_EL1h;
env->pc = cpu->rvbar;
#endif
} else {
#if defined(CONFIG_USER_ONLY)
/* Userspace expects access to cp10 and cp11 for FP/Neon */
env->cp15.c1_coproc = deposit64(env->cp15.c1_coproc, 20, 4, 0xf);
#endif
}
@@ -252,16 +262,20 @@ static void arm_cpu_initfn(Object *obj)
}
static Property arm_cpu_reset_cbar_property =
DEFINE_PROP_UINT32("reset-cbar", ARMCPU, reset_cbar, 0);
DEFINE_PROP_UINT64("reset-cbar", ARMCPU, reset_cbar, 0);
static Property arm_cpu_reset_hivecs_property =
DEFINE_PROP_BOOL("reset-hivecs", ARMCPU, reset_hivecs, false);
static Property arm_cpu_rvbar_property =
DEFINE_PROP_UINT64("rvbar", ARMCPU, rvbar, 0);
static void arm_cpu_post_init(Object *obj)
{
ARMCPU *cpu = ARM_CPU(obj);
if (arm_feature(&cpu->env, ARM_FEATURE_CBAR)) {
if (arm_feature(&cpu->env, ARM_FEATURE_CBAR) ||
arm_feature(&cpu->env, ARM_FEATURE_CBAR_RO)) {
qdev_property_add_static(DEVICE(obj), &arm_cpu_reset_cbar_property,
&error_abort);
}
@@ -270,6 +284,11 @@ static void arm_cpu_post_init(Object *obj)
qdev_property_add_static(DEVICE(obj), &arm_cpu_reset_hivecs_property,
&error_abort);
}
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
qdev_property_add_static(DEVICE(obj), &arm_cpu_rvbar_property,
&error_abort);
}
}
static void arm_cpu_finalizefn(Object *obj)
@@ -331,6 +350,9 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
set_feature(env, ARM_FEATURE_V7MP);
set_feature(env, ARM_FEATURE_PXN);
}
if (arm_feature(env, ARM_FEATURE_CBAR_RO)) {
set_feature(env, ARM_FEATURE_CBAR);
}
if (cpu->reset_hivecs) {
cpu->reset_sctlr |= (1 << 13);
@@ -417,7 +439,7 @@ static void arm1026_initfn(Object *obj)
ARMCPRegInfo ifar = {
.name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 1,
.access = PL1_RW,
.fieldoffset = offsetof(CPUARMState, cp15.c6_insn),
.fieldoffset = offsetofhigh32(CPUARMState, cp15.far_el1),
.resetvalue = 0
};
define_one_arm_cp_reg(cpu, &ifar);
@@ -722,7 +744,7 @@ static void cortex_a15_initfn(Object *obj)
set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
set_feature(&cpu->env, ARM_FEATURE_CBAR);
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
set_feature(&cpu->env, ARM_FEATURE_LPAE);
cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15;
cpu->midr = 0x412fc0f1;

View File

@@ -111,11 +111,6 @@ typedef struct ARMGenericTimer {
#define GTIMER_VIRT 1
#define NUM_GTIMERS 2
/* Scale factor for generic timers, ie number of ns per tick.
* This gives a 62.5MHz timer.
*/
#define GTIMER_SCALE 16
typedef struct CPUARMState {
/* Regs for current mode. */
uint32_t regs[16];
@@ -148,7 +143,7 @@ typedef struct CPUARMState {
uint32_t spsr;
/* Banked registers. */
uint32_t banked_spsr[6];
uint64_t banked_spsr[6];
uint32_t banked_r13[6];
uint32_t banked_r14[6];
@@ -165,7 +160,10 @@ typedef struct CPUARMState {
uint32_t GE; /* cpsr[19:16] */
uint32_t thumb; /* cpsr[5]. 0 = arm mode, 1 = thumb mode. */
uint32_t condexec_bits; /* IT bits. cpsr[15:10,26:25]. */
uint32_t daif; /* exception masks, in the bits they are in in PSTATE */
uint64_t daif; /* exception masks, in the bits they are in in PSTATE */
uint64_t elr_el1; /* AArch64 ELR_EL1 */
uint64_t sp_el[2]; /* AArch64 banked stack pointers */
/* System control coprocessor (cp15) */
struct {
@@ -184,13 +182,13 @@ typedef struct CPUARMState {
uint32_t c2_insn; /* MPU instruction cachable bits. */
uint32_t c3; /* MMU domain access control register
MPU write buffer control. */
uint32_t c5_insn; /* Fault status registers. */
uint32_t c5_data;
uint32_t pmsav5_data_ap; /* PMSAv5 MPU data access permissions */
uint32_t pmsav5_insn_ap; /* PMSAv5 MPU insn access permissions */
uint32_t ifsr_el2; /* Fault status registers. */
uint64_t esr_el1;
uint32_t c6_region[8]; /* MPU base/size registers. */
uint32_t c6_insn; /* Fault address registers. */
uint32_t c6_data;
uint32_t c7_par; /* Translation result. */
uint32_t c7_par_hi; /* Translation result, high 32 bits */
uint64_t far_el1; /* Fault address registers. */
uint64_t par_el1; /* Translation result. */
uint32_t c9_insn; /* Cache lockdown registers. */
uint32_t c9_data;
uint32_t c9_pmcr; /* performance monitor control register */
@@ -202,7 +200,7 @@ typedef struct CPUARMState {
uint64_t mair_el1;
uint64_t c12_vbar; /* vector base address register */
uint32_t c13_fcse; /* FCSE PID. */
uint32_t c13_context; /* Context ID. */
uint64_t contextidr_el1; /* Context ID. */
uint64_t tpidr_el0; /* User RW Thread register. */
uint64_t tpidrro_el0; /* User RO Thread register. */
uint64_t tpidr_el1; /* Privileged Thread register. */
@@ -238,6 +236,21 @@ typedef struct CPUARMState {
int pending_exception;
} v7m;
/* Information associated with an exception about to be taken:
* code which raises an exception must set cs->exception_index and
* the relevant parts of this structure; the cpu_do_interrupt function
* will then set the guest-visible registers as part of the exception
* entry process.
*/
struct {
uint32_t syndrome; /* AArch64 format syndrome register */
uint32_t fsr; /* AArch32 format fault status register info */
uint64_t vaddress; /* virtual addr associated with exception, if any */
/* If we implement EL2 we will also need to store information
* about the intermediate physical address for stage 2 faults.
*/
} exception;
/* Thumb-2 EE state. */
uint32_t teecr;
uint32_t teehbr;
@@ -322,11 +335,7 @@ typedef struct CPUARMState {
#include "cpu-qom.h"
ARMCPU *cpu_arm_init(const char *cpu_model);
void arm_translate_init(void);
void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu);
int cpu_arm_exec(CPUARMState *s);
int bank_number(int mode);
void switch_mode(CPUARMState *, int);
uint32_t do_arm_semihosting(CPUARMState *env);
static inline bool is_a64(CPUARMState *env)
@@ -425,6 +434,7 @@ int arm_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
* Only these are valid when in AArch64 mode; in
* AArch32 mode SPSRs are basically CPSR-format.
*/
#define PSTATE_SP (1U)
#define PSTATE_M (0xFU)
#define PSTATE_nRW (1U << 4)
#define PSTATE_F (1U << 6)
@@ -548,17 +558,6 @@ static inline void vfp_set_fpcr(CPUARMState *env, uint32_t val)
vfp_set_fpscr(env, new_fpscr);
}
enum arm_fprounding {
FPROUNDING_TIEEVEN,
FPROUNDING_POSINF,
FPROUNDING_NEGINF,
FPROUNDING_ZERO,
FPROUNDING_TIEAWAY,
FPROUNDING_ODD
};
int arm_rmode_to_sf(int rmode);
enum arm_cpu_mode {
ARM_CPU_MODE_USR = 0x10,
ARM_CPU_MODE_FIQ = 0x11,
@@ -572,6 +571,7 @@ enum arm_cpu_mode {
/* VFP system registers. */
#define ARM_VFP_FPSID 0
#define ARM_VFP_FPSCR 1
#define ARM_VFP_MVFR2 5
#define ARM_VFP_MVFR1 6
#define ARM_VFP_MVFR0 7
#define ARM_VFP_FPEXC 8
@@ -630,6 +630,7 @@ enum arm_features {
ARM_FEATURE_V8_AES, /* implements AES part of v8 Crypto Extensions */
ARM_FEATURE_CBAR, /* has cp15 CBAR */
ARM_FEATURE_CRC, /* ARMv8 CRC instructions */
ARM_FEATURE_CBAR_RO, /* has cp15 CBAR and it is read-only */
};
static inline int arm_feature(CPUARMState *env, int feature)
@@ -763,7 +764,8 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
#define ARM_CP_WFI (ARM_CP_SPECIAL | (2 << 8))
#define ARM_CP_NZCV (ARM_CP_SPECIAL | (3 << 8))
#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | (4 << 8))
#define ARM_LAST_SPECIAL ARM_CP_CURRENTEL
#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | (5 << 8))
#define ARM_LAST_SPECIAL ARM_CP_DC_ZVA
/* Used only as a terminator for ARMCPRegInfo lists */
#define ARM_CP_SENTINEL 0xffff
/* Mask of only the flag bits in a type field */
@@ -1109,10 +1111,14 @@ static inline int cpu_mmu_index (CPUARMState *env)
#define ARM_TBFLAG_CONDEXEC_MASK (0xff << ARM_TBFLAG_CONDEXEC_SHIFT)
#define ARM_TBFLAG_BSWAP_CODE_SHIFT 16
#define ARM_TBFLAG_BSWAP_CODE_MASK (1 << ARM_TBFLAG_BSWAP_CODE_SHIFT)
#define ARM_TBFLAG_CPACR_FPEN_SHIFT 17
#define ARM_TBFLAG_CPACR_FPEN_MASK (1 << ARM_TBFLAG_CPACR_FPEN_SHIFT)
/* Bit usage when in AArch64 state */
#define ARM_TBFLAG_AA64_EL_SHIFT 0
#define ARM_TBFLAG_AA64_EL_MASK (0x3 << ARM_TBFLAG_AA64_EL_SHIFT)
#define ARM_TBFLAG_AA64_FPEN_SHIFT 2
#define ARM_TBFLAG_AA64_FPEN_MASK (1 << ARM_TBFLAG_AA64_FPEN_SHIFT)
/* some convenience accessor macros */
#define ARM_TBFLAG_AARCH64_STATE(F) \
@@ -1131,16 +1137,25 @@ static inline int cpu_mmu_index (CPUARMState *env)
(((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT)
#define ARM_TBFLAG_BSWAP_CODE(F) \
(((F) & ARM_TBFLAG_BSWAP_CODE_MASK) >> ARM_TBFLAG_BSWAP_CODE_SHIFT)
#define ARM_TBFLAG_CPACR_FPEN(F) \
(((F) & ARM_TBFLAG_CPACR_FPEN_MASK) >> ARM_TBFLAG_CPACR_FPEN_SHIFT)
#define ARM_TBFLAG_AA64_EL(F) \
(((F) & ARM_TBFLAG_AA64_EL_MASK) >> ARM_TBFLAG_AA64_EL_SHIFT)
#define ARM_TBFLAG_AA64_FPEN(F) \
(((F) & ARM_TBFLAG_AA64_FPEN_MASK) >> ARM_TBFLAG_AA64_FPEN_SHIFT)
static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
target_ulong *cs_base, int *flags)
{
int fpen = extract32(env->cp15.c1_coproc, 20, 2);
if (is_a64(env)) {
*pc = env->pc;
*flags = ARM_TBFLAG_AARCH64_STATE_MASK
| (arm_current_pl(env) << ARM_TBFLAG_AA64_EL_SHIFT);
if (fpen == 3 || (fpen == 1 && arm_current_pl(env) != 0)) {
*flags |= ARM_TBFLAG_AA64_FPEN_MASK;
}
} else {
int privmode;
*pc = env->regs[15];
@@ -1157,9 +1172,13 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
if (privmode) {
*flags |= ARM_TBFLAG_PRIV_MASK;
}
if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
|| arm_el_is_aa64(env, 1)) {
*flags |= ARM_TBFLAG_VFPEN_MASK;
}
if (fpen == 3 || (fpen == 1 && arm_current_pl(env) != 0)) {
*flags |= ARM_TBFLAG_CPACR_FPEN_MASK;
}
}
*cs_base = 0;

View File

@@ -32,6 +32,104 @@ static inline void set_feature(CPUARMState *env, int feature)
env->features |= 1ULL << feature;
}
#ifndef CONFIG_USER_ONLY
static uint64_t a57_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
{
/* Number of processors is in [25:24]; otherwise we RAZ */
return (smp_cpus - 1) << 24;
}
#endif
static const ARMCPRegInfo cortexa57_cp_reginfo[] = {
#ifndef CONFIG_USER_ONLY
{ .name = "L2CTLR_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 1, .crn = 11, .crm = 0, .opc2 = 2,
.access = PL1_RW, .readfn = a57_l2ctlr_read,
.writefn = arm_cp_write_ignore },
{ .name = "L2CTLR",
.cp = 15, .opc1 = 1, .crn = 9, .crm = 0, .opc2 = 2,
.access = PL1_RW, .readfn = a57_l2ctlr_read,
.writefn = arm_cp_write_ignore },
#endif
{ .name = "L2ECTLR_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 1, .crn = 11, .crm = 0, .opc2 = 3,
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
{ .name = "L2ECTLR",
.cp = 15, .opc1 = 1, .crn = 9, .crm = 0, .opc2 = 3,
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
{ .name = "L2ACTLR", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 0, .opc2 = 0,
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
{ .name = "CPUACTLR_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 0,
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
{ .name = "CPUACTLR",
.cp = 15, .opc1 = 0, .crm = 15,
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
{ .name = "CPUECTLR_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 1,
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
{ .name = "CPUECTLR",
.cp = 15, .opc1 = 1, .crm = 15,
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
{ .name = "CPUMERRSR_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 2,
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
{ .name = "CPUMERRSR",
.cp = 15, .opc1 = 2, .crm = 15,
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
{ .name = "L2MERRSR_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 3,
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
{ .name = "L2MERRSR",
.cp = 15, .opc1 = 3, .crm = 15,
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
REGINFO_SENTINEL
};
static void aarch64_a57_initfn(Object *obj)
{
ARMCPU *cpu = ARM_CPU(obj);
set_feature(&cpu->env, ARM_FEATURE_V8);
set_feature(&cpu->env, ARM_FEATURE_VFP4);
set_feature(&cpu->env, ARM_FEATURE_VFP_FP16);
set_feature(&cpu->env, ARM_FEATURE_NEON);
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A57;
cpu->midr = 0x411fd070;
cpu->reset_fpsid = 0x41034070;
cpu->mvfr0 = 0x10110222;
cpu->mvfr1 = 0x12111111;
cpu->mvfr2 = 0x00000043;
cpu->ctr = 0x8444c004;
cpu->reset_sctlr = 0x00c50838;
cpu->id_pfr0 = 0x00000131;
cpu->id_pfr1 = 0x00011011;
cpu->id_dfr0 = 0x03010066;
cpu->id_afr0 = 0x00000000;
cpu->id_mmfr0 = 0x10101105;
cpu->id_mmfr1 = 0x40000000;
cpu->id_mmfr2 = 0x01260000;
cpu->id_mmfr3 = 0x02102211;
cpu->id_isar0 = 0x02101110;
cpu->id_isar1 = 0x13112111;
cpu->id_isar2 = 0x21232042;
cpu->id_isar3 = 0x01112131;
cpu->id_isar4 = 0x00011142;
cpu->id_aa64pfr0 = 0x00002222;
cpu->id_aa64dfr0 = 0x10305106;
cpu->id_aa64isar0 = 0x00010000;
cpu->id_aa64mmfr0 = 0x00001124;
cpu->clidr = 0x0a200023;
cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */
cpu->ccsidr[2] = 0x70ffe07a; /* 2048KB L2 cache */
cpu->dcz_blocksize = 4; /* 64 bytes */
}
#ifdef CONFIG_USER_ONLY
static void aarch64_any_initfn(Object *obj)
{
@@ -41,11 +139,11 @@ static void aarch64_any_initfn(Object *obj)
set_feature(&cpu->env, ARM_FEATURE_VFP4);
set_feature(&cpu->env, ARM_FEATURE_VFP_FP16);
set_feature(&cpu->env, ARM_FEATURE_NEON);
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
set_feature(&cpu->env, ARM_FEATURE_V7MP);
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
cpu->ctr = 0x80030003; /* 32 byte I and D cacheline size, VIPT icache */
cpu->dcz_blocksize = 7; /* 512 bytes */
}
#endif
@@ -56,6 +154,7 @@ typedef struct ARMCPUInfo {
} ARMCPUInfo;
static const ARMCPUInfo aarch64_cpus[] = {
{ .name = "cortex-a57", .initfn = aarch64_a57_initfn },
#ifdef CONFIG_USER_ONLY
{ .name = "any", .initfn = aarch64_any_initfn },
#endif
@@ -73,18 +172,22 @@ static void aarch64_cpu_finalizefn(Object *obj)
static void aarch64_cpu_set_pc(CPUState *cs, vaddr value)
{
ARMCPU *cpu = ARM_CPU(cs);
/*
* TODO: this will need updating for system emulation,
* when the core may be in AArch32 mode.
/* It's OK to look at env for the current mode here, because it's
* never possible for an AArch64 TB to chain to an AArch32 TB.
* (Otherwise we would need to use synchronize_from_tb instead.)
*/
cpu->env.pc = value;
if (is_a64(&cpu->env)) {
cpu->env.pc = value;
} else {
cpu->env.regs[15] = value;
}
}
static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
{
CPUClass *cc = CPU_CLASS(oc);
cc->dump_state = aarch64_cpu_dump_state;
cc->do_interrupt = aarch64_cpu_do_interrupt;
cc->set_pc = aarch64_cpu_set_pc;
cc->gdb_read_register = aarch64_cpu_gdb_read_register;
cc->gdb_write_register = aarch64_cpu_gdb_write_register;

View File

@@ -32,10 +32,8 @@ int aarch64_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
switch (n) {
case 31:
return gdb_get_reg64(mem_buf, env->xregs[31]);
break;
case 32:
return gdb_get_reg64(mem_buf, env->pc);
break;
case 33:
return gdb_get_reg32(mem_buf, pstate_read(env));
}

View File

@@ -23,6 +23,7 @@
#include "qemu/host-utils.h"
#include "sysemu/sysemu.h"
#include "qemu/bitops.h"
#include "internals.h"
/* C2.4.7 Multiply and divide */
/* special cases for 0 and LLONG_MIN are mandated by the standard */
@@ -436,3 +437,78 @@ float32 HELPER(fcvtx_f64_to_f32)(float64 a, CPUARMState *env)
set_float_exception_flags(exflags, fpst);
return r;
}
/* Handle a CPU exception. */
void aarch64_cpu_do_interrupt(CPUState *cs)
{
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
target_ulong addr = env->cp15.c12_vbar;
int i;
if (arm_current_pl(env) == 0) {
if (env->aarch64) {
addr += 0x400;
} else {
addr += 0x600;
}
} else if (pstate_read(env) & PSTATE_SP) {
addr += 0x200;
}
arm_log_exception(cs->exception_index);
qemu_log_mask(CPU_LOG_INT, "...from EL%d\n", arm_current_pl(env));
if (qemu_loglevel_mask(CPU_LOG_INT)
&& !excp_is_internal(cs->exception_index)) {
qemu_log_mask(CPU_LOG_INT, "...with ESR 0x%" PRIx32 "\n",
env->exception.syndrome);
}
env->cp15.esr_el1 = env->exception.syndrome;
env->cp15.far_el1 = env->exception.vaddress;
switch (cs->exception_index) {
case EXCP_PREFETCH_ABORT:
case EXCP_DATA_ABORT:
qemu_log_mask(CPU_LOG_INT, "...with FAR 0x%" PRIx64 "\n",
env->cp15.far_el1);
break;
case EXCP_BKPT:
case EXCP_UDEF:
case EXCP_SWI:
break;
case EXCP_IRQ:
addr += 0x80;
break;
case EXCP_FIQ:
addr += 0x100;
break;
default:
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
}
if (is_a64(env)) {
env->banked_spsr[0] = pstate_read(env);
env->sp_el[arm_current_pl(env)] = env->xregs[31];
env->xregs[31] = env->sp_el[1];
env->elr_el1 = env->pc;
} else {
env->banked_spsr[0] = cpsr_read(env);
if (!env->thumb) {
env->cp15.esr_el1 |= 1 << 25;
}
env->elr_el1 = env->regs[15];
for (i = 0; i < 15; i++) {
env->xregs[i] = env->regs[i];
}
env->condexec_bits = 0;
}
pstate_write(env, PSTATE_DAIF | PSTATE_MODE_EL1h);
env->aarch64 = 1;
env->pc = addr;
cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
}

File diff suppressed because it is too large Load Diff

View File

@@ -48,7 +48,8 @@ DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32)
DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
i32, i32, i32, i32)
DEF_HELPER_2(exception, void, env, i32)
DEF_HELPER_2(exception_internal, void, env, i32)
DEF_HELPER_3(exception_with_syndrome, void, env, i32, i32)
DEF_HELPER_1(wfi, void, env)
DEF_HELPER_1(wfe, void, env)
@@ -58,13 +59,14 @@ DEF_HELPER_1(cpsr_read, i32, env)
DEF_HELPER_3(v7m_msr, void, env, i32, i32)
DEF_HELPER_2(v7m_mrs, i32, env, i32)
DEF_HELPER_2(access_check_cp_reg, void, env, ptr)
DEF_HELPER_3(access_check_cp_reg, void, env, ptr, i32)
DEF_HELPER_3(set_cp_reg, void, env, ptr, i32)
DEF_HELPER_2(get_cp_reg, i32, env, ptr)
DEF_HELPER_3(set_cp_reg64, void, env, ptr, i64)
DEF_HELPER_2(get_cp_reg64, i64, env, ptr)
DEF_HELPER_3(msr_i_pstate, void, env, i32, i32)
DEF_HELPER_1(exception_return, void, env)
DEF_HELPER_2(get_r13_banked, i32, env, i32)
DEF_HELPER_3(set_r13_banked, void, env, i32, i32)
@@ -514,6 +516,7 @@ DEF_HELPER_4(crypto_aesmc, void, env, i32, i32, i32)
DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
DEF_HELPER_2(dc_zva, void, env, i64)
#ifdef TARGET_AARCH64
#include "helper-a64.h"

267
target-arm/internals.h Normal file
View File

@@ -0,0 +1,267 @@
/*
* QEMU ARM CPU -- internal functions and types
*
* Copyright (c) 2014 Linaro Ltd
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see
* <http://www.gnu.org/licenses/gpl-2.0.html>
*
* This header defines functions, types, etc which need to be shared
* between different source files within target-arm/ but which are
* private to it and not required by the rest of QEMU.
*/
#ifndef TARGET_ARM_INTERNALS_H
#define TARGET_ARM_INTERNALS_H
static inline bool excp_is_internal(int excp)
{
/* Return true if this exception number represents a QEMU-internal
* exception that will not be passed to the guest.
*/
return excp == EXCP_INTERRUPT
|| excp == EXCP_HLT
|| excp == EXCP_DEBUG
|| excp == EXCP_HALTED
|| excp == EXCP_EXCEPTION_EXIT
|| excp == EXCP_KERNEL_TRAP
|| excp == EXCP_STREX;
}
/* Exception names for debug logging; note that not all of these
* precisely correspond to architectural exceptions.
*/
static const char * const excnames[] = {
[EXCP_UDEF] = "Undefined Instruction",
[EXCP_SWI] = "SVC",
[EXCP_PREFETCH_ABORT] = "Prefetch Abort",
[EXCP_DATA_ABORT] = "Data Abort",
[EXCP_IRQ] = "IRQ",
[EXCP_FIQ] = "FIQ",
[EXCP_BKPT] = "Breakpoint",
[EXCP_EXCEPTION_EXIT] = "QEMU v7M exception exit",
[EXCP_KERNEL_TRAP] = "QEMU intercept of kernel commpage",
[EXCP_STREX] = "QEMU intercept of STREX",
};
static inline void arm_log_exception(int idx)
{
if (qemu_loglevel_mask(CPU_LOG_INT)) {
const char *exc = NULL;
if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
exc = excnames[idx];
}
if (!exc) {
exc = "unknown";
}
qemu_log_mask(CPU_LOG_INT, "Taking exception %d [%s]\n", idx, exc);
}
}
/* Scale factor for generic timers, ie number of ns per tick.
* This gives a 62.5MHz timer.
*/
#define GTIMER_SCALE 16
int bank_number(int mode);
void switch_mode(CPUARMState *, int);
void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu);
void arm_translate_init(void);
enum arm_fprounding {
FPROUNDING_TIEEVEN,
FPROUNDING_POSINF,
FPROUNDING_NEGINF,
FPROUNDING_ZERO,
FPROUNDING_TIEAWAY,
FPROUNDING_ODD
};
int arm_rmode_to_sf(int rmode);
static inline void update_spsel(CPUARMState *env, uint32_t imm)
{
/* Update PSTATE SPSel bit; this requires us to update the
* working stack pointer in xregs[31].
*/
if (!((imm ^ env->pstate) & PSTATE_SP)) {
return;
}
env->pstate = deposit32(env->pstate, 0, 1, imm);
/* EL0 has no access rights to update SPSel, and this code
* assumes we are updating SP for EL1 while running as EL1.
*/
assert(arm_current_pl(env) == 1);
if (env->pstate & PSTATE_SP) {
/* Switch from using SP_EL0 to using SP_ELx */
env->sp_el[0] = env->xregs[31];
env->xregs[31] = env->sp_el[1];
} else {
/* Switch from SP_EL0 to SP_ELx */
env->sp_el[1] = env->xregs[31];
env->xregs[31] = env->sp_el[0];
}
}
/* Valid Syndrome Register EC field values */
enum arm_exception_class {
EC_UNCATEGORIZED = 0x00,
EC_WFX_TRAP = 0x01,
EC_CP15RTTRAP = 0x03,
EC_CP15RRTTRAP = 0x04,
EC_CP14RTTRAP = 0x05,
EC_CP14DTTRAP = 0x06,
EC_ADVSIMDFPACCESSTRAP = 0x07,
EC_FPIDTRAP = 0x08,
EC_CP14RRTTRAP = 0x0c,
EC_ILLEGALSTATE = 0x0e,
EC_AA32_SVC = 0x11,
EC_AA32_HVC = 0x12,
EC_AA32_SMC = 0x13,
EC_AA64_SVC = 0x15,
EC_AA64_HVC = 0x16,
EC_AA64_SMC = 0x17,
EC_SYSTEMREGISTERTRAP = 0x18,
EC_INSNABORT = 0x20,
EC_INSNABORT_SAME_EL = 0x21,
EC_PCALIGNMENT = 0x22,
EC_DATAABORT = 0x24,
EC_DATAABORT_SAME_EL = 0x25,
EC_SPALIGNMENT = 0x26,
EC_AA32_FPTRAP = 0x28,
EC_AA64_FPTRAP = 0x2c,
EC_SERROR = 0x2f,
EC_BREAKPOINT = 0x30,
EC_BREAKPOINT_SAME_EL = 0x31,
EC_SOFTWARESTEP = 0x32,
EC_SOFTWARESTEP_SAME_EL = 0x33,
EC_WATCHPOINT = 0x34,
EC_WATCHPOINT_SAME_EL = 0x35,
EC_AA32_BKPT = 0x38,
EC_VECTORCATCH = 0x3a,
EC_AA64_BKPT = 0x3c,
};
#define ARM_EL_EC_SHIFT 26
#define ARM_EL_IL_SHIFT 25
#define ARM_EL_IL (1 << ARM_EL_IL_SHIFT)
/* Utility functions for constructing various kinds of syndrome value.
* Note that in general we follow the AArch64 syndrome values; in a
* few cases the value in HSR for exceptions taken to AArch32 Hyp
* mode differs slightly, so if we ever implemented Hyp mode then the
* syndrome value would need some massaging on exception entry.
* (One example of this is that AArch64 defaults to IL bit set for
* exceptions which don't specifically indicate information about the
* trapping instruction, whereas AArch32 defaults to IL bit clear.)
*/
static inline uint32_t syn_uncategorized(void)
{
return (EC_UNCATEGORIZED << ARM_EL_EC_SHIFT) | ARM_EL_IL;
}
static inline uint32_t syn_aa64_svc(uint32_t imm16)
{
return (EC_AA64_SVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
}
static inline uint32_t syn_aa32_svc(uint32_t imm16, bool is_thumb)
{
return (EC_AA32_SVC << ARM_EL_EC_SHIFT) | (imm16 & 0xffff)
| (is_thumb ? 0 : ARM_EL_IL);
}
static inline uint32_t syn_aa64_bkpt(uint32_t imm16)
{
return (EC_AA64_BKPT << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
}
static inline uint32_t syn_aa32_bkpt(uint32_t imm16, bool is_thumb)
{
return (EC_AA32_BKPT << ARM_EL_EC_SHIFT) | (imm16 & 0xffff)
| (is_thumb ? 0 : ARM_EL_IL);
}
static inline uint32_t syn_aa64_sysregtrap(int op0, int op1, int op2,
int crn, int crm, int rt,
int isread)
{
return (EC_SYSTEMREGISTERTRAP << ARM_EL_EC_SHIFT) | ARM_EL_IL
| (op0 << 20) | (op2 << 17) | (op1 << 14) | (crn << 10) | (rt << 5)
| (crm << 1) | isread;
}
static inline uint32_t syn_cp14_rt_trap(int cv, int cond, int opc1, int opc2,
int crn, int crm, int rt, int isread,
bool is_thumb)
{
return (EC_CP14RTTRAP << ARM_EL_EC_SHIFT)
| (is_thumb ? 0 : ARM_EL_IL)
| (cv << 24) | (cond << 20) | (opc2 << 17) | (opc1 << 14)
| (crn << 10) | (rt << 5) | (crm << 1) | isread;
}
static inline uint32_t syn_cp15_rt_trap(int cv, int cond, int opc1, int opc2,
int crn, int crm, int rt, int isread,
bool is_thumb)
{
return (EC_CP15RTTRAP << ARM_EL_EC_SHIFT)
| (is_thumb ? 0 : ARM_EL_IL)
| (cv << 24) | (cond << 20) | (opc2 << 17) | (opc1 << 14)
| (crn << 10) | (rt << 5) | (crm << 1) | isread;
}
static inline uint32_t syn_cp14_rrt_trap(int cv, int cond, int opc1, int crm,
int rt, int rt2, int isread,
bool is_thumb)
{
return (EC_CP14RRTTRAP << ARM_EL_EC_SHIFT)
| (is_thumb ? 0 : ARM_EL_IL)
| (cv << 24) | (cond << 20) | (opc1 << 16)
| (rt2 << 10) | (rt << 5) | (crm << 1) | isread;
}
static inline uint32_t syn_cp15_rrt_trap(int cv, int cond, int opc1, int crm,
int rt, int rt2, int isread,
bool is_thumb)
{
return (EC_CP15RRTTRAP << ARM_EL_EC_SHIFT)
| (is_thumb ? 0 : ARM_EL_IL)
| (cv << 24) | (cond << 20) | (opc1 << 16)
| (rt2 << 10) | (rt << 5) | (crm << 1) | isread;
}
static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_thumb)
{
return (EC_ADVSIMDFPACCESSTRAP << ARM_EL_EC_SHIFT)
| (is_thumb ? 0 : ARM_EL_IL)
| (cv << 24) | (cond << 20);
}
static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc)
{
return (EC_INSNABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
| (ea << 9) | (s1ptw << 7) | fsc;
}
static inline uint32_t syn_data_abort(int same_el, int ea, int cm, int s1ptw,
int wnr, int fsc)
{
return (EC_DATAABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
| (ea << 9) | (cm << 8) | (s1ptw << 7) | (wnr << 6) | fsc;
}
#endif

View File

@@ -21,6 +21,7 @@
#include "sysemu/kvm.h"
#include "kvm_arm.h"
#include "cpu.h"
#include "internals.h"
#include "hw/arm/arm.h"
static inline void set_feature(uint64_t *features, int feature)
@@ -294,6 +295,14 @@ typedef struct Reg {
offsetof(CPUARMState, vfp.xregs[ARM_VFP_##R]) \
}
/* Like COREREG, but handle fields which are in a uint64_t in CPUARMState. */
#define COREREG64(KERNELNAME, QEMUFIELD) \
{ \
KVM_REG_ARM | KVM_REG_SIZE_U32 | \
KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(KERNELNAME), \
offsetoflow32(CPUARMState, QEMUFIELD) \
}
static const Reg regs[] = {
/* R0_usr .. R14_usr */
COREREG(usr_regs.uregs[0], regs[0]),
@@ -314,16 +323,16 @@ static const Reg regs[] = {
/* R13, R14, SPSR for SVC, ABT, UND, IRQ banks */
COREREG(svc_regs[0], banked_r13[1]),
COREREG(svc_regs[1], banked_r14[1]),
COREREG(svc_regs[2], banked_spsr[1]),
COREREG64(svc_regs[2], banked_spsr[1]),
COREREG(abt_regs[0], banked_r13[2]),
COREREG(abt_regs[1], banked_r14[2]),
COREREG(abt_regs[2], banked_spsr[2]),
COREREG64(abt_regs[2], banked_spsr[2]),
COREREG(und_regs[0], banked_r13[3]),
COREREG(und_regs[1], banked_r14[3]),
COREREG(und_regs[2], banked_spsr[3]),
COREREG64(und_regs[2], banked_spsr[3]),
COREREG(irq_regs[0], banked_r13[4]),
COREREG(irq_regs[1], banked_r14[4]),
COREREG(irq_regs[2], banked_spsr[4]),
COREREG64(irq_regs[2], banked_spsr[4]),
/* R8_fiq .. R14_fiq and SPSR_fiq */
COREREG(fiq_regs[0], fiq_regs[0]),
COREREG(fiq_regs[1], fiq_regs[1]),
@@ -332,7 +341,7 @@ static const Reg regs[] = {
COREREG(fiq_regs[4], fiq_regs[4]),
COREREG(fiq_regs[5], banked_r13[5]),
COREREG(fiq_regs[6], banked_r14[5]),
COREREG(fiq_regs[7], banked_spsr[5]),
COREREG64(fiq_regs[7], banked_spsr[5]),
/* R15 */
COREREG(usr_regs.uregs[15], regs[15]),
/* VFP system registers */

View File

@@ -121,8 +121,24 @@ int kvm_arch_put_registers(CPUState *cs, int level)
}
}
/* KVM puts SP_EL0 in regs.sp and SP_EL1 in regs.sp_el1. On the
* QEMU side we keep the current SP in xregs[31] as well.
*/
if (env->pstate & PSTATE_SP) {
env->sp_el[1] = env->xregs[31];
} else {
env->sp_el[0] = env->xregs[31];
}
reg.id = AARCH64_CORE_REG(regs.sp);
reg.addr = (uintptr_t) &env->xregs[31];
reg.addr = (uintptr_t) &env->sp_el[0];
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
if (ret) {
return ret;
}
reg.id = AARCH64_CORE_REG(sp_el1);
reg.addr = (uintptr_t) &env->sp_el[1];
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
if (ret) {
return ret;
@@ -144,10 +160,23 @@ int kvm_arch_put_registers(CPUState *cs, int level)
return ret;
}
reg.id = AARCH64_CORE_REG(elr_el1);
reg.addr = (uintptr_t) &env->elr_el1;
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
if (ret) {
return ret;
}
for (i = 0; i < KVM_NR_SPSR; i++) {
reg.id = AARCH64_CORE_REG(spsr[i]);
reg.addr = (uintptr_t) &env->banked_spsr[i - 1];
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
if (ret) {
return ret;
}
}
/* TODO:
* SP_EL1
* ELR_EL1
* SPSR[]
* FP state
* system registers
*/
@@ -174,7 +203,14 @@ int kvm_arch_get_registers(CPUState *cs)
}
reg.id = AARCH64_CORE_REG(regs.sp);
reg.addr = (uintptr_t) &env->xregs[31];
reg.addr = (uintptr_t) &env->sp_el[0];
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
if (ret) {
return ret;
}
reg.id = AARCH64_CORE_REG(sp_el1);
reg.addr = (uintptr_t) &env->sp_el[1];
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
if (ret) {
return ret;
@@ -188,6 +224,15 @@ int kvm_arch_get_registers(CPUState *cs)
}
pstate_write(env, val);
/* KVM puts SP_EL0 in regs.sp and SP_EL1 in regs.sp_el1. On the
* QEMU side we keep the current SP in xregs[31] as well.
*/
if (env->pstate & PSTATE_SP) {
env->xregs[31] = env->sp_el[1];
} else {
env->xregs[31] = env->sp_el[0];
}
reg.id = AARCH64_CORE_REG(regs.pc);
reg.addr = (uintptr_t) &env->pc;
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
@@ -195,6 +240,22 @@ int kvm_arch_get_registers(CPUState *cs)
return ret;
}
reg.id = AARCH64_CORE_REG(elr_el1);
reg.addr = (uintptr_t) &env->elr_el1;
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
if (ret) {
return ret;
}
for (i = 0; i < KVM_NR_SPSR; i++) {
reg.id = AARCH64_CORE_REG(spsr[i]);
reg.addr = (uintptr_t) &env->banked_spsr[i - 1];
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
if (ret) {
return ret;
}
}
/* TODO: other registers */
return ret;
}

View File

@@ -222,9 +222,9 @@ static int cpu_post_load(void *opaque, int version_id)
const VMStateDescription vmstate_arm_cpu = {
.name = "cpu",
.version_id = 14,
.minimum_version_id = 14,
.minimum_version_id_old = 14,
.version_id = 17,
.minimum_version_id = 17,
.minimum_version_id_old = 17,
.pre_save = cpu_pre_save,
.post_load = cpu_post_load,
.fields = (VMStateField[]) {
@@ -238,11 +238,13 @@ const VMStateDescription vmstate_arm_cpu = {
.offset = 0,
},
VMSTATE_UINT32(env.spsr, ARMCPU),
VMSTATE_UINT32_ARRAY(env.banked_spsr, ARMCPU, 6),
VMSTATE_UINT64_ARRAY(env.banked_spsr, ARMCPU, 6),
VMSTATE_UINT32_ARRAY(env.banked_r13, ARMCPU, 6),
VMSTATE_UINT32_ARRAY(env.banked_r14, ARMCPU, 6),
VMSTATE_UINT32_ARRAY(env.usr_regs, ARMCPU, 5),
VMSTATE_UINT32_ARRAY(env.fiq_regs, ARMCPU, 5),
VMSTATE_UINT64(env.elr_el1, ARMCPU),
VMSTATE_UINT64_ARRAY(env.sp_el, ARMCPU, 2),
/* The length-check must come before the arrays to avoid
* incoming data possibly overflowing the array.
*/
@@ -257,6 +259,9 @@ const VMStateDescription vmstate_arm_cpu = {
VMSTATE_UINT64(env.exclusive_val, ARMCPU),
VMSTATE_UINT64(env.exclusive_high, ARMCPU),
VMSTATE_UINT64(env.features, ARMCPU),
VMSTATE_UINT32(env.exception.syndrome, ARMCPU),
VMSTATE_UINT32(env.exception.fsr, ARMCPU),
VMSTATE_UINT64(env.exception.vaddress, ARMCPU),
VMSTATE_TIMER(gt_timer[GTIMER_PHYS], ARMCPU),
VMSTATE_TIMER(gt_timer[GTIMER_VIRT], ARMCPU),
VMSTATE_END_OF_LIST()

View File

@@ -18,6 +18,7 @@
*/
#include "cpu.h"
#include "helper.h"
#include "internals.h"
#define SIGNBIT (uint32_t)0x80000000
#define SIGNBIT64 ((uint64_t)1 << 63)
@@ -243,14 +244,33 @@ void HELPER(wfe)(CPUARMState *env)
cpu_loop_exit(cs);
}
void HELPER(exception)(CPUARMState *env, uint32_t excp)
/* Raise an internal-to-QEMU exception. This is limited to only
* those EXCP values which are special cases for QEMU to interrupt
* execution and not to be used for exceptions which are passed to
* the guest (those must all have syndrome information and thus should
* use exception_with_syndrome).
*/
void HELPER(exception_internal)(CPUARMState *env, uint32_t excp)
{
CPUState *cs = CPU(arm_env_get_cpu(env));
assert(excp_is_internal(excp));
cs->exception_index = excp;
cpu_loop_exit(cs);
}
/* Raise an exception with the specified syndrome register value */
void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp,
uint32_t syndrome)
{
CPUState *cs = CPU(arm_env_get_cpu(env));
assert(!excp_is_internal(excp));
cs->exception_index = excp;
env->exception.syndrome = syndrome;
cpu_loop_exit(cs);
}
uint32_t HELPER(cpsr_read)(CPUARMState *env)
{
return cpsr_read(env) & ~CPSR_EXEC;
@@ -293,17 +313,17 @@ void HELPER(set_user_reg)(CPUARMState *env, uint32_t regno, uint32_t val)
}
}
void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip)
void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome)
{
const ARMCPRegInfo *ri = rip;
switch (ri->accessfn(env, ri)) {
case CP_ACCESS_OK:
return;
case CP_ACCESS_TRAP:
env->exception.syndrome = syndrome;
break;
case CP_ACCESS_TRAP_UNCATEGORIZED:
/* These cases will eventually need to generate different
* syndrome information.
*/
env->exception.syndrome = syn_uncategorized();
break;
default:
g_assert_not_reached();
@@ -351,7 +371,7 @@ void HELPER(msr_i_pstate)(CPUARMState *env, uint32_t op, uint32_t imm)
switch (op) {
case 0x05: /* SPSel */
env->pstate = deposit32(env->pstate, 0, 1, imm);
update_spsel(env, imm);
break;
case 0x1e: /* DAIFSet */
env->daif |= (imm << 6) & PSTATE_DAIF;
@@ -364,6 +384,66 @@ void HELPER(msr_i_pstate)(CPUARMState *env, uint32_t op, uint32_t imm)
}
}
void HELPER(exception_return)(CPUARMState *env)
{
uint32_t spsr = env->banked_spsr[0];
int new_el, i;
if (env->pstate & PSTATE_SP) {
env->sp_el[1] = env->xregs[31];
} else {
env->sp_el[0] = env->xregs[31];
}
env->exclusive_addr = -1;
if (spsr & PSTATE_nRW) {
env->aarch64 = 0;
new_el = 0;
env->uncached_cpsr = 0x10;
cpsr_write(env, spsr, ~0);
for (i = 0; i < 15; i++) {
env->regs[i] = env->xregs[i];
}
env->regs[15] = env->elr_el1 & ~0x1;
} else {
new_el = extract32(spsr, 2, 2);
if (new_el > 1) {
/* Return to unimplemented EL */
goto illegal_return;
}
if (extract32(spsr, 1, 1)) {
/* Return with reserved M[1] bit set */
goto illegal_return;
}
if (new_el == 0 && (spsr & PSTATE_SP)) {
/* Return to EL1 with M[0] bit set */
goto illegal_return;
}
env->aarch64 = 1;
pstate_write(env, spsr);
env->xregs[31] = env->sp_el[new_el];
env->pc = env->elr_el1;
}
return;
illegal_return:
/* Illegal return events of various kinds have architecturally
* mandated behaviour:
* restore NZCV and DAIF from SPSR_ELx
* set PSTATE.IL
* restore PC from ELR_ELx
* no change to exception level, execution state or stack pointer
*/
env->pstate |= PSTATE_IL;
env->pc = env->elr_el1;
spsr &= PSTATE_NZCV | PSTATE_DAIF;
spsr |= pstate_read(env) & ~(PSTATE_NZCV | PSTATE_DAIF);
pstate_write(env, spsr);
}
/* ??? Flag setting arithmetic is awkward because we need to do comparisons.
The only way to do that in TCG is a conditional branch, which clobbers
all our temporaries. For now implement these as helper functions. */

File diff suppressed because it is too large Load Diff

View File

@@ -25,6 +25,7 @@
#include <inttypes.h>
#include "cpu.h"
#include "internals.h"
#include "disas/disas.h"
#include "tcg-op.h"
#include "qemu/log.h"
@@ -182,12 +183,23 @@ static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
/* Set NZCV flags from the high 4 bits of var. */
#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
static void gen_exception(int excp)
static void gen_exception_internal(int excp)
{
TCGv_i32 tmp = tcg_temp_new_i32();
tcg_gen_movi_i32(tmp, excp);
gen_helper_exception(cpu_env, tmp);
tcg_temp_free_i32(tmp);
TCGv_i32 tcg_excp = tcg_const_i32(excp);
assert(excp_is_internal(excp));
gen_helper_exception_internal(cpu_env, tcg_excp);
tcg_temp_free_i32(tcg_excp);
}
static void gen_exception(int excp, uint32_t syndrome)
{
TCGv_i32 tcg_excp = tcg_const_i32(excp);
TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
gen_helper_exception_with_syndrome(cpu_env, tcg_excp, tcg_syn);
tcg_temp_free_i32(tcg_syn);
tcg_temp_free_i32(tcg_excp);
}
static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
@@ -899,6 +911,33 @@ static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
tcg_gen_movi_i32(cpu_R[15], val);
}
static inline void
gen_set_condexec (DisasContext *s)
{
if (s->condexec_mask) {
uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
TCGv_i32 tmp = tcg_temp_new_i32();
tcg_gen_movi_i32(tmp, val);
store_cpu_field(tmp, condexec_bits);
}
}
static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
{
gen_set_condexec(s);
gen_set_pc_im(s, s->pc - offset);
gen_exception_internal(excp);
s->is_jmp = DISAS_JUMP;
}
static void gen_exception_insn(DisasContext *s, int offset, int excp, int syn)
{
gen_set_condexec(s);
gen_set_pc_im(s, s->pc - offset);
gen_exception(excp, syn);
s->is_jmp = DISAS_JUMP;
}
/* Force a TB lookup after an instruction that changes the CPU state. */
static inline void gen_lookup_tb(DisasContext *s)
{
@@ -2913,14 +2952,25 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
if (!arm_feature(env, ARM_FEATURE_VFP))
return 1;
/* FIXME: this access check should not take precedence over UNDEF
* for invalid encodings; we will generate incorrect syndrome information
* for attempts to execute invalid vfp/neon encodings with FP disabled.
*/
if (!s->cpacr_fpen) {
gen_exception_insn(s, 4, EXCP_UDEF,
syn_fp_access_trap(1, 0xe, s->thumb));
return 0;
}
if (!s->vfp_enabled) {
/* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
if ((insn & 0x0fe00fff) != 0x0ee00a10)
return 1;
rn = (insn >> 16) & 0xf;
if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
&& rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC && rn != ARM_VFP_MVFR2
&& rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0) {
return 1;
}
}
if (extract32(insn, 28, 4) == 0xf) {
@@ -3066,6 +3116,11 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
gen_helper_vfp_get_fpscr(tmp, cpu_env);
}
break;
case ARM_VFP_MVFR2:
if (!arm_feature(env, ARM_FEATURE_V8)) {
return 1;
}
/* fall through */
case ARM_VFP_MVFR0:
case ARM_VFP_MVFR1:
if (IS_USER(s)
@@ -3912,25 +3967,6 @@ static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
s->is_jmp = DISAS_UPDATE;
}
static inline void
gen_set_condexec (DisasContext *s)
{
if (s->condexec_mask) {
uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
TCGv_i32 tmp = tcg_temp_new_i32();
tcg_gen_movi_i32(tmp, val);
store_cpu_field(tmp, condexec_bits);
}
}
static void gen_exception_insn(DisasContext *s, int offset, int excp)
{
gen_set_condexec(s);
gen_set_pc_im(s, s->pc - offset);
gen_exception(excp);
s->is_jmp = DISAS_JUMP;
}
static void gen_nop_hint(DisasContext *s, int val)
{
switch (val) {
@@ -4212,6 +4248,16 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
TCGv_i32 tmp2;
TCGv_i64 tmp64;
/* FIXME: this access check should not take precedence over UNDEF
* for invalid encodings; we will generate incorrect syndrome information
* for attempts to execute invalid vfp/neon encodings with FP disabled.
*/
if (!s->cpacr_fpen) {
gen_exception_insn(s, 4, EXCP_UDEF,
syn_fp_access_trap(1, 0xe, s->thumb));
return 0;
}
if (!s->vfp_enabled)
return 1;
VFP_DREG_D(rd, insn);
@@ -4934,6 +4980,16 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
TCGv_i64 tmp64;
/* FIXME: this access check should not take precedence over UNDEF
* for invalid encodings; we will generate incorrect syndrome information
* for attempts to execute invalid vfp/neon encodings with FP disabled.
*/
if (!s->cpacr_fpen) {
gen_exception_insn(s, 4, EXCP_UDEF,
syn_fp_access_trap(1, 0xe, s->thumb));
return 0;
}
if (!s->vfp_enabled)
return 1;
q = (insn & (1 << 6)) != 0;
@@ -6861,10 +6917,53 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
* runtime; this may result in an exception.
*/
TCGv_ptr tmpptr;
TCGv_i32 tcg_syn;
uint32_t syndrome;
/* Note that since we are an implementation which takes an
* exception on a trapped conditional instruction only if the
* instruction passes its condition code check, we can take
* advantage of the clause in the ARM ARM that allows us to set
* the COND field in the instruction to 0xE in all cases.
* We could fish the actual condition out of the insn (ARM)
* or the condexec bits (Thumb) but it isn't necessary.
*/
switch (cpnum) {
case 14:
if (is64) {
syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
isread, s->thumb);
} else {
syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
rt, isread, s->thumb);
}
break;
case 15:
if (is64) {
syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
isread, s->thumb);
} else {
syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
rt, isread, s->thumb);
}
break;
default:
/* ARMv8 defines that only coprocessors 14 and 15 exist,
* so this can only happen if this is an ARMv7 or earlier CPU,
* in which case the syndrome information won't actually be
* guest visible.
*/
assert(!arm_feature(env, ARM_FEATURE_V8));
syndrome = syn_uncategorized();
break;
}
gen_set_pc_im(s, s->pc);
tmpptr = tcg_const_ptr(ri);
gen_helper_access_check_cp_reg(cpu_env, tmpptr);
tcg_syn = tcg_const_i32(syndrome);
gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn);
tcg_temp_free_ptr(tmpptr);
tcg_temp_free_i32(tcg_syn);
}
/* Handle special cases first */
@@ -7116,7 +7215,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
tcg_gen_extu_i32_i64(cpu_exclusive_test, addr);
tcg_gen_movi_i32(cpu_exclusive_info,
size | (rd << 4) | (rt << 8) | (rt2 << 12));
gen_exception_insn(s, 4, EXCP_STREX);
gen_exception_internal_insn(s, 4, EXCP_STREX);
}
#else
static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
@@ -7626,6 +7725,8 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
store_reg(s, rd, tmp);
break;
case 7:
{
int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
/* SMC instruction (op1 == 3)
and undefined instructions (op1 == 0 || op1 == 2)
will trap */
@@ -7634,8 +7735,9 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
}
/* bkpt */
ARCH(5);
gen_exception_insn(s, 4, EXCP_BKPT);
gen_exception_insn(s, 4, EXCP_BKPT, syn_aa32_bkpt(imm16, false));
break;
}
case 0x8: /* signed multiply */
case 0xa:
case 0xc:
@@ -8328,27 +8430,39 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
if (insn & (1 << 5))
gen_swap_half(tmp2);
gen_smul_dual(tmp, tmp2);
if (insn & (1 << 6)) {
/* This subtraction cannot overflow. */
tcg_gen_sub_i32(tmp, tmp, tmp2);
} else {
/* This addition cannot overflow 32 bits;
* however it may overflow considered as a signed
* operation, in which case we must set the Q flag.
*/
gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
}
tcg_temp_free_i32(tmp2);
if (insn & (1 << 22)) {
/* smlald, smlsld */
TCGv_i64 tmp64_2;
tmp64 = tcg_temp_new_i64();
tmp64_2 = tcg_temp_new_i64();
tcg_gen_ext_i32_i64(tmp64, tmp);
tcg_gen_ext_i32_i64(tmp64_2, tmp2);
tcg_temp_free_i32(tmp);
tcg_temp_free_i32(tmp2);
if (insn & (1 << 6)) {
tcg_gen_sub_i64(tmp64, tmp64, tmp64_2);
} else {
tcg_gen_add_i64(tmp64, tmp64, tmp64_2);
}
tcg_temp_free_i64(tmp64_2);
gen_addq(s, tmp64, rd, rn);
gen_storeq_reg(s, rd, rn, tmp64);
tcg_temp_free_i64(tmp64);
} else {
/* smuad, smusd, smlad, smlsd */
if (insn & (1 << 6)) {
/* This subtraction cannot overflow. */
tcg_gen_sub_i32(tmp, tmp, tmp2);
} else {
/* This addition cannot overflow 32 bits;
* however it may overflow considered as a
* signed operation, in which case we must set
* the Q flag.
*/
gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
}
tcg_temp_free_i32(tmp2);
if (rd != 15)
{
tmp2 = load_reg(s, rd);
@@ -8642,11 +8756,12 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
case 0xf:
/* swi */
gen_set_pc_im(s, s->pc);
s->svc_imm = extract32(insn, 0, 24);
s->is_jmp = DISAS_SWI;
break;
default:
illegal_op:
gen_exception_insn(s, 4, EXCP_UDEF);
gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized());
break;
}
}
@@ -10457,9 +10572,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
break;
case 0xe: /* bkpt */
{
int imm8 = extract32(insn, 0, 8);
ARCH(5);
gen_exception_insn(s, 2, EXCP_BKPT);
gen_exception_insn(s, 2, EXCP_BKPT, syn_aa32_bkpt(imm8, true));
break;
}
case 0xa: /* rev */
ARCH(6);
@@ -10576,6 +10694,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (cond == 0xf) {
/* swi */
gen_set_pc_im(s, s->pc);
s->svc_imm = extract32(insn, 0, 8);
s->is_jmp = DISAS_SWI;
break;
}
@@ -10611,11 +10730,11 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
}
return;
undef32:
gen_exception_insn(s, 4, EXCP_UDEF);
gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized());
return;
illegal_op:
undef:
gen_exception_insn(s, 2, EXCP_UDEF);
gen_exception_insn(s, 2, EXCP_UDEF, syn_uncategorized());
}
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
@@ -10665,6 +10784,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
#if !defined(CONFIG_USER_ONLY)
dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
#endif
dc->cpacr_fpen = ARM_TBFLAG_CPACR_FPEN(tb->flags);
dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
@@ -10736,7 +10856,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
if (dc->pc >= 0xffff0000) {
/* We always get here via a jump, so know we are not in a
conditional execution block. */
gen_exception(EXCP_KERNEL_TRAP);
gen_exception_internal(EXCP_KERNEL_TRAP);
dc->is_jmp = DISAS_UPDATE;
break;
}
@@ -10744,7 +10864,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
if (dc->pc >= 0xfffffff0 && IS_M(env)) {
/* We always get here via a jump, so know we are not in a
conditional execution block. */
gen_exception(EXCP_EXCEPTION_EXIT);
gen_exception_internal(EXCP_EXCEPTION_EXIT);
dc->is_jmp = DISAS_UPDATE;
break;
}
@@ -10753,7 +10873,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == dc->pc) {
gen_exception_insn(dc, 0, EXCP_DEBUG);
gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
/* Advance PC so that clearing the breakpoint will
invalidate this TB. */
dc->pc += 2;
@@ -10833,9 +10953,9 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
if (dc->condjmp) {
gen_set_condexec(dc);
if (dc->is_jmp == DISAS_SWI) {
gen_exception(EXCP_SWI);
gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
} else {
gen_exception(EXCP_DEBUG);
gen_exception_internal(EXCP_DEBUG);
}
gen_set_label(dc->condlabel);
}
@@ -10845,11 +10965,11 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
}
gen_set_condexec(dc);
if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
gen_exception(EXCP_SWI);
gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
} else {
/* FIXME: Single stepping a WFI insn will not halt
the CPU. */
gen_exception(EXCP_DEBUG);
gen_exception_internal(EXCP_DEBUG);
}
} else {
/* While branches must always occur at the end of an IT block,
@@ -10881,7 +11001,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
gen_helper_wfe(cpu_env);
break;
case DISAS_SWI:
gen_exception(EXCP_SWI);
gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
break;
}
if (dc->condjmp) {
@@ -10939,6 +11059,11 @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
int i;
uint32_t psr;
if (is_a64(env)) {
aarch64_cpu_dump_state(cs, f, cpu_fprintf, flags);
return;
}
for(i=0;i<16;i++) {
cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
if ((i % 4) == 3)

View File

@@ -20,13 +20,26 @@ typedef struct DisasContext {
#if !defined(CONFIG_USER_ONLY)
int user;
#endif
int vfp_enabled;
bool cpacr_fpen; /* FP enabled via CPACR.FPEN */
bool vfp_enabled; /* FP enabled via FPSCR.EN */
int vec_len;
int vec_stride;
/* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI
* so that top level loop can generate correct syndrome information.
*/
uint32_t svc_imm;
int aarch64;
int current_pl;
GHashTable *cp_regs;
uint64_t features; /* CPU features bits */
/* Because unallocated encodings generate different exception syndrome
* information from traps due to FP being disabled, we can't do a single
* "is fp access disabled" check at a high level in the decode tree.
* To help in catching bugs where the access check was forgotten in some
* code path, we set this flag when the access check is done, and assert
* that it is set at the point where we actually touch the FP regs.
*/
bool fp_access_checked;
#define TMP_A64_MAX 16
int tmp_a64_count;
TCGv_i64 tmp_a64[TMP_A64_MAX];
@@ -59,6 +72,8 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
TranslationBlock *tb,
bool search_pc);
void gen_a64_set_pc_im(uint64_t val);
void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
fprintf_function cpu_fprintf, int flags);
#else
static inline void a64_translate_init(void)
{
@@ -73,6 +88,12 @@ static inline void gen_intermediate_code_internal_a64(ARMCPU *cpu,
static inline void gen_a64_set_pc_im(uint64_t val)
{
}
static inline void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
fprintf_function cpu_fprintf,
int flags)
{
}
#endif
void arm_gen_test_cc(int cc, int label);

View File

@@ -1133,6 +1133,7 @@ uint64_t cpu_ppc_load_atbl (CPUPPCState *env);
uint32_t cpu_ppc_load_atbu (CPUPPCState *env);
void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value);
void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value);
bool ppc_decr_clear_on_delivery(CPUPPCState *env);
uint32_t cpu_ppc_load_decr (CPUPPCState *env);
void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value);
uint32_t cpu_ppc_load_hdecr (CPUPPCState *env);

View File

@@ -723,7 +723,6 @@ void ppc_hw_interrupt(CPUPPCState *env)
if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
/* Hypervisor decrementer exception */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
return;
}
@@ -767,7 +766,9 @@ void ppc_hw_interrupt(CPUPPCState *env)
}
/* Decrementer exception */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
if (ppc_decr_clear_on_delivery(env)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
}
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR);
return;
}

View File

@@ -1782,11 +1782,19 @@ typedef union _ppc_vsr_t {
float64 f64[2];
} ppc_vsr_t;
#if defined(HOST_WORDS_BIGENDIAN)
#define VsrW(i) u32[i]
#define VsrD(i) u64[i]
#else
#define VsrW(i) u32[3-(i)]
#define VsrD(i) u64[1-(i)]
#endif
static void getVSR(int n, ppc_vsr_t *vsr, CPUPPCState *env)
{
if (n < 32) {
vsr->f64[0] = env->fpr[n];
vsr->u64[1] = env->vsr[n];
vsr->VsrD(0) = env->fpr[n];
vsr->VsrD(1) = env->vsr[n];
} else {
vsr->u64[0] = env->avr[n-32].u64[0];
vsr->u64[1] = env->avr[n-32].u64[1];
@@ -1796,8 +1804,8 @@ static void getVSR(int n, ppc_vsr_t *vsr, CPUPPCState *env)
static void putVSR(int n, ppc_vsr_t *vsr, CPUPPCState *env)
{
if (n < 32) {
env->fpr[n] = vsr->f64[0];
env->vsr[n] = vsr->u64[1];
env->fpr[n] = vsr->VsrD(0);
env->vsr[n] = vsr->VsrD(1);
} else {
env->avr[n-32].u64[0] = vsr->u64[0];
env->avr[n-32].u64[1] = vsr->u64[1];
@@ -1812,7 +1820,7 @@ static void putVSR(int n, ppc_vsr_t *vsr, CPUPPCState *env)
* op - operation (add or sub)
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
* fld - vsr_t field (f32 or f64)
* fld - vsr_t field (VsrD(*) or VsrW(*))
* sfprf - set FPRF
*/
#define VSX_ADD_SUB(name, op, nels, tp, fld, sfprf, r2sp) \
@@ -1829,44 +1837,44 @@ void helper_##name(CPUPPCState *env, uint32_t opcode) \
for (i = 0; i < nels; i++) { \
float_status tstat = env->fp_status; \
set_float_exception_flags(0, &tstat); \
xt.fld[i] = tp##_##op(xa.fld[i], xb.fld[i], &tstat); \
xt.fld = tp##_##op(xa.fld, xb.fld, &tstat); \
env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
\
if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
if (tp##_is_infinity(xa.fld[i]) && tp##_is_infinity(xb.fld[i])) {\
if (tp##_is_infinity(xa.fld) && tp##_is_infinity(xb.fld)) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, sfprf); \
} else if (tp##_is_signaling_nan(xa.fld[i]) || \
tp##_is_signaling_nan(xb.fld[i])) { \
} else if (tp##_is_signaling_nan(xa.fld) || \
tp##_is_signaling_nan(xb.fld)) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
} \
} \
\
if (r2sp) { \
xt.fld[i] = helper_frsp(env, xt.fld[i]); \
xt.fld = helper_frsp(env, xt.fld); \
} \
\
if (sfprf) { \
helper_compute_fprf(env, xt.fld[i], sfprf); \
helper_compute_fprf(env, xt.fld, sfprf); \
} \
} \
putVSR(xT(opcode), &xt, env); \
helper_float_check_status(env); \
}
VSX_ADD_SUB(xsadddp, add, 1, float64, f64, 1, 0)
VSX_ADD_SUB(xsaddsp, add, 1, float64, f64, 1, 1)
VSX_ADD_SUB(xvadddp, add, 2, float64, f64, 0, 0)
VSX_ADD_SUB(xvaddsp, add, 4, float32, f32, 0, 0)
VSX_ADD_SUB(xssubdp, sub, 1, float64, f64, 1, 0)
VSX_ADD_SUB(xssubsp, sub, 1, float64, f64, 1, 1)
VSX_ADD_SUB(xvsubdp, sub, 2, float64, f64, 0, 0)
VSX_ADD_SUB(xvsubsp, sub, 4, float32, f32, 0, 0)
VSX_ADD_SUB(xsadddp, add, 1, float64, VsrD(0), 1, 0)
VSX_ADD_SUB(xsaddsp, add, 1, float64, VsrD(0), 1, 1)
VSX_ADD_SUB(xvadddp, add, 2, float64, VsrD(i), 0, 0)
VSX_ADD_SUB(xvaddsp, add, 4, float32, VsrW(i), 0, 0)
VSX_ADD_SUB(xssubdp, sub, 1, float64, VsrD(0), 1, 0)
VSX_ADD_SUB(xssubsp, sub, 1, float64, VsrD(0), 1, 1)
VSX_ADD_SUB(xvsubdp, sub, 2, float64, VsrD(i), 0, 0)
VSX_ADD_SUB(xvsubsp, sub, 4, float32, VsrW(i), 0, 0)
/* VSX_MUL - VSX floating point multiply
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
* fld - vsr_t field (f32 or f64)
* fld - vsr_t field (VsrD(*) or VsrW(*))
* sfprf - set FPRF
*/
#define VSX_MUL(op, nels, tp, fld, sfprf, r2sp) \
@@ -1883,25 +1891,25 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
for (i = 0; i < nels; i++) { \
float_status tstat = env->fp_status; \
set_float_exception_flags(0, &tstat); \
xt.fld[i] = tp##_mul(xa.fld[i], xb.fld[i], &tstat); \
xt.fld = tp##_mul(xa.fld, xb.fld, &tstat); \
env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
\
if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
if ((tp##_is_infinity(xa.fld[i]) && tp##_is_zero(xb.fld[i])) || \
(tp##_is_infinity(xb.fld[i]) && tp##_is_zero(xa.fld[i]))) { \
if ((tp##_is_infinity(xa.fld) && tp##_is_zero(xb.fld)) || \
(tp##_is_infinity(xb.fld) && tp##_is_zero(xa.fld))) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, sfprf); \
} else if (tp##_is_signaling_nan(xa.fld[i]) || \
tp##_is_signaling_nan(xb.fld[i])) { \
} else if (tp##_is_signaling_nan(xa.fld) || \
tp##_is_signaling_nan(xb.fld)) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
} \
} \
\
if (r2sp) { \
xt.fld[i] = helper_frsp(env, xt.fld[i]); \
xt.fld = helper_frsp(env, xt.fld); \
} \
\
if (sfprf) { \
helper_compute_fprf(env, xt.fld[i], sfprf); \
helper_compute_fprf(env, xt.fld, sfprf); \
} \
} \
\
@@ -1909,16 +1917,16 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
helper_float_check_status(env); \
}
VSX_MUL(xsmuldp, 1, float64, f64, 1, 0)
VSX_MUL(xsmulsp, 1, float64, f64, 1, 1)
VSX_MUL(xvmuldp, 2, float64, f64, 0, 0)
VSX_MUL(xvmulsp, 4, float32, f32, 0, 0)
VSX_MUL(xsmuldp, 1, float64, VsrD(0), 1, 0)
VSX_MUL(xsmulsp, 1, float64, VsrD(0), 1, 1)
VSX_MUL(xvmuldp, 2, float64, VsrD(i), 0, 0)
VSX_MUL(xvmulsp, 4, float32, VsrW(i), 0, 0)
/* VSX_DIV - VSX floating point divide
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
* fld - vsr_t field (f32 or f64)
* fld - vsr_t field (VsrD(*) or VsrW(*))
* sfprf - set FPRF
*/
#define VSX_DIV(op, nels, tp, fld, sfprf, r2sp) \
@@ -1935,27 +1943,27 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
for (i = 0; i < nels; i++) { \
float_status tstat = env->fp_status; \
set_float_exception_flags(0, &tstat); \
xt.fld[i] = tp##_div(xa.fld[i], xb.fld[i], &tstat); \
xt.fld = tp##_div(xa.fld, xb.fld, &tstat); \
env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
\
if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
if (tp##_is_infinity(xa.fld[i]) && tp##_is_infinity(xb.fld[i])) { \
if (tp##_is_infinity(xa.fld) && tp##_is_infinity(xb.fld)) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, sfprf); \
} else if (tp##_is_zero(xa.fld[i]) && \
tp##_is_zero(xb.fld[i])) { \
} else if (tp##_is_zero(xa.fld) && \
tp##_is_zero(xb.fld)) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, sfprf); \
} else if (tp##_is_signaling_nan(xa.fld[i]) || \
tp##_is_signaling_nan(xb.fld[i])) { \
} else if (tp##_is_signaling_nan(xa.fld) || \
tp##_is_signaling_nan(xb.fld)) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
} \
} \
\
if (r2sp) { \
xt.fld[i] = helper_frsp(env, xt.fld[i]); \
xt.fld = helper_frsp(env, xt.fld); \
} \
\
if (sfprf) { \
helper_compute_fprf(env, xt.fld[i], sfprf); \
helper_compute_fprf(env, xt.fld, sfprf); \
} \
} \
\
@@ -1963,16 +1971,16 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
helper_float_check_status(env); \
}
VSX_DIV(xsdivdp, 1, float64, f64, 1, 0)
VSX_DIV(xsdivsp, 1, float64, f64, 1, 1)
VSX_DIV(xvdivdp, 2, float64, f64, 0, 0)
VSX_DIV(xvdivsp, 4, float32, f32, 0, 0)
VSX_DIV(xsdivdp, 1, float64, VsrD(0), 1, 0)
VSX_DIV(xsdivsp, 1, float64, VsrD(0), 1, 1)
VSX_DIV(xvdivdp, 2, float64, VsrD(i), 0, 0)
VSX_DIV(xvdivsp, 4, float32, VsrW(i), 0, 0)
/* VSX_RE - VSX floating point reciprocal estimate
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
* fld - vsr_t field (f32 or f64)
* fld - vsr_t field (VsrD(*) or VsrW(*))
* sfprf - set FPRF
*/
#define VSX_RE(op, nels, tp, fld, sfprf, r2sp) \
@@ -1986,17 +1994,17 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
helper_reset_fpstatus(env); \
\
for (i = 0; i < nels; i++) { \
if (unlikely(tp##_is_signaling_nan(xb.fld[i]))) { \
if (unlikely(tp##_is_signaling_nan(xb.fld))) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
} \
xt.fld[i] = tp##_div(tp##_one, xb.fld[i], &env->fp_status); \
xt.fld = tp##_div(tp##_one, xb.fld, &env->fp_status); \
\
if (r2sp) { \
xt.fld[i] = helper_frsp(env, xt.fld[i]); \
xt.fld = helper_frsp(env, xt.fld); \
} \
\
if (sfprf) { \
helper_compute_fprf(env, xt.fld[0], sfprf); \
helper_compute_fprf(env, xt.fld, sfprf); \
} \
} \
\
@@ -2004,16 +2012,16 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
helper_float_check_status(env); \
}
VSX_RE(xsredp, 1, float64, f64, 1, 0)
VSX_RE(xsresp, 1, float64, f64, 1, 1)
VSX_RE(xvredp, 2, float64, f64, 0, 0)
VSX_RE(xvresp, 4, float32, f32, 0, 0)
VSX_RE(xsredp, 1, float64, VsrD(0), 1, 0)
VSX_RE(xsresp, 1, float64, VsrD(0), 1, 1)
VSX_RE(xvredp, 2, float64, VsrD(i), 0, 0)
VSX_RE(xvresp, 4, float32, VsrW(i), 0, 0)
/* VSX_SQRT - VSX floating point square root
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
* fld - vsr_t field (f32 or f64)
* fld - vsr_t field (VsrD(*) or VsrW(*))
* sfprf - set FPRF
*/
#define VSX_SQRT(op, nels, tp, fld, sfprf, r2sp) \
@@ -2029,23 +2037,23 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
for (i = 0; i < nels; i++) { \
float_status tstat = env->fp_status; \
set_float_exception_flags(0, &tstat); \
xt.fld[i] = tp##_sqrt(xb.fld[i], &tstat); \
xt.fld = tp##_sqrt(xb.fld, &tstat); \
env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
\
if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
if (tp##_is_neg(xb.fld[i]) && !tp##_is_zero(xb.fld[i])) { \
if (tp##_is_neg(xb.fld) && !tp##_is_zero(xb.fld)) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, sfprf); \
} else if (tp##_is_signaling_nan(xb.fld[i])) { \
} else if (tp##_is_signaling_nan(xb.fld)) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
} \
} \
\
if (r2sp) { \
xt.fld[i] = helper_frsp(env, xt.fld[i]); \
xt.fld = helper_frsp(env, xt.fld); \
} \
\
if (sfprf) { \
helper_compute_fprf(env, xt.fld[i], sfprf); \
helper_compute_fprf(env, xt.fld, sfprf); \
} \
} \
\
@@ -2053,16 +2061,16 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
helper_float_check_status(env); \
}
VSX_SQRT(xssqrtdp, 1, float64, f64, 1, 0)
VSX_SQRT(xssqrtsp, 1, float64, f64, 1, 1)
VSX_SQRT(xvsqrtdp, 2, float64, f64, 0, 0)
VSX_SQRT(xvsqrtsp, 4, float32, f32, 0, 0)
VSX_SQRT(xssqrtdp, 1, float64, VsrD(0), 1, 0)
VSX_SQRT(xssqrtsp, 1, float64, VsrD(0), 1, 1)
VSX_SQRT(xvsqrtdp, 2, float64, VsrD(i), 0, 0)
VSX_SQRT(xvsqrtsp, 4, float32, VsrW(i), 0, 0)
/* VSX_RSQRTE - VSX floating point reciprocal square root estimate
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
* fld - vsr_t field (f32 or f64)
* fld - vsr_t field (VsrD(*) or VsrW(*))
* sfprf - set FPRF
*/
#define VSX_RSQRTE(op, nels, tp, fld, sfprf, r2sp) \
@@ -2078,24 +2086,24 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
for (i = 0; i < nels; i++) { \
float_status tstat = env->fp_status; \
set_float_exception_flags(0, &tstat); \
xt.fld[i] = tp##_sqrt(xb.fld[i], &tstat); \
xt.fld[i] = tp##_div(tp##_one, xt.fld[i], &tstat); \
xt.fld = tp##_sqrt(xb.fld, &tstat); \
xt.fld = tp##_div(tp##_one, xt.fld, &tstat); \
env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
\
if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
if (tp##_is_neg(xb.fld[i]) && !tp##_is_zero(xb.fld[i])) { \
if (tp##_is_neg(xb.fld) && !tp##_is_zero(xb.fld)) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, sfprf); \
} else if (tp##_is_signaling_nan(xb.fld[i])) { \
} else if (tp##_is_signaling_nan(xb.fld)) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
} \
} \
\
if (r2sp) { \
xt.fld[i] = helper_frsp(env, xt.fld[i]); \
xt.fld = helper_frsp(env, xt.fld); \
} \
\
if (sfprf) { \
helper_compute_fprf(env, xt.fld[i], sfprf); \
helper_compute_fprf(env, xt.fld, sfprf); \
} \
} \
\
@@ -2103,16 +2111,16 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
helper_float_check_status(env); \
}
VSX_RSQRTE(xsrsqrtedp, 1, float64, f64, 1, 0)
VSX_RSQRTE(xsrsqrtesp, 1, float64, f64, 1, 1)
VSX_RSQRTE(xvrsqrtedp, 2, float64, f64, 0, 0)
VSX_RSQRTE(xvrsqrtesp, 4, float32, f32, 0, 0)
VSX_RSQRTE(xsrsqrtedp, 1, float64, VsrD(0), 1, 0)
VSX_RSQRTE(xsrsqrtesp, 1, float64, VsrD(0), 1, 1)
VSX_RSQRTE(xvrsqrtedp, 2, float64, VsrD(i), 0, 0)
VSX_RSQRTE(xvrsqrtesp, 4, float32, VsrW(i), 0, 0)
/* VSX_TDIV - VSX floating point test for divide
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
* fld - vsr_t field (f32 or f64)
* fld - vsr_t field (VsrD(*) or VsrW(*))
* emin - minimum unbiased exponent
* emax - maximum unbiased exponent
* nbits - number of fraction bits
@@ -2129,28 +2137,28 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
getVSR(xB(opcode), &xb, env); \
\
for (i = 0; i < nels; i++) { \
if (unlikely(tp##_is_infinity(xa.fld[i]) || \
tp##_is_infinity(xb.fld[i]) || \
tp##_is_zero(xb.fld[i]))) { \
if (unlikely(tp##_is_infinity(xa.fld) || \
tp##_is_infinity(xb.fld) || \
tp##_is_zero(xb.fld))) { \
fe_flag = 1; \
fg_flag = 1; \
} else { \
int e_a = ppc_##tp##_get_unbiased_exp(xa.fld[i]); \
int e_b = ppc_##tp##_get_unbiased_exp(xb.fld[i]); \
int e_a = ppc_##tp##_get_unbiased_exp(xa.fld); \
int e_b = ppc_##tp##_get_unbiased_exp(xb.fld); \
\
if (unlikely(tp##_is_any_nan(xa.fld[i]) || \
tp##_is_any_nan(xb.fld[i]))) { \
if (unlikely(tp##_is_any_nan(xa.fld) || \
tp##_is_any_nan(xb.fld))) { \
fe_flag = 1; \
} else if ((e_b <= emin) || (e_b >= (emax-2))) { \
fe_flag = 1; \
} else if (!tp##_is_zero(xa.fld[i]) && \
} else if (!tp##_is_zero(xa.fld) && \
(((e_a - e_b) >= emax) || \
((e_a - e_b) <= (emin+1)) || \
(e_a <= (emin+nbits)))) { \
fe_flag = 1; \
} \
\
if (unlikely(tp##_is_zero_or_denormal(xb.fld[i]))) { \
if (unlikely(tp##_is_zero_or_denormal(xb.fld))) { \
/* XB is not zero because of the above check and */ \
/* so must be denormalized. */ \
fg_flag = 1; \
@@ -2161,15 +2169,15 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
env->crf[BF(opcode)] = 0x8 | (fg_flag ? 4 : 0) | (fe_flag ? 2 : 0); \
}
VSX_TDIV(xstdivdp, 1, float64, f64, -1022, 1023, 52)
VSX_TDIV(xvtdivdp, 2, float64, f64, -1022, 1023, 52)
VSX_TDIV(xvtdivsp, 4, float32, f32, -126, 127, 23)
VSX_TDIV(xstdivdp, 1, float64, VsrD(0), -1022, 1023, 52)
VSX_TDIV(xvtdivdp, 2, float64, VsrD(i), -1022, 1023, 52)
VSX_TDIV(xvtdivsp, 4, float32, VsrW(i), -126, 127, 23)
/* VSX_TSQRT - VSX floating point test for square root
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
* fld - vsr_t field (f32 or f64)
* fld - vsr_t field (VsrD(*) or VsrW(*))
* emin - minimum unbiased exponent
* emax - maximum unbiased exponent
* nbits - number of fraction bits
@@ -2186,25 +2194,25 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
getVSR(xB(opcode), &xb, env); \
\
for (i = 0; i < nels; i++) { \
if (unlikely(tp##_is_infinity(xb.fld[i]) || \
tp##_is_zero(xb.fld[i]))) { \
if (unlikely(tp##_is_infinity(xb.fld) || \
tp##_is_zero(xb.fld))) { \
fe_flag = 1; \
fg_flag = 1; \
} else { \
int e_b = ppc_##tp##_get_unbiased_exp(xb.fld[i]); \
int e_b = ppc_##tp##_get_unbiased_exp(xb.fld); \
\
if (unlikely(tp##_is_any_nan(xb.fld[i]))) { \
if (unlikely(tp##_is_any_nan(xb.fld))) { \
fe_flag = 1; \
} else if (unlikely(tp##_is_zero(xb.fld[i]))) { \
} else if (unlikely(tp##_is_zero(xb.fld))) { \
fe_flag = 1; \
} else if (unlikely(tp##_is_neg(xb.fld[i]))) { \
} else if (unlikely(tp##_is_neg(xb.fld))) { \
fe_flag = 1; \
} else if (!tp##_is_zero(xb.fld[i]) && \
} else if (!tp##_is_zero(xb.fld) && \
(e_b <= (emin+nbits))) { \
fe_flag = 1; \
} \
\
if (unlikely(tp##_is_zero_or_denormal(xb.fld[i]))) { \
if (unlikely(tp##_is_zero_or_denormal(xb.fld))) { \
/* XB is not zero because of the above check and */ \
/* therefore must be denormalized. */ \
fg_flag = 1; \
@@ -2215,15 +2223,15 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
env->crf[BF(opcode)] = 0x8 | (fg_flag ? 4 : 0) | (fe_flag ? 2 : 0); \
}
VSX_TSQRT(xstsqrtdp, 1, float64, f64, -1022, 52)
VSX_TSQRT(xvtsqrtdp, 2, float64, f64, -1022, 52)
VSX_TSQRT(xvtsqrtsp, 4, float32, f32, -126, 23)
VSX_TSQRT(xstsqrtdp, 1, float64, VsrD(0), -1022, 52)
VSX_TSQRT(xvtsqrtdp, 2, float64, VsrD(i), -1022, 52)
VSX_TSQRT(xvtsqrtsp, 4, float32, VsrW(i), -126, 23)
/* VSX_MADD - VSX floating point muliply/add variations
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
* fld - vsr_t field (f32 or f64)
* fld - vsr_t field (VsrD(*) or VsrW(*))
* maddflgs - flags for the float*muladd routine that control the
* various forms (madd, msub, nmadd, nmsub)
* afrm - A form (1=A, 0=M)
@@ -2259,43 +2267,43 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
/* Avoid double rounding errors by rounding the intermediate */ \
/* result to odd. */ \
set_float_rounding_mode(float_round_to_zero, &tstat); \
xt_out.fld[i] = tp##_muladd(xa.fld[i], b->fld[i], c->fld[i], \
xt_out.fld = tp##_muladd(xa.fld, b->fld, c->fld, \
maddflgs, &tstat); \
xt_out.fld[i] |= (get_float_exception_flags(&tstat) & \
xt_out.fld |= (get_float_exception_flags(&tstat) & \
float_flag_inexact) != 0; \
} else { \
xt_out.fld[i] = tp##_muladd(xa.fld[i], b->fld[i], c->fld[i], \
xt_out.fld = tp##_muladd(xa.fld, b->fld, c->fld, \
maddflgs, &tstat); \
} \
env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
\
if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
if (tp##_is_signaling_nan(xa.fld[i]) || \
tp##_is_signaling_nan(b->fld[i]) || \
tp##_is_signaling_nan(c->fld[i])) { \
if (tp##_is_signaling_nan(xa.fld) || \
tp##_is_signaling_nan(b->fld) || \
tp##_is_signaling_nan(c->fld)) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
tstat.float_exception_flags &= ~float_flag_invalid; \
} \
if ((tp##_is_infinity(xa.fld[i]) && tp##_is_zero(b->fld[i])) || \
(tp##_is_zero(xa.fld[i]) && tp##_is_infinity(b->fld[i]))) { \
xt_out.fld[i] = float64_to_##tp(fload_invalid_op_excp(env, \
if ((tp##_is_infinity(xa.fld) && tp##_is_zero(b->fld)) || \
(tp##_is_zero(xa.fld) && tp##_is_infinity(b->fld))) { \
xt_out.fld = float64_to_##tp(fload_invalid_op_excp(env, \
POWERPC_EXCP_FP_VXIMZ, sfprf), &env->fp_status); \
tstat.float_exception_flags &= ~float_flag_invalid; \
} \
if ((tstat.float_exception_flags & float_flag_invalid) && \
((tp##_is_infinity(xa.fld[i]) || \
tp##_is_infinity(b->fld[i])) && \
tp##_is_infinity(c->fld[i]))) { \
((tp##_is_infinity(xa.fld) || \
tp##_is_infinity(b->fld)) && \
tp##_is_infinity(c->fld))) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, sfprf); \
} \
} \
\
if (r2sp) { \
xt_out.fld[i] = helper_frsp(env, xt_out.fld[i]); \
xt_out.fld = helper_frsp(env, xt_out.fld); \
} \
\
if (sfprf) { \
helper_compute_fprf(env, xt_out.fld[i], sfprf); \
helper_compute_fprf(env, xt_out.fld, sfprf); \
} \
} \
putVSR(xT(opcode), &xt_out, env); \
@@ -2307,41 +2315,41 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
#define NMADD_FLGS float_muladd_negate_result
#define NMSUB_FLGS (float_muladd_negate_c | float_muladd_negate_result)
VSX_MADD(xsmaddadp, 1, float64, f64, MADD_FLGS, 1, 1, 0)
VSX_MADD(xsmaddmdp, 1, float64, f64, MADD_FLGS, 0, 1, 0)
VSX_MADD(xsmsubadp, 1, float64, f64, MSUB_FLGS, 1, 1, 0)
VSX_MADD(xsmsubmdp, 1, float64, f64, MSUB_FLGS, 0, 1, 0)
VSX_MADD(xsnmaddadp, 1, float64, f64, NMADD_FLGS, 1, 1, 0)
VSX_MADD(xsnmaddmdp, 1, float64, f64, NMADD_FLGS, 0, 1, 0)
VSX_MADD(xsnmsubadp, 1, float64, f64, NMSUB_FLGS, 1, 1, 0)
VSX_MADD(xsnmsubmdp, 1, float64, f64, NMSUB_FLGS, 0, 1, 0)
VSX_MADD(xsmaddadp, 1, float64, VsrD(0), MADD_FLGS, 1, 1, 0)
VSX_MADD(xsmaddmdp, 1, float64, VsrD(0), MADD_FLGS, 0, 1, 0)
VSX_MADD(xsmsubadp, 1, float64, VsrD(0), MSUB_FLGS, 1, 1, 0)
VSX_MADD(xsmsubmdp, 1, float64, VsrD(0), MSUB_FLGS, 0, 1, 0)
VSX_MADD(xsnmaddadp, 1, float64, VsrD(0), NMADD_FLGS, 1, 1, 0)
VSX_MADD(xsnmaddmdp, 1, float64, VsrD(0), NMADD_FLGS, 0, 1, 0)
VSX_MADD(xsnmsubadp, 1, float64, VsrD(0), NMSUB_FLGS, 1, 1, 0)
VSX_MADD(xsnmsubmdp, 1, float64, VsrD(0), NMSUB_FLGS, 0, 1, 0)
VSX_MADD(xsmaddasp, 1, float64, f64, MADD_FLGS, 1, 1, 1)
VSX_MADD(xsmaddmsp, 1, float64, f64, MADD_FLGS, 0, 1, 1)
VSX_MADD(xsmsubasp, 1, float64, f64, MSUB_FLGS, 1, 1, 1)
VSX_MADD(xsmsubmsp, 1, float64, f64, MSUB_FLGS, 0, 1, 1)
VSX_MADD(xsnmaddasp, 1, float64, f64, NMADD_FLGS, 1, 1, 1)
VSX_MADD(xsnmaddmsp, 1, float64, f64, NMADD_FLGS, 0, 1, 1)
VSX_MADD(xsnmsubasp, 1, float64, f64, NMSUB_FLGS, 1, 1, 1)
VSX_MADD(xsnmsubmsp, 1, float64, f64, NMSUB_FLGS, 0, 1, 1)
VSX_MADD(xsmaddasp, 1, float64, VsrD(0), MADD_FLGS, 1, 1, 1)
VSX_MADD(xsmaddmsp, 1, float64, VsrD(0), MADD_FLGS, 0, 1, 1)
VSX_MADD(xsmsubasp, 1, float64, VsrD(0), MSUB_FLGS, 1, 1, 1)
VSX_MADD(xsmsubmsp, 1, float64, VsrD(0), MSUB_FLGS, 0, 1, 1)
VSX_MADD(xsnmaddasp, 1, float64, VsrD(0), NMADD_FLGS, 1, 1, 1)
VSX_MADD(xsnmaddmsp, 1, float64, VsrD(0), NMADD_FLGS, 0, 1, 1)
VSX_MADD(xsnmsubasp, 1, float64, VsrD(0), NMSUB_FLGS, 1, 1, 1)
VSX_MADD(xsnmsubmsp, 1, float64, VsrD(0), NMSUB_FLGS, 0, 1, 1)
VSX_MADD(xvmaddadp, 2, float64, f64, MADD_FLGS, 1, 0, 0)
VSX_MADD(xvmaddmdp, 2, float64, f64, MADD_FLGS, 0, 0, 0)
VSX_MADD(xvmsubadp, 2, float64, f64, MSUB_FLGS, 1, 0, 0)
VSX_MADD(xvmsubmdp, 2, float64, f64, MSUB_FLGS, 0, 0, 0)
VSX_MADD(xvnmaddadp, 2, float64, f64, NMADD_FLGS, 1, 0, 0)
VSX_MADD(xvnmaddmdp, 2, float64, f64, NMADD_FLGS, 0, 0, 0)
VSX_MADD(xvnmsubadp, 2, float64, f64, NMSUB_FLGS, 1, 0, 0)
VSX_MADD(xvnmsubmdp, 2, float64, f64, NMSUB_FLGS, 0, 0, 0)
VSX_MADD(xvmaddadp, 2, float64, VsrD(i), MADD_FLGS, 1, 0, 0)
VSX_MADD(xvmaddmdp, 2, float64, VsrD(i), MADD_FLGS, 0, 0, 0)
VSX_MADD(xvmsubadp, 2, float64, VsrD(i), MSUB_FLGS, 1, 0, 0)
VSX_MADD(xvmsubmdp, 2, float64, VsrD(i), MSUB_FLGS, 0, 0, 0)
VSX_MADD(xvnmaddadp, 2, float64, VsrD(i), NMADD_FLGS, 1, 0, 0)
VSX_MADD(xvnmaddmdp, 2, float64, VsrD(i), NMADD_FLGS, 0, 0, 0)
VSX_MADD(xvnmsubadp, 2, float64, VsrD(i), NMSUB_FLGS, 1, 0, 0)
VSX_MADD(xvnmsubmdp, 2, float64, VsrD(i), NMSUB_FLGS, 0, 0, 0)
VSX_MADD(xvmaddasp, 4, float32, f32, MADD_FLGS, 1, 0, 0)
VSX_MADD(xvmaddmsp, 4, float32, f32, MADD_FLGS, 0, 0, 0)
VSX_MADD(xvmsubasp, 4, float32, f32, MSUB_FLGS, 1, 0, 0)
VSX_MADD(xvmsubmsp, 4, float32, f32, MSUB_FLGS, 0, 0, 0)
VSX_MADD(xvnmaddasp, 4, float32, f32, NMADD_FLGS, 1, 0, 0)
VSX_MADD(xvnmaddmsp, 4, float32, f32, NMADD_FLGS, 0, 0, 0)
VSX_MADD(xvnmsubasp, 4, float32, f32, NMSUB_FLGS, 1, 0, 0)
VSX_MADD(xvnmsubmsp, 4, float32, f32, NMSUB_FLGS, 0, 0, 0)
VSX_MADD(xvmaddasp, 4, float32, VsrW(i), MADD_FLGS, 1, 0, 0)
VSX_MADD(xvmaddmsp, 4, float32, VsrW(i), MADD_FLGS, 0, 0, 0)
VSX_MADD(xvmsubasp, 4, float32, VsrW(i), MSUB_FLGS, 1, 0, 0)
VSX_MADD(xvmsubmsp, 4, float32, VsrW(i), MSUB_FLGS, 0, 0, 0)
VSX_MADD(xvnmaddasp, 4, float32, VsrW(i), NMADD_FLGS, 1, 0, 0)
VSX_MADD(xvnmaddmsp, 4, float32, VsrW(i), NMADD_FLGS, 0, 0, 0)
VSX_MADD(xvnmsubasp, 4, float32, VsrW(i), NMSUB_FLGS, 1, 0, 0)
VSX_MADD(xvnmsubmsp, 4, float32, VsrW(i), NMSUB_FLGS, 0, 0, 0)
#define VSX_SCALAR_CMP(op, ordered) \
void helper_##op(CPUPPCState *env, uint32_t opcode) \
@@ -2352,10 +2360,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
getVSR(xA(opcode), &xa, env); \
getVSR(xB(opcode), &xb, env); \
\
if (unlikely(float64_is_any_nan(xa.f64[0]) || \
float64_is_any_nan(xb.f64[0]))) { \
if (float64_is_signaling_nan(xa.f64[0]) || \
float64_is_signaling_nan(xb.f64[0])) { \
if (unlikely(float64_is_any_nan(xa.VsrD(0)) || \
float64_is_any_nan(xb.VsrD(0)))) { \
if (float64_is_signaling_nan(xa.VsrD(0)) || \
float64_is_signaling_nan(xb.VsrD(0))) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
} \
if (ordered) { \
@@ -2363,9 +2371,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
} \
cc = 1; \
} else { \
if (float64_lt(xa.f64[0], xb.f64[0], &env->fp_status)) { \
if (float64_lt(xa.VsrD(0), xb.VsrD(0), &env->fp_status)) { \
cc = 8; \
} else if (!float64_le(xa.f64[0], xb.f64[0], &env->fp_status)) { \
} else if (!float64_le(xa.VsrD(0), xb.VsrD(0), \
&env->fp_status)) { \
cc = 4; \
} else { \
cc = 2; \
@@ -2390,7 +2399,7 @@ VSX_SCALAR_CMP(xscmpudp, 0)
* op - operation (max or min)
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
* fld - vsr_t field (f32 or f64)
* fld - vsr_t field (VsrD(*) or VsrW(*))
*/
#define VSX_MAX_MIN(name, op, nels, tp, fld) \
void helper_##name(CPUPPCState *env, uint32_t opcode) \
@@ -2403,9 +2412,9 @@ void helper_##name(CPUPPCState *env, uint32_t opcode) \
getVSR(xT(opcode), &xt, env); \
\
for (i = 0; i < nels; i++) { \
xt.fld[i] = tp##_##op(xa.fld[i], xb.fld[i], &env->fp_status); \
if (unlikely(tp##_is_signaling_nan(xa.fld[i]) || \
tp##_is_signaling_nan(xb.fld[i]))) { \
xt.fld = tp##_##op(xa.fld, xb.fld, &env->fp_status); \
if (unlikely(tp##_is_signaling_nan(xa.fld) || \
tp##_is_signaling_nan(xb.fld))) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
} \
} \
@@ -2414,18 +2423,18 @@ void helper_##name(CPUPPCState *env, uint32_t opcode) \
helper_float_check_status(env); \
}
VSX_MAX_MIN(xsmaxdp, maxnum, 1, float64, f64)
VSX_MAX_MIN(xvmaxdp, maxnum, 2, float64, f64)
VSX_MAX_MIN(xvmaxsp, maxnum, 4, float32, f32)
VSX_MAX_MIN(xsmindp, minnum, 1, float64, f64)
VSX_MAX_MIN(xvmindp, minnum, 2, float64, f64)
VSX_MAX_MIN(xvminsp, minnum, 4, float32, f32)
VSX_MAX_MIN(xsmaxdp, maxnum, 1, float64, VsrD(0))
VSX_MAX_MIN(xvmaxdp, maxnum, 2, float64, VsrD(i))
VSX_MAX_MIN(xvmaxsp, maxnum, 4, float32, VsrW(i))
VSX_MAX_MIN(xsmindp, minnum, 1, float64, VsrD(0))
VSX_MAX_MIN(xvmindp, minnum, 2, float64, VsrD(i))
VSX_MAX_MIN(xvminsp, minnum, 4, float32, VsrW(i))
/* VSX_CMP - VSX floating point compare
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
* fld - vsr_t field (f32 or f64)
* fld - vsr_t field (VsrD(*) or VsrW(*))
* cmp - comparison operation
* svxvc - set VXVC bit
*/
@@ -2442,23 +2451,23 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
getVSR(xT(opcode), &xt, env); \
\
for (i = 0; i < nels; i++) { \
if (unlikely(tp##_is_any_nan(xa.fld[i]) || \
tp##_is_any_nan(xb.fld[i]))) { \
if (tp##_is_signaling_nan(xa.fld[i]) || \
tp##_is_signaling_nan(xb.fld[i])) { \
if (unlikely(tp##_is_any_nan(xa.fld) || \
tp##_is_any_nan(xb.fld))) { \
if (tp##_is_signaling_nan(xa.fld) || \
tp##_is_signaling_nan(xb.fld)) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
} \
if (svxvc) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0); \
} \
xt.fld[i] = 0; \
xt.fld = 0; \
all_true = 0; \
} else { \
if (tp##_##cmp(xb.fld[i], xa.fld[i], &env->fp_status) == 1) { \
xt.fld[i] = -1; \
if (tp##_##cmp(xb.fld, xa.fld, &env->fp_status) == 1) { \
xt.fld = -1; \
all_false = 0; \
} else { \
xt.fld[i] = 0; \
xt.fld = 0; \
all_true = 0; \
} \
} \
@@ -2471,18 +2480,12 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
helper_float_check_status(env); \
}
VSX_CMP(xvcmpeqdp, 2, float64, f64, eq, 0)
VSX_CMP(xvcmpgedp, 2, float64, f64, le, 1)
VSX_CMP(xvcmpgtdp, 2, float64, f64, lt, 1)
VSX_CMP(xvcmpeqsp, 4, float32, f32, eq, 0)
VSX_CMP(xvcmpgesp, 4, float32, f32, le, 1)
VSX_CMP(xvcmpgtsp, 4, float32, f32, lt, 1)
#if defined(HOST_WORDS_BIGENDIAN)
#define JOFFSET 0
#else
#define JOFFSET 1
#endif
VSX_CMP(xvcmpeqdp, 2, float64, VsrD(i), eq, 0)
VSX_CMP(xvcmpgedp, 2, float64, VsrD(i), le, 1)
VSX_CMP(xvcmpgtdp, 2, float64, VsrD(i), lt, 1)
VSX_CMP(xvcmpeqsp, 4, float32, VsrW(i), eq, 0)
VSX_CMP(xvcmpgesp, 4, float32, VsrW(i), le, 1)
VSX_CMP(xvcmpgtsp, 4, float32, VsrW(i), lt, 1)
/* VSX_CVT_FP_TO_FP - VSX floating point/floating point conversion
* op - instruction mnemonic
@@ -2503,7 +2506,6 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
getVSR(xT(opcode), &xt, env); \
\
for (i = 0; i < nels; i++) { \
int j = 2*i + JOFFSET; \
xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status); \
if (unlikely(stp##_is_signaling_nan(xb.sfld))) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
@@ -2519,10 +2521,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
helper_float_check_status(env); \
}
VSX_CVT_FP_TO_FP(xscvdpsp, 1, float64, float32, f64[i], f32[j], 1)
VSX_CVT_FP_TO_FP(xscvspdp, 1, float32, float64, f32[j], f64[i], 1)
VSX_CVT_FP_TO_FP(xvcvdpsp, 2, float64, float32, f64[i], f32[j], 0)
VSX_CVT_FP_TO_FP(xvcvspdp, 2, float32, float64, f32[j], f64[i], 0)
VSX_CVT_FP_TO_FP(xscvdpsp, 1, float64, float32, VsrD(0), VsrW(0), 1)
VSX_CVT_FP_TO_FP(xscvspdp, 1, float32, float64, VsrW(0), VsrD(0), 1)
VSX_CVT_FP_TO_FP(xvcvdpsp, 2, float64, float32, VsrD(i), VsrW(2*i), 0)
VSX_CVT_FP_TO_FP(xvcvspdp, 2, float32, float64, VsrW(2*i), VsrD(i), 0)
uint64_t helper_xscvdpspn(CPUPPCState *env, uint64_t xb)
{
@@ -2547,10 +2549,9 @@ uint64_t helper_xscvspdpn(CPUPPCState *env, uint64_t xb)
* ttp - target type (int32, uint32, int64 or uint64)
* sfld - source vsr_t field
* tfld - target vsr_t field
* jdef - definition of the j index (i or 2*i)
* rnan - resulting NaN
*/
#define VSX_CVT_FP_TO_INT(op, nels, stp, ttp, sfld, tfld, jdef, rnan) \
#define VSX_CVT_FP_TO_INT(op, nels, stp, ttp, sfld, tfld, rnan) \
void helper_##op(CPUPPCState *env, uint32_t opcode) \
{ \
ppc_vsr_t xt, xb; \
@@ -2560,7 +2561,6 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
getVSR(xT(opcode), &xt, env); \
\
for (i = 0; i < nels; i++) { \
int j = jdef; \
if (unlikely(stp##_is_any_nan(xb.sfld))) { \
if (stp##_is_signaling_nan(xb.sfld)) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
@@ -2568,7 +2568,8 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0); \
xt.tfld = rnan; \
} else { \
xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status); \
xt.tfld = stp##_to_##ttp##_round_to_zero(xb.sfld, \
&env->fp_status); \
if (env->fp_status.float_exception_flags & float_flag_invalid) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0); \
} \
@@ -2579,27 +2580,23 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
helper_float_check_status(env); \
}
VSX_CVT_FP_TO_INT(xscvdpsxds, 1, float64, int64, f64[j], u64[i], i, \
VSX_CVT_FP_TO_INT(xscvdpsxds, 1, float64, int64, VsrD(0), VsrD(0), \
0x8000000000000000ULL)
VSX_CVT_FP_TO_INT(xscvdpsxws, 1, float64, int32, f64[i], u32[j], \
2*i + JOFFSET, 0x80000000U)
VSX_CVT_FP_TO_INT(xscvdpuxds, 1, float64, uint64, f64[j], u64[i], i, 0ULL)
VSX_CVT_FP_TO_INT(xscvdpuxws, 1, float64, uint32, f64[i], u32[j], \
2*i + JOFFSET, 0U)
VSX_CVT_FP_TO_INT(xvcvdpsxds, 2, float64, int64, f64[j], u64[i], i, \
0x8000000000000000ULL)
VSX_CVT_FP_TO_INT(xvcvdpsxws, 2, float64, int32, f64[i], u32[j], \
2*i + JOFFSET, 0x80000000U)
VSX_CVT_FP_TO_INT(xvcvdpuxds, 2, float64, uint64, f64[j], u64[i], i, 0ULL)
VSX_CVT_FP_TO_INT(xvcvdpuxws, 2, float64, uint32, f64[i], u32[j], \
2*i + JOFFSET, 0U)
VSX_CVT_FP_TO_INT(xvcvspsxds, 2, float32, int64, f32[j], u64[i], \
2*i + JOFFSET, 0x8000000000000000ULL)
VSX_CVT_FP_TO_INT(xvcvspsxws, 4, float32, int32, f32[j], u32[j], i, \
VSX_CVT_FP_TO_INT(xscvdpsxws, 1, float64, int32, VsrD(0), VsrW(1), \
0x80000000U)
VSX_CVT_FP_TO_INT(xvcvspuxds, 2, float32, uint64, f32[j], u64[i], \
2*i + JOFFSET, 0ULL)
VSX_CVT_FP_TO_INT(xvcvspuxws, 4, float32, uint32, f32[j], u32[i], i, 0U)
VSX_CVT_FP_TO_INT(xscvdpuxds, 1, float64, uint64, VsrD(0), VsrD(0), 0ULL)
VSX_CVT_FP_TO_INT(xscvdpuxws, 1, float64, uint32, VsrD(0), VsrW(1), 0U)
VSX_CVT_FP_TO_INT(xvcvdpsxds, 2, float64, int64, VsrD(i), VsrD(i), \
0x8000000000000000ULL)
VSX_CVT_FP_TO_INT(xvcvdpsxws, 2, float64, int32, VsrD(i), VsrW(2*i), \
0x80000000U)
VSX_CVT_FP_TO_INT(xvcvdpuxds, 2, float64, uint64, VsrD(i), VsrD(i), 0ULL)
VSX_CVT_FP_TO_INT(xvcvdpuxws, 2, float64, uint32, VsrD(i), VsrW(2*i), 0U)
VSX_CVT_FP_TO_INT(xvcvspsxds, 2, float32, int64, VsrW(2*i), VsrD(i), \
0x8000000000000000ULL)
VSX_CVT_FP_TO_INT(xvcvspsxws, 4, float32, int32, VsrW(i), VsrW(i), 0x80000000U)
VSX_CVT_FP_TO_INT(xvcvspuxds, 2, float32, uint64, VsrW(2*i), VsrD(i), 0ULL)
VSX_CVT_FP_TO_INT(xvcvspuxws, 4, float32, uint32, VsrW(i), VsrW(i), 0U)
/* VSX_CVT_INT_TO_FP - VSX integer to floating point conversion
* op - instruction mnemonic
@@ -2611,7 +2608,7 @@ VSX_CVT_FP_TO_INT(xvcvspuxws, 4, float32, uint32, f32[j], u32[i], i, 0U)
* jdef - definition of the j index (i or 2*i)
* sfprf - set FPRF
*/
#define VSX_CVT_INT_TO_FP(op, nels, stp, ttp, sfld, tfld, jdef, sfprf, r2sp) \
#define VSX_CVT_INT_TO_FP(op, nels, stp, ttp, sfld, tfld, sfprf, r2sp) \
void helper_##op(CPUPPCState *env, uint32_t opcode) \
{ \
ppc_vsr_t xt, xb; \
@@ -2621,7 +2618,6 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
getVSR(xT(opcode), &xt, env); \
\
for (i = 0; i < nels; i++) { \
int j = jdef; \
xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status); \
if (r2sp) { \
xt.tfld = helper_frsp(env, xt.tfld); \
@@ -2635,22 +2631,18 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
helper_float_check_status(env); \
}
VSX_CVT_INT_TO_FP(xscvsxddp, 1, int64, float64, u64[j], f64[i], i, 1, 0)
VSX_CVT_INT_TO_FP(xscvuxddp, 1, uint64, float64, u64[j], f64[i], i, 1, 0)
VSX_CVT_INT_TO_FP(xscvsxdsp, 1, int64, float64, u64[j], f64[i], i, 1, 1)
VSX_CVT_INT_TO_FP(xscvuxdsp, 1, uint64, float64, u64[j], f64[i], i, 1, 1)
VSX_CVT_INT_TO_FP(xvcvsxddp, 2, int64, float64, u64[j], f64[i], i, 0, 0)
VSX_CVT_INT_TO_FP(xvcvuxddp, 2, uint64, float64, u64[j], f64[i], i, 0, 0)
VSX_CVT_INT_TO_FP(xvcvsxwdp, 2, int32, float64, u32[j], f64[i], \
2*i + JOFFSET, 0, 0)
VSX_CVT_INT_TO_FP(xvcvuxwdp, 2, uint64, float64, u32[j], f64[i], \
2*i + JOFFSET, 0, 0)
VSX_CVT_INT_TO_FP(xvcvsxdsp, 2, int64, float32, u64[i], f32[j], \
2*i + JOFFSET, 0, 0)
VSX_CVT_INT_TO_FP(xvcvuxdsp, 2, uint64, float32, u64[i], f32[j], \
2*i + JOFFSET, 0, 0)
VSX_CVT_INT_TO_FP(xvcvsxwsp, 4, int32, float32, u32[j], f32[i], i, 0, 0)
VSX_CVT_INT_TO_FP(xvcvuxwsp, 4, uint32, float32, u32[j], f32[i], i, 0, 0)
VSX_CVT_INT_TO_FP(xscvsxddp, 1, int64, float64, VsrD(0), VsrD(0), 1, 0)
VSX_CVT_INT_TO_FP(xscvuxddp, 1, uint64, float64, VsrD(0), VsrD(0), 1, 0)
VSX_CVT_INT_TO_FP(xscvsxdsp, 1, int64, float64, VsrD(0), VsrD(0), 1, 1)
VSX_CVT_INT_TO_FP(xscvuxdsp, 1, uint64, float64, VsrD(0), VsrD(0), 1, 1)
VSX_CVT_INT_TO_FP(xvcvsxddp, 2, int64, float64, VsrD(i), VsrD(i), 0, 0)
VSX_CVT_INT_TO_FP(xvcvuxddp, 2, uint64, float64, VsrD(i), VsrD(i), 0, 0)
VSX_CVT_INT_TO_FP(xvcvsxwdp, 2, int32, float64, VsrW(2*i), VsrD(i), 0, 0)
VSX_CVT_INT_TO_FP(xvcvuxwdp, 2, uint64, float64, VsrW(2*i), VsrD(i), 0, 0)
VSX_CVT_INT_TO_FP(xvcvsxdsp, 2, int64, float32, VsrD(i), VsrW(2*i), 0, 0)
VSX_CVT_INT_TO_FP(xvcvuxdsp, 2, uint64, float32, VsrD(i), VsrW(2*i), 0, 0)
VSX_CVT_INT_TO_FP(xvcvsxwsp, 4, int32, float32, VsrW(i), VsrW(i), 0, 0)
VSX_CVT_INT_TO_FP(xvcvuxwsp, 4, uint32, float32, VsrW(i), VsrW(i), 0, 0)
/* For "use current rounding mode", define a value that will not be one of
* the existing rounding model enums.
@@ -2662,7 +2654,7 @@ VSX_CVT_INT_TO_FP(xvcvuxwsp, 4, uint32, float32, u32[j], f32[i], i, 0, 0)
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
* fld - vsr_t field (f32 or f64)
* fld - vsr_t field (VsrD(*) or VsrW(*))
* rmode - rounding mode
* sfprf - set FPRF
*/
@@ -2679,14 +2671,14 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
} \
\
for (i = 0; i < nels; i++) { \
if (unlikely(tp##_is_signaling_nan(xb.fld[i]))) { \
if (unlikely(tp##_is_signaling_nan(xb.fld))) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
xt.fld[i] = tp##_snan_to_qnan(xb.fld[i]); \
xt.fld = tp##_snan_to_qnan(xb.fld); \
} else { \
xt.fld[i] = tp##_round_to_int(xb.fld[i], &env->fp_status); \
xt.fld = tp##_round_to_int(xb.fld, &env->fp_status); \
} \
if (sfprf) { \
helper_compute_fprf(env, xt.fld[i], sfprf); \
helper_compute_fprf(env, xt.fld, sfprf); \
} \
} \
\
@@ -2702,23 +2694,23 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
helper_float_check_status(env); \
}
VSX_ROUND(xsrdpi, 1, float64, f64, float_round_nearest_even, 1)
VSX_ROUND(xsrdpic, 1, float64, f64, FLOAT_ROUND_CURRENT, 1)
VSX_ROUND(xsrdpim, 1, float64, f64, float_round_down, 1)
VSX_ROUND(xsrdpip, 1, float64, f64, float_round_up, 1)
VSX_ROUND(xsrdpiz, 1, float64, f64, float_round_to_zero, 1)
VSX_ROUND(xsrdpi, 1, float64, VsrD(0), float_round_nearest_even, 1)
VSX_ROUND(xsrdpic, 1, float64, VsrD(0), FLOAT_ROUND_CURRENT, 1)
VSX_ROUND(xsrdpim, 1, float64, VsrD(0), float_round_down, 1)
VSX_ROUND(xsrdpip, 1, float64, VsrD(0), float_round_up, 1)
VSX_ROUND(xsrdpiz, 1, float64, VsrD(0), float_round_to_zero, 1)
VSX_ROUND(xvrdpi, 2, float64, f64, float_round_nearest_even, 0)
VSX_ROUND(xvrdpic, 2, float64, f64, FLOAT_ROUND_CURRENT, 0)
VSX_ROUND(xvrdpim, 2, float64, f64, float_round_down, 0)
VSX_ROUND(xvrdpip, 2, float64, f64, float_round_up, 0)
VSX_ROUND(xvrdpiz, 2, float64, f64, float_round_to_zero, 0)
VSX_ROUND(xvrdpi, 2, float64, VsrD(i), float_round_nearest_even, 0)
VSX_ROUND(xvrdpic, 2, float64, VsrD(i), FLOAT_ROUND_CURRENT, 0)
VSX_ROUND(xvrdpim, 2, float64, VsrD(i), float_round_down, 0)
VSX_ROUND(xvrdpip, 2, float64, VsrD(i), float_round_up, 0)
VSX_ROUND(xvrdpiz, 2, float64, VsrD(i), float_round_to_zero, 0)
VSX_ROUND(xvrspi, 4, float32, f32, float_round_nearest_even, 0)
VSX_ROUND(xvrspic, 4, float32, f32, FLOAT_ROUND_CURRENT, 0)
VSX_ROUND(xvrspim, 4, float32, f32, float_round_down, 0)
VSX_ROUND(xvrspip, 4, float32, f32, float_round_up, 0)
VSX_ROUND(xvrspiz, 4, float32, f32, float_round_to_zero, 0)
VSX_ROUND(xvrspi, 4, float32, VsrW(i), float_round_nearest_even, 0)
VSX_ROUND(xvrspic, 4, float32, VsrW(i), FLOAT_ROUND_CURRENT, 0)
VSX_ROUND(xvrspim, 4, float32, VsrW(i), float_round_down, 0)
VSX_ROUND(xvrspip, 4, float32, VsrW(i), float_round_up, 0)
VSX_ROUND(xvrspiz, 4, float32, VsrW(i), float_round_to_zero, 0)
uint64_t helper_xsrsp(CPUPPCState *env, uint64_t xb)
{

View File

@@ -101,7 +101,7 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
hreg_compute_hflags(env);
#if !defined(CONFIG_USER_ONLY)
if (unlikely(msr_pow == 1)) {
if ((*env->check_pow)(env)) {
if (!env->pending_interrupts && (*env->check_pow)(env)) {
cs->halted = 1;
excp = EXCP_HALTED;
}

View File

@@ -6699,6 +6699,8 @@ POWERPC_FAMILY(970)(ObjectClass *oc, void *data)
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
POWERPC_FLAG_BUS_CLK;
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x10000;
}
static int check_pow_970FX (CPUPPCState *env)
@@ -6791,6 +6793,8 @@ POWERPC_FAMILY(970FX)(ObjectClass *oc, void *data)
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
POWERPC_FLAG_BUS_CLK;
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x10000;
}
static int check_pow_970MP (CPUPPCState *env)
@@ -6877,6 +6881,8 @@ POWERPC_FAMILY(970MP)(ObjectClass *oc, void *data)
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
POWERPC_FLAG_BUS_CLK;
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x10000;
}
static void init_proc_power5plus(CPUPPCState *env)
@@ -6967,6 +6973,8 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data)
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
POWERPC_FLAG_BUS_CLK;
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x10000;
}
static void init_proc_POWER7 (CPUPPCState *env)

File diff suppressed because it is too large Load Diff

View File

@@ -17,17 +17,23 @@
#undef TCG_TARGET_STACK_GROWSUP
typedef enum {
TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3, TCG_REG_X4,
TCG_REG_X5, TCG_REG_X6, TCG_REG_X7, TCG_REG_X8, TCG_REG_X9,
TCG_REG_X10, TCG_REG_X11, TCG_REG_X12, TCG_REG_X13, TCG_REG_X14,
TCG_REG_X15, TCG_REG_X16, TCG_REG_X17, TCG_REG_X18, TCG_REG_X19,
TCG_REG_X20, TCG_REG_X21, TCG_REG_X22, TCG_REG_X23, TCG_REG_X24,
TCG_REG_X25, TCG_REG_X26, TCG_REG_X27, TCG_REG_X28,
TCG_REG_FP, /* frame pointer */
TCG_REG_LR, /* link register */
TCG_REG_SP, /* stack pointer or zero register */
TCG_REG_XZR = TCG_REG_SP /* same register number */
/* program counter is not directly accessible! */
TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3,
TCG_REG_X4, TCG_REG_X5, TCG_REG_X6, TCG_REG_X7,
TCG_REG_X8, TCG_REG_X9, TCG_REG_X10, TCG_REG_X11,
TCG_REG_X12, TCG_REG_X13, TCG_REG_X14, TCG_REG_X15,
TCG_REG_X16, TCG_REG_X17, TCG_REG_X18, TCG_REG_X19,
TCG_REG_X20, TCG_REG_X21, TCG_REG_X22, TCG_REG_X23,
TCG_REG_X24, TCG_REG_X25, TCG_REG_X26, TCG_REG_X27,
TCG_REG_X28, TCG_REG_X29, TCG_REG_X30,
/* X31 is either the stack pointer or zero, depending on context. */
TCG_REG_SP = 31,
TCG_REG_XZR = 31,
/* Aliases. */
TCG_REG_FP = TCG_REG_X29,
TCG_REG_LR = TCG_REG_X30,
TCG_AREG0 = TCG_REG_X19,
} TCGReg;
#define TCG_TARGET_NB_REGS 32
@@ -92,11 +98,7 @@ typedef enum {
#define TCG_TARGET_HAS_muluh_i64 1
#define TCG_TARGET_HAS_mulsh_i64 1
enum {
TCG_AREG0 = TCG_REG_X19,
};
#define TCG_TARGET_HAS_new_ldst 0
#define TCG_TARGET_HAS_new_ldst 1
static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
{

View File

@@ -394,7 +394,8 @@ check-block: $(patsubst %,check-%, $(check-block-y))
check: check-qapi-schema check-unit check-qtest
check-clean:
$(MAKE) -C tests/tcg clean
rm -rf $(check-unit-y) $(check-qtest-i386-y) $(check-qtest-x86_64-y) $(check-qtest-sparc64-y) $(check-qtest-sparc-y) tests/*.o $(QEMU_IOTESTS_HELPERS-y)
rm -rf $(check-unit-y) tests/*.o $(QEMU_IOTESTS_HELPERS-y)
rm -rf $(sort $(foreach target,$(SYSEMU_TARGET_LIST), $(check-qtest-$(target)-y)))
clean: check-clean

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -69,10 +69,14 @@ _use_sample_img empty.bochs.bz2
poke_file "$TEST_IMG" "$disk_size_offset" "\x00\xc0\x0f\x00\x00\x00\x00\x7f"
{ $QEMU_IO -c "read 2T 4k" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
_use_sample_img empty.bochs.bz2
poke_file "$TEST_IMG" "$catalog_size_offset" "\x10\x00\x00\x00"
{ $QEMU_IO -c "read 0xfbe00 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
echo
echo "== Negative extent size =="
_use_sample_img empty.bochs.bz2
poke_file "$TEST_IMG" "$extent_size_offset" "\xff\xff\xff\xff"
poke_file "$TEST_IMG" "$extent_size_offset" "\x00\x00\x00\x80"
{ $QEMU_IO -c "read 768k 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
echo

View File

@@ -15,12 +15,14 @@ no file open, try 'help open'
== Too small catalog bitmap for image size ==
qemu-io: can't open device TEST_DIR/empty.bochs: Catalog size is too small for this disk size
no file open, try 'help open'
qemu-io: can't open device TEST_DIR/empty.bochs: Catalog size is too small for this disk size
no file open, try 'help open'
== Negative extent size ==
qemu-io: can't open device TEST_DIR/empty.bochs: Extent size 4294967295 is too large
qemu-io: can't open device TEST_DIR/empty.bochs: Extent size 2147483648 is too large
no file open, try 'help open'
== Zero extent size ==
qemu-io: can't open device TEST_DIR/empty.bochs: Extent size may not be zero
qemu-io: can't open device TEST_DIR/empty.bochs: Extent size must be at least 512
no file open, try 'help open'
*** done

View File

@@ -433,6 +433,27 @@ usb_uas_tmf_abort_task(int addr, uint16_t tag, uint16_t task_tag) "dev %d, tag 0
usb_uas_tmf_logical_unit_reset(int addr, uint16_t tag, int lun) "dev %d, tag 0x%x, lun %d"
usb_uas_tmf_unsupported(int addr, uint16_t tag, uint32_t function) "dev %d, tag 0x%x, function 0x%x"
# hw/usb/dev-mtp.c
usb_mtp_reset(int addr) "dev %d"
usb_mtp_command(int dev, uint16_t code, uint32_t trans, uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4) "dev %d, code 0x%x, trans 0x%x, args 0x%x, 0x%x, 0x%x, 0x%x, 0x%x"
usb_mtp_success(int dev, uint32_t trans, uint32_t arg0, uint32_t arg1) "dev %d, trans 0x%x, args 0x%x, 0x%x"
usb_mtp_error(int dev, uint16_t code, uint32_t trans, uint32_t arg0, uint32_t arg1) "dev %d, code 0x%x, trans 0x%x, args 0x%x, 0x%x"
usb_mtp_data_in(int dev, uint32_t trans, uint32_t len) "dev %d, trans 0x%x, len %d"
usb_mtp_data_out(int dev, uint32_t trans, uint32_t len) "dev %d, trans 0x%x, len %d"
usb_mtp_xfer(int dev, uint32_t ep, uint32_t dlen, uint32_t plen) "dev %d, ep %d, %d/%d"
usb_mtp_nak(int dev, uint32_t ep) "dev %d, ep %d"
usb_mtp_stall(int dev, const char *reason) "dev %d, reason: %s"
usb_mtp_op_get_device_info(int dev) "dev %d"
usb_mtp_op_open_session(int dev) "dev %d"
usb_mtp_op_close_session(int dev) "dev %d"
usb_mtp_op_get_storage_ids(int dev) "dev %d"
usb_mtp_op_get_storage_info(int dev) "dev %d"
usb_mtp_op_get_num_objects(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
usb_mtp_op_get_object_handles(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
usb_mtp_op_get_object_info(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
usb_mtp_op_get_object(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
usb_mtp_op_get_partial_object(int dev, uint32_t handle, const char *path, uint32_t offset, uint32_t length) "dev %d, handle 0x%x, path %s, off %d, len %d"
# hw/usb/host-libusb.c
usb_host_open_started(int bus, int addr) "dev %d:%d"
usb_host_open_success(int bus, int addr) "dev %d:%d"

View File

@@ -476,8 +476,15 @@ static void gd_change_runstate(void *opaque, int running, RunState state)
static void gd_mouse_mode_change(Notifier *notify, void *data)
{
gd_update_cursor(container_of(notify, GtkDisplayState, mouse_mode_notifier),
FALSE);
GtkDisplayState *s;
s = container_of(notify, GtkDisplayState, mouse_mode_notifier);
/* release the grab at switching to absolute mode */
if (qemu_input_is_absolute() && gd_is_grab_active(s)) {
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
FALSE);
}
gd_update_cursor(s, FALSE);
}
/** GTK Events **/
@@ -685,6 +692,14 @@ static gboolean gd_button_event(GtkWidget *widget, GdkEventButton *button,
GtkDisplayState *s = opaque;
InputButton btn;
/* implicitly grab the input at the first click in the relative mode */
if (button->button == 1 && button->type == GDK_BUTTON_PRESS &&
!qemu_input_is_absolute() && !gd_is_grab_active(s)) {
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
TRUE);
return TRUE;
}
if (button->button == 1) {
btn = INPUT_BUTTON_LEFT;
} else if (button->button == 2) {

View File

@@ -278,7 +278,7 @@ static void sdl_hide_cursor(void)
SDL_ShowCursor(1);
SDL_SetCursor(sdl_cursor_hidden);
} else {
SDL_ShowCursor(0);
SDL_SetRelativeMouseMode(SDL_TRUE);
}
}
@@ -289,6 +289,7 @@ static void sdl_show_cursor(void)
}
if (!qemu_input_is_absolute()) {
SDL_SetRelativeMouseMode(SDL_FALSE);
SDL_ShowCursor(1);
if (guest_cursor &&
(gui_grab || qemu_input_is_absolute() || absolute_enabled)) {
@@ -403,13 +404,17 @@ static void sdl_send_mouse_event(struct sdl2_state *scon, int dx, int dy,
}
qemu_input_queue_abs(scon->dcl.con, INPUT_AXIS_X, off_x + x, max_w);
qemu_input_queue_abs(scon->dcl.con, INPUT_AXIS_Y, off_y + y, max_h);
} else if (guest_cursor) {
x -= guest_x;
y -= guest_y;
guest_x += x;
guest_y += y;
qemu_input_queue_rel(scon->dcl.con, INPUT_AXIS_X, x);
qemu_input_queue_rel(scon->dcl.con, INPUT_AXIS_Y, y);
} else {
if (guest_cursor) {
x -= guest_x;
y -= guest_y;
guest_x += x;
guest_y += y;
dx = x;
dy = y;
}
qemu_input_queue_rel(scon->dcl.con, INPUT_AXIS_X, dx);
qemu_input_queue_rel(scon->dcl.con, INPUT_AXIS_Y, dy);
}
qemu_input_event_sync();
}

View File

@@ -549,6 +549,10 @@ static int interface_client_monitors_config(QXLInstance *sin,
QemuUIInfo info;
int rc;
if (!mc) {
return 1;
}
/*
* FIXME: multihead is tricky due to the way
* spice has multihead implemented.

View File

@@ -465,16 +465,29 @@ int cpu_signal_handler(int host_signum, void *pinfo,
#elif defined(__aarch64__)
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
{
siginfo_t *info = pinfo;
struct ucontext *uc = puc;
uint64_t pc;
int is_write = 0; /* XXX how to determine? */
uintptr_t pc = uc->uc_mcontext.pc;
uint32_t insn = *(uint32_t *)pc;
bool is_write;
pc = uc->uc_mcontext.pc;
return handle_cpu_signal(pc, (uint64_t)info->si_addr,
/* XXX: need kernel patch to get write flag faster. */
is_write = ( (insn & 0xbfff0000) == 0x0c000000 /* C3.3.1 */
|| (insn & 0xbfe00000) == 0x0c800000 /* C3.3.2 */
|| (insn & 0xbfdf0000) == 0x0d000000 /* C3.3.3 */
|| (insn & 0xbfc00000) == 0x0d800000 /* C3.3.4 */
|| (insn & 0x3f400000) == 0x08000000 /* C3.3.6 */
|| (insn & 0x3bc00000) == 0x39000000 /* C3.3.13 */
|| (insn & 0x3fc00000) == 0x3d800000 /* ... 128bit */
/* Ingore bits 10, 11 & 21, controlling indexing. */
|| (insn & 0x3bc00000) == 0x38000000 /* C3.3.8-12 */
|| (insn & 0x3fe00000) == 0x3c800000 /* ... 128bit */
/* Ignore bits 23 & 24, controlling indexing. */
|| (insn & 0x3a400000) == 0x28000000); /* C3.3.7,14-16 */
return handle_cpu_signal(pc, (uintptr_t)info->si_addr,
is_write, &uc->uc_sigmask, puc);
}