Re: [RFC v2 1/1] memory: Delete assertion in memory_region_unregister_iommu_notifier

2020-06-28 Thread Jason Wang



On 2020/6/28 下午10:47, Peter Xu wrote:

On Sun, Jun 28, 2020 at 03:03:41PM +0800, Jason Wang wrote:

On 2020/6/27 上午5:29, Peter Xu wrote:

Hi, Eugenio,

(CCing Eric, Yan and Michael too)

On Fri, Jun 26, 2020 at 08:41:22AM +0200, Eugenio Pérez wrote:

diff --git a/memory.c b/memory.c
index 2f15a4b250..7f789710d2 100644
--- a/memory.c
+++ b/memory.c
@@ -1915,8 +1915,6 @@ void memory_region_notify_one(IOMMUNotifier *notifier,
   return;
   }
-assert(entry->iova >= notifier->start && entry_end <= notifier->end);

I can understand removing the assertion should solve the issue, however imho
the major issue is not about this single assertion but the whole addr_mask
issue behind with virtio...


I don't get here, it looks to the the range was from guest IOMMU drivers.

Yes.  Note that I didn't mean that it's a problem in virtio, it's just the fact
that virtio is the only one I know that would like to support arbitrary address
range for the translated region.  I don't know about tcg, but vfio should still
need some kind of page alignment in both the address and the addr_mask.  We
have that assumption too across the memory core when we do translations.



Right but it looks to me the issue is not the alignment.




A further cause of the issue is the MSI region when vIOMMU enabled - currently
we implemented the interrupt region using another memory region so it split the
whole DMA region into two parts.  That's really a clean approach to IR
implementation, however that's also a burden to the invalidation part because
then we'll need to handle things like this when the listened range is not page
alighed at all (neither 0-0xfed, nor 0xfef-MAX).  If without the IR
region (so the whole iommu address range will be a single FlatRange),



Is this a bug? I remember that at least for vtd, it won't do any DMAR on 
the intrrupt address range




  I think
we probably don't need most of the logic in vtd_address_space_unmap() at all,
then we can directly deliver all the IOTLB invalidations without splitting into
small page aligned ranges to all the iommu notifiers.  Sadly, so far I still
don't have ideal solution for it, because we definitely need IR.



Another possible (theoretical) issue (for vhost) is that it can't 
trigger interrupt through the interrupt range.








For normal IOTLB invalidations, we were trying our best to always make
IOMMUTLBEntry contain a valid addr_mask to be 2**N-1.  E.g., that's what we're
doing with the loop in vtd_address_space_unmap().


I'm sure such such assumption can work for any type of IOMMU.



But this is not the first time that we may want to break this assumption for
virtio so that we make the IOTLB a tuple of (start, len), then that len can be
not a address mask any more.  That seems to be more efficient for things like
vhost because iotlbs there are not page based, so it'll be inefficient if we
always guarantee the addr_mask because it'll be quite a lot more roundtrips of
the same range of invalidation.  Here we've encountered another issue of
triggering the assertion with virtio-net, but only with the old RHEL7 guest.

I'm thinking whether we can make the IOTLB invalidation configurable by
specifying whether the backend of the notifier can handle arbitary address
range in some way.  So we still have the guaranteed addr_masks by default
(since I still don't think totally break the addr_mask restriction is wise...),
however we can allow the special backends to take adavantage of using arbitary
(start, len) ranges for reasons like performance.

To do that, a quick idea is to introduce a flag IOMMU_NOTIFIER_ARBITRARY_MASK
to IOMMUNotifierFlag, to declare that the iommu notifier (and its backend) can
take arbitrary address mask, then it can be any value and finally becomes a
length rather than an addr_mask.  Then for every iommu notify() we can directly
deliver whatever we've got from the upper layer to this notifier.  With the new
flag, vhost can do iommu_notifier_init() with UNMAP|ARBITRARY_MASK so it
declares this capability.  Then no matter for device iotlb or normal iotlb, we
skip the complicated procedure to split a big range into small ranges that are
with strict addr_mask, but directly deliver the message to the iommu notifier.
E.g., we can skip the loop in vtd_address_space_unmap() if the notifier is with
ARBITRARY flag set.


I'm not sure coupling IOMMU capability to notifier is the best choice.

IMHO it's not an IOMMU capability.  The flag I wanted to introduce is a
capability of the one who listens to the IOMMU TLB updates.  For our case, it's
virtio/vhost's capability to allow arbitrary length. The IOMMU itself
definitely has some limitation on the address range to be bound to an IOTLB
invalidation, e.g., the device-iotlb we're talking here only accept both the
iova address and addr_mask to be aligned to 2**N-1.



I think this go back to one of our previous discussion of whether to 
introduce a dedicated notifiers for device IOTLB.


For IOMMU, 

[Bug 1882123] Re: ARM cpu emulation regression on QEMU 4.2.0

2020-06-28 Thread Hajin Jang
Dear Peter Maydell (@pmaydell), is there any update on this bug?

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1882123

Title:
  ARM cpu emulation regression on QEMU 4.2.0

Status in QEMU:
  New

Bug description:
  [*] Summary

  Latest QEMU has an ARM CPU emulation regression.
  Regression is reproducible by building any C# project with .NET Core SDK 
3.1.300 on Debian 10 armhf guest OS.

  Releases affected: QEMU 4.2.0, 5.0.0
  Releases not affected: QEMU 4.1.0, QEMU 4.1.1

  [*] Detail

  .NET Core SDK 3.1 fails to run on Debian 10 emulated by qemu-system-
  arm.

  I occasionally test my C# projects on the virtual armhf/arm64 system
  emulated by QEMU. MSBuild, a build engine of the .NET Core SDK,
  crashes on QEMU 4.2.0 or later. The crash only happens when MSBuild
  tries to do any JIT compiling (dotnet build / dotnet test).

  I attached the MSBuild crash logs. MSBuild always crashes with
  SEHException, which means it tried to call C binary from .NET binary.

  I think the ARM CPU emulation regression happened between QEMU 4.1.1 ~
  4.2.0. The issue affects QEMU 4.2.0 and 5.0.0. QEMU 4.1.0, 4.1.1, and
  real Raspberry Pi 2 are not affected by this issue, and .NET Core SDK
  works completely fine.

  [*] Environment

  [Host OS]
  Distribution: Linux Mint 19.3 amd64
  CPU: AMD Ryzen 5 3600
  Kernel: Ubuntu 5.3.0-51-generic

  [QEMU Guest OS]
  Distribution: Debian 10 Buster armhf
  Kernel: Debian 4.19.0-9-armmp-lpae
  .NET Core SDK: 3.1.300

  [Raspberry Pi 2]
  Distribution: Raspberry Pi OS Buster armhf
  Kernel: 4.19.118-v7+

  [Tested C# Projects]
  This is a list of C# projects I have tested on QEMU and RPI2.
  - https://github.com/ied206/Joveler.DynLoader
  - https://github.com/ied206/Joveler.Compression
  - https://github.com/ied206/ManagedWimLib

  [QEMU Launch Arguments]
  qemu-system-arm \
  -smp 3 -M virt -m 4096 \
  -kernel vmlinuz-4.19.0-9-armmp-lpae \
  -initrd initrd.img-4.19.0-9-armmp-lpae \
  -append "root=/dev/vda2" \
  -drive if=none,file=debian_arm.qcow2,format=qcow2,id=hd \
  -device virtio-blk-device,drive=hd \
  -netdev user,id=mynet,hostfwd=tcp::-:22 \
  -device virtio-net-device,netdev=mynet \
  -device virtio-rng-device

  [QEMU Configure Arguments]
  ./configure --enable-spice --enable-gtk --enable-vnc-jpeg --enable-vnc-png 
--enable-avx2 --enable-libusb --enable-opengl --enable-virglrenderer 
--enable-kvm --enable-system --enable-modules --audio-drv-list=pa

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1882123/+subscriptions



[RFC] secure boot: is it necessary to let qemu verify EDK2 efi file

2020-06-28 Thread Zhangbo (Oscar)
Hi all:
    Secure boot for virtual machine NOWADAYS starts from edk2’s vBIOS, which 
verifies guest OS’s shim/grub2. Then grub2 verifies guest OS’s kernel.
  From the view of the whole complete trust chain, the GUEST part is 
disconnected from the HOST part, as the verification of vBIOS is missing, that 
is to say, no one verifies vBIOS image file(QEMU_EFI.fd).
#   
 
#   
 
#   
 
#  _   __ ___   
 
# | |_|  |___|   |HOST part 
 
# |_RTM_| |_BIOS_|   |_kernel|  
 
#   
 
#   
 
#   _____   
 
#  |  |__|   | GUEST part   
 
#  |_vBIOS|  |guest kernel  
 
#   
 
#   
 
  Thus, we have to verify vBIOS in order to complete the trust chain, 
connecting the host part with the guest part. 
  One solution is using IMA to verify the libvirt/qemu binaries and vBIOS image 
file(QEMU_EFI.fd).
  The other is let IMA verify libvirt/qemu, but let qemu verify vBIOS image 
file afterwards.

  Solution 1:
#   
 
#   
 
#   
 
#  _   __ ___ __
 
# | |_|  |___|   |___|  |   
 
# |_RTM_| |_BIOS_|   |_kernel|   |__libvirt_|   
 
#  |  __
 
#  |_|  |   
 
#  | |__qemu|   
 
#  |
 
#  |  __
 
#  |_|  |   
 
#|_vBIOS|   
    
 
Solution 2:
#   
 
#   
 
#   
 
#  _   __ ___ __
 
# | |_|  |___|   |___|  |   
 
# |_RTM_| |_BIOS_|   |_kernel|   |__libvirt_|   
 
#  |  __   
__
#  |_|  |_| 
 |   
#|__qemu| 
|_vBIOS|   
#   
 
#   
 
#   
 
#   
 

    Which solution shoule we choose? 
  Solution 1 seems much easier.
  But when we consider TRUST BOOT in, in that situation, qemu HAS to measure 
vBIOS image, and put the measured value into vTPM's PCR, that means,
  qemu is responsible for measuring the vBIOS during TRUST BOOT, it plays a 
role there.
  So, as long as qemu has 

Re: [PULL 00/63] riscv-to-apply queue

2020-06-28 Thread LIU Zhiwei




On 2020/6/29 6:51, Alistair Francis wrote:

On Sun, Jun 28, 2020 at 7:30 AM Peter Maydell  wrote:

On Fri, 26 Jun 2020 at 22:53, Alistair Francis  wrote:

The following changes since commit 553cf5d7c47bee05a3dec9461c1f8430316d516b:

   Merge remote-tracking branch 
'remotes/pmaydell/tags/pull-target-arm-20200626' into staging (2020-06-26 
18:22:36 +0100)

are available in the Git repository at:

   g...@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20200626-1

for you to fetch changes up to b39d59434ea10649fdb9e0a339c30c76e38c5e17:

   target/riscv: configure and turn on vector extension from command line 
(2020-06-26 14:22:15 -0700)


This PR contains two patches to improve PLIC support in QEMU.

The rest of the PR is adding support for the v0.7.1 RISC-V vector
extensions. This is experimental support as the vector extensions are
still in a draft state.


Hi; I'm afraid this fails to build on PPC64 and s390x (ie
our big-endian hosts):

LIU Zhiwei do you mind looking into this?

Sure, I will.
I have applied for a gcc compile farm account today, but it maybe a few 
days later before I can login.

Please accept my apologies for my oversight.

Zhiwei


Alistair


/home/ubuntu/qemu/target/riscv/vector_helper.c: In function ‘vext_clear’:
/home/ubuntu/qemu/target/riscv/vector_helper.c: In function ‘vext_clear’:
/home/ubuntu/qemu/target/riscv/vector_helper.c:154:21: error: invalid
operands to binary & (have ‘void *’ and ‘long long unsigned int’)
  memset(tail & ~(7ULL), 0, part1);
  ^
/home/ubuntu/qemu/target/riscv/vector_helper.c:155:27: error: invalid
operands to binary & (have ‘void *’ and ‘long long unsigned int’)
  memset((tail + 8) & ~(7ULL), 0, part2);
 ~~ ^
/home/ubuntu/qemu/target/riscv/vector_helper.c:154:21: error: invalid
operands to binary & (have ‘void *’ and ‘long long unsigned int’)
  memset(tail & ~(7ULL), 0, part1);
  ^
/home/ubuntu/qemu/target/riscv/vector_helper.c:155:27: error: invalid
operands to binary & (have ‘void *’ and ‘long long unsigned int’)
  memset((tail + 8) & ~(7ULL), 0, part2);
 ~~ ^
/home/ubuntu/qemu/rules.mak:69: recipe for target
'target/riscv/vector_helper.o' failed


thanks
-- PMM





[PATCH v2 1/2] hw/net: Added CSO for IPv6

2020-06-28 Thread andrew
From: Andrew 

Added fix for checksum offload for IPv6 if a backend doesn't
have a virtual header.
This patch is a part of IPv6 fragmentation.

Signed-off-by: Andrew Melnychenko 
---
 hw/net/net_tx_pkt.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c
index 162f802dd7..331c73cfc0 100644
--- a/hw/net/net_tx_pkt.c
+++ b/hw/net/net_tx_pkt.c
@@ -468,8 +468,8 @@ static void net_tx_pkt_do_sw_csum(struct NetTxPkt *pkt)
 /* num of iovec without vhdr */
 uint32_t iov_len = pkt->payload_frags + NET_TX_PKT_PL_START_FRAG - 1;
 uint16_t csl;
-struct ip_header *iphdr;
 size_t csum_offset = pkt->virt_hdr.csum_start + pkt->virt_hdr.csum_offset;
+uint16_t l3_proto = eth_get_l3_proto(iov, 1, iov->iov_len);
 
 /* Put zero to checksum field */
 iov_from_buf(iov, iov_len, csum_offset, &csum, sizeof csum);
@@ -477,9 +477,18 @@ static void net_tx_pkt_do_sw_csum(struct NetTxPkt *pkt)
 /* Calculate L4 TCP/UDP checksum */
 csl = pkt->payload_len;
 
+csum_cntr = 0;
+cso = 0;
 /* add pseudo header to csum */
-iphdr = pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_base;
-csum_cntr = eth_calc_ip4_pseudo_hdr_csum(iphdr, csl, &cso);
+if (l3_proto == ETH_P_IP) {
+csum_cntr = eth_calc_ip4_pseudo_hdr_csum(
+pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_base,
+csl, &cso);
+} else if (l3_proto == ETH_P_IPV6) {
+csum_cntr = eth_calc_ip6_pseudo_hdr_csum(
+pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_base,
+csl, pkt->l4proto, &cso);
+}
 
 /* data checksum */
 csum_cntr +=
-- 
2.27.0




[PATCH v2 2/2] hw/net: Added basic IPv6 fragmentation

2020-06-28 Thread andrew
From: Andrew 

Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1708065
Overall, there was an issue that big frames of IPv6 doesn't sent.
With network backend with 'virtual header' - there was an issue
in 'plen' field. Overall, during TSO, 'plen' would be changed,
but with 'vheader' this field should be set to the size of the
payload itself instead of '0'.
For software offload - there is added basic IPv6 fragmentation.
The basic IPv6 fragmentation - adding 'frag' extension to
the packet, overall shares some logic with IPv4. It works,
but there are still issues with a combination of
extensions - in the future, it would require refactoring
work to implement workflow with IPv6 and extension.
e1000e driver doesn't set the 'plen' field for IPv6 for big packets
if TSO is enabled. "Jumbo option" isn't added yet, until
qemu supports packets greater than 64K.

Signed-off-by: Andrew Melnychenko 
---
 hw/net/net_tx_pkt.c | 30 --
 hw/net/net_tx_pkt.h | 14 +++
 include/net/eth.h   | 15 +--
 net/eth.c   | 99 ++---
 4 files changed, 147 insertions(+), 11 deletions(-)

diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c
index 331c73cfc0..74044c6618 100644
--- a/hw/net/net_tx_pkt.c
+++ b/hw/net/net_tx_pkt.c
@@ -589,10 +589,11 @@ static bool net_tx_pkt_do_sw_fragmentation(struct 
NetTxPkt *pkt,
 
 more_frags = (fragment_offset + fragment_len < pkt->payload_len);
 
-eth_setup_ip4_fragmentation(l2_iov_base, l2_iov_len, l3_iov_base,
-l3_iov_len, fragment_len, fragment_offset, more_frags);
+eth_setup_ip_fragmentation(l2_iov_base, l2_iov_len, l3_iov_base,
+&l3_iov_len, ETH_MAX_IP_DGRAM_LEN,
+fragment_len, fragment_offset, more_frags);
 
-eth_fix_ip4_checksum(l3_iov_base, l3_iov_len);
+fragment[NET_TX_PKT_FRAGMENT_L3_HDR_POS].iov_len = l3_iov_len;
 
 net_tx_pkt_sendv(pkt, nc, fragment, dst_idx);
 
@@ -626,6 +627,7 @@ bool net_tx_pkt_send(struct NetTxPkt *pkt, NetClientState 
*nc)
 
 if (pkt->has_virt_hdr ||
 pkt->virt_hdr.gso_type == VIRTIO_NET_HDR_GSO_NONE) {
+net_tx_pkt_fix_ip6_payload_len(pkt);
 net_tx_pkt_sendv(pkt, nc, pkt->vec,
 pkt->payload_frags + NET_TX_PKT_PL_START_FRAG);
 return true;
@@ -644,3 +646,25 @@ bool net_tx_pkt_send_loopback(struct NetTxPkt *pkt, 
NetClientState *nc)
 
 return res;
 }
+
+void net_tx_pkt_fix_ip6_payload_len(struct NetTxPkt *pkt)
+{
+struct iovec *l2 = &pkt->vec[NET_TX_PKT_L2HDR_FRAG];
+if (eth_get_l3_proto(l2, 1, l2->iov_len) == ETH_P_IPV6) {
+struct ip6_header *ip6 = (struct ip6_header *) pkt->l3_hdr;
+/*
+ * TODO: if qemu would support >64K packets - add jumbo option check
+ * something like that:
+ * 'if (ip6->ip6_plen == 0 && !has_jumbo_option(ip6)) {'
+ */
+if (ip6->ip6_plen == 0) {
+if (pkt->payload_len <= ETH_MAX_IP_DGRAM_LEN) {
+ip6->ip6_plen = htons(pkt->payload_len);
+}
+/*
+ * TODO: if qemu would support >64K packets
+ * add jumbo option for packets greater then 65,535 bytes
+ */
+}
+}
+}
diff --git a/hw/net/net_tx_pkt.h b/hw/net/net_tx_pkt.h
index 212ecc62fc..4ec8bbe9bd 100644
--- a/hw/net/net_tx_pkt.h
+++ b/hw/net/net_tx_pkt.h
@@ -187,4 +187,18 @@ bool net_tx_pkt_parse(struct NetTxPkt *pkt);
 */
 bool net_tx_pkt_has_fragments(struct NetTxPkt *pkt);
 
+/**
+ * Fix IPv6 'plen' field.
+ * If ipv6 payload length field is 0 - then there should be Hop-by-Hop
+ * option for packets greater than 65,535.
+ * For packets with a payload less than 65,535: fix 'plen' field.
+ * For backends with vheader, we need just one packet with proper
+ * payload size. For now, qemu drops every packet with size greater 64K
+ * (see net_tx_pkt_send()) so, there is no reason to add jumbo option to ip6
+ * hop-by-hop extension if it's missed
+ *
+ * @pktpacket
+ */
+void net_tx_pkt_fix_ip6_payload_len(struct NetTxPkt *pkt);
+
 #endif
diff --git a/include/net/eth.h b/include/net/eth.h
index 7f45c678e7..05c75ac9fc 100644
--- a/include/net/eth.h
+++ b/include/net/eth.h
@@ -139,6 +139,14 @@ struct ip6_ext_hdr_routing {
 uint8_t rsvd[4];
 };
 
+struct ip6_ext_hdr_fragment {
+uint8_t nxt;
+uint8_t res0;
+uint16_toff;
+uint32_tid;
+};
+
+
 struct ip6_option_hdr {
 #define IP6_OPT_PAD1   (0x00)
 #define IP6_OPT_HOME   (0xC9)
@@ -186,6 +194,7 @@ struct tcp_hdr {
 
 #define ip6_nxt  ip6_ctlun.ip6_un1.ip6_un1_nxt
 #define ip6_ecn_acc  ip6_ctlun.ip6_un3.ip6_un3_ecn
+#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen
 
 #define PKT_GET_ETH_HDR(p)\
 ((struct eth_header *)(p))
@@ -398,9 +407,9 @@ void eth_get_protocols(const struct iovec *iov, int iovcnt,
eth_ip4_hdr_info *ip4hdr_info,
eth_l4_hdr_info  *l4hdr_info);
 
-void eth_setup_ip4_fr

[Bug 1883268] Re: random errors on aarch64 when executing __aarch64_cas8_acq_rel

2020-06-28 Thread Richard Henderson
There's nothing wrong with the atomic operation, which
makes sense since it's against a NULL pointer.  The
problem that I see is in the unwinding -- the catch
never happens and std::terminate gets called.

There must be some sort of 32-bit TCG error though,
because the same binary works on x86_64 host.

The most confusing thing about this test case is that
12 previous throws work correctly, but the 13th fails.

** Changed in: qemu
   Status: Confirmed => In Progress

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1883268

Title:
  random errors on aarch64 when executing __aarch64_cas8_acq_rel

Status in QEMU:
  In Progress

Bug description:
  Hello,

  Since I upgraded to qemu-5.0 when executing the GCC testsuite,
  I've noticed random failures of g++.dg/ext/sync-4.C.

  I'm attaching the source of the testcase, the binary executable and
  the qemu traces (huge, 111MB!) starting at main (with qemu-aarch64
  -cpu cortex-a57 -R 0 -d
  in_asm,int,exec,cpu,unimp,guest_errors,nochain)

  The traces where generated by a CI build, I built the executable
  manually but I expect it to be the same as the one executed by CI.

  In seems the problem occurs in f13, which leads to a call to abort()

  The preprocessed version of f13/t13 are as follows:
  static bool f13 (void *p) __attribute__ ((noinline));
  static bool f13 (void *p)
  {
return (__sync_bool_compare_and_swap((ditype*)p, 1, 2));
  }
  static void t13 ()
  {
try {
  f13(0);
}
catch (...) {
  return;
}
abort();
  }

  
  When looking at the execution traces at address 0x00400c9c, main calls f13, 
which in turn calls __aarch64_cas8_acq_rel (at 0x00401084)
  __aarch64_cas8_acq_rel returns to f13 (address 0x0040113c), then f13 returns 
to main (0x0040108c) which then calls abort (0x00400ca0)

  I'm not quite sure what's wrong :-(

  I've not noticed such random problems with native aarch64 hardware.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1883268/+subscriptions



Re: [PULL 00/63] riscv-to-apply queue

2020-06-28 Thread Alistair Francis
On Sun, Jun 28, 2020 at 7:30 AM Peter Maydell  wrote:
>
> On Fri, 26 Jun 2020 at 22:53, Alistair Francis  
> wrote:
> >
> > The following changes since commit 553cf5d7c47bee05a3dec9461c1f8430316d516b:
> >
> >   Merge remote-tracking branch 
> > 'remotes/pmaydell/tags/pull-target-arm-20200626' into staging (2020-06-26 
> > 18:22:36 +0100)
> >
> > are available in the Git repository at:
> >
> >   g...@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20200626-1
> >
> > for you to fetch changes up to b39d59434ea10649fdb9e0a339c30c76e38c5e17:
> >
> >   target/riscv: configure and turn on vector extension from command line 
> > (2020-06-26 14:22:15 -0700)
> >
> > 
> > This PR contains two patches to improve PLIC support in QEMU.
> >
> > The rest of the PR is adding support for the v0.7.1 RISC-V vector
> > extensions. This is experimental support as the vector extensions are
> > still in a draft state.
> >
>
> Hi; I'm afraid this fails to build on PPC64 and s390x (ie
> our big-endian hosts):

LIU Zhiwei do you mind looking into this?

Alistair

>
> /home/ubuntu/qemu/target/riscv/vector_helper.c: In function ‘vext_clear’:
> /home/ubuntu/qemu/target/riscv/vector_helper.c: In function ‘vext_clear’:
> /home/ubuntu/qemu/target/riscv/vector_helper.c:154:21: error: invalid
> operands to binary & (have ‘void *’ and ‘long long unsigned int’)
>  memset(tail & ~(7ULL), 0, part1);
>  ^
> /home/ubuntu/qemu/target/riscv/vector_helper.c:155:27: error: invalid
> operands to binary & (have ‘void *’ and ‘long long unsigned int’)
>  memset((tail + 8) & ~(7ULL), 0, part2);
> ~~ ^
> /home/ubuntu/qemu/target/riscv/vector_helper.c:154:21: error: invalid
> operands to binary & (have ‘void *’ and ‘long long unsigned int’)
>  memset(tail & ~(7ULL), 0, part1);
>  ^
> /home/ubuntu/qemu/target/riscv/vector_helper.c:155:27: error: invalid
> operands to binary & (have ‘void *’ and ‘long long unsigned int’)
>  memset((tail + 8) & ~(7ULL), 0, part2);
> ~~ ^
> /home/ubuntu/qemu/rules.mak:69: recipe for target
> 'target/riscv/vector_helper.o' failed
>
>
> thanks
> -- PMM



[Bug 1883268] Re: random errors on aarch64 when executing __aarch64_cas8_acq_rel

2020-06-28 Thread Richard Henderson
FWIW, I cannot reproduce the problem with x86_64 host,
but I can reproduce it on a 32-bit i686 host.

** Changed in: qemu
   Status: New => Confirmed

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1883268

Title:
  random errors on aarch64 when executing __aarch64_cas8_acq_rel

Status in QEMU:
  Confirmed

Bug description:
  Hello,

  Since I upgraded to qemu-5.0 when executing the GCC testsuite,
  I've noticed random failures of g++.dg/ext/sync-4.C.

  I'm attaching the source of the testcase, the binary executable and
  the qemu traces (huge, 111MB!) starting at main (with qemu-aarch64
  -cpu cortex-a57 -R 0 -d
  in_asm,int,exec,cpu,unimp,guest_errors,nochain)

  The traces where generated by a CI build, I built the executable
  manually but I expect it to be the same as the one executed by CI.

  In seems the problem occurs in f13, which leads to a call to abort()

  The preprocessed version of f13/t13 are as follows:
  static bool f13 (void *p) __attribute__ ((noinline));
  static bool f13 (void *p)
  {
return (__sync_bool_compare_and_swap((ditype*)p, 1, 2));
  }
  static void t13 ()
  {
try {
  f13(0);
}
catch (...) {
  return;
}
abort();
  }

  
  When looking at the execution traces at address 0x00400c9c, main calls f13, 
which in turn calls __aarch64_cas8_acq_rel (at 0x00401084)
  __aarch64_cas8_acq_rel returns to f13 (address 0x0040113c), then f13 returns 
to main (0x0040108c) which then calls abort (0x00400ca0)

  I'm not quite sure what's wrong :-(

  I've not noticed such random problems with native aarch64 hardware.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1883268/+subscriptions



[PATCH 1/2] hw/arm/palm.c: Detabify

2020-06-28 Thread Peter Maydell
Remove hard-tabs from palm.c.

Signed-off-by: Peter Maydell 
---
 hw/arm/palm.c | 64 +--
 1 file changed, 32 insertions(+), 32 deletions(-)

diff --git a/hw/arm/palm.c b/hw/arm/palm.c
index 97ca105d297..569836178f6 100644
--- a/hw/arm/palm.c
+++ b/hw/arm/palm.c
@@ -61,21 +61,21 @@ static const MemoryRegionOps static_ops = {
 /* Palm Tunsgten|E support */
 
 /* Shared GPIOs */
-#define PALMTE_USBDETECT_GPIO  0
-#define PALMTE_USB_OR_DC_GPIO  1
-#define PALMTE_TSC_GPIO4
-#define PALMTE_PINTDAV_GPIO6
-#define PALMTE_MMC_WP_GPIO 8
-#define PALMTE_MMC_POWER_GPIO  9
-#define PALMTE_HDQ_GPIO11
-#define PALMTE_HEADPHONES_GPIO 14
-#define PALMTE_SPEAKER_GPIO15
+#define PALMTE_USBDETECT_GPIO   0
+#define PALMTE_USB_OR_DC_GPIO   1
+#define PALMTE_TSC_GPIO 4
+#define PALMTE_PINTDAV_GPIO 6
+#define PALMTE_MMC_WP_GPIO  8
+#define PALMTE_MMC_POWER_GPIO   9
+#define PALMTE_HDQ_GPIO 11
+#define PALMTE_HEADPHONES_GPIO  14
+#define PALMTE_SPEAKER_GPIO 15
 /* MPU private GPIOs */
-#define PALMTE_DC_GPIO 2
-#define PALMTE_MMC_SWITCH_GPIO 4
-#define PALMTE_MMC1_GPIO   6
-#define PALMTE_MMC2_GPIO   7
-#define PALMTE_MMC3_GPIO   11
+#define PALMTE_DC_GPIO  2
+#define PALMTE_MMC_SWITCH_GPIO  4
+#define PALMTE_MMC1_GPIO6
+#define PALMTE_MMC2_GPIO7
+#define PALMTE_MMC3_GPIO11
 
 static MouseTransformInfo palmte_pointercal = {
 .x = 320,
@@ -100,17 +100,17 @@ static struct {
 int column;
 } palmte_keymap[0x80] = {
 [0 ... 0x7f] = { -1, -1 },
-[0x3b] = { 0, 0 }, /* F1   -> Calendar */
-[0x3c] = { 1, 0 }, /* F2   -> Contacts */
-[0x3d] = { 2, 0 }, /* F3   -> Tasks List */
-[0x3e] = { 3, 0 }, /* F4   -> Note Pad */
-[0x01] = { 4, 0 }, /* Esc  -> Power */
-[0x4b] = { 0, 1 }, /* Left */
-[0x50] = { 1, 1 }, /* Down */
-[0x48] = { 2, 1 }, /* Up */
-[0x4d] = { 3, 1 }, /* Right */
-[0x4c] = { 4, 1 }, /* Centre */
-[0x39] = { 4, 1 }, /* Spc  -> Centre */
+[0x3b] = { 0, 0 },  /* F1   -> Calendar */
+[0x3c] = { 1, 0 },  /* F2   -> Contacts */
+[0x3d] = { 2, 0 },  /* F3   -> Tasks List */
+[0x3e] = { 3, 0 },  /* F4   -> Note Pad */
+[0x01] = { 4, 0 },  /* Esc  -> Power */
+[0x4b] = { 0, 1 },  /* Left */
+[0x50] = { 1, 1 },  /* Down */
+[0x48] = { 2, 1 },  /* Up */
+[0x4d] = { 3, 1 },  /* Right */
+[0x4c] = { 4, 1 },  /* Centre */
+[0x39] = { 4, 1 },  /* Spc  -> Centre */
 };
 
 static void palmte_button_event(void *opaque, int keycode)
@@ -161,13 +161,13 @@ static void palmte_gpio_setup(struct omap_mpu_state_s 
*cpu)
 [PALMTE_MMC_SWITCH_GPIO]));
 
 misc_gpio = qemu_allocate_irqs(palmte_onoff_gpios, cpu, 7);
-qdev_connect_gpio_out(cpu->gpio, PALMTE_MMC_POWER_GPIO,misc_gpio[0]);
-qdev_connect_gpio_out(cpu->gpio, PALMTE_SPEAKER_GPIO,  misc_gpio[1]);
-qdev_connect_gpio_out(cpu->gpio, 11,   misc_gpio[2]);
-qdev_connect_gpio_out(cpu->gpio, 12,   misc_gpio[3]);
-qdev_connect_gpio_out(cpu->gpio, 13,   misc_gpio[4]);
-omap_mpuio_out_set(cpu->mpuio, 1,  misc_gpio[5]);
-omap_mpuio_out_set(cpu->mpuio, 3,  misc_gpio[6]);
+qdev_connect_gpio_out(cpu->gpio, PALMTE_MMC_POWER_GPIO, misc_gpio[0]);
+qdev_connect_gpio_out(cpu->gpio, PALMTE_SPEAKER_GPIO,   misc_gpio[1]);
+qdev_connect_gpio_out(cpu->gpio, 11,misc_gpio[2]);
+qdev_connect_gpio_out(cpu->gpio, 12,misc_gpio[3]);
+qdev_connect_gpio_out(cpu->gpio, 13,misc_gpio[4]);
+omap_mpuio_out_set(cpu->mpuio, 1,   misc_gpio[5]);
+omap_mpuio_out_set(cpu->mpuio, 3,   misc_gpio[6]);
 
 /* Reset some inputs to initial state.  */
 qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USBDETECT_GPIO));
-- 
2.20.1




[PATCH 2/2] hw/arm/palm.c: Encapsulate misc GPIO handling in a device

2020-06-28 Thread Peter Maydell
Replace the free-floating set of IRQs and palmte_onoff_gpios()
function with a simple QOM device that encapsulates this
behaviour.

This fixes Coverity issue CID 1421944, which points out that
the memory returned by qemu_allocate_irqs() is leaked.

Signed-off-by: Peter Maydell 
---
 hw/arm/palm.c | 61 +++
 1 file changed, 52 insertions(+), 9 deletions(-)

diff --git a/hw/arm/palm.c b/hw/arm/palm.c
index 569836178f6..e7bc9ea4c6a 100644
--- a/hw/arm/palm.c
+++ b/hw/arm/palm.c
@@ -124,6 +124,21 @@ static void palmte_button_event(void *opaque, int keycode)
 !(keycode & 0x80));
 }
 
+/*
+ * Encapsulation of some GPIO line behaviour for the Palm board
+ *
+ * QEMU interface:
+ *  + unnamed GPIO inputs 0..6: for the various miscellaneous input lines
+ */
+
+#define TYPE_PALM_MISC_GPIO "palm-misc-gpio"
+#define PALM_MISC_GPIO(obj) \
+OBJECT_CHECK(PalmMiscGPIOState, (obj), TYPE_PALM_MISC_GPIO)
+
+typedef struct PalmMiscGPIOState {
+SysBusDevice parent_obj;
+} PalmMiscGPIOState;
+
 static void palmte_onoff_gpios(void *opaque, int line, int level)
 {
 switch (line) {
@@ -151,23 +166,44 @@ static void palmte_onoff_gpios(void *opaque, int line, 
int level)
 }
 }
 
+static void palm_misc_gpio_init(Object *obj)
+{
+DeviceState *dev = DEVICE(obj);
+
+qdev_init_gpio_in(dev, palmte_onoff_gpios, 7);
+}
+
+static const TypeInfo palm_misc_gpio_info = {
+.name = TYPE_PALM_MISC_GPIO,
+.parent = TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(PalmMiscGPIOState),
+.instance_init = palm_misc_gpio_init,
+/*
+ * No class init required: device has no internal state so does not
+ * need to set up reset or vmstate, and has no realize method.
+ */
+};
+
 static void palmte_gpio_setup(struct omap_mpu_state_s *cpu)
 {
-qemu_irq *misc_gpio;
+DeviceState *misc_gpio;
+
+misc_gpio = sysbus_create_simple(TYPE_PALM_MISC_GPIO, -1, NULL);
 
 omap_mmc_handlers(cpu->mmc,
 qdev_get_gpio_in(cpu->gpio, PALMTE_MMC_WP_GPIO),
 qemu_irq_invert(omap_mpuio_in_get(cpu->mpuio)
 [PALMTE_MMC_SWITCH_GPIO]));
 
-misc_gpio = qemu_allocate_irqs(palmte_onoff_gpios, cpu, 7);
-qdev_connect_gpio_out(cpu->gpio, PALMTE_MMC_POWER_GPIO, misc_gpio[0]);
-qdev_connect_gpio_out(cpu->gpio, PALMTE_SPEAKER_GPIO,   misc_gpio[1]);
-qdev_connect_gpio_out(cpu->gpio, 11,misc_gpio[2]);
-qdev_connect_gpio_out(cpu->gpio, 12,misc_gpio[3]);
-qdev_connect_gpio_out(cpu->gpio, 13,misc_gpio[4]);
-omap_mpuio_out_set(cpu->mpuio, 1,   misc_gpio[5]);
-omap_mpuio_out_set(cpu->mpuio, 3,   misc_gpio[6]);
+qdev_connect_gpio_out(cpu->gpio, PALMTE_MMC_POWER_GPIO,
+  qdev_get_gpio_in(misc_gpio, 0));
+qdev_connect_gpio_out(cpu->gpio, PALMTE_SPEAKER_GPIO,
+  qdev_get_gpio_in(misc_gpio, 1));
+qdev_connect_gpio_out(cpu->gpio, 11, qdev_get_gpio_in(misc_gpio, 2));
+qdev_connect_gpio_out(cpu->gpio, 12, qdev_get_gpio_in(misc_gpio, 3));
+qdev_connect_gpio_out(cpu->gpio, 13, qdev_get_gpio_in(misc_gpio, 4));
+omap_mpuio_out_set(cpu->mpuio, 1, qdev_get_gpio_in(misc_gpio, 5));
+omap_mpuio_out_set(cpu->mpuio, 3, qdev_get_gpio_in(misc_gpio, 6));
 
 /* Reset some inputs to initial state.  */
 qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USBDETECT_GPIO));
@@ -276,3 +312,10 @@ static void palmte_machine_init(MachineClass *mc)
 }
 
 DEFINE_MACHINE("cheetah", palmte_machine_init)
+
+static void palm_register_types(void)
+{
+type_register_static(&palm_misc_gpio_info);
+}
+
+type_init(palm_register_types)
-- 
2.20.1




[PATCH 0/2] hw/arm/palm.c: Fix Coverity issue CID 1421944

2020-06-28 Thread Peter Maydell
As for spitz and tosa, fix the Coverity issue CID 1421944 which
points out that memory returned from qemu_allocate_irqs() is leaked
by encapsulating the GPIO handling into a simple device.
As with the other series, detabify the file first.

thanks
-- PMM

Peter Maydell (2):
  hw/arm/palm.c: Detabify
  hw/arm/palm.c: Encapsulate misc GPIO handling in a device

 hw/arm/palm.c | 111 ++
 1 file changed, 77 insertions(+), 34 deletions(-)

-- 
2.20.1




[PATCH] tests: Inject test name also when the test fails

2020-06-28 Thread Havard Skinnemoen
If a test is unsuccessful, the result is "not ok", which does not match
the regex because it includes a space.

This regex matches both "ok" and "not ok".

Signed-off-by: Havard Skinnemoen 
---
 tests/Makefile.include | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/Makefile.include b/tests/Makefile.include
index 3f4448a20b..09df2d3f86 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -637,7 +637,7 @@ define do_test_tap
   { export MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$(( $${RANDOM:-0} % 
255 + 1))} $2; \
 $(foreach COMMAND, $1, \
  $(COMMAND) -m=$(SPEED) -k --tap < /dev/null \
- | sed "s/^[a-z][a-z]* [0-9]* /&$(notdir $(COMMAND)) /" || true; ) 
} \
+ | sed "s/^\(not \)\?ok [0-9]* /&$(notdir $(COMMAND)) /" || true; 
) } \
  | ./scripts/tap-merge.pl | tee "$@" \
  | ./scripts/tap-driver.pl $(if $(V),, --show-failures-only), \
  "TAP","$@")
-- 
2.27.0.212.ge8ba1cc988-goog




[PATCH 2/2] hw/arm/tosa: Encapsulate misc GPIO handling in a device

2020-06-28 Thread Peter Maydell
Currently we have a free-floating set of IRQs and a function
tosa_out_switch() which handle the GPIO lines on the tosa board which
connect to LEDs, and another free-floating IRQ and tosa_reset()
function to handle the GPIO line that resets the system.  Encapsulate
this behaviour in a simple QOM device.

This commit fixes Coverity issue CID 1421929 (which pointed out that
the 'outsignals' in tosa_gpio_setup() were leaked), because it
removes the use of the qemu_allocate_irqs() API from this code
entirely.

Signed-off-by: Peter Maydell 
---
This is simpler than the spitz changes because the new device
doesn't need to refer to any of the other devices on the board.
---
 hw/arm/tosa.c | 88 +--
 1 file changed, 64 insertions(+), 24 deletions(-)

diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
index 06ecf1e7824..383b3b22e24 100644
--- a/hw/arm/tosa.c
+++ b/hw/arm/tosa.c
@@ -65,24 +65,39 @@ static void tosa_microdrive_attach(PXA2xxState *cpu)
 pxa2xx_pcmcia_attach(cpu->pcmcia[0], md);
 }
 
-static void tosa_out_switch(void *opaque, int line, int level)
+/*
+ * Encapsulation of some GPIO line behaviour for the Tosa board
+ *
+ * QEMU interface:
+ *  + named GPIO inputs "leds[0..3]": assert to light LEDs
+ *  + named GPIO input "reset": when asserted, resets the system
+ */
+
+#define TYPE_TOSA_MISC_GPIO "tosa-misc-gpio"
+#define TOSA_MISC_GPIO(obj) \
+OBJECT_CHECK(TosaMiscGPIOState, (obj), TYPE_TOSA_MISC_GPIO)
+
+typedef struct TosaMiscGPIOState {
+SysBusDevice parent_obj;
+} TosaMiscGPIOState;
+
+static void tosa_gpio_leds(void *opaque, int line, int level)
 {
 switch (line) {
-case 0:
-fprintf(stderr, "blue LED %s.\n", level ? "on" : "off");
-break;
-case 1:
-fprintf(stderr, "green LED %s.\n", level ? "on" : "off");
-break;
-case 2:
-fprintf(stderr, "amber LED %s.\n", level ? "on" : "off");
-break;
-case 3:
-fprintf(stderr, "wlan LED %s.\n", level ? "on" : "off");
-break;
-default:
-fprintf(stderr, "Uhandled out event: %d = %d\n", line, level);
-break;
+case 0:
+fprintf(stderr, "blue LED %s.\n", level ? "on" : "off");
+break;
+case 1:
+fprintf(stderr, "green LED %s.\n", level ? "on" : "off");
+break;
+case 2:
+fprintf(stderr, "amber LED %s.\n", level ? "on" : "off");
+break;
+case 3:
+fprintf(stderr, "wlan LED %s.\n", level ? "on" : "off");
+break;
+default:
+g_assert_not_reached();
 }
 }
 
@@ -93,13 +108,22 @@ static void tosa_reset(void *opaque, int line, int level)
 }
 }
 
+static void tosa_misc_gpio_init(Object *obj)
+{
+DeviceState *dev = DEVICE(obj);
+
+qdev_init_gpio_in_named(dev, tosa_gpio_leds, "leds", 4);
+qdev_init_gpio_in_named(dev, tosa_reset, "reset", 1);
+}
+
 static void tosa_gpio_setup(PXA2xxState *cpu,
 DeviceState *scp0,
 DeviceState *scp1,
 TC6393xbState *tmio)
 {
-qemu_irq *outsignals = qemu_allocate_irqs(tosa_out_switch, cpu, 4);
-qemu_irq reset;
+DeviceState *misc_gpio;
+
+misc_gpio = sysbus_create_simple(TYPE_TOSA_MISC_GPIO, -1, NULL);
 
 /* MMC/SD host */
 pxa2xx_mmci_handlers(cpu->mmc,
@@ -107,8 +131,8 @@ static void tosa_gpio_setup(PXA2xxState *cpu,
 qemu_irq_invert(qdev_get_gpio_in(cpu->gpio, 
TOSA_GPIO_nSD_DETECT)));
 
 /* Handle reset */
-reset = qemu_allocate_irq(tosa_reset, cpu, 0);
-qdev_connect_gpio_out(cpu->gpio, TOSA_GPIO_ON_RESET, reset);
+qdev_connect_gpio_out(cpu->gpio, TOSA_GPIO_ON_RESET,
+  qdev_get_gpio_in_named(misc_gpio, "reset", 0));
 
 /* PCMCIA signals: card's IRQ and Card-Detect */
 pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0],
@@ -119,10 +143,14 @@ static void tosa_gpio_setup(PXA2xxState *cpu,
 qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_JC_CF_IRQ),
 NULL);
 
-qdev_connect_gpio_out(scp1, TOSA_GPIO_BT_LED, outsignals[0]);
-qdev_connect_gpio_out(scp1, TOSA_GPIO_NOTE_LED, outsignals[1]);
-qdev_connect_gpio_out(scp1, TOSA_GPIO_CHRG_ERR_LED, outsignals[2]);
-qdev_connect_gpio_out(scp1, TOSA_GPIO_WLAN_LED, outsignals[3]);
+qdev_connect_gpio_out(scp1, TOSA_GPIO_BT_LED,
+  qdev_get_gpio_in_named(misc_gpio, "leds", 0));
+qdev_connect_gpio_out(scp1, TOSA_GPIO_NOTE_LED,
+  qdev_get_gpio_in_named(misc_gpio, "leds", 1));
+qdev_connect_gpio_out(scp1, TOSA_GPIO_CHRG_ERR_LED,
+  qdev_get_gpio_in_named(misc_gpio, "leds", 2));
+qdev_connect_gpio_out(scp1, TOSA_GPIO_WLAN_LED,
+  qdev_get_gpio_in_named(misc_gpio, "leds", 3));
 
 qdev_connect_gpio_out(scp1, TOSA_GPIO_TC6393XB_L3V_ON, 
tc6393xb_l3v_get(tmio));
 
@@ -287,10 +315,22 @@ static const TypeInfo to

[PATCH 1/2] hw/arm/tosa.c: Detabify

2020-06-28 Thread Peter Maydell
Remove the hardcoded tabs from hw/arm/tosa.c. There aren't
many, but since they're all in constant #defines they're not
going to go away with our usual "only when we touch a function"
policy on reformatting.

Signed-off-by: Peter Maydell 
---
 hw/arm/tosa.c | 44 ++--
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
index 5dee2d76c61..06ecf1e7824 100644
--- a/hw/arm/tosa.c
+++ b/hw/arm/tosa.c
@@ -26,32 +26,32 @@
 #include "hw/sysbus.h"
 #include "exec/address-spaces.h"
 
-#define TOSA_RAM0x0400
-#define TOSA_ROM   0x0080
+#define TOSA_RAM 0x0400
+#define TOSA_ROM 0x0080
 
-#define TOSA_GPIO_USB_IN   (5)
-#define TOSA_GPIO_nSD_DETECT   (9)
-#define TOSA_GPIO_ON_RESET (19)
-#define TOSA_GPIO_CF_IRQ   (21)/* CF slot0 Ready */
-#define TOSA_GPIO_CF_CD(13)
-#define TOSA_GPIO_TC6393XB_INT  (15)
-#define TOSA_GPIO_JC_CF_IRQ(36)/* CF slot1 Ready */
+#define TOSA_GPIO_USB_IN(5)
+#define TOSA_GPIO_nSD_DETECT(9)
+#define TOSA_GPIO_ON_RESET  (19)
+#define TOSA_GPIO_CF_IRQ(21)/* CF slot0 Ready */
+#define TOSA_GPIO_CF_CD (13)
+#define TOSA_GPIO_TC6393XB_INT  (15)
+#define TOSA_GPIO_JC_CF_IRQ (36)/* CF slot1 Ready */
 
-#define TOSA_SCOOP_GPIO_BASE   1
-#define TOSA_GPIO_IR_POWERDWN  (TOSA_SCOOP_GPIO_BASE + 2)
-#define TOSA_GPIO_SD_WP(TOSA_SCOOP_GPIO_BASE + 3)
-#define TOSA_GPIO_PWR_ON   (TOSA_SCOOP_GPIO_BASE + 4)
+#define TOSA_SCOOP_GPIO_BASE1
+#define TOSA_GPIO_IR_POWERDWN   (TOSA_SCOOP_GPIO_BASE + 2)
+#define TOSA_GPIO_SD_WP (TOSA_SCOOP_GPIO_BASE + 3)
+#define TOSA_GPIO_PWR_ON(TOSA_SCOOP_GPIO_BASE + 4)
 
-#define TOSA_SCOOP_JC_GPIO_BASE1
-#define TOSA_GPIO_BT_LED   (TOSA_SCOOP_JC_GPIO_BASE + 0)
-#define TOSA_GPIO_NOTE_LED (TOSA_SCOOP_JC_GPIO_BASE + 1)
-#define TOSA_GPIO_CHRG_ERR_LED (TOSA_SCOOP_JC_GPIO_BASE + 2)
-#define TOSA_GPIO_TC6393XB_L3V_ON  (TOSA_SCOOP_JC_GPIO_BASE + 5)
-#define TOSA_GPIO_WLAN_LED (TOSA_SCOOP_JC_GPIO_BASE + 7)
+#define TOSA_SCOOP_JC_GPIO_BASE 1
+#define TOSA_GPIO_BT_LED(TOSA_SCOOP_JC_GPIO_BASE + 0)
+#define TOSA_GPIO_NOTE_LED  (TOSA_SCOOP_JC_GPIO_BASE + 1)
+#define TOSA_GPIO_CHRG_ERR_LED  (TOSA_SCOOP_JC_GPIO_BASE + 2)
+#define TOSA_GPIO_TC6393XB_L3V_ON   (TOSA_SCOOP_JC_GPIO_BASE + 5)
+#define TOSA_GPIO_WLAN_LED  (TOSA_SCOOP_JC_GPIO_BASE + 7)
 
-#defineDAC_BASE0x4e
-#define DAC_CH10
-#define DAC_CH21
+#define DAC_BASE 0x4e
+#define DAC_CH1 0
+#define DAC_CH2 1
 
 static void tosa_microdrive_attach(PXA2xxState *cpu)
 {
-- 
2.20.1




[PATCH 0/2] tosa: fix Coverity CID 1421929

2020-06-28 Thread Peter Maydell
This series fixes Coverity issue CID 1421929, which pointed out that
the 'outsignals' in tosa_gpio_setup() were leaked, in the same way
that the equivalent bug for spitz was fixed in the series I posted
earlier: instead of using qemu_allocate_irqs() we create a device
to encapsulate the handling of the misc GPIO lines on this board.
This is simpler than the spitz case because for tosa we don't need
to work with any of the other devices on the board, so the misc-gpio
device can be simple and self-contained.

As with spitz, I started out by tidying up some stray hard-tabs.

thanks
-- PMM

Peter Maydell (2):
  hw/arm/tosa.c: Detabify
  hw/arm/tosa: Encapsulate misc GPIO handling in a device

 hw/arm/tosa.c | 132 --
 1 file changed, 86 insertions(+), 46 deletions(-)

-- 
2.20.1




[PATCH 3/3] Select MDIO device 2 and 1 as PHY devices for i.MX6UL EVK board.

2020-06-28 Thread Jean-Christophe Dubois
The i.MX6UL EVK 14x14 board uses:
- PHY 2 for FEC 1
- PHY 1 for FEC 2

Signed-off-by: Jean-Christophe Dubois 
---
 hw/arm/mcimx6ul-evk.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/arm/mcimx6ul-evk.c b/hw/arm/mcimx6ul-evk.c
index 2f845cedfce..9033d3f8f38 100644
--- a/hw/arm/mcimx6ul-evk.c
+++ b/hw/arm/mcimx6ul-evk.c
@@ -40,6 +40,8 @@ static void mcimx6ul_evk_init(MachineState *machine)
 
 s = FSL_IMX6UL(object_new(TYPE_FSL_IMX6UL));
 object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
+object_property_set_uint(OBJECT(s), 2, "fec1-phy-num", &error_fatal);
+object_property_set_uint(OBJECT(s), 1, "fec2-phy-num", &error_fatal);
 qdev_realize(DEVICE(s), NULL, &error_fatal);
 
 memory_region_add_subregion(get_system_memory(), FSL_IMX6UL_MMDC_ADDR,
-- 
2.25.1




[PATCH 2/3] Add the ability to select a different PHY for each i.MX6UL FEC interface

2020-06-28 Thread Jean-Christophe Dubois
Add properties to the i.MX6UL processor to be able to select a
particular PHY on the MDIO bus for each FEC device.

Signed-off-by: Jean-Christophe Dubois 
---
 hw/arm/fsl-imx6ul.c | 10 ++
 include/hw/arm/fsl-imx6ul.h |  2 ++
 2 files changed, 12 insertions(+)

diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
index 6446034711e..51b2f256ec8 100644
--- a/hw/arm/fsl-imx6ul.c
+++ b/hw/arm/fsl-imx6ul.c
@@ -427,6 +427,9 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error 
**errp)
 FSL_IMX6UL_ENET2_TIMER_IRQ,
 };
 
+object_property_set_uint(OBJECT(&s->eth[i]),
+ s->phy_num[i],
+ "phy-num", &error_abort);
 object_property_set_uint(OBJECT(&s->eth[i]),
  FSL_IMX6UL_ETH_NUM_TX_RINGS,
  "tx-ring-num", &error_abort);
@@ -607,10 +610,17 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error 
**errp)
 FSL_IMX6UL_OCRAM_ALIAS_ADDR, &s->ocram_alias);
 }
 
+static Property fsl_imx6ul_properties[] = {
+DEFINE_PROP_UINT32("fec1-phy-num", FslIMX6ULState, phy_num[0], 0),
+DEFINE_PROP_UINT32("fec2-phy-num", FslIMX6ULState, phy_num[1], 1),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static void fsl_imx6ul_class_init(ObjectClass *oc, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(oc);
 
+device_class_set_props(dc, fsl_imx6ul_properties);
 dc->realize = fsl_imx6ul_realize;
 dc->desc = "i.MX6UL SOC";
 /* Reason: Uses serial_hds and nd_table in realize() directly */
diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h
index 37c89cc5f92..fcbaf3dc861 100644
--- a/include/hw/arm/fsl-imx6ul.h
+++ b/include/hw/arm/fsl-imx6ul.h
@@ -87,6 +87,8 @@ typedef struct FslIMX6ULState {
 MemoryRegion   caam;
 MemoryRegion   ocram;
 MemoryRegion   ocram_alias;
+
+uint32_t   phy_num[FSL_IMX6UL_NUM_ETHS];
 } FslIMX6ULState;
 
 enum FslIMX6ULMemoryMap {
-- 
2.25.1




[PATCH 1/3] Add a phy-num property to the i.MX FEC emulator

2020-06-28 Thread Jean-Christophe Dubois
We need a solution to use an Ethernet PHY that is not the first device
on the MDIO bus (device 0 on MDIO bus).

As an example with the i.MX6UL the NXP SOC has 2 Ethernet devices but
only one MDIO bus on which the 2 related PHY are connected but at unique
addresses.

Signed-off-by: Jean-Christophe Dubois 
---
 hw/net/imx_fec.c | 24 +---
 hw/net/trace-events  |  4 ++--
 include/hw/net/imx_fec.h |  1 +
 3 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index eefedc252de..2c148040414 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -280,12 +280,16 @@ static void imx_phy_reset(IMXFECState *s)
 static uint32_t imx_phy_read(IMXFECState *s, int reg)
 {
 uint32_t val;
+uint32_t phy = reg / 32;
 
-if (reg > 31) {
-/* we only advertise one phy */
+if (phy != s->phy_num) {
+qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad phy num %u\n",
+  TYPE_IMX_FEC, __func__, phy);
 return 0;
 }
 
+reg %= 32;
+
 switch (reg) {
 case 0: /* Basic Control */
 val = s->phy_control;
@@ -331,20 +335,25 @@ static uint32_t imx_phy_read(IMXFECState *s, int reg)
 break;
 }
 
-trace_imx_phy_read(val, reg);
+trace_imx_phy_read(val, phy, reg);
 
 return val;
 }
 
 static void imx_phy_write(IMXFECState *s, int reg, uint32_t val)
 {
-trace_imx_phy_write(val, reg);
+uint32_t phy = reg / 32;
 
-if (reg > 31) {
-/* we only advertise one phy */
+if (phy != s->phy_num) {
+qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad phy num %u\n",
+  TYPE_IMX_FEC, __func__, phy);
 return;
 }
 
+reg %= 32;
+
+trace_imx_phy_write(val, phy, reg);
+
 switch (reg) {
 case 0: /* Basic Control */
 if (val & 0x8000) {
@@ -926,7 +935,7 @@ static void imx_eth_write(void *opaque, hwaddr offset, 
uint64_t value,
extract32(value,
  18, 10)));
 } else {
-/* This a write operation */
+/* This is a write operation */
 imx_phy_write(s, extract32(value, 18, 10), extract32(value, 0, 
16));
 }
 /* raise the interrupt as the PHY operation is done */
@@ -1315,6 +1324,7 @@ static void imx_eth_realize(DeviceState *dev, Error 
**errp)
 static Property imx_eth_properties[] = {
 DEFINE_NIC_PROPERTIES(IMXFECState, conf),
 DEFINE_PROP_UINT32("tx-ring-num", IMXFECState, tx_ring_num, 1),
+DEFINE_PROP_UINT32("phy-num", IMXFECState, phy_num, 0),
 DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/net/trace-events b/hw/net/trace-events
index e6875c4c0f6..5db45456d92 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -413,8 +413,8 @@ i82596_set_multicast(uint16_t count) "Added %d multicast 
entries"
 i82596_channel_attention(void *s) "%p: Received CHANNEL ATTENTION"
 
 # imx_fec.c
-imx_phy_read(uint32_t val, int reg) "0x%04"PRIx32" <= reg[%d]"
-imx_phy_write(uint32_t val, int reg) "0x%04"PRIx32" => reg[%d]"
+imx_phy_read(uint32_t val, int phy, int reg) "0x%04"PRIx32" <= phy[%d].reg[%d]"
+imx_phy_write(uint32_t val, int phy, int reg) "0x%04"PRIx32" => 
phy[%d].reg[%d]"
 imx_phy_update_link(const char *s) "%s"
 imx_phy_reset(void) ""
 imx_fec_read_bd(uint64_t addr, int flags, int len, int data) "tx_bd 
0x%"PRIx64" flags 0x%04x len %d data 0x%08x"
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
index 7b3faa40194..9f03034b893 100644
--- a/include/hw/net/imx_fec.h
+++ b/include/hw/net/imx_fec.h
@@ -268,6 +268,7 @@ typedef struct IMXFECState {
 uint32_t phy_advertise;
 uint32_t phy_int;
 uint32_t phy_int_mask;
+uint32_t phy_num;
 
 bool is_fec;
 
-- 
2.25.1




[PATCH 0/3] Allow to specify the PHY number to use with a specific i.MX FEC/ENET Ethernet device

2020-06-28 Thread Jean-Christophe Dubois
The PHY device associated to a specific i.MX Ethernet device is not 
necessarily at address 0 on the MDIO bus.

This patch series adds the ability to set the PHY number on the MDIO bus
for any i.MX6UL based board.

Jean-Christophe Dubois (3):
  Add a phy-num property to the i.MX FEC emulator
  Add the ability to select a different PHY for each i.MX6UL FEC
interface
  Select MDIO device 2 and 1 as PHY devices for i.MW6UL EVK board.

 hw/arm/fsl-imx6ul.c | 10 ++
 hw/arm/mcimx6ul-evk.c   |  2 ++
 hw/net/imx_fec.c| 24 +---
 hw/net/trace-events |  4 ++--
 include/hw/arm/fsl-imx6ul.h |  2 ++
 include/hw/net/imx_fec.h|  1 +
 6 files changed, 34 insertions(+), 9 deletions(-)

-- 
2.25.1




Re: [REPORT] [GSoC - TCG Continuous Benchmarking] [#1] Measuring Basic Performance Metrics of QEMU

2020-06-28 Thread Ahmed Karaman
On Sun, Jun 28, 2020 at 7:20 PM Aleksandar Markovic
 wrote:
>
> Now, thinking longer about topN scripts, I think one really missing
> thing is number of invocations (or calls, whatever term you prefer)
> for any function in the list. This data must be possible to obtain
> using callgrind_annotate (most likely by using --tree option). With
> perf, i don't think this is possible, given that perf works based on
> sampling.
>
> You don't need to start working on it right now, or work on it at all
> - this is more like a brainstorming suggestion from me. You can make
> improvements and correction all the way towards the end of the
> project, on Aug 31st.
>
> At the end of the project, perhaps you can publish a "Master Project
> Report" - a pdf that is basically a sum of all your reports produced
> during the project. That would be a nice reading!
>
> Regards,
> Aleksandar
>

Thanks Mr. Aleksandar for always sharring your thoughts and suggestions.
I will consider this for an updated version of the report.

Regards,
Ahmed Karaman



[PATCH] hw/display/bcm2835_fb.c: Initialize all fields of struct

2020-06-28 Thread Peter Maydell
In bcm2835_fb_mbox_push(), Coverity complains (CID 1429989) that we
pass a pointer to a local struct to another function without
initializing all its fields.  This is a real bug:
bcm2835_fb_reconfigure() copies the whole of our new BCM2385FBConfig
struct into s->config, so any fields we don't initialize will corrupt
the state of the device.

Copy the two fields which we don't want to update (pixo and alpha)
from the existing config so we don't accidentally change them.

Fixes: cfb7ba983857e40e88
Signed-off-by: Peter Maydell 
---
Not sure why this wasn't a visible bug -- alpha isn't used,
but if pixo changes from zero to non-zero we flip from
RGB to BGR...
---
 hw/display/bcm2835_fb.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
index c6263808a27..7c0e5eef2d5 100644
--- a/hw/display/bcm2835_fb.c
+++ b/hw/display/bcm2835_fb.c
@@ -282,6 +282,10 @@ static void bcm2835_fb_mbox_push(BCM2835FBState *s, 
uint32_t value)
 newconf.base = s->vcram_base | (value & 0xc000);
 newconf.base += BCM2835_FB_OFFSET;
 
+/* Copy fields which we don't want to change from the existing config */
+newconf.pixo = s->config.pixo;
+newconf.alpha = s->config.alpha;
+
 bcm2835_fb_validate_config(&newconf);
 
 pitch = bcm2835_fb_get_pitch(&newconf);
-- 
2.20.1




Re: Crash when running Qemu.

2020-06-28 Thread Jean-Christophe DUBOIS
I am not sure how it could influence the fact that I experience this bug 
and others not necessarily but for what it is worth, I am using gcc 
10.0.1 to compile Qemu.


I might try to use a previous version to check if it changes the overall 
behavior.


JC

Le 28/06/2020 à 18:32, Jean-Christophe DUBOIS a écrit :
By reverting the recent (june 23) commit series on PCA9552 I can run 
Qemu again.


Here is the git revert command I did.

jcd@jcd-UX305CA:~/Projects/qemu/qemu$ git revert 
8208335b9539e7b5aa4702b36e2f9a8abd704079..586f495b1e78c27e141ff432dd971eb41866fb80


Regards

JC

Le 28/06/2020 à 17:57, Jean-Christophe DUBOIS a écrit :
When ran from valgrind, qemu does not crash but the following output 
is returned.


valgrind --track-origins=yes 
../../qemu/qemu/arm-softmmu/qemu-system-arm -machine mcimx6ul-evk -m 
128M -display none -serial stdio -kernel ./OS.elf

==77479== Memcheck, a memory error detector
==77479== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et 
al.
==77479== Using Valgrind-3.15.0 and LibVEX; rerun with -h for 
copyright info
==77479== Command: ../../qemu/qemu/arm-softmmu/qemu-system-arm 
-machine mcimx6ul-evk -m 128M -display none -serial stdio -kernel 
./OS.elf

==77479==
==77479== Invalid write of size 2
==77479==    at 0x6D8322: pca9552_class_init (pca9552.c:424)
==77479==    by 0x844D1F: type_initialize (object.c:1029)
==77479==    by 0x844D1F: object_class_foreach_tramp (object.c:1016)
==77479==    by 0x4AE1057: g_hash_table_foreach (in 
/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)

==77479==    by 0x8453A4: object_class_foreach (object.c:1038)
==77479==    by 0x8453A4: object_class_get_list (object.c:1095)
==77479==    by 0x556194: select_machine (vl.c:2416)
==77479==    by 0x556194: qemu_init (vl.c:3828)
==77479==    by 0x40AF9C: main (main.c:48)
==77479==  Address 0x583f108 is 0 bytes after a block of size 200 
alloc'd
==77479==    at 0x483DD99: calloc (in 
/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==77479==    by 0x4AF8D30: g_malloc0 (in 
/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)

==77479==    by 0x844258: type_initialize.part.0 (object.c:306)
==77479==    by 0x844D1F: type_initialize (object.c:1029)
==77479==    by 0x844D1F: object_class_foreach_tramp (object.c:1016)
==77479==    by 0x4AE1057: g_hash_table_foreach (in 
/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)

==77479==    by 0x8453A4: object_class_foreach (object.c:1038)
==77479==    by 0x8453A4: object_class_get_list (object.c:1095)
==77479==    by 0x556194: select_machine (vl.c:2416)
==77479==    by 0x556194: qemu_init (vl.c:3828)
==77479==    by 0x40AF9C: main (main.c:48)
==77479==
==77479== Conditional jump or move depends on uninitialised value(s)
==77479==    at 0x41D944: tcg_target_init (tcg-target.inc.c:3867)
==77479==    by 0x41D944: tcg_context_init (tcg.c:983)
==77479==    by 0x48E60D: cpu_gen_init (translate-all.c:246)
==77479==    by 0x48E60D: tcg_exec_init (translate-all.c:1152)
==77479==    by 0x46FE7B: tcg_init (tcg-all.c:129)
==77479==    by 0x5E15A5: accel_init_machine (accel.c:55)
==77479==    by 0x55402F: do_configure_accelerator (vl.c:2708)
==77479==    by 0x94F1D1: qemu_opts_foreach (qemu-option.c:1163)
==77479==    by 0x5598B3: configure_accelerators (vl.c:2775)
==77479==    by 0x5598B3: qemu_init (vl.c:4152)
==77479==    by 0x40AF9C: main (main.c:48)
==77479==  Uninitialised value was created by a stack allocation
==77479==    at 0x4ADFE5F: ??? (in 
/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)

==77479==
==77479== Warning: set address range perms: large range [0x6483000, 
0x46483000) (defined)


===
=   TCPIP INITIALIZATION =
===
Initializing TCPIP...

--- i.MX6UL-EVK BOARD NETWORK CONFIG 



Starting ENET1...

NetIF_LinkStateWaitUntilUp() failed w/ err = 30


Starting ENET2...

NetIF_LinkStateWaitUntilUp() failed w/ err = 30

Network Configuration:
qemu-system-arm: terminating on signal 2
==77479==
==77479== HEAP SUMMARY:
==77479== in use at exit: 8,452,515 bytes in 57,040 blocks
==77479==   total heap usage: 97,248 allocs, 40,208 frees, 21,279,482 
bytes allocated

==77479==
==77479== LEAK SUMMARY:
==77479==    definitely lost: 0 bytes in 0 blocks
==77479==    indirectly lost: 0 bytes in 0 blocks
==77479==  possibly lost: 3,474 bytes in 45 blocks
==77479==    still reachable: 8,449,041 bytes in 56,995 blocks
==77479==   of which reachable via heuristic:
==77479== newarray   : 1,536 bytes in 
16 blocks

==77479== suppressed: 0 bytes in 0 blocks
==77479== Rerun with --leak-check=full to see details of leaked memory
==77479==
==77479== For lists of detected and suppressed errors, rerun with: -s
==77479== ERROR SUMMARY: 3 errors from 2 contexts (suppressed: 0 from 0)

Le 28/06/2020 à 12:55, Jean-Christophe DU

Re: [PATCH 03/19] iotests/common.rc: Add _require_working_luks

2020-06-28 Thread Maxim Levitsky
On Thu, 2020-06-25 at 14:55 +0200, Max Reitz wrote:
> That the luks driver is present is little indication on whether it is
> actually working.  Without the crypto libraries linked in, it does not
> work.  So add this function, which tries to create a luks image to see
> whether that actually works.
> 
> Signed-off-by: Max Reitz 
> ---
>  tests/qemu-iotests/common.rc | 27 +++
>  1 file changed, 27 insertions(+)
> 
> diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
> index ba912555ca..f3667f48ab 100644
> --- a/tests/qemu-iotests/common.rc
> +++ b/tests/qemu-iotests/common.rc
> @@ -740,6 +740,33 @@ _unsupported_imgopts()
>  done
>  }
>  
> +# Caution: Overwrites $TEST_DIR/t.luks
> +_require_working_luks()
> +{
> +file="$TEST_DIR/t.luks"
> +
> +output=$(
> +$QEMU_IMG create -f luks \
> +--object secret,id=sec0,data=hunter0 \
> +-o key-secret=sec0 \
> +-o iter-time=10 \
> +"$file" \
> +1M \
> +2>&1
> +)
> +status=$?
> +
> +IMGFMT='luks' _rm_test_img "$file"
> +
> +if [ $status != 0 ]; then
> +reason=$(echo "$output" | grep "$file:" | $SED -e "s#.*$file: *##")
> +if [ -z "$reason" ]; then
> +reason="Failed to create a LUKS image"
> +fi
> +_notrun "$reason"
> +fi
> +}
> +
>  # this test requires that a specified command (executable) exists
>  #
>  _require_command()


Look OK. I also tested this by building the qemu with all the patches applied,a
and with --disable-nettle --disable-gcrypt

And now all my tests are skipped with this nice message:
"No crypto library supporting PBKDF in this build: Function not implemented"

Thank you very very much for implementing this!

Reviewed-by: Maxim Levitsky 


Best regards,
Maxim Levitsky




Re: [PATCH v5 00/11] Mac Old World ROM experiment

2020-06-28 Thread BALATON Zoltan

On Fri, 26 Jun 2020, Mark Cave-Ayland wrote:

On 26/06/2020 11:21, BALATON Zoltan wrote:

What about these patches? At least those that are finished (up to patch 9) 
could be
merged. I've seen you sent a pull request but not including any of these. Will 
this
need another rebase after your patches? If I rebase them will you consider 
merging
them? (Otherwise I won't spend time with it.)


Ah sorry I missed the latest version of these. I'll take a quick look now.


In case you missed that I've just sent the latest v6 version of the series 
with changes you've suggested and I made since.



(BTW it seems the patches in your patchset have started appearing in a random 
order
when sent to the list again?)


I've noticed this too but don't know why that happens or what to do to 
prevent it. I submit these in one batch to my mail server which then seems 
to send it off simultaneously and may end up out of order. I've tried 
adding a 1 sec delay now but apparently that did not solve it. Sorry for 
the inconvenience.


Regards,
BALATON Zoltan



[PATCH v6 11/11] mac_oldworld: Add SPD data to cover RAM

2020-06-28 Thread BALATON Zoltan
OpenBIOS gets RAM size via fw_cfg but rhe original board firmware
detects RAM using SPD data so generate and add SDP eeproms to cover as
much RAM as possible to describe with SPD (this may be less than the
actual ram_size due to SDRAM size constraints).

This patch is more complex as it should be which I intend to fix once
agreement can be made on how to get back the necessary functionality
removed by previous patches. See in this thread:
https://lists.nongnu.org/archive/html/qemu-devel/2020-06/msg08710.html

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/mac_oldworld.c | 19 ++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 8fbddba4eb..5ad54370d0 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -34,6 +34,7 @@
 #include "hw/input/adb.h"
 #include "sysemu/sysemu.h"
 #include "net/net.h"
+#include "hw/i2c/smbus_eeprom.h"
 #include "hw/isa/isa.h"
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_host.h"
@@ -133,6 +134,8 @@ static void ppc_heathrow_init(MachineState *machine)
 DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
 void *fw_cfg;
 uint64_t tbfreq;
+uint8_t *spd_data[3] = {};
+I2CBus *i2c_bus;
 
 /* init CPUs */
 for (i = 0; i < smp_cpus; i++) {
@@ -150,8 +153,16 @@ static void ppc_heathrow_init(MachineState *machine)
  "maximum 2047 MB", ram_size / MiB);
 exit(1);
 }
-
 memory_region_add_subregion(get_system_memory(), 0, machine->ram);
+for (i = 0; i < 3; i++) {
+int size_left = ram_size - i * 512 * MiB;
+if (size_left > 0) {
+uint32_t s = size_left / MiB;
+s = (s > 512 ? 512 : s);
+s = 1U << (31 - clz32(s));
+spd_data[i] = spd_data_generate(SDR, s * MiB);
+}
+}
 
 /* allocate and load firmware ROM */
 memory_region_init_rom(bios, NULL, "ppc_heathrow.bios", PROM_SIZE,
@@ -337,6 +348,12 @@ static void ppc_heathrow_init(MachineState *machine)
 macio_ide_init_drives(macio_ide, &hd[MAX_IDE_DEVS]);
 
 dev = DEVICE(object_resolve_path_component(OBJECT(macio), "cuda"));
+i2c_bus = I2C_BUS(qdev_get_child_bus(dev, "i2c"));
+for (i = 0; i < 3; i++) {
+if (spd_data[i]) {
+smbus_eeprom_init_one(i2c_bus, 0x50 + i, spd_data[i]);
+}
+}
 adb_bus = qdev_get_child_bus(dev, "adb.0");
 dev = qdev_new(TYPE_ADB_KEYBOARD);
 qdev_realize_and_unref(dev, adb_bus, &error_fatal);
-- 
2.21.3




[PATCH v6 06/11] mac_oldworld: Rename ppc_heathrow_reset to ppc_heathrow_cpu_reset

2020-06-28 Thread BALATON Zoltan
This function resets a CPU not the whole machine so reflect that in
its name.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/ppc/mac_oldworld.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 428851..f97f241e0c 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -73,7 +73,7 @@ static uint64_t translate_kernel_address(void *opaque, 
uint64_t addr)
 return (addr & 0x0fff) + KERNEL_LOAD_ADDR;
 }
 
-static void ppc_heathrow_reset(void *opaque)
+static void ppc_heathrow_cpu_reset(void *opaque)
 {
 PowerPCCPU *cpu = opaque;
 
@@ -112,7 +112,7 @@ static void ppc_heathrow_init(MachineState *machine)
 
 /* Set time-base frequency to 16.6 Mhz */
 cpu_ppc_tb_init(env,  TBFREQ);
-qemu_register_reset(ppc_heathrow_reset, cpu);
+qemu_register_reset(ppc_heathrow_cpu_reset, cpu);
 }
 
 /* allocate RAM */
-- 
2.21.3




[PATCH v6 09/11] i2c: Match parameters of i2c_start_transfer and i2c_send_recv

2020-06-28 Thread BALATON Zoltan
These functions have a parameter that decides the direction of
transfer but totally confusingly they don't match but inverted sense.
To avoid frequent mistakes when using these functions change
i2c_send_recv to match i2c_start_transfer. Also use bool in
i2c_start_transfer instead of int to match i2c_send_recv.

Signed-off-by: BALATON Zoltan 
---
This probably won't be the solution accepted as Philippe has an
alternative series fixing this problem here:
https://lists.nongnu.org/archive/html/qemu-devel/2020-06/msg07022.html
but until that or something else is merged this will do for the next
patch. When this gets sorted out I'll send a rebased version.

 hw/display/sm501.c   |  2 +-
 hw/i2c/core.c| 34 +-
 hw/i2c/ppc4xx_i2c.c  |  2 +-
 include/hw/i2c/i2c.h |  4 ++--
 4 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/hw/display/sm501.c b/hw/display/sm501.c
index a7fc08c52b..e714674681 100644
--- a/hw/display/sm501.c
+++ b/hw/display/sm501.c
@@ -1041,7 +1041,7 @@ static void sm501_i2c_write(void *opaque, hwaddr addr, 
uint64_t value,
   s->i2c_byte_count + 1, s->i2c_addr >> 1);
 for (i = 0; i <= s->i2c_byte_count; i++) {
 res = i2c_send_recv(s->i2c_bus, &s->i2c_data[i],
-!(s->i2c_addr & 1));
+s->i2c_addr & 1);
 if (res) {
 SM501_DPRINTF("sm501 i2c : transfer failed"
   " i=%d, res=%d\n", i, res);
diff --git a/hw/i2c/core.c b/hw/i2c/core.c
index acf34a12d6..0303fefeaf 100644
--- a/hw/i2c/core.c
+++ b/hw/i2c/core.c
@@ -91,7 +91,7 @@ int i2c_bus_busy(I2CBus *bus)
  * without releasing the bus.  If that fails, the bus is still
  * in a transaction.
  */
-int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv)
+int i2c_start_transfer(I2CBus *bus, uint8_t address, bool recv)
 {
 BusChild *kid;
 I2CSlaveClass *sc;
@@ -175,26 +175,14 @@ void i2c_end_transfer(I2CBus *bus)
 bus->broadcast = false;
 }
 
-int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send)
+int i2c_send_recv(I2CBus *bus, uint8_t *data, bool recv)
 {
 I2CSlaveClass *sc;
 I2CSlave *s;
 I2CNode *node;
 int ret = 0;
 
-if (send) {
-QLIST_FOREACH(node, &bus->current_devs, next) {
-s = node->elt;
-sc = I2C_SLAVE_GET_CLASS(s);
-if (sc->send) {
-trace_i2c_send(s->address, *data);
-ret = ret || sc->send(s, *data);
-} else {
-ret = -1;
-}
-}
-return ret ? -1 : 0;
-} else {
+if (recv) {
 ret = 0xff;
 if (!QLIST_EMPTY(&bus->current_devs) && !bus->broadcast) {
 sc = I2C_SLAVE_GET_CLASS(QLIST_FIRST(&bus->current_devs)->elt);
@@ -206,19 +194,31 @@ int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send)
 }
 *data = ret;
 return 0;
+} else {
+QLIST_FOREACH(node, &bus->current_devs, next) {
+s = node->elt;
+sc = I2C_SLAVE_GET_CLASS(s);
+if (sc->send) {
+trace_i2c_send(s->address, *data);
+ret = ret || sc->send(s, *data);
+} else {
+ret = -1;
+}
+}
+return ret ? -1 : 0;
 }
 }
 
 int i2c_send(I2CBus *bus, uint8_t data)
 {
-return i2c_send_recv(bus, &data, true);
+return i2c_send_recv(bus, &data, false);
 }
 
 uint8_t i2c_recv(I2CBus *bus)
 {
 uint8_t data = 0xff;
 
-i2c_send_recv(bus, &data, false);
+i2c_send_recv(bus, &data, true);
 return data;
 }
 
diff --git a/hw/i2c/ppc4xx_i2c.c b/hw/i2c/ppc4xx_i2c.c
index c0a8e04567..d3899203a4 100644
--- a/hw/i2c/ppc4xx_i2c.c
+++ b/hw/i2c/ppc4xx_i2c.c
@@ -239,7 +239,7 @@ static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, 
uint64_t value,
 }
 }
 if (!(i2c->sts & IIC_STS_ERR) &&
-i2c_send_recv(i2c->bus, &i2c->mdata[i], !recv)) {
+i2c_send_recv(i2c->bus, &i2c->mdata[i], recv)) {
 i2c->sts |= IIC_STS_ERR;
 i2c->extsts |= IIC_EXTSTS_XFRA;
 break;
diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h
index d6e3d85faf..ad2475d6a2 100644
--- a/include/hw/i2c/i2c.h
+++ b/include/hw/i2c/i2c.h
@@ -72,10 +72,10 @@ struct I2CBus {
 I2CBus *i2c_init_bus(DeviceState *parent, const char *name);
 void i2c_set_slave_address(I2CSlave *dev, uint8_t address);
 int i2c_bus_busy(I2CBus *bus);
-int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv);
+int i2c_start_transfer(I2CBus *bus, uint8_t address, bool recv);
 void i2c_end_transfer(I2CBus *bus);
 void i2c_nack(I2CBus *bus);
-int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send);
+int i2c_send_recv(I2CBus *bus, uint8_t *data, bool recv);

[PATCH v6 08/11] mac_oldworld: Add machine ID register

2020-06-28 Thread BALATON Zoltan
The G3 beige machine has a machine ID register that is accessed by the
firmware to deternine the board config. Add basic emulation of it.

Signed-off-by: BALATON Zoltan 
---
v6: Make MemoryRegionOps static const
v4: Move MermoryRegion to MachineState, use constants

 hw/ppc/mac.h  |  1 +
 hw/ppc/mac_oldworld.c | 24 
 2 files changed, 25 insertions(+)

diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h
index 58ae5a2226..75f1853a7b 100644
--- a/hw/ppc/mac.h
+++ b/hw/ppc/mac.h
@@ -69,6 +69,7 @@ typedef struct HeathrowMachineState {
 /*< private >*/
 MachineState parent;
 
+MemoryRegion machine_id;
 PCIDevice *macio;
 } HeathrowMachineState;
 
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 13562e26e6..8fbddba4eb 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -52,6 +52,9 @@
 
 #define MAX_IDE_BUS 2
 #define CFG_ADDR 0xf510
+#define MACHINE_ID_ADDR 0xff04
+#define MACHINE_ID_VAL 0x3d8c
+
 #define TBFREQ 1660UL
 #define CLOCKFREQ 26600UL
 #define BUSFREQ 6600UL
@@ -89,6 +92,22 @@ static void ppc_heathrow_cpu_reset(void *opaque)
 cpu_reset(CPU(cpu));
 }
 
+static uint64_t machine_id_read(void *opaque, hwaddr addr, unsigned size)
+{
+return (addr == 0 && size == 2 ? MACHINE_ID_VAL : 0);
+}
+
+static void machine_id_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size)
+{
+return;
+}
+
+static const MemoryRegionOps machine_id_reg_ops = {
+.read = machine_id_read,
+.write = machine_id_write,
+};
+
 static void ppc_heathrow_init(MachineState *machine)
 {
 HeathrowMachineState *hm = HEATHROW_MACHINE(machine);
@@ -239,6 +258,11 @@ static void ppc_heathrow_init(MachineState *machine)
 }
 }
 
+memory_region_init_io(&hm->machine_id, OBJECT(machine),
+  &machine_id_reg_ops, NULL, "machine_id", 2);
+memory_region_add_subregion(get_system_memory(), MACHINE_ID_ADDR,
+&hm->machine_id);
+
 /* XXX: we register only 1 output pin for heathrow PIC */
 pic_dev = qdev_new(TYPE_HEATHROW);
 sysbus_realize_and_unref(SYS_BUS_DEVICE(pic_dev), &error_fatal);
-- 
2.21.3




[RFC PATCH v6 10/11] WIP macio/cuda: Attempt to add i2c support

2020-06-28 Thread BALATON Zoltan
This is not a final, RFC patch attempt to implement i2c bus in CUDA
needed for firmware to access SPD data of installed RAM. The skeleton
is there but actual implementation of I2C commands need to be refined
because I don't know how this is supposed to work. In my understanding
after an I2C command (at least for combined transfer) CUDA should
enter a mode where reading subsequent values from VIA[SR] should
return bytes received from the i2C device but not sure what ends this
mode or how to model it correctly. So this patch just returns fixed
amount of bytes expected by reading SPD eeproms just to make testing
the firmware ROM possible. Help fixing and finishing this is welcome,
I don't plan to spend more time with this so just submitted it for
whoever picks this up.

Signed-off-by: BALATON Zoltan 
---
 hw/misc/macio/cuda.c | 76 +++-
 include/hw/misc/macio/cuda.h |  1 +
 2 files changed, 76 insertions(+), 1 deletion(-)

diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c
index 5bbc7770fa..3fc9773717 100644
--- a/hw/misc/macio/cuda.c
+++ b/hw/misc/macio/cuda.c
@@ -28,6 +28,7 @@
 #include "hw/ppc/mac.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
+#include "hw/i2c/i2c.h"
 #include "hw/input/adb.h"
 #include "hw/misc/mos6522.h"
 #include "hw/misc/macio/cuda.h"
@@ -370,6 +371,75 @@ static bool cuda_cmd_set_time(CUDAState *s,
 return true;
 }
 
+static bool cuda_cmd_get_set_iic(CUDAState *s,
+ const uint8_t *in_data, int in_len,
+ uint8_t *out_data, int *out_len)
+{
+int i;
+
+qemu_log_mask(LOG_UNIMP, "CUDA: unimplemented GET_SET_IIC %s 0x%x %d\n",
+  (in_data[0] & 1 ? "read" : "write"), in_data[0] >> 1,
+  in_len);
+if (i2c_start_transfer(s->i2c_bus, in_data[0] >> 1, in_data[0] & 1)) {
+return false;
+}
+for (i = 0; i < in_len - 3; i++) {
+if (i2c_send(s->i2c_bus, in_data[i])) {
+i2c_end_transfer(s->i2c_bus);
+return false;
+}
+}
+return true;
+}
+
+static bool cuda_cmd_combined_iic(CUDAState *s,
+  const uint8_t *in_data, int in_len,
+  uint8_t *out_data, int *out_len)
+{
+int i;
+
+if (in_len < 3) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "CUDA: COMBINED_FORMAT_IIC too few input bytes\n");
+return false;
+}
+if ((in_data[0] & 0xfe) != (in_data[2] & 0xfe)) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "CUDA: COMBINED_FORMAT_IIC address mismatch\n");
+return false;
+}
+
+uint8_t data = in_data[1];
+if (i2c_start_transfer(s->i2c_bus, in_data[0] >> 1, in_data[0] & 1) ||
+i2c_send_recv(s->i2c_bus, &data, in_data[0] & 1)) {
+return false;
+}
+i2c_end_transfer(s->i2c_bus);
+if (in_data[2] & 1) {
+if (i2c_start_transfer(s->i2c_bus, in_data[2] >> 1, in_data[2] & 1)) {
+i2c_end_transfer(s->i2c_bus);
+return false;
+}
+for (i = 0; i < 5; i++) {
+if (i2c_send_recv(s->i2c_bus, &out_data[i], in_data[2] & 1)) {
+i2c_end_transfer(s->i2c_bus);
+return false;
+}
+}
+*out_len = i;
+i2c_end_transfer(s->i2c_bus);
+} else {
+for (i = 0; i < in_len - 3; i++) {
+data = in_data[3 + i];
+if (i2c_send_recv(s->i2c_bus, &data, in_data[2] & 1)) {
+i2c_end_transfer(s->i2c_bus);
+return false;
+}
+}
+}
+return true;
+}
+
 static const CudaCommand handlers[] = {
 { CUDA_AUTOPOLL, "AUTOPOLL", cuda_cmd_autopoll },
 { CUDA_SET_AUTO_RATE, "SET_AUTO_RATE",  cuda_cmd_set_autorate },
@@ -382,6 +452,8 @@ static const CudaCommand handlers[] = {
   cuda_cmd_set_power_message },
 { CUDA_GET_TIME, "GET_TIME", cuda_cmd_get_time },
 { CUDA_SET_TIME, "SET_TIME", cuda_cmd_set_time },
+{ CUDA_GET_SET_IIC, "GET_SET_IIC", cuda_cmd_get_set_iic },
+{ CUDA_COMBINED_FORMAT_IIC, "COMBINED_FORMAT_IIC", cuda_cmd_combined_iic },
 };
 
 static void cuda_receive_packet(CUDAState *s,
@@ -549,6 +621,7 @@ static void cuda_init(Object *obj)
 {
 CUDAState *s = CUDA(obj);
 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+DeviceState *dev = DEVICE(obj);
 
 object_initialize_child(obj, "mos6522-cuda", &s->mos6522_cuda,
 TYPE_MOS6522_CUDA);
@@ -557,7 +630,8 @@ static void cuda_init(Object *obj)
 sysbus_init_mmio(sbd, &s->mem);
 
 qbus_create_inplace(&s->adb_bus, sizeof(s->adb_bus), TYPE_ADB_BUS,
-DEVICE(obj), "adb.0");
+dev, "adb.0");
+s->i2c_bus = i2c_init_bus(dev, "i2c");
 }
 
 static Property cuda_properties[] = {
diff --git a/include/hw/misc/macio/cuda.h b/include/hw/misc/macio/cuda.h
index a8cf0be1ec..6856ed7704 100644

[PATCH v6 07/11] mac_oldworld: Map macio to expected address at reset

2020-06-28 Thread BALATON Zoltan
Add a reset function that maps macio to the address expected by the
firmware of the board at startup.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/mac.h  | 12 
 hw/ppc/mac_oldworld.c | 15 ++-
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h
index 195967facd..58ae5a2226 100644
--- a/hw/ppc/mac.h
+++ b/hw/ppc/mac.h
@@ -60,6 +60,18 @@
 #define OLDWORLD_SCREAMER_TX_DMA_IRQ 0x08
 #define OLDWORLD_SCREAMER_RX_IRQ  0x09
 
+/* g3beige machine */
+#define TYPE_HEATHROW_MACHINE MACHINE_TYPE_NAME("g3beige")
+#define HEATHROW_MACHINE(obj) OBJECT_CHECK(HeathrowMachineState, (obj), \
+   TYPE_HEATHROW_MACHINE)
+
+typedef struct HeathrowMachineState {
+/*< private >*/
+MachineState parent;
+
+PCIDevice *macio;
+} HeathrowMachineState;
+
 /* New World IRQs */
 #define NEWWORLD_CUDA_IRQ  0x19
 #define NEWWORLD_PMU_IRQ   0x19
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index f97f241e0c..13562e26e6 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -73,6 +73,15 @@ static uint64_t translate_kernel_address(void *opaque, 
uint64_t addr)
 return (addr & 0x0fff) + KERNEL_LOAD_ADDR;
 }
 
+static void ppc_heathrow_reset(MachineState *machine)
+{
+HeathrowMachineState *m = HEATHROW_MACHINE(machine);
+
+qemu_devices_reset();
+pci_default_write_config(m->macio, PCI_COMMAND, PCI_COMMAND_MEMORY, 2);
+pci_default_write_config(m->macio, PCI_BASE_ADDRESS_0, 0xf300, 4);
+}
+
 static void ppc_heathrow_cpu_reset(void *opaque)
 {
 PowerPCCPU *cpu = opaque;
@@ -82,6 +91,7 @@ static void ppc_heathrow_cpu_reset(void *opaque)
 
 static void ppc_heathrow_init(MachineState *machine)
 {
+HeathrowMachineState *hm = HEATHROW_MACHINE(machine);
 ram_addr_t ram_size = machine->ram_size;
 const char *boot_device = machine->boot_order;
 PowerPCCPU *cpu = NULL;
@@ -287,6 +297,7 @@ static void ppc_heathrow_init(MachineState *machine)
 
 /* MacIO */
 macio = pci_new(-1, TYPE_OLDWORLD_MACIO);
+hm->macio = macio;
 dev = DEVICE(macio);
 qdev_prop_set_uint64(dev, "frequency", tbfreq);
 object_property_set_link(OBJECT(macio), OBJECT(pic_dev), "pic",
@@ -439,6 +450,7 @@ static void heathrow_class_init(ObjectClass *oc, void *data)
 
 mc->desc = "Heathrow based PowerMAC";
 mc->init = ppc_heathrow_init;
+mc->reset = ppc_heathrow_reset;
 mc->block_default_type = IF_IDE;
 mc->max_cpus = MAX_CPUS;
 #ifndef TARGET_PPC64
@@ -455,9 +467,10 @@ static void heathrow_class_init(ObjectClass *oc, void 
*data)
 }
 
 static const TypeInfo ppc_heathrow_machine_info = {
-.name  = MACHINE_TYPE_NAME("g3beige"),
+.name  = TYPE_HEATHROW_MACHINE,
 .parent= TYPE_MACHINE,
 .class_init= heathrow_class_init,
+.instance_size = sizeof(HeathrowMachineState),
 .interfaces = (InterfaceInfo[]) {
 { TYPE_FW_PATH_PROVIDER },
 { }
-- 
2.21.3




[PATCH v6 05/11] grackle: Set revision in PCI config to match hardware

2020-06-28 Thread BALATON Zoltan
Signed-off-by: BALATON Zoltan 
---
 hw/pci-host/grackle.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/pci-host/grackle.c b/hw/pci-host/grackle.c
index 4b3af0c704..48d11f13ab 100644
--- a/hw/pci-host/grackle.c
+++ b/hw/pci-host/grackle.c
@@ -130,7 +130,7 @@ static void grackle_pci_class_init(ObjectClass *klass, void 
*data)
 k->realize   = grackle_pci_realize;
 k->vendor_id = PCI_VENDOR_ID_MOTOROLA;
 k->device_id = PCI_DEVICE_ID_MOTOROLA_MPC106;
-k->revision  = 0x00;
+k->revision  = 0x40;
 k->class_id  = PCI_CLASS_BRIDGE_HOST;
 /*
  * PCI-facing part of the host bridge, not usable without the
-- 
2.21.3




[PATCH v6 03/11] mac_oldworld: Drop a variable, use get_system_memory() directly

2020-06-28 Thread BALATON Zoltan
Half of the occurances already use get_system_memory() directly
instead of sysmem variable, convert the two other uses to
get_system_memory() too which seems to be more common and drop the
variable.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Mark Cave-Ayland 
---
 hw/ppc/mac_oldworld.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index baf3da6f90..d1c4244b1e 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -87,7 +87,6 @@ static void ppc_heathrow_init(MachineState *machine)
 const char *kernel_cmdline = machine->kernel_cmdline;
 const char *initrd_filename = machine->initrd_filename;
 const char *boot_device = machine->boot_order;
-MemoryRegion *sysmem = get_system_memory();
 PowerPCCPU *cpu = NULL;
 CPUPPCState *env = NULL;
 char *filename;
@@ -128,12 +127,12 @@ static void ppc_heathrow_init(MachineState *machine)
 exit(1);
 }
 
-memory_region_add_subregion(sysmem, 0, machine->ram);
+memory_region_add_subregion(get_system_memory(), 0, machine->ram);
 
 /* allocate and load firmware ROM */
 memory_region_init_rom(bios, NULL, "ppc_heathrow.bios", PROM_SIZE,
&error_fatal);
-memory_region_add_subregion(sysmem, PROM_BASE, bios);
+memory_region_add_subregion(get_system_memory(), PROM_BASE, bios);
 
 if (!bios_name) {
 bios_name = PROM_FILENAME;
-- 
2.21.3




[PATCH v6 00/11] Mac Old World ROM experiment

2020-06-28 Thread BALATON Zoltan
Latest version of this series with addressing review comments, adding
review tags and tweaks to the WIP CUDA I2C support so with this on top
of Mark's screaper patches (with a small fix) the ROM now plays the
startup sound but then gets confused about some memory addresses. I
don't want to debug this further so either some hints are needed what
may be needed or someone could take over and finish these.

I think at least up to patch 8 this could be merged already, the rest
needs more work.

Regards,
BALATON Zoltan

BALATON Zoltan (11):
  mac_oldworld: Allow loading binary ROM image
  mac_newworld: Allow loading binary ROM image
  mac_oldworld: Drop a variable, use get_system_memory() directly
  mac_oldworld: Drop some variables
  grackle: Set revision in PCI config to match hardware
  mac_oldworld: Rename ppc_heathrow_reset to ppc_heathrow_cpu_reset
  mac_oldworld: Map macio to expected address at reset
  mac_oldworld: Add machine ID register
  i2c: Match parameters of i2c_start_transfer and i2c_send_recv
  WIP macio/cuda: Attempt to add i2c support
  mac_oldworld: Add SPD data to cover RAM

 hw/display/sm501.c   |   2 +-
 hw/i2c/core.c|  34 +-
 hw/i2c/ppc4xx_i2c.c  |   2 +-
 hw/misc/macio/cuda.c |  76 -
 hw/pci-host/grackle.c|   2 +-
 hw/ppc/mac.h |  15 -
 hw/ppc/mac_newworld.c|  22 +++---
 hw/ppc/mac_oldworld.c| 127 ++-
 include/hw/i2c/i2c.h |   4 +-
 include/hw/misc/macio/cuda.h |   1 +
 10 files changed, 220 insertions(+), 65 deletions(-)

-- 
2.21.3




[PATCH v6 04/11] mac_oldworld: Drop some variables

2020-06-28 Thread BALATON Zoltan
Values not used frequently enough may not worth putting in a local
variable, especially with names almost as long as the original value
because that does not improve readability, to the contrary it makes it
harder to see what value is used. Drop a few such variables.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Mark Cave-Ayland 
---
 hw/ppc/mac_oldworld.c | 33 -
 1 file changed, 16 insertions(+), 17 deletions(-)

diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index d1c4244b1e..428851 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -83,14 +83,11 @@ static void ppc_heathrow_reset(void *opaque)
 static void ppc_heathrow_init(MachineState *machine)
 {
 ram_addr_t ram_size = machine->ram_size;
-const char *kernel_filename = machine->kernel_filename;
-const char *kernel_cmdline = machine->kernel_cmdline;
-const char *initrd_filename = machine->initrd_filename;
 const char *boot_device = machine->boot_order;
 PowerPCCPU *cpu = NULL;
 CPUPPCState *env = NULL;
 char *filename;
-int linux_boot, i;
+int i;
 MemoryRegion *bios = g_new(MemoryRegion, 1);
 uint32_t kernel_base, initrd_base, cmdline_base = 0;
 int32_t kernel_size, initrd_size;
@@ -108,8 +105,6 @@ static void ppc_heathrow_init(MachineState *machine)
 void *fw_cfg;
 uint64_t tbfreq;
 
-linux_boot = (kernel_filename != NULL);
-
 /* init CPUs */
 for (i = 0; i < smp_cpus; i++) {
 cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
@@ -159,7 +154,7 @@ static void ppc_heathrow_init(MachineState *machine)
 exit(1);
 }
 
-if (linux_boot) {
+if (machine->kernel_filename) {
 uint64_t lowaddr = 0;
 int bswap_needed;
 
@@ -169,30 +164,33 @@ static void ppc_heathrow_init(MachineState *machine)
 bswap_needed = 0;
 #endif
 kernel_base = KERNEL_LOAD_ADDR;
-kernel_size = load_elf(kernel_filename, NULL,
+kernel_size = load_elf(machine->kernel_filename, NULL,
translate_kernel_address, NULL,
NULL, &lowaddr, NULL, NULL, 1, PPC_ELF_MACHINE,
0, 0);
 if (kernel_size < 0)
-kernel_size = load_aout(kernel_filename, kernel_base,
+kernel_size = load_aout(machine->kernel_filename, kernel_base,
 ram_size - kernel_base, bswap_needed,
 TARGET_PAGE_SIZE);
 if (kernel_size < 0)
-kernel_size = load_image_targphys(kernel_filename,
+kernel_size = load_image_targphys(machine->kernel_filename,
   kernel_base,
   ram_size - kernel_base);
 if (kernel_size < 0) {
-error_report("could not load kernel '%s'", kernel_filename);
+error_report("could not load kernel '%s'",
+ machine->kernel_filename);
 exit(1);
 }
 /* load initrd */
-if (initrd_filename) {
-initrd_base = TARGET_PAGE_ALIGN(kernel_base + kernel_size + 
KERNEL_GAP);
-initrd_size = load_image_targphys(initrd_filename, initrd_base,
+if (machine->initrd_filename) {
+initrd_base = TARGET_PAGE_ALIGN(kernel_base + kernel_size +
+KERNEL_GAP);
+initrd_size = load_image_targphys(machine->initrd_filename,
+  initrd_base,
   ram_size - initrd_base);
 if (initrd_size < 0) {
 error_report("could not load initial ram disk '%s'",
- initrd_filename);
+ machine->initrd_filename);
 exit(1);
 }
 cmdline_base = TARGET_PAGE_ALIGN(initrd_base + initrd_size);
@@ -336,9 +334,10 @@ static void ppc_heathrow_init(MachineState *machine)
 fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, ARCH_HEATHROW);
 fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base);
 fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
-if (kernel_cmdline) {
+if (machine->kernel_cmdline) {
 fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, cmdline_base);
-pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, 
kernel_cmdline);
+pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE,
+ machine->kernel_cmdline);
 } else {
 fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
 }
-- 
2.21.3




[PATCH v6 01/11] mac_oldworld: Allow loading binary ROM image

2020-06-28 Thread BALATON Zoltan
The beige G3 Power Macintosh has a 4MB firmware ROM. Fix the size of
the rom region and fall back to loading a binary image with -bios if
loading ELF image failed. This allows testing emulation with a ROM
image from real hardware as well as using an ELF OpenBIOS image.

Signed-off-by: BALATON Zoltan 
---
v4: use load address from ELF to check if ROM is too big

 hw/ppc/mac_oldworld.c | 29 -
 1 file changed, 20 insertions(+), 9 deletions(-)

diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index f8c204ead7..baf3da6f90 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -59,6 +59,8 @@
 #define NDRV_VGA_FILENAME "qemu_vga.ndrv"
 
 #define GRACKLE_BASE 0xfec0
+#define PROM_BASE 0xffc0
+#define PROM_SIZE (4 * MiB)
 
 static void fw_cfg_boot_set(void *opaque, const char *boot_device,
 Error **errp)
@@ -99,6 +101,7 @@ static void ppc_heathrow_init(MachineState *machine)
 SysBusDevice *s;
 DeviceState *dev, *pic_dev;
 BusState *adb_bus;
+uint64_t bios_addr;
 int bios_size;
 unsigned int smp_cpus = machine->smp.cpus;
 uint16_t ppc_boot_device;
@@ -127,24 +130,32 @@ static void ppc_heathrow_init(MachineState *machine)
 
 memory_region_add_subregion(sysmem, 0, machine->ram);
 
-/* allocate and load BIOS */
-memory_region_init_rom(bios, NULL, "ppc_heathrow.bios", BIOS_SIZE,
+/* allocate and load firmware ROM */
+memory_region_init_rom(bios, NULL, "ppc_heathrow.bios", PROM_SIZE,
&error_fatal);
+memory_region_add_subregion(sysmem, PROM_BASE, bios);
 
-if (bios_name == NULL)
+if (!bios_name) {
 bios_name = PROM_FILENAME;
+}
 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-memory_region_add_subregion(sysmem, PROM_ADDR, bios);
-
-/* Load OpenBIOS (ELF) */
 if (filename) {
-bios_size = load_elf(filename, NULL, 0, NULL, NULL, NULL, NULL, NULL,
- 1, PPC_ELF_MACHINE, 0, 0);
+/* Load OpenBIOS (ELF) */
+bios_size = load_elf(filename, NULL, NULL, NULL, NULL, &bios_addr,
+ NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0);
+if (bios_size <= 0) {
+/* or load binary ROM image */
+bios_size = load_image_targphys(filename, PROM_BASE, PROM_SIZE);
+bios_addr = PROM_BASE;
+} else {
+/* load_elf sets high 32 bits for some reason, strip those */
+bios_addr &= 0xULL;
+}
 g_free(filename);
 } else {
 bios_size = -1;
 }
-if (bios_size < 0 || bios_size > BIOS_SIZE) {
+if (bios_size < 0 || bios_addr - PROM_BASE + bios_size > PROM_SIZE) {
 error_report("could not load PowerPC bios '%s'", bios_name);
 exit(1);
 }
-- 
2.21.3




[PATCH v6 02/11] mac_newworld: Allow loading binary ROM image

2020-06-28 Thread BALATON Zoltan
Fall back to load binary ROM image if loading ELF fails. This also
moves PROM_BASE and PROM_SIZE defines to board as these are matching
the ROM size and address on this board and removes the now unused
PROM_ADDR and BIOS_SIZE defines from common mac.h.

Signed-off-by: BALATON Zoltan 
---
Unlike mac_oldworld where the openbios-ppc image loads at end of ROM
region here we only check size and assume ELF image is loaded from
PROM_BASE, Checking the load addr here is tricky because this board is
also be compiled both 64 and 32 bit and load_elf seems to always
return 64 bit value so handling that could become a mess. If this is a
problem then it's a preexisting one so should be fixed in a separate
patch. This one just allows loading ROM binary too otherwise
preserving previous behaviour.

 hw/ppc/mac.h  |  2 --
 hw/ppc/mac_newworld.c | 22 ++
 2 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h
index 04e498bc57..195967facd 100644
--- a/hw/ppc/mac.h
+++ b/hw/ppc/mac.h
@@ -40,10 +40,8 @@
 /* SMP is not enabled, for now */
 #define MAX_CPUS 1
 
-#define BIOS_SIZE(1 * MiB)
 #define NVRAM_SIZE0x2000
 #define PROM_FILENAME"openbios-ppc"
-#define PROM_ADDR 0xfff0
 
 #define KERNEL_LOAD_ADDR 0x0100
 #define KERNEL_GAP   0x0010
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 828c5992ae..c88142af57 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -82,6 +82,8 @@
 
 #define NDRV_VGA_FILENAME "qemu_vga.ndrv"
 
+#define PROM_BASE 0xfff0
+#define PROM_SIZE (1 * MiB)
 
 static void fw_cfg_boot_set(void *opaque, const char *boot_device,
 Error **errp)
@@ -100,7 +102,7 @@ static void ppc_core99_reset(void *opaque)
 
 cpu_reset(CPU(cpu));
 /* 970 CPUs want to get their initial IP as part of their boot protocol */
-cpu->env.nip = PROM_ADDR + 0x100;
+cpu->env.nip = PROM_BASE + 0x100;
 }
 
 /* PowerPC Mac99 hardware initialisation */
@@ -153,25 +155,29 @@ static void ppc_core99_init(MachineState *machine)
 /* allocate RAM */
 memory_region_add_subregion(get_system_memory(), 0, machine->ram);
 
-/* allocate and load BIOS */
-memory_region_init_rom(bios, NULL, "ppc_core99.bios", BIOS_SIZE,
+/* allocate and load firmware ROM */
+memory_region_init_rom(bios, NULL, "ppc_core99.bios", PROM_SIZE,
&error_fatal);
+memory_region_add_subregion(get_system_memory(), PROM_BASE, bios);
 
-if (bios_name == NULL)
+if (!bios_name) {
 bios_name = PROM_FILENAME;
+}
 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-memory_region_add_subregion(get_system_memory(), PROM_ADDR, bios);
-
-/* Load OpenBIOS (ELF) */
 if (filename) {
+/* Load OpenBIOS (ELF) */
 bios_size = load_elf(filename, NULL, NULL, NULL, NULL,
  NULL, NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0);
 
+if (bios_size <= 0) {
+/* or load binary ROM image */
+bios_size = load_image_targphys(filename, PROM_BASE, PROM_SIZE);
+}
 g_free(filename);
 } else {
 bios_size = -1;
 }
-if (bios_size < 0 || bios_size > BIOS_SIZE) {
+if (bios_size < 0 || bios_size > PROM_SIZE) {
 error_report("could not load PowerPC bios '%s'", bios_name);
 exit(1);
 }
-- 
2.21.3




Re: [REPORT] [GSoC - TCG Continuous Benchmarking] [#1] Measuring Basic Performance Metrics of QEMU

2020-06-28 Thread Aleksandar Markovic
пон, 22. јун 2020. у 12:31 Ahmed Karaman
 је написао/ла:
>
> Greetings,
>
> Welcome to the TCG Continuous Benchmarking GSoC project!
> This is the first report in a series that will be posted here on the
> mailing list as part of the project.
>
> During the project, multiple Linux profiling tools will be used.
> These tools will help you profile your different QEMU execution
> scenarios, and locate performance bottlenecks as well as performance
> regression problems.
>
> To provide you with a better understanding of these tools, this report
> presents two of them - Perf and Callgrind.
> It starts with measuring the basic performance metrics when running
> a program using both tools, then it proceeds to calculating the top 25
> most executed functions in QEMU

Now, thinking longer about topN scripts, I think one really missing
thing is number of invocations (or calls, whatever term you prefer)
for any function in the list. This data must be possible to obtain
using callgrind_annotate (most likely by using --tree option). With
perf, i don't think this is possible, given that perf works based on
sampling.

You don't need to start working on it right now, or work on it at all
- this is more like a brainstorming suggestion from me. You can make
improvements and correction all the way towards the end of the
project, on Aug 31st.

At the end of the project, perhaps you can publish a "Master Project
Report" - a pdf that is basically a sum of all your reports produced
during the project. That would be a nice reading!

Regards,
Aleksandar

> To dissect the output of each of the two tools, a separate section
> for comparing the output results is presented which focuses on how
> these results apply to QEMU.
> Finally, a stability test is devised that compares how the output
> of the two tools differ with each subsequent invocation of QEMU.
>
> For easier accessibility, all reports will be hosted on a dedicated
> website:
> https://ahmedkrmn.github.io/TCG-Continuous-Benchmarking/
>
> Link to the first report:
> https://ahmedkrmn.github.io/TCG-Continuous-Benchmarking/Measuring-Basic-Performance-Metrics-of-QEMU/
>
> Best regards,
> Ahmed Karaman



Re: Crash when running Qemu.

2020-06-28 Thread Peter Maydell
On Sun, 28 Jun 2020 at 17:46, Jean-Christophe DUBOIS
 wrote:
>
> Le 28/06/2020 à 16:38, Peter Maydell a écrit :
> > On Sun, 28 Jun 2020 at 11:56, Jean-Christophe DUBOIS
> >  wrote:
> >> jcd@jcd-UX305CA:~/Projects/µCOS/work$
> >> ../../qemu/qemu/arm-softmmu/qemu-system-arm -machine mcimx6ul-evk -m
> >> 128M -display none -serial stdio -kernel ./OS.elf
> >> double free or corruption (!prev)
> >> Abandon (core dumped)
> > I can't repro using your command line but without the -kernel option,
> > so it's probably specific to something your guest code is doing.
> > I tested with git commit e7651153a8801dad6; which commit are you
> > using?
>
> I was on master (553cf5d7c47bee05a3dec9461c1f8430316d516b)
>
> Reverting the June 23rd commit series on PCA9552 fixed the problem for me.
>
> > Can you provide either the elf file or a repro example that
> > doesn't need it ?
>
> Please, find the OS.elf file as attachment.

Ah, thanks for tracking that down. Philippe, the valgrind
error in Jean-Christophe's other email in this thread suggests
something's wrong in the typeinfo or the class init for the
pca9552 changes you've made -- would you mind having a look at it?

thanks
-- PMM



Re: Crash when running Qemu.

2020-06-28 Thread Jean-Christophe DUBOIS
By reverting the recent (june 23) commit series on PCA9552 I can run 
Qemu again.


Here is the git revert command I did.

jcd@jcd-UX305CA:~/Projects/qemu/qemu$ git revert 
8208335b9539e7b5aa4702b36e2f9a8abd704079..586f495b1e78c27e141ff432dd971eb41866fb80


Regards

JC

Le 28/06/2020 à 17:57, Jean-Christophe DUBOIS a écrit :
When ran from valgrind, qemu does not crash but the following output 
is returned.


valgrind --track-origins=yes 
../../qemu/qemu/arm-softmmu/qemu-system-arm -machine mcimx6ul-evk -m 
128M -display none -serial stdio -kernel ./OS.elf

==77479== Memcheck, a memory error detector
==77479== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==77479== Using Valgrind-3.15.0 and LibVEX; rerun with -h for 
copyright info
==77479== Command: ../../qemu/qemu/arm-softmmu/qemu-system-arm 
-machine mcimx6ul-evk -m 128M -display none -serial stdio -kernel 
./OS.elf

==77479==
==77479== Invalid write of size 2
==77479==    at 0x6D8322: pca9552_class_init (pca9552.c:424)
==77479==    by 0x844D1F: type_initialize (object.c:1029)
==77479==    by 0x844D1F: object_class_foreach_tramp (object.c:1016)
==77479==    by 0x4AE1057: g_hash_table_foreach (in 
/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)

==77479==    by 0x8453A4: object_class_foreach (object.c:1038)
==77479==    by 0x8453A4: object_class_get_list (object.c:1095)
==77479==    by 0x556194: select_machine (vl.c:2416)
==77479==    by 0x556194: qemu_init (vl.c:3828)
==77479==    by 0x40AF9C: main (main.c:48)
==77479==  Address 0x583f108 is 0 bytes after a block of size 200 alloc'd
==77479==    at 0x483DD99: calloc (in 
/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==77479==    by 0x4AF8D30: g_malloc0 (in 
/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)

==77479==    by 0x844258: type_initialize.part.0 (object.c:306)
==77479==    by 0x844D1F: type_initialize (object.c:1029)
==77479==    by 0x844D1F: object_class_foreach_tramp (object.c:1016)
==77479==    by 0x4AE1057: g_hash_table_foreach (in 
/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)

==77479==    by 0x8453A4: object_class_foreach (object.c:1038)
==77479==    by 0x8453A4: object_class_get_list (object.c:1095)
==77479==    by 0x556194: select_machine (vl.c:2416)
==77479==    by 0x556194: qemu_init (vl.c:3828)
==77479==    by 0x40AF9C: main (main.c:48)
==77479==
==77479== Conditional jump or move depends on uninitialised value(s)
==77479==    at 0x41D944: tcg_target_init (tcg-target.inc.c:3867)
==77479==    by 0x41D944: tcg_context_init (tcg.c:983)
==77479==    by 0x48E60D: cpu_gen_init (translate-all.c:246)
==77479==    by 0x48E60D: tcg_exec_init (translate-all.c:1152)
==77479==    by 0x46FE7B: tcg_init (tcg-all.c:129)
==77479==    by 0x5E15A5: accel_init_machine (accel.c:55)
==77479==    by 0x55402F: do_configure_accelerator (vl.c:2708)
==77479==    by 0x94F1D1: qemu_opts_foreach (qemu-option.c:1163)
==77479==    by 0x5598B3: configure_accelerators (vl.c:2775)
==77479==    by 0x5598B3: qemu_init (vl.c:4152)
==77479==    by 0x40AF9C: main (main.c:48)
==77479==  Uninitialised value was created by a stack allocation
==77479==    at 0x4ADFE5F: ??? (in 
/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)

==77479==
==77479== Warning: set address range perms: large range [0x6483000, 
0x46483000) (defined)


===
=   TCPIP INITIALIZATION =
===
Initializing TCPIP...

--- i.MX6UL-EVK BOARD NETWORK CONFIG 



Starting ENET1...

NetIF_LinkStateWaitUntilUp() failed w/ err = 30


Starting ENET2...

NetIF_LinkStateWaitUntilUp() failed w/ err = 30

Network Configuration:
qemu-system-arm: terminating on signal 2
==77479==
==77479== HEAP SUMMARY:
==77479== in use at exit: 8,452,515 bytes in 57,040 blocks
==77479==   total heap usage: 97,248 allocs, 40,208 frees, 21,279,482 
bytes allocated

==77479==
==77479== LEAK SUMMARY:
==77479==    definitely lost: 0 bytes in 0 blocks
==77479==    indirectly lost: 0 bytes in 0 blocks
==77479==  possibly lost: 3,474 bytes in 45 blocks
==77479==    still reachable: 8,449,041 bytes in 56,995 blocks
==77479==   of which reachable via heuristic:
==77479== newarray   : 1,536 bytes in 
16 blocks

==77479== suppressed: 0 bytes in 0 blocks
==77479== Rerun with --leak-check=full to see details of leaked memory
==77479==
==77479== For lists of detected and suppressed errors, rerun with: -s
==77479== ERROR SUMMARY: 3 errors from 2 contexts (suppressed: 0 from 0)

Le 28/06/2020 à 12:55, Jean-Christophe DUBOIS a écrit :

Hi,

Since the last pull I did this week end on the qemu git tree (master 
branch) I am unable to "start" qemu anymore (It was working OK from 
git master previously).


Traces are provided bellow.

Am I the only one to get this behavior?

JC

jcd@jcd-UX305CA:~/Projects/µCOS/work$ 
../../qemu/qemu/ar

Re: Crash when running Qemu.

2020-06-28 Thread Jean-Christophe DUBOIS
When ran from valgrind, qemu does not crash but the following output is 
returned.


valgrind --track-origins=yes ../../qemu/qemu/arm-softmmu/qemu-system-arm 
-machine mcimx6ul-evk -m 128M -display none -serial stdio -kernel ./OS.elf

==77479== Memcheck, a memory error detector
==77479== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==77479== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==77479== Command: ../../qemu/qemu/arm-softmmu/qemu-system-arm -machine 
mcimx6ul-evk -m 128M -display none -serial stdio -kernel ./OS.elf

==77479==
==77479== Invalid write of size 2
==77479==    at 0x6D8322: pca9552_class_init (pca9552.c:424)
==77479==    by 0x844D1F: type_initialize (object.c:1029)
==77479==    by 0x844D1F: object_class_foreach_tramp (object.c:1016)
==77479==    by 0x4AE1057: g_hash_table_foreach (in 
/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)

==77479==    by 0x8453A4: object_class_foreach (object.c:1038)
==77479==    by 0x8453A4: object_class_get_list (object.c:1095)
==77479==    by 0x556194: select_machine (vl.c:2416)
==77479==    by 0x556194: qemu_init (vl.c:3828)
==77479==    by 0x40AF9C: main (main.c:48)
==77479==  Address 0x583f108 is 0 bytes after a block of size 200 alloc'd
==77479==    at 0x483DD99: calloc (in 
/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==77479==    by 0x4AF8D30: g_malloc0 (in 
/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)

==77479==    by 0x844258: type_initialize.part.0 (object.c:306)
==77479==    by 0x844D1F: type_initialize (object.c:1029)
==77479==    by 0x844D1F: object_class_foreach_tramp (object.c:1016)
==77479==    by 0x4AE1057: g_hash_table_foreach (in 
/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)

==77479==    by 0x8453A4: object_class_foreach (object.c:1038)
==77479==    by 0x8453A4: object_class_get_list (object.c:1095)
==77479==    by 0x556194: select_machine (vl.c:2416)
==77479==    by 0x556194: qemu_init (vl.c:3828)
==77479==    by 0x40AF9C: main (main.c:48)
==77479==
==77479== Conditional jump or move depends on uninitialised value(s)
==77479==    at 0x41D944: tcg_target_init (tcg-target.inc.c:3867)
==77479==    by 0x41D944: tcg_context_init (tcg.c:983)
==77479==    by 0x48E60D: cpu_gen_init (translate-all.c:246)
==77479==    by 0x48E60D: tcg_exec_init (translate-all.c:1152)
==77479==    by 0x46FE7B: tcg_init (tcg-all.c:129)
==77479==    by 0x5E15A5: accel_init_machine (accel.c:55)
==77479==    by 0x55402F: do_configure_accelerator (vl.c:2708)
==77479==    by 0x94F1D1: qemu_opts_foreach (qemu-option.c:1163)
==77479==    by 0x5598B3: configure_accelerators (vl.c:2775)
==77479==    by 0x5598B3: qemu_init (vl.c:4152)
==77479==    by 0x40AF9C: main (main.c:48)
==77479==  Uninitialised value was created by a stack allocation
==77479==    at 0x4ADFE5F: ??? (in 
/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)

==77479==
==77479== Warning: set address range perms: large range [0x6483000, 
0x46483000) (defined)


===
=   TCPIP INITIALIZATION =
===
Initializing TCPIP...

--- i.MX6UL-EVK BOARD NETWORK CONFIG 



Starting ENET1...

NetIF_LinkStateWaitUntilUp() failed w/ err = 30


Starting ENET2...

NetIF_LinkStateWaitUntilUp() failed w/ err = 30

Network Configuration:
qemu-system-arm: terminating on signal 2
==77479==
==77479== HEAP SUMMARY:
==77479== in use at exit: 8,452,515 bytes in 57,040 blocks
==77479==   total heap usage: 97,248 allocs, 40,208 frees, 21,279,482 
bytes allocated

==77479==
==77479== LEAK SUMMARY:
==77479==    definitely lost: 0 bytes in 0 blocks
==77479==    indirectly lost: 0 bytes in 0 blocks
==77479==  possibly lost: 3,474 bytes in 45 blocks
==77479==    still reachable: 8,449,041 bytes in 56,995 blocks
==77479==   of which reachable via heuristic:
==77479== newarray   : 1,536 bytes in 16 
blocks

==77479== suppressed: 0 bytes in 0 blocks
==77479== Rerun with --leak-check=full to see details of leaked memory
==77479==
==77479== For lists of detected and suppressed errors, rerun with: -s
==77479== ERROR SUMMARY: 3 errors from 2 contexts (suppressed: 0 from 0)

Le 28/06/2020 à 12:55, Jean-Christophe DUBOIS a écrit :

Hi,

Since the last pull I did this week end on the qemu git tree (master 
branch) I am unable to "start" qemu anymore (It was working OK from 
git master previously).


Traces are provided bellow.

Am I the only one to get this behavior?

JC

jcd@jcd-UX305CA:~/Projects/µCOS/work$ 
../../qemu/qemu/arm-softmmu/qemu-system-arm -machine mcimx6ul-evk -m 
128M -display none -serial stdio -kernel ./OS.elf

double free or corruption (!prev)
Abandon (core dumped)

Running the same command from "gdb" provides the following backtrace.

jcd@jcd-UX305CA:~/Projects/µCOS/work$ gdb 
../../qemu/qemu/arm-softmmu/qemu-system-arm

GNU gdb (Ub

Re: [PATCH 01/19] iotests: Make _filter_img_create more active

2020-06-28 Thread Maxim Levitsky
On Thu, 2020-06-25 at 14:55 +0200, Max Reitz wrote:
> Right now, _filter_img_create just filters out everything that looks
> format-dependent, and applies some filename filters.  That means that we
> have to add another filter line every time some format gets a new
> creation option.  This can be avoided by instead discarding everything
> and just keeping what we know is format-independent (format, size,
> backing file, encryption information[1], preallocation) or just
> interesting to have in the reference output (external data file path).
> 
> Furthermore, we probably want to sort these options.  Format drivers are
> not required to define them in any specific order, so the output is
> effectively random (although this has never bothered us until now).  We
> need a specific order for our reference outputs, though.  Unfortunately,
> just using a plain "sort" would change a lot of existing reference
> outputs, so we have to pre-filter the option keys to keep our existing
> order (fmt, size, backing*, data, encryption info, preallocation).
> 
> Finally, this makes it difficult for _filter_img_create to automagically
> work for QMP output.  Thus, this patch adds a separate
> _filter_img_create_for_qmp function that echos every line verbatim that
> does not start with "Formatting", and pipes those "Formatting" lines to
> _filter_img_create.
> 
> [1] Actually, the only thing that is really important is whether
> encryption is enabled or not.  A patch by Maxim thus removes all
> other "encrypt.*" options from the output:
> https://lists.nongnu.org/archive/html/qemu-block/2020-06/msg00339.html
> But that patch needs to come later so we can get away with changing
> as few reference outputs in this patch here as possible.
> 
> Signed-off-by: Max Reitz 

I went over this patch again, and it looks OK, but
I might have missed something.


Reviewed-by: Maxim Levitsky 

Best regards,
Maxim Levitsky

> ---
>  tests/qemu-iotests/112.out   |   2 +-
>  tests/qemu-iotests/141   |   2 +-
>  tests/qemu-iotests/153   |   9 ++-
>  tests/qemu-iotests/common.filter | 109 ---
>  4 files changed, 91 insertions(+), 31 deletions(-)
> 
> diff --git a/tests/qemu-iotests/112.out b/tests/qemu-iotests/112.out
> index ae0318cabe..182655dbf6 100644
> --- a/tests/qemu-iotests/112.out
> +++ b/tests/qemu-iotests/112.out
> @@ -5,7 +5,7 @@ QA output created by 112
>  qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may 
> not exceed 64 bits
>  Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
>  qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may 
> not exceed 64 bits
> -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 refcount_bits=-1
> +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
>  qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may 
> not exceed 64 bits
>  Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
>  qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may 
> not exceed 64 bits
> diff --git a/tests/qemu-iotests/141 b/tests/qemu-iotests/141
> index 5192d256e3..6d1b7b0d4c 100755
> --- a/tests/qemu-iotests/141
> +++ b/tests/qemu-iotests/141
> @@ -68,7 +68,7 @@ test_blockjob()
>  _send_qemu_cmd $QEMU_HANDLE \
>  "$1" \
>  "$2" \
> -| _filter_img_create | _filter_qmp_empty_return
> +| _filter_img_create_in_qmp | _filter_qmp_empty_return
>  
>  # We want this to return an error because the block job is still running
>  _send_qemu_cmd $QEMU_HANDLE \
> diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153
> index cf961d3609..11e3d28841 100755
> --- a/tests/qemu-iotests/153
> +++ b/tests/qemu-iotests/153
> @@ -167,11 +167,10 @@ done
>  
>  echo
>  echo "== Creating ${TEST_IMG}.[abc] ==" | _filter_testdir
> -(
> -$QEMU_IMG create -f qcow2 "${TEST_IMG}.a" -b "${TEST_IMG}"
> -$QEMU_IMG create -f qcow2 "${TEST_IMG}.b" -b "${TEST_IMG}"
> -$QEMU_IMG create -f qcow2 "${TEST_IMG}.c" -b "${TEST_IMG}.b"
> -) | _filter_img_create
> +$QEMU_IMG create -f qcow2 "${TEST_IMG}.a" -b "${TEST_IMG}" | 
> _filter_img_create
> +$QEMU_IMG create -f qcow2 "${TEST_IMG}.b" -b "${TEST_IMG}" | 
> _filter_img_create
> +$QEMU_IMG create -f qcow2 "${TEST_IMG}.c" -b "${TEST_IMG}.b" \
> +| _filter_img_create
>  
>  echo
>  echo "== Two devices sharing the same file in backing chain =="
> diff --git a/tests/qemu-iotests/common.filter 
> b/tests/qemu-iotests/common.filter
> index 03e4f71808..f8cd80ff1f 100644
> --- a/tests/qemu-iotests/common.filter
> +++ b/tests/qemu-iotests/common.filter
> @@ -122,38 +122,99 @@ _filter_actual_image_size()
>  # replace driver-specific options in the "Formatting..." line
>  _filter_img_create()
>  {
> -data_file_filter=()
> -if data_file=$(_get_data_file "$TEST_IMG"); then
> -data_file_filter=(-e "s# data_file=$data_file##")
> +# Split the line into the pre-options

[PATCH v8 1/2] target/arm: kvm: Handle DABT with no valid ISS

2020-06-28 Thread Beata Michalska
On ARMv7 & ARMv8 some load/store instructions might trigger a data abort
exception with no valid ISS info to be decoded. The lack of decode info
makes it at least tricky to emulate those instruction which is one of the
(many) reasons why KVM will not even try to do so.

Add support for handling those by requesting KVM to inject external
dabt into the quest.

Signed-off-by: Beata Michalska 
---
 target/arm/kvm.c | 57 +++-
 1 file changed, 56 insertions(+), 1 deletion(-)

diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index eef3bbd..2dd8a9a 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -39,6 +39,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
 
 static bool cap_has_mp_state;
 static bool cap_has_inject_serror_esr;
+static bool cap_has_inject_ext_dabt;
 
 static ARMHostCPUFeatures arm_host_cpu_features;
 
@@ -245,6 +246,16 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
 ret = -EINVAL;
 }
 
+if (kvm_check_extension(s, KVM_CAP_ARM_NISV_TO_USER)) {
+if (kvm_vm_enable_cap(s, KVM_CAP_ARM_NISV_TO_USER, 0)) {
+error_report("Failed to enable KVM_CAP_ARM_NISV_TO_USER cap");
+} else {
+/* Set status for supporting the external dabt injection */
+cap_has_inject_ext_dabt = kvm_check_extension(s,
+KVM_CAP_ARM_INJECT_EXT_DABT);
+}
+}
+
 return ret;
 }
 
@@ -810,6 +821,45 @@ void kvm_arm_vm_state_change(void *opaque, int running, 
RunState state)
 }
 }
 
+/**
+ * kvm_arm_handle_dabt_nisv:
+ * @cs: CPUState
+ * @esr_iss: ISS encoding (limited) for the exception from Data Abort
+ *   ISV bit set to '0b0' -> no valid instruction syndrome
+ * @fault_ipa: faulting address for the synchronous data abort
+ *
+ * Returns: 0 if the exception has been handled, < 0 otherwise
+ */
+static int kvm_arm_handle_dabt_nisv(CPUState *cs, uint64_t esr_iss,
+ uint64_t fault_ipa)
+{
+/*
+ * Request KVM to inject the external data abort into the guest
+ */
+if (cap_has_inject_ext_dabt) {
+struct kvm_vcpu_events events = { };
+/*
+ * The external data abort event will be handled immediately by KVM
+ * using the address fault that triggered the exit on given VCPU.
+ * Requesting injection of the external data abort does not rely
+ * on any other VCPU state. Therefore, in this particular case, the 
VCPU
+ * synchronization can be exceptionally skipped.
+ */
+events.exception.ext_dabt_pending = 1;
+/*
+ * KVM_CAP_ARM_INJECT_EXT_DABT implies KVM_CAP_VCPU_EVENTS
+ */
+return kvm_vcpu_ioctl(cs, KVM_SET_VCPU_EVENTS, &events);
+
+} else {
+error_report("Data abort exception triggered by guest memory access "
+ "at physical address: 0x"  TARGET_FMT_lx,
+ (target_ulong)fault_ipa);
+error_printf("KVM unable to emulate faulting instruction.\n");
+}
+return -1;
+}
+
 int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
 {
 int ret = 0;
@@ -820,7 +870,12 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
 ret = EXCP_DEBUG;
 } /* otherwise return to guest */
 break;
-default:
+case KVM_EXIT_ARM_NISV:
+/* External DABT with no valid iss to decode */
+ret = kvm_arm_handle_dabt_nisv(cs, run->arm_nisv.esr_iss,
+   run->arm_nisv.fault_ipa);
+break;
+ default:
 qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n",
   __func__, run->exit_reason);
 break;
-- 
2.7.4




[PATCH v8 2/2] target/arm: kvm: Handle misconfigured dabt injection

2020-06-28 Thread Beata Michalska
Injecting external data abort through KVM might trigger
an issue on kernels that do not get updated to include the KVM fix.
For those and aarch32 guests, the injected abort gets misconfigured
to be an implementation defined exception. This leads to the guest
repeatedly re-running the faulting instruction.

Add support for handling that case.

[
  Fixed-by: 018f22f95e8a
('KVM: arm: Fix DFSR setting for non-LPAE aarch32 guests')
  Fixed-by: 21aecdbd7f3a
('KVM: arm: Make inject_abt32() inject an external abort instead')
]

Signed-off-by: Beata Michalska 
---
 target/arm/cpu.h |  2 ++
 target/arm/kvm.c | 30 +-
 target/arm/kvm32.c   | 34 ++
 target/arm/kvm64.c   | 49 +
 target/arm/kvm_arm.h | 10 ++
 5 files changed, 124 insertions(+), 1 deletion(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 677584e..ed0ff09 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -570,6 +570,8 @@ typedef struct CPUARMState {
 uint64_t esr;
 } serror;
 
+uint8_t ext_dabt_raised; /* Tracking/verifying injection of ext DABT */
+
 /* State of our input IRQ/FIQ/VIRQ/VFIQ lines */
 uint32_t irq_line_state;
 
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 2dd8a9a..e7a596e 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -749,6 +749,29 @@ int kvm_get_vcpu_events(ARMCPU *cpu)
 
 void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
 {
+ARMCPU *cpu = ARM_CPU(cs);
+CPUARMState *env = &cpu->env;
+
+if (unlikely(env->ext_dabt_raised)) {
+/*
+ * Verifying that the ext DABT has been properly injected,
+ * otherwise risking indefinitely re-running the faulting instruction
+ * Covering a very narrow case for kernels 5.5..5.5.4
+ * when injected abort was misconfigured to be
+ * an IMPLEMENTATION DEFINED exception (for 32-bit EL1)
+ */
+if (!arm_feature(env, ARM_FEATURE_AARCH64) &&
+unlikely(!kvm_arm_verify_ext_dabt_pending(cs))) {
+
+error_report("Data abort exception with no valid ISS generated by "
+   "guest memory access. KVM unable to emulate faulting "
+   "instruction. Failed to inject an external data abort "
+   "into the guest.");
+abort();
+   }
+   /* Clear the status */
+   env->ext_dabt_raised = 0;
+}
 }
 
 MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
@@ -833,6 +856,8 @@ void kvm_arm_vm_state_change(void *opaque, int running, 
RunState state)
 static int kvm_arm_handle_dabt_nisv(CPUState *cs, uint64_t esr_iss,
  uint64_t fault_ipa)
 {
+ARMCPU *cpu = ARM_CPU(cs);
+CPUARMState *env = &cpu->env;
 /*
  * Request KVM to inject the external data abort into the guest
  */
@@ -849,7 +874,10 @@ static int kvm_arm_handle_dabt_nisv(CPUState *cs, uint64_t 
esr_iss,
 /*
  * KVM_CAP_ARM_INJECT_EXT_DABT implies KVM_CAP_VCPU_EVENTS
  */
-return kvm_vcpu_ioctl(cs, KVM_SET_VCPU_EVENTS, &events);
+if (!kvm_vcpu_ioctl(cs, KVM_SET_VCPU_EVENTS, &events)) {
+env->ext_dabt_raised = 1;
+return 0;
+}
 
 } else {
 error_report("Data abort exception triggered by guest memory access "
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
index 7b3a19e..0af46b4 100644
--- a/target/arm/kvm32.c
+++ b/target/arm/kvm32.c
@@ -559,3 +559,37 @@ void kvm_arm_pmu_init(CPUState *cs)
 {
 qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
 }
+
+#define ARM_REG_DFSR  ARM_CP15_REG32(0, 5, 0, 0)
+#define ARM_REG_TTBCR ARM_CP15_REG32(0, 2, 0, 2)
+/*
+ *DFSR:
+ *  TTBCR.EAE == 0
+ *  FS[4]   - DFSR[10]
+ *  FS[3:0] - DFSR[3:0]
+ *  TTBCR.EAE == 1
+ *  FS, bits [5:0]
+ */
+#define DFSR_FSC(lpae, v) \
+((lpae) ? ((v) & 0x3F) : (((v) >> 6) | ((v) & 0x1F)))
+
+#define DFSC_EXTABT(lpae) ((lpae) ? 0x10 : 0x08)
+
+bool kvm_arm_verify_ext_dabt_pending(CPUState *cs)
+{
+uint32_t dfsr_val;
+
+if (!kvm_get_one_reg(cs, ARM_REG_DFSR, &dfsr_val)) {
+ARMCPU *cpu = ARM_CPU(cs);
+CPUARMState *env = &cpu->env;
+uint32_t ttbcr;
+int lpae = 0;
+
+if (!kvm_get_one_reg(cs, ARM_REG_TTBCR, &ttbcr)) {
+lpae = arm_feature(env, ARM_FEATURE_LPAE) && (ttbcr & TTBCR_EAE);
+}
+/* The verification is based on FS filed of the DFSR reg only*/
+return (DFSR_FSC(lpae, dfsr_val) == DFSC_EXTABT(lpae));
+}
+return false;
+}
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index f09ed9f..88cf10c 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -1497,3 +1497,52 @@ bool kvm_arm_handle_debug(CPUState *cs, struct 
kvm_debug_exit_arch *debug_exit)
 
 return false;
 }
+
+#define ARM64_REG_ESR_EL1 ARM64_SYS_REG(3, 0, 5, 2, 0)
+#define ARM64_REG_TCR_EL1 AR

Re: [PATCH v5 09/11] macio: Add dummy screamer register area

2020-06-28 Thread BALATON Zoltan

On Sun, 28 Jun 2020, BALATON Zoltan wrote:

SCREAMER: ### AUDIO WRITE! 0 / 11104 - 11104
Unassigned mem write f3011190 = 0x900
Unassigned mem write f3011190 = 0xb00
Unassigned mem write f3011190 = 0x900
Unassigned mem write f3011190 = 0x900
Unassigned mem write f3011190 = 0xb00
Unassigned mem write f3011190 = 0x900
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x300
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x300
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x300
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x900
Unassigned mem write f3011190 = 0xb00
Unassigned mem write f3011190 = 0x900
Unassigned mem write f3011190 = 0x900
Unassigned mem write f3011190 = 0xb00
Unassigned mem write f3011190 = 0x900
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x300
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x300
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x300
Unassigned mem read f3011190
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x300
Unassigned mem read f3011190
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x300
Unassigned mem read f3011190
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x300
Unassigned mem read f3011190
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x300
Unassigned mem read f3011190
[bunch of more accesses to this address...]
Unassigned mem read f3011170
Unassigned mem read f3011170


According to 
https://github.com/dingusdev/dingusppc/blob/master/devices/macio.h this is 
probably the ethernet port, may want to map some unimplemented device 
there to log access, otherwise it probably OK ans could do without it for 
now.



Unassigned mem read 0fefe7b0
Unassigned mem write 0fec = 0x0
Unassigned mem write 0fe8 = 0x0


Still not sure about this one I'd expect it to write to frame buffer at 
this point but probably it's accessing wrong area due to something 
nonsense returned by some earlier read of some register and it did not 
seem to talk to PCI devices to set up the BARs earlier so either we're 
missing some register writes that are silently discarded in some 
partially emulated device or it expects things to be already set up some 
way at startup.


Regards,
BALATON Zoltan



[PATCH v8 0/2] target/arm: kvm: Support for KVM DABT with no valid ISS

2020-06-28 Thread Beata Michalska
Some of the ARMv7 & ARMv8 load/store instructions might trigger a data abort
exception with no valid ISS info to be decoded. The lack of decode info
makes it at least tricky to emulate the instruction which is one of the
(many) reasons why KVM will not even try to do so.

So far, if a guest made an attempt to access memory outside the memory slot,
KVM reported vague ENOSYS. As a result QEMU exited with no useful information
being provided or even a clue on what has just happened.

ARM KVM introduced support for notifying of an attempt to execute
an instruction that resulted in dabt with no valid ISS decoding info.
This still leaves QEMU to handle the case, but at least now it gives more
control and a start point for more meaningful handling of such cases.

This patchset relies on KVM to insert the external data abort into the guest.


--
v8:
 - moving the comment re support for VCPU events - missed in previous patchset

v7:
 - Rephrasing the comment regarding abort injection and vcpu synchronization
 - switching to struct initialization instead of memset

v6:
 - replacing calling kvm_put_vcpu_events with an actual ioctl call
 - making the handler function static

v5:
 - Drop syncing vcpu regs in favour of calling kvm_put_vcpu_events directly
 - Fix decoding DFSC for LPAE case
 - Add/clarify comments
 - Switch to reporting error case failure when enabling the cap

v4:
 - Removing one of the patches as it is being picked-up separately
 target/arm: kvm: Inject events at the last stage of sync
 - Moving handling KVM issue to a separate patch
 - Minor changes wrt the review comments

v3:
 - Fix setting KVM cap per vm not per vcpu
 - Simplifying the handler to bare minimum with no default logging to address
   the potential risk of overflooding the host (adding support for rate
   limiting the logs turned out to be bit too invasive to justify the little
   add-on value from logs in this particular case)
 - Adding handling KVM bug (for small range of affected kernels):
   little bit of trade-off between what's reasonable and what's effective:
   aborting qemu when running on buggy host kernel

v2:
- Improving/re-phrasing messaging
- Dropping messing around with forced sync (@see [PATCH v2 1/2])
  and PC alignment

Beata Michalska (2):
  target/arm: kvm: Handle DABT with no valid ISS
  target/arm: kvm: Handle misconfigured dabt injection

 target/arm/cpu.h |  2 ++
 target/arm/kvm.c | 85 +++-
 target/arm/kvm32.c   | 34 +
 target/arm/kvm64.c   | 49 ++
 target/arm/kvm_arm.h | 10 +++
 5 files changed, 179 insertions(+), 1 deletion(-)

-- 
2.7.4




Re: [PATCH v5 09/11] macio: Add dummy screamer register area

2020-06-28 Thread BALATON Zoltan
With increasing screamer buffer size (you may want to fix this and 
prevent buffer overflows, maybe should allocate it dynamically based on 
what the guest programs?):


diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h
index 75f1853a7b..05b289e086 100644
--- a/hw/ppc/mac.h
+++ b/hw/ppc/mac.h
@@ -108,7 +108,7 @@ typedef struct Core99MachineState {
 #define TYPE_SCREAMER "screamer"
 #define SCREAMER(obj) OBJECT_CHECK(ScreamerState, (obj), TYPE_SCREAMER)

-#define SCREAMER_BUFFER_SIZE 0x4000
+#define SCREAMER_BUFFER_SIZE 0x8000

 typedef struct ScreamerState {
 /*< private >*/

it now plays the startup chord and goes further but ends up accessing some 
unassigned memory (I think it probably wants to map framebuffer or detect 
PCI devices but something is not yet right, I don't see it talking to PCI 
devices yet):


SCREAMER: Processing deferred buffer
SCREAMER: DMA TX transfer: addr 58100 len: 8000  bpos: 0
SCREAMER: DMA TX defer interrupt!
SCREAMER: ### AUDIO WRITE! 0 / 32768 - 11152
SCREAMER: ### AUDIO WRITE! 11152 / 32768 - 4128
SCREAMER: ### AUDIO WRITE! 15280 / 32768 - 1104
SCREAMER: ### AUDIO WRITE! 16384 / 32768 - 7024
SCREAMER: ### AUDIO WRITE! 23408 / 32768 - 4128
SCREAMER: ### AUDIO WRITE! 27536 / 32768 - 4128
SCREAMER: ### AUDIO WRITE! 31664 / 32768 - 1104
SCREAMER: Processing deferred buffer
SCREAMER: DMA TX transfer: addr 60100 len: 2b60  bpos: 0
SCREAMER: screamer_write: addr 0001 val 1280
SCREAMER: screamer_codec_write: addr 0001 val 280
SCREAMER: setting mute: 0, attenuation L: 0 R: 0
SCREAMER: screamer_read: addr 0002 -> 403100
SCREAMER: screamer_read: addr 0001 -> 1280
SCREAMER: screamer_write: addr 0001 val 6002
SCREAMER: screamer_codec_write: addr 0006 val 2
cuda_delay_set_sr_int
cuda_delay_set_sr_int
cuda_data_send send: 0x01
cuda_delay_set_sr_int
cuda_data_send send: 0x22
cuda_delay_set_sr_int
cuda_data_send send: 0x8a
cuda_delay_set_sr_int
cuda_data_send send: 0x01
cuda_delay_set_sr_int
cuda_data_send send: 0x6f
cuda_delay_set_sr_int
cuda_delay_set_sr_int
cuda_packet_receive length 5
cuda_packet_receive_data [0] 0x01
cuda_packet_receive_data [1] 0x22
cuda_packet_receive_data [2] 0x8a
cuda_packet_receive_data [3] 0x01
cuda_packet_receive_data [4] 0x6f
cuda_receive_packet_cmd handling command GET_SET_IIC
CUDA: unimplemented GET_SET_IIC write 0x45 3
CUDA: GET_SET_IIC: wrong parameters 4
cuda_packet_send length 4
cuda_packet_send_data [0] 0x02
cuda_packet_send_data [1] 0x05
cuda_packet_send_data [2] 0x01
cuda_packet_send_data [3] 0x22
cuda_delay_set_sr_int
cuda_data_recv recv: 0x02
cuda_delay_set_sr_int
cuda_data_recv recv: 0x05
cuda_delay_set_sr_int
cuda_data_recv recv: 0x01
cuda_delay_set_sr_int
cuda_data_recv recv: 0x22
cuda_delay_set_sr_int
cuda_delay_set_sr_int
pci_cfg_read grackle 00:0 @0x8 -> 0x6000140
pci_cfg_read grackle 00:0 @0xa8 -> 0x40e0c
pci_cfg_write grackle 00:0 @0xa8 <- 0x40e0e
pci_cfg_read grackle 00:0 @0xac -> 0x200
pci_cfg_write grackle 00:0 @0xac <- 0x82470284
pci_cfg_write grackle 00:0 @0xac <- 0xc2470284
SCREAMER: ### AUDIO WRITE! 0 / 11104 - 11104
Unassigned mem write f3011190 = 0x900
Unassigned mem write f3011190 = 0xb00
Unassigned mem write f3011190 = 0x900
Unassigned mem write f3011190 = 0x900
Unassigned mem write f3011190 = 0xb00
Unassigned mem write f3011190 = 0x900
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x300
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x300
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x300
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x900
Unassigned mem write f3011190 = 0xb00
Unassigned mem write f3011190 = 0x900
Unassigned mem write f3011190 = 0x900
Unassigned mem write f3011190 = 0xb00
Unassigned mem write f3011190 = 0x900
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x300
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x300
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x300
Unassigned mem read f3011190
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x300
Unassigned mem read f3011190
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x300
Unassigned mem read f3011190
Unassigned mem write f3011190 = 0x100
Unassigned mem write f3011190 = 0x300
Unassigned

QEMU | Pipeline #160886695 has failed for master | e7651153

2020-06-28 Thread GitLab via


Your pipeline has failed.

Project: QEMU ( https://gitlab.com/qemu-project/qemu )
Branch: master ( https://gitlab.com/qemu-project/qemu/-/commits/master )

Commit: e7651153 ( 
https://gitlab.com/qemu-project/qemu/-/commit/e7651153a8801dad6805d450ea8bef9b46c1adf5
 )
Commit Message: Merge remote-tracking branch 'remotes/amarkovic...
Commit Author: Peter Maydell ( https://gitlab.com/pm215 )

Pipeline #160886695 ( 
https://gitlab.com/qemu-project/qemu/-/pipelines/160886695 ) triggered by Alex 
Bennée ( https://gitlab.com/stsquad )
had 2 failed builds.

Job #614631322 ( https://gitlab.com/qemu-project/qemu/-/jobs/614631322/raw )

Stage: test
Name: build-disabled
Trace: qemu-system-i386: falling back to tcg
Could not access KVM kernel module: No such file or directory
qemu-system-i386: -accel kvm: failed to initialize kvm: No such file or 
directory
qemu-system-i386: falling back to tcg
Could not access KVM kernel module: No such file or directory
qemu-system-i386: -accel kvm: failed to initialize kvm: No such file or 
directory
qemu-system-i386: falling back to tcg
  TESTcheck-qtest-i386: tests/qtest/device-introspect-test
  TESTcheck-qtest-i386: tests/qtest/machine-none-test
  TESTcheck-qtest-i386: tests/qtest/qmp-test
  TESTcheck-qtest-i386: tests/qtest/qmp-cmd-test
  TESTcheck-qtest-i386: tests/qtest/qom-test
  TESTcheck-qtest-i386: tests/qtest/test-hmp
  TESTcheck-qtest-i386: tests/qtest/qos-test
  TESTcheck-qtest-mips64: tests/qtest/endianness-test
  TESTcheck-qtest-mips64: tests/qtest/display-vga-test
  TESTcheck-qtest-mips64: tests/qtest/cdrom-test
  TESTcheck-qtest-mips64: tests/qtest/device-introspect-test
  TESTcheck-qtest-mips64: tests/qtest/machine-none-test
  TESTcheck-qtest-mips64: tests/qtest/qmp-test
  TESTcheck-qtest-mips64: tests/qtest/qmp-cmd-test
  TESTcheck-qtest-mips64: tests/qtest/qom-test
  TESTcheck-qtest-mips64: tests/qtest/test-hmp
  TESTcheck-qtest-mips64: tests/qtest/qos-test
  TESTcheck-qtest-ppc64: tests/qtest/machine-none-test
  TESTcheck-qtest-ppc64: tests/qtest/qmp-test
  TESTcheck-qtest-ppc64: tests/qtest/qmp-cmd-test
  TESTcheck-qtest-ppc64: tests/qtest/qom-test
section_end:1593355801:step_script
ERROR: Job failed: execution took longer than 1h0m0s seconds


Job #614631323 ( https://gitlab.com/qemu-project/qemu/-/jobs/614631323/raw )

Stage: test
Name: build-tcg-disabled
Trace: 208  ...[14:12:05] ...  
208  pass   [14:12:05] [14:12:06]   1s   
209  ...[14:12:06] ...  
209  pass   [14:12:06] [14:12:06]   0s   
215  ...[14:12:06] ...  
215  pass   [14:12:06] [14:13:34]  87s   
216  ...[14:13:34] ...  
216  pass   [14:13:34] [14:13:38]   4s   
218  ...[14:13:38] ...  
218  pass   [14:13:38] [14:13:40]   2s   
222  ...[14:13:40] ...  
222  pass   [14:13:40] [14:13:41]   1s   
227  ...[14:13:41] ...  
227  pass   [14:13:41] [14:13:41]   0s   
234  ...[14:13:41] ...  
234  pass   [14:13:41] [14:13:42]   1s   
246  ...[14:13:42] ...  
246  pass   [14:13:42] [14:13:43]   1s   
247  ...[14:13:43] ...  
247  pass   [14:13:43] [14:13:44]   1s   
248  ...[14:13:44] ...  
248  pass   [14:13:44] [14:13:44]   0s   
250  ...[14:13:44] ...  
250  pass   [14:13:44] [14:13:45]   1s   
254  ...[14:13:45] ...  
254  pass   [14:13:45] [14:13:45]   0s   
255  ...[14:13:45] ...  
255  pass   [14:13:45] [14:13:47]   2s   
257  ...[14:13:47] ...  
257  pass   [14:13:47] [14:13:58]  11s   
258  ...[14:13:58] ...  
258  pass   [14:13:58] [14:13:58]   0s   
260  ...[14:13:58] ...  
260  pass   [14:13:58] [14:13:59]   1s   
261  ...[14:13:59] ...  
261  pass   [14:13:59] [14:14:25]  26s   
262  ...[14:14:25] ...  
262  pass   [14:14:25] [14:14:25]   0s   
263  ...[14:14:26] 

Re: [RFC v2 1/1] memory: Delete assertion in memory_region_unregister_iommu_notifier

2020-06-28 Thread Peter Xu
On Sun, Jun 28, 2020 at 03:03:41PM +0800, Jason Wang wrote:
> 
> On 2020/6/27 上午5:29, Peter Xu wrote:
> > Hi, Eugenio,
> > 
> > (CCing Eric, Yan and Michael too)
> > 
> > On Fri, Jun 26, 2020 at 08:41:22AM +0200, Eugenio Pérez wrote:
> > > diff --git a/memory.c b/memory.c
> > > index 2f15a4b250..7f789710d2 100644
> > > --- a/memory.c
> > > +++ b/memory.c
> > > @@ -1915,8 +1915,6 @@ void memory_region_notify_one(IOMMUNotifier 
> > > *notifier,
> > >   return;
> > >   }
> > > -assert(entry->iova >= notifier->start && entry_end <= notifier->end);
> > I can understand removing the assertion should solve the issue, however imho
> > the major issue is not about this single assertion but the whole addr_mask
> > issue behind with virtio...
> 
> 
> I don't get here, it looks to the the range was from guest IOMMU drivers.

Yes.  Note that I didn't mean that it's a problem in virtio, it's just the fact
that virtio is the only one I know that would like to support arbitrary address
range for the translated region.  I don't know about tcg, but vfio should still
need some kind of page alignment in both the address and the addr_mask.  We
have that assumption too across the memory core when we do translations.

A further cause of the issue is the MSI region when vIOMMU enabled - currently
we implemented the interrupt region using another memory region so it split the
whole DMA region into two parts.  That's really a clean approach to IR
implementation, however that's also a burden to the invalidation part because
then we'll need to handle things like this when the listened range is not page
alighed at all (neither 0-0xfed, nor 0xfef-MAX).  If without the IR
region (so the whole iommu address range will be a single FlatRange), I think
we probably don't need most of the logic in vtd_address_space_unmap() at all,
then we can directly deliver all the IOTLB invalidations without splitting into
small page aligned ranges to all the iommu notifiers.  Sadly, so far I still
don't have ideal solution for it, because we definitely need IR.

> 
> 
> > 
> > For normal IOTLB invalidations, we were trying our best to always make
> > IOMMUTLBEntry contain a valid addr_mask to be 2**N-1.  E.g., that's what 
> > we're
> > doing with the loop in vtd_address_space_unmap().
> 
> 
> I'm sure such such assumption can work for any type of IOMMU.
> 
> 
> > 
> > But this is not the first time that we may want to break this assumption for
> > virtio so that we make the IOTLB a tuple of (start, len), then that len can 
> > be
> > not a address mask any more.  That seems to be more efficient for things 
> > like
> > vhost because iotlbs there are not page based, so it'll be inefficient if we
> > always guarantee the addr_mask because it'll be quite a lot more roundtrips 
> > of
> > the same range of invalidation.  Here we've encountered another issue of
> > triggering the assertion with virtio-net, but only with the old RHEL7 guest.
> > 
> > I'm thinking whether we can make the IOTLB invalidation configurable by
> > specifying whether the backend of the notifier can handle arbitary address
> > range in some way.  So we still have the guaranteed addr_masks by default
> > (since I still don't think totally break the addr_mask restriction is 
> > wise...),
> > however we can allow the special backends to take adavantage of using 
> > arbitary
> > (start, len) ranges for reasons like performance.
> > 
> > To do that, a quick idea is to introduce a flag 
> > IOMMU_NOTIFIER_ARBITRARY_MASK
> > to IOMMUNotifierFlag, to declare that the iommu notifier (and its backend) 
> > can
> > take arbitrary address mask, then it can be any value and finally becomes a
> > length rather than an addr_mask.  Then for every iommu notify() we can 
> > directly
> > deliver whatever we've got from the upper layer to this notifier.  With the 
> > new
> > flag, vhost can do iommu_notifier_init() with UNMAP|ARBITRARY_MASK so it
> > declares this capability.  Then no matter for device iotlb or normal iotlb, 
> > we
> > skip the complicated procedure to split a big range into small ranges that 
> > are
> > with strict addr_mask, but directly deliver the message to the iommu 
> > notifier.
> > E.g., we can skip the loop in vtd_address_space_unmap() if the notifier is 
> > with
> > ARBITRARY flag set.
> 
> 
> I'm not sure coupling IOMMU capability to notifier is the best choice.

IMHO it's not an IOMMU capability.  The flag I wanted to introduce is a
capability of the one who listens to the IOMMU TLB updates.  For our case, it's
virtio/vhost's capability to allow arbitrary length. The IOMMU itself
definitely has some limitation on the address range to be bound to an IOTLB
invalidation, e.g., the device-iotlb we're talking here only accept both the
iova address and addr_mask to be aligned to 2**N-1.

> 
> How about just convert to use a range [start, end] for any notifier and move
> the checks (e.g the assert) into the actual notifier implemented (vhost or
> vfio

Re: [PATCH 00/17] spitz: fix hacks, fix CID 1421913, various cleanups

2020-06-28 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20200628142429.17111-1-peter.mayd...@linaro.org/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Subject: [PATCH 00/17] spitz: fix hacks, fix CID 1421913, various cleanups
Type: series
Message-id: 20200628142429.17111-1-peter.mayd...@linaro.org

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

From https://github.com/patchew-project/qemu
   553cf5d..e765115  master -> master
From https://github.com/patchew-project/qemu
 * [new tag] patchew/20200628142429.17111-1-peter.mayd...@linaro.org -> 
patchew/20200628142429.17111-1-peter.mayd...@linaro.org
Switched to a new branch 'test'
108665c Replace uses of FROM_SSI_SLAVE() macro with QOM casts
6c99757 hw/arm/spitz: Provide usual QOM macros for corgi-ssp and spitz-lcdtg
98348e5 hw/arm/pxa2xx_pic: Use LOG_GUEST_ERROR for bad guest register accesses
0c5e2a2 hw/arm/spitz: Use LOG_GUEST_ERROR for bad guest register accesses
7856c52 hw/gpio/zaurus.c: Use LOG_GUEST_ERROR for bad guest register accesses
45b5766 hw/arm/spitz: Encapsulate misc GPIO handling in a device
7c67922 hw/misc/max111x: Create header file for documentation, TYPE_ macros
952c610 hw/misc/max111x: Use GPIO lines rather than max111x_set_input()
8febdff hw/arm/spitz: Use max111x properties to set initial values
9a1ed3c ssi: Add ssi_realize_and_unref()
efa4918 hw/misc/max111x: Don't use vmstate_register()
ccc835d hw/misc/max111x: provide QOM properties for setting initial values
9e5c852 hw/arm/spitz: Implement inbound GPIO lines for bit5 and power signals
0ec3ef7 hw/arm/spitz: Keep pointers to scp0, scp1 in SpitzMachineState
7be6379 hw/arm/spitz: Keep pointers to MPU and SSI devices in SpitzMachineState
8059a4e hw/arm/spitz: Create SpitzMachineClass abstract base class
736d97f hw/arm/spitz: Detabify

=== OUTPUT BEGIN ===
1/17 Checking commit 736d97fd84fb (hw/arm/spitz: Detabify)
ERROR: space prohibited before that '++' (ctx:WxB)
#110: FILE: hw/arm/spitz.c:303:
+#define QUEUE_KEY(c)s->fifo[(s->fifopos + s->fifolen ++) & 0xf] = c
  ^

ERROR: Macros with complex values should be enclosed in parenthesis
#110: FILE: hw/arm/spitz.c:303:
+#define QUEUE_KEY(c)s->fifo[(s->fifopos + s->fifolen ++) & 0xf] = c

total: 2 errors, 0 warnings, 259 lines checked

Patch 1/17 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

2/17 Checking commit 8059a4e54d2b (hw/arm/spitz: Create SpitzMachineClass 
abstract base class)
3/17 Checking commit 7be6379c8f45 (hw/arm/spitz: Keep pointers to MPU and SSI 
devices in SpitzMachineState)
4/17 Checking commit 0ec3ef7a8701 (hw/arm/spitz: Keep pointers to scp0, scp1 in 
SpitzMachineState)
5/17 Checking commit 9e5c852ff9ad (hw/arm/spitz: Implement inbound GPIO lines 
for bit5 and power signals)
WARNING: line over 80 characters
#94: FILE: hw/arm/spitz.c:859:
+  qdev_get_gpio_in_named(sms->lcdtg, "bl_power", 
0));

total: 0 errors, 1 warnings, 68 lines checked

Patch 5/17 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
6/17 Checking commit ccc835da8b9e (hw/misc/max111x: provide QOM properties for 
setting initial values)
7/17 Checking commit efa4918480f8 (hw/misc/max111x: Don't use 
vmstate_register())
8/17 Checking commit 9a1ed3c4a634 (ssi: Add ssi_realize_and_unref())
9/17 Checking commit 8febdffc3c42 (hw/arm/spitz: Use max111x properties to set 
initial values)
WARNING: Block comments use a leading /* on a separate line
#29: FILE: hw/arm/spitz.c:736:
+qdev_prop_set_uint8(sms->max, "input1" /* BATT_VOLT */,

WARNING: Block comments use a leading /* on a separate line
#31: FILE: hw/arm/spitz.c:738:
+qdev_prop_set_uint8(sms->max, "input2" /* BATT_TEMP */, 0);

WARNING: Block comments use a leading /* on a separate line
#32: FILE: hw/arm/spitz.c:739:
+qdev_prop_set_uint8(sms->max, "input3" /* ACIN_VOLT */,

total: 0 errors, 3 warnings, 18 lines checked

Patch 9/17 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
10/17 Checking commit 952c610248da (hw/misc/max111x: Use GPIO lines rather than 
max111x_set_input())
11/17 Checking commit 7c6792207add (hw/misc/max111x: Create header file for 
documentation, TYPE_ macros)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#94: 
new file mode 100644

total: 0 errors, 1 warnings, 114 lines checked

Patch 11/17 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHEC

Re: [PULL 00/63] riscv-to-apply queue

2020-06-28 Thread Peter Maydell
On Fri, 26 Jun 2020 at 22:53, Alistair Francis  wrote:
>
> The following changes since commit 553cf5d7c47bee05a3dec9461c1f8430316d516b:
>
>   Merge remote-tracking branch 
> 'remotes/pmaydell/tags/pull-target-arm-20200626' into staging (2020-06-26 
> 18:22:36 +0100)
>
> are available in the Git repository at:
>
>   g...@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20200626-1
>
> for you to fetch changes up to b39d59434ea10649fdb9e0a339c30c76e38c5e17:
>
>   target/riscv: configure and turn on vector extension from command line 
> (2020-06-26 14:22:15 -0700)
>
> 
> This PR contains two patches to improve PLIC support in QEMU.
>
> The rest of the PR is adding support for the v0.7.1 RISC-V vector
> extensions. This is experimental support as the vector extensions are
> still in a draft state.
>

Hi; I'm afraid this fails to build on PPC64 and s390x (ie
our big-endian hosts):

/home/ubuntu/qemu/target/riscv/vector_helper.c: In function ‘vext_clear’:
/home/ubuntu/qemu/target/riscv/vector_helper.c: In function ‘vext_clear’:
/home/ubuntu/qemu/target/riscv/vector_helper.c:154:21: error: invalid
operands to binary & (have ‘void *’ and ‘long long unsigned int’)
 memset(tail & ~(7ULL), 0, part1);
 ^
/home/ubuntu/qemu/target/riscv/vector_helper.c:155:27: error: invalid
operands to binary & (have ‘void *’ and ‘long long unsigned int’)
 memset((tail + 8) & ~(7ULL), 0, part2);
~~ ^
/home/ubuntu/qemu/target/riscv/vector_helper.c:154:21: error: invalid
operands to binary & (have ‘void *’ and ‘long long unsigned int’)
 memset(tail & ~(7ULL), 0, part1);
 ^
/home/ubuntu/qemu/target/riscv/vector_helper.c:155:27: error: invalid
operands to binary & (have ‘void *’ and ‘long long unsigned int’)
 memset((tail + 8) & ~(7ULL), 0, part2);
~~ ^
/home/ubuntu/qemu/rules.mak:69: recipe for target
'target/riscv/vector_helper.o' failed


thanks
-- PMM



Re: Crash when running Qemu.

2020-06-28 Thread Peter Maydell
On Sun, 28 Jun 2020 at 11:56, Jean-Christophe DUBOIS
 wrote:
> Since the last pull I did this week end on the qemu git tree (master
> branch) I am unable to "start" qemu anymore (It was working OK from git
> master previously).
>
> Traces are provided bellow.
>
> Am I the only one to get this behavior?
>
> JC
>
> jcd@jcd-UX305CA:~/Projects/µCOS/work$
> ../../qemu/qemu/arm-softmmu/qemu-system-arm -machine mcimx6ul-evk -m
> 128M -display none -serial stdio -kernel ./OS.elf
> double free or corruption (!prev)
> Abandon (core dumped)

I can't repro using your command line but without the -kernel option,
so it's probably specific to something your guest code is doing.
I tested with git commit e7651153a8801dad6; which commit are you
using?

Can you provide either the elf file or a repro example that
doesn't need it ?

thanks
-- PMM



[PATCH v2] ftgmac100: fix dblac write test

2020-06-28 Thread erik-smit
The test of the write of the dblac register was testing the old value
instead of the new value. This would accept the write of an invalid value
but subsequently refuse any following valid writes.

Signed-off-by: erik-smit 
---
Changes since v1:

Changed %ld to HWADDR_PRIx to fix building on mingw

 hw/net/ftgmac100.c | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
index 043ba61b86..b69e3dd14e 100644
--- a/hw/net/ftgmac100.c
+++ b/hw/net/ftgmac100.c
@@ -810,16 +810,18 @@ static void ftgmac100_write(void *opaque, hwaddr addr,
 s->phydata = value & 0x;
 break;
 case FTGMAC100_DBLAC: /* DMA Burst Length and Arbitration Control */
-if (FTGMAC100_DBLAC_TXDES_SIZE(s->dblac) < sizeof(FTGMAC100Desc)) {
+if (FTGMAC100_DBLAC_TXDES_SIZE(value) < sizeof(FTGMAC100Desc)) {
 qemu_log_mask(LOG_GUEST_ERROR,
-  "%s: transmit descriptor too small : %d bytes\n",
-  __func__, FTGMAC100_DBLAC_TXDES_SIZE(s->dblac));
+  "%s: transmit descriptor too small: %" HWADDR_PRIx
+  " bytes\n", __func__,
+  FTGMAC100_DBLAC_TXDES_SIZE(value));
 break;
 }
-if (FTGMAC100_DBLAC_RXDES_SIZE(s->dblac) < sizeof(FTGMAC100Desc)) {
+if (FTGMAC100_DBLAC_RXDES_SIZE(value) < sizeof(FTGMAC100Desc)) {
 qemu_log_mask(LOG_GUEST_ERROR,
-  "%s: receive descriptor too small : %d bytes\n",
-  __func__, FTGMAC100_DBLAC_RXDES_SIZE(s->dblac));
+  "%s: receive descriptor too small : %" HWADDR_PRIx
+  " bytes\n", __func__,
+  FTGMAC100_DBLAC_RXDES_SIZE(value));
 break;
 }
 s->dblac = value;
-- 
2.25.1




[PATCH 17/17] Replace uses of FROM_SSI_SLAVE() macro with QOM casts

2020-06-28 Thread Peter Maydell
The FROM_SSI_SLAVE() macro predates QOM and is used as a typesafe way
to cast from an SSISlave* to the instance struct of a subtype of
TYPE_SSI_SLAVE.  Switch to using the QOM cast macros instead, which
have the same effect (by writing the QOM macros if the types were
previously missing them.)

(The FROM_SSI_SLAVE() macro allows the SSISlave member of the
subtype's struct to be anywhere as long as it is named "ssidev",
whereas a QOM cast macro insists that it is the first thing in the
subtype's struct.  This is true for all the types we convert here.)

This removes all the uses of FROM_SSI_SLAVE() so we can delete the
definition.

Signed-off-by: Peter Maydell 
---
 include/hw/ssi/ssi.h |  2 --
 hw/arm/z2.c  | 11 +++
 hw/display/ads7846.c |  9 ++---
 hw/display/ssd0323.c | 10 +++---
 hw/sd/ssi-sd.c   |  4 ++--
 5 files changed, 22 insertions(+), 14 deletions(-)

diff --git a/include/hw/ssi/ssi.h b/include/hw/ssi/ssi.h
index 5fd411f2e4e..eac168aa1db 100644
--- a/include/hw/ssi/ssi.h
+++ b/include/hw/ssi/ssi.h
@@ -66,8 +66,6 @@ struct SSISlave {
 bool cs;
 };
 
-#define FROM_SSI_SLAVE(type, dev) DO_UPCAST(type, ssidev, dev)
-
 extern const VMStateDescription vmstate_ssi_slave;
 
 #define VMSTATE_SSI_SLAVE(_field, _state) {  \
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
index a0f40959904..e1f22f58681 100644
--- a/hw/arm/z2.c
+++ b/hw/arm/z2.c
@@ -111,9 +111,12 @@ typedef struct {
 int pos;
 } ZipitLCD;
 
+#define TYPE_ZIPIT_LCD "zipit-lcd"
+#define ZIPIT_LCD(obj) OBJECT_CHECK(ZipitLCD, (obj), TYPE_ZIPIT_LCD)
+
 static uint32_t zipit_lcd_transfer(SSISlave *dev, uint32_t value)
 {
-ZipitLCD *z = FROM_SSI_SLAVE(ZipitLCD, dev);
+ZipitLCD *z = ZIPIT_LCD(dev);
 uint16_t val;
 if (z->selected) {
 z->buf[z->pos] = value & 0xff;
@@ -153,7 +156,7 @@ static void z2_lcd_cs(void *opaque, int line, int level)
 
 static void zipit_lcd_realize(SSISlave *dev, Error **errp)
 {
-ZipitLCD *z = FROM_SSI_SLAVE(ZipitLCD, dev);
+ZipitLCD *z = ZIPIT_LCD(dev);
 z->selected = 0;
 z->enabled = 0;
 z->pos = 0;
@@ -185,7 +188,7 @@ static void zipit_lcd_class_init(ObjectClass *klass, void 
*data)
 }
 
 static const TypeInfo zipit_lcd_info = {
-.name  = "zipit-lcd",
+.name  = TYPE_ZIPIT_LCD,
 .parent= TYPE_SSI_SLAVE,
 .instance_size = sizeof(ZipitLCD),
 .class_init= zipit_lcd_class_init,
@@ -325,7 +328,7 @@ static void z2_init(MachineState *machine)
 
 type_register_static(&zipit_lcd_info);
 type_register_static(&aer915_info);
-z2_lcd = ssi_create_slave(mpu->ssp[1], "zipit-lcd");
+z2_lcd = ssi_create_slave(mpu->ssp[1], TYPE_ZIPIT_LCD);
 bus = pxa2xx_i2c_bus(mpu->i2c[0]);
 i2c_create_slave(bus, TYPE_AER915, 0x55);
 wm = i2c_create_slave(bus, TYPE_WM8750, 0x1b);
diff --git a/hw/display/ads7846.c b/hw/display/ads7846.c
index 9228b40b1af..56bf82fe079 100644
--- a/hw/display/ads7846.c
+++ b/hw/display/ads7846.c
@@ -29,6 +29,9 @@ typedef struct {
 int output;
 } ADS7846State;
 
+#define TYPE_ADS7846 "ads7846"
+#define ADS7846(obj) OBJECT_CHECK(ADS7846State, (obj), TYPE_ADS7846)
+
 /* Control-byte bitfields */
 #define CB_PD0 (1 << 0)
 #define CB_PD1 (1 << 1)
@@ -61,7 +64,7 @@ static void ads7846_int_update(ADS7846State *s)
 
 static uint32_t ads7846_transfer(SSISlave *dev, uint32_t value)
 {
-ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, dev);
+ADS7846State *s = ADS7846(dev);
 
 switch (s->cycle ++) {
 case 0:
@@ -139,7 +142,7 @@ static const VMStateDescription vmstate_ads7846 = {
 static void ads7846_realize(SSISlave *d, Error **errp)
 {
 DeviceState *dev = DEVICE(d);
-ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, d);
+ADS7846State *s = ADS7846(d);
 
 qdev_init_gpio_out(dev, &s->interrupt, 1);
 
@@ -166,7 +169,7 @@ static void ads7846_class_init(ObjectClass *klass, void 
*data)
 }
 
 static const TypeInfo ads7846_info = {
-.name  = "ads7846",
+.name  = TYPE_ADS7846,
 .parent= TYPE_SSI_SLAVE,
 .instance_size = sizeof(ADS7846State),
 .class_init= ads7846_class_init,
diff --git a/hw/display/ssd0323.c b/hw/display/ssd0323.c
index c3bdb18742c..32d27f008ae 100644
--- a/hw/display/ssd0323.c
+++ b/hw/display/ssd0323.c
@@ -66,9 +66,13 @@ typedef struct {
 uint8_t framebuffer[128 * 80 / 2];
 } ssd0323_state;
 
+#define TYPE_SSD0323 "ssd0323"
+#define SSD0323(obj) OBJECT_CHECK(ssd0323_state, (obj), TYPE_SSD0323)
+
+
 static uint32_t ssd0323_transfer(SSISlave *dev, uint32_t data)
 {
-ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, dev);
+ssd0323_state *s = SSD0323(dev);
 
 switch (s->mode) {
 case SSD0323_DATA:
@@ -346,7 +350,7 @@ static const GraphicHwOps ssd0323_ops = {
 static void ssd0323_realize(SSISlave *d, Error **errp)
 {
 DeviceState *dev = DEVICE(d);
-ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, d);
+ssd0323_state *s = SSD0323(d);
 
 s-

Re: [PATCH v5 09/11] macio: Add dummy screamer register area

2020-06-28 Thread BALATON Zoltan

On Sun, 28 Jun 2020, BALATON Zoltan wrote:

Here it is with --enable-debug and additional screamer debug:

SCREAMER: screamer_read: addr  -> 0
SCREAMER: screamer_write: addr  val 11
SCREAMER: screamer_control_write: val 17
SCREAMER: basic rate: 44100
DBDMA[10]: writel 0x080c <= 0x0010
DBDMA[10]: channel 0x10 reg 0x3
DBDMA[10]: dbdma_cmdptr_load 0x0010
DBDMA[10]: writel 0x0800 <= 0xf000
DBDMA[10]: channel 0x10 reg 0x0
DBDMA[10]:  Clearing RUN !
DBDMA[10]:  clearing PAUSE !
DBDMA[10]:   -> ACTIVE down !
DBDMA[10]:  new status=0x
SCREAMER: DMA TX flush!
DBDMA[10]: readl 0x0804 => 0x
DBDMA[10]: channel 0x10 reg 0x1
DBDMA[10]: writel 0x0800 <= 0xf0008000
DBDMA[10]: channel 0x10 reg 0x0
DBDMA[10]:  Setting RUN !
DBDMA[10]:  clearing PAUSE !
DBDMA[10]:  -> ACTIVE up !
DBDMA[10]:  new status=0x8400
DBDMA[10]: readl 0x0804 => 0x8400
DBDMA[10]: channel 0x10 reg 0x1
DBDMA: -> DBDMA_run_bh
DBDMA[10]: channel_run
DBDMA[10]: dbdma_cmd 0x56aac340
DBDMA[10]: req_count 0x8000
DBDMA[10]: command 0x
DBDMA[10]: phy_addr 0x0100
DBDMA[10]: cmd_dep 0x
DBDMA[10]: res_count 0x
DBDMA[10]: xfer_status 0x
DBDMA[10]: * OUTPUT_MORE *
DBDMA[10]: start_output
DBDMA[10]: addr 0x100 key 0x0
SCREAMER: DMA TX defer interrupt!
DBDMA: <- DBDMA_run_bh
SCREAMER: Processing deferred buffer
SCREAMER: DMA TX transfer: addr 100 len: 8000  bpos: 0

Thread 1 "qemu-system-ppc" received signal SIGSEGV, Segmentation fault.
0x94ff7c19 in ?? ()

(gdb) bt
#0  0x94ff7c19 in  ()
#1  0x55acb1e2 in pmac_screamer_tx_transfer (io=0x56ab1a98) at 
hw/audio/screamer.c:79
#2  0x55acb4dd in screamerspk_callback (opaque=0x56aad630, 
avail=16384) at hw/audio/screamer.c:155
#3  0x55a6af3d in audio_run_out (s=0x56b12bd0) at 
audio/audio.c:1181
#4  0x55a6b886 in audio_run (s=0x56b12bd0, msg=0x5609d4a9 
"alsa run (prepared)") at audio/audio.c:1372
#5  0x55d00ce9 in alsa_poll_handler (opaque=0x57959c60) at 
audio/alsaaudio.c:199
#6  0x55e57079 in aio_dispatch_handler (ctx=0x567257f0, 
node=0x57a0c6b0) at util/aio-posix.c:328
#7  0x55e57232 in aio_dispatch_handlers (ctx=0x567257f0) at 
util/aio-posix.c:371
#8  0x55e57288 in aio_dispatch (ctx=0x567257f0) at 
util/aio-posix.c:381
#9  0x55e6d373 in aio_ctx_dispatch (source=0x567257f0, 
callback=0x0, user_data=0x0) at util/async.c:306
#10 0x77cc6665 in g_main_context_dispatch () at 
/lib64/libglib-2.0.so.0

#11 0x55e74898 in glib_pollfds_poll () at util/main-loop.c:219
#12 0x55e74912 in os_host_main_loop_wait (timeout=28915159) at 
util/main-loop.c:242
#13 0x55e74a17 in main_loop_wait (nonblocking=0) at 
util/main-loop.c:518

#14 0x55981d35 in qemu_main_loop () at qemu/softmmu/vl.c:1664
#15 0x55df59dc in main (argc=17, argv=0x7fffdf28, 
envp=0x7fffdfb8) at qemu/softmmu/main.c:49

(gdb) up
#1  0x55acb1e2 in pmac_screamer_tx_transfer (io=0x56ab1a98) at 
hw/audio/screamer.c:79

79  io->dma_end(io);
(gdb) p/x *io
$1 = {opaque = 0xa2140923, channel = 0x79130821, addr = 0x14137e1f, len = 
0x0, is_last = 0x0, is_dma_out = 0x3408f81a, dma_end = 0x94ff7c19, processing 
= 0x19,  dma_mem = 0x53f5351b, dma_len = 0xc7f99f1e, dir = 0x21fbe921}


Looks like dma_end is not pointing to the expected end procedure. Maybe 
something has overwritten it?


Looks like the dma op itself corrupts the struct:

(gdb) b pmac_screamer_tx_transfer
Breakpoint 1 at 0x55acb12c: file hw/audio/screamer.c, line 66.
[...]
DBDMA: -> DBDMA_run_bh
DBDMA[10]: channel_run
DBDMA[10]: dbdma_cmd 0x56aac340
DBDMA[10]: req_count 0x8000
DBDMA[10]: command 0x
DBDMA[10]: phy_addr 0x0100
DBDMA[10]: cmd_dep 0x
DBDMA[10]: res_count 0x
DBDMA[10]: xfer_status 0x
DBDMA[10]: * OUTPUT_MORE *
DBDMA[10]: start_output
DBDMA[10]: addr 0x100 key 0x0
SCREAMER: DMA TX defer interrupt!
DBDMA: <- DBDMA_run_bh
SCREAMER: Processing deferred buffer

Thread 1 "qemu-system-ppc" hit Breakpoint 1, pmac_screamer_tx_transfer 
(io=0x56ab1a98) at hw/audio/screamer.c:66

66  ScreamerState *s = io->opaque;
(gdb) p/x *io
$4 = {opaque = 0x56aad630, channel = 0x56aac290, addr = 0x100, len = 
0x8000, is_last = 0x0, is_dma_out = 0x1, dma_end = 0x55b7d2aa, processing = 
0x1, dma_mem = 0x0, dma_len = 0x0, dir = 0x0}
(gdb) p dbdma_end
$5 = {void (DBDMA_io *)} 0x55b7d2aa 
(gdb) n
68  SCREAMER_DPRINTF("DMA TX transfer: addr %" HWADDR_PRIx
(gdb)
SCREAMER: DMA TX transfer: addr 100 len: 8000  bpos: 0
71	dma_memory_read(&address_space_memory, io->addr, 
&s->buf[s->bpos], io->len);

(gdb) n
73  s->bpos += io->len;
(gdb) p/x *io
$6 = {opaque = 0xa2140923, channel = 0x79130821, addr = 0x14137e1f, len = 
0x60f3d1d, is_last = 0x0, is_dma_out 

[PATCH 16/17] hw/arm/spitz: Provide usual QOM macros for corgi-ssp and spitz-lcdtg

2020-06-28 Thread Peter Maydell
The QOM types "spitz-lcdtg" and "corgi-ssp" are missing the
usual QOM TYPE and casting macros; provide and use them.

In particular, we can safely use the QOM cast macros instead of
FROM_SSI_SLAVE() because in both cases the 'ssidev' field of
the instance state struct is the first field in it.

Signed-off-by: Peter Maydell 
---
 hw/arm/spitz.c | 23 +++
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index 49eae3fce4e..f020aff9747 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -579,6 +579,9 @@ static void spitz_keyboard_realize(DeviceState *dev, Error 
**errp)
 #define LCDTG_PICTRL0x06
 #define LCDTG_POLCTRL   0x07
 
+#define TYPE_SPITZ_LCDTG "spitz-lcdtg"
+#define SPITZ_LCDTG(obj) OBJECT_CHECK(SpitzLCDTG, (obj), TYPE_SPITZ_LCDTG)
+
 typedef struct {
 SSISlave ssidev;
 uint32_t bl_intensity;
@@ -616,7 +619,7 @@ static inline void spitz_bl_power(void *opaque, int line, 
int level)
 
 static uint32_t spitz_lcdtg_transfer(SSISlave *dev, uint32_t value)
 {
-SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev);
+SpitzLCDTG *s = SPITZ_LCDTG(dev);
 int addr;
 addr = value >> 5;
 value &= 0x1f;
@@ -645,7 +648,7 @@ static uint32_t spitz_lcdtg_transfer(SSISlave *dev, 
uint32_t value)
 
 static void spitz_lcdtg_realize(SSISlave *ssi, Error **errp)
 {
-SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, ssi);
+SpitzLCDTG *s = SPITZ_LCDTG(ssi);
 DeviceState *dev = DEVICE(s);
 
 s->bl_power = 0;
@@ -664,6 +667,9 @@ static void spitz_lcdtg_realize(SSISlave *ssi, Error **errp)
 #define SPITZ_GPIO_MAX_CS   20
 #define SPITZ_GPIO_TP_INT   11
 
+#define TYPE_CORGI_SSP "corgi-ssp"
+#define CORGI_SSP(obj) OBJECT_CHECK(CorgiSSPState, (obj), TYPE_CORGI_SSP)
+
 /* "Demux" the signal based on current chipselect */
 typedef struct {
 SSISlave ssidev;
@@ -673,7 +679,7 @@ typedef struct {
 
 static uint32_t corgi_ssp_transfer(SSISlave *dev, uint32_t value)
 {
-CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, dev);
+CorgiSSPState *s = CORGI_SSP(dev);
 int i;
 
 for (i = 0; i < 3; i++) {
@@ -702,7 +708,7 @@ static void corgi_ssp_gpio_cs(void *opaque, int line, int 
level)
 static void corgi_ssp_realize(SSISlave *d, Error **errp)
 {
 DeviceState *dev = DEVICE(d);
-CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, d);
+CorgiSSPState *s = CORGI_SSP(d);
 
 qdev_init_gpio_in(dev, corgi_ssp_gpio_cs, 3);
 s->bus[0] = ssi_create_bus(dev, "ssi0");
@@ -714,10 +720,11 @@ static void spitz_ssp_attach(SpitzMachineState *sms)
 {
 void *bus;
 
-sms->mux = ssi_create_slave(sms->mpu->ssp[CORGI_SSP_PORT - 1], 
"corgi-ssp");
+sms->mux = ssi_create_slave(sms->mpu->ssp[CORGI_SSP_PORT - 1],
+TYPE_CORGI_SSP);
 
 bus = qdev_get_child_bus(sms->mux, "ssi0");
-sms->lcdtg = ssi_create_slave(bus, "spitz-lcdtg");
+sms->lcdtg = ssi_create_slave(bus, TYPE_SPITZ_LCDTG);
 
 bus = qdev_get_child_bus(sms->mux, "ssi1");
 sms->ads7846 = ssi_create_slave(bus, "ads7846");
@@ -1220,7 +1227,7 @@ static void corgi_ssp_class_init(ObjectClass *klass, void 
*data)
 }
 
 static const TypeInfo corgi_ssp_info = {
-.name  = "corgi-ssp",
+.name  = TYPE_CORGI_SSP,
 .parent= TYPE_SSI_SLAVE,
 .instance_size = sizeof(CorgiSSPState),
 .class_init= corgi_ssp_class_init,
@@ -1249,7 +1256,7 @@ static void spitz_lcdtg_class_init(ObjectClass *klass, 
void *data)
 }
 
 static const TypeInfo spitz_lcdtg_info = {
-.name  = "spitz-lcdtg",
+.name  = TYPE_SPITZ_LCDTG,
 .parent= TYPE_SSI_SLAVE,
 .instance_size = sizeof(SpitzLCDTG),
 .class_init= spitz_lcdtg_class_init,
-- 
2.20.1




[PATCH 13/17] hw/gpio/zaurus.c: Use LOG_GUEST_ERROR for bad guest register accesses

2020-06-28 Thread Peter Maydell
Instead of logging guest accesses to invalid register offsets in this
device using zaurus_printf() (which just prints to stderr), use the
usual qemu_log_mask(LOG_GUEST_ERROR,...).

Since this was the only use of the zaurus_printf() macro outside
spitz.c, we can move the definition of that macro from sharpsl.h
to spitz.c.

Signed-off-by: Peter Maydell 
---
 include/hw/arm/sharpsl.h |  3 ---
 hw/arm/spitz.c   |  3 +++
 hw/gpio/zaurus.c | 12 +++-
 3 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/include/hw/arm/sharpsl.h b/include/hw/arm/sharpsl.h
index 89e168fbff3..e986b28c527 100644
--- a/include/hw/arm/sharpsl.h
+++ b/include/hw/arm/sharpsl.h
@@ -9,9 +9,6 @@
 
 #include "exec/hwaddr.h"
 
-#define zaurus_printf(format, ...) \
-fprintf(stderr, "%s: " format, __func__, ##__VA_ARGS__)
-
 /* zaurus.c */
 
 #define SL_PXA_PARAM_BASE  0xaa00
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index bab9968ccee..6eb46869157 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -62,6 +62,9 @@ typedef struct {
 #define SPITZ_MACHINE_CLASS(klass) \
 OBJECT_CLASS_CHECK(SpitzMachineClass, klass, TYPE_SPITZ_MACHINE)
 
+#define zaurus_printf(format, ...)  \
+fprintf(stderr, "%s: " format, __func__, ##__VA_ARGS__)
+
 #undef REG_FMT
 #define REG_FMT "0x%02lx"
 
diff --git a/hw/gpio/zaurus.c b/hw/gpio/zaurus.c
index 9a12c683420..258e9264930 100644
--- a/hw/gpio/zaurus.c
+++ b/hw/gpio/zaurus.c
@@ -22,9 +22,7 @@
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
 #include "qemu/module.h"
-
-#undef REG_FMT
-#define REG_FMT"0x%02lx"
+#include "qemu/log.h"
 
 /* SCOOP devices */
 
@@ -104,7 +102,9 @@ static uint64_t scoop_read(void *opaque, hwaddr addr,
 case SCOOP_GPRR:
 return s->gpio_level;
 default:
-zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned 
long)addr);
+qemu_log_mask(LOG_GUEST_ERROR,
+  "scoop_read: bad register offset 0x%02" HWADDR_PRIx "\n",
+  addr);
 }
 
 return 0;
@@ -150,7 +150,9 @@ static void scoop_write(void *opaque, hwaddr addr,
 scoop_gpio_handler_update(s);
 break;
 default:
-zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned 
long)addr);
+qemu_log_mask(LOG_GUEST_ERROR,
+  "scoop_write: bad register offset 0x%02" HWADDR_PRIx 
"\n",
+  addr);
 }
 }
 
-- 
2.20.1




[PATCH 14/17] hw/arm/spitz: Use LOG_GUEST_ERROR for bad guest register accesses

2020-06-28 Thread Peter Maydell
Instead of logging guest accesses to invalid register offsets in the
Spitz flash device with zaurus_printf() (which just prints to stderr),
use the usual qemu_log_mask(LOG_GUEST_ERROR,...).

Signed-off-by: Peter Maydell 
---
 hw/arm/spitz.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index 6eb46869157..49eae3fce4e 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -23,6 +23,7 @@
 #include "hw/ssi/ssi.h"
 #include "hw/block/flash.h"
 #include "qemu/timer.h"
+#include "qemu/log.h"
 #include "hw/arm/sharpsl.h"
 #include "ui/console.h"
 #include "hw/audio/wm8750.h"
@@ -65,9 +66,6 @@ typedef struct {
 #define zaurus_printf(format, ...)  \
 fprintf(stderr, "%s: " format, __func__, ##__VA_ARGS__)
 
-#undef REG_FMT
-#define REG_FMT "0x%02lx"
-
 /* Spitz Flash */
 #define FLASH_BASE  0x0c00
 #define FLASH_ECCLPLB   0x00/* Line parity 7 - 0 bit */
@@ -137,7 +135,9 @@ static uint64_t sl_read(void *opaque, hwaddr addr, unsigned 
size)
 return ecc_digest(&s->ecc, nand_getio(s->nand));
 
 default:
-zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned 
long)addr);
+qemu_log_mask(LOG_GUEST_ERROR,
+  "sl_read: bad register offset 0x%02" HWADDR_PRIx "\n",
+  addr);
 }
 return 0;
 }
@@ -168,7 +168,9 @@ static void sl_write(void *opaque, hwaddr addr,
 break;
 
 default:
-zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned 
long)addr);
+qemu_log_mask(LOG_GUEST_ERROR,
+  "sl_write: bad register offset 0x%02" HWADDR_PRIx "\n",
+  addr);
 }
 }
 
-- 
2.20.1




[PATCH 12/17] hw/arm/spitz: Encapsulate misc GPIO handling in a device

2020-06-28 Thread Peter Maydell
Currently we have a free-floating set of IRQs and a function
spitz_out_switch() which handle some miscellaneous GPIO lines for the
spitz board.  Encapsulate this behaviour in a simple QOM device.

At this point we can finally remove the 'max' global, because the
ADC battery-temperature value is now handled by the misc-gpio device
writing the value to its outbound "adc-temp" GPIO, which the board
code wires up to the appropriate inbound GPIO line on the max.

This commit also fixes Coverity issue CID 1421913 (which pointed out
that the 'outsignals' in spitz_scoop_gpio_setup() were leaked),
because it removes the use of the qemu_allocate_irqs() API from this
code entirely.

Signed-off-by: Peter Maydell 
---
 hw/arm/spitz.c | 129 +
 1 file changed, 87 insertions(+), 42 deletions(-)

diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index 1400a56729d..bab9968ccee 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -51,6 +51,7 @@ typedef struct {
 DeviceState *max;
 DeviceState *scp0;
 DeviceState *scp1;
+DeviceState *misc_gpio;
 } SpitzMachineState;
 
 #define TYPE_SPITZ_MACHINE "spitz-common"
@@ -658,8 +659,6 @@ static void spitz_lcdtg_realize(SSISlave *ssi, Error **errp)
 #define SPITZ_GPIO_MAX_CS   20
 #define SPITZ_GPIO_TP_INT   11
 
-static DeviceState *max;
-
 /* "Demux" the signal based on current chipselect */
 typedef struct {
 SSISlave ssidev;
@@ -695,18 +694,6 @@ static void corgi_ssp_gpio_cs(void *opaque, int line, int 
level)
 #define SPITZ_BATTERY_VOLT  0xd0/* About 4.0V */
 #define SPITZ_CHARGEON_ACIN 0x80/* About 5.0V */
 
-static void spitz_adc_temp_on(void *opaque, int line, int level)
-{
-int batt_temp;
-
-if (!max)
-return;
-
-batt_temp = level ? SPITZ_BATTERY_TEMP : 0;
-
-qemu_set_irq(qdev_get_gpio_in(max, MAX_BATT_TEMP), batt_temp);
-}
-
 static void corgi_ssp_realize(SSISlave *d, Error **errp)
 {
 DeviceState *dev = DEVICE(d);
@@ -734,7 +721,6 @@ static void spitz_ssp_attach(SpitzMachineState *sms)
 
 bus = qdev_get_child_bus(sms->mux, "ssi2");
 sms->max = qdev_new(TYPE_MAX_);
-max = sms->max;
 qdev_prop_set_uint8(sms->max, "input1" /* BATT_VOLT */,
 SPITZ_BATTERY_VOLT);
 qdev_prop_set_uint8(sms->max, "input2" /* BATT_TEMP */, 0);
@@ -810,27 +796,66 @@ static void spitz_akita_i2c_setup(PXA2xxState *cpu)
 
 /* Other peripherals */
 
-static void spitz_out_switch(void *opaque, int line, int level)
+/*
+ * Encapsulation of some miscellaneous GPIO line behaviour for the Spitz 
boards.
+ *
+ * QEMU interface:
+ *  + named GPIO inputs "green-led", "orange-led", "charging", "discharging":
+ *these currently just print messages that the line has been signalled
+ *  + named GPIO input "adc-temp-on": set to cause the battery-temperature
+ *value to be passed to the max111x ADC
+ *  + named GPIO output "adc-temp": the ADC value, to be wired up to the 
max111x
+ */
+#define TYPE_SPITZ_MISC_GPIO "spitz-misc-gpio"
+#define SPITZ_MISC_GPIO(obj) \
+OBJECT_CHECK(SpitzMiscGPIOState, (obj), TYPE_SPITZ_MISC_GPIO)
+
+typedef struct SpitzMiscGPIOState {
+SysBusDevice parent_obj;
+
+qemu_irq adc_value;
+} SpitzMiscGPIOState;
+
+static void spitz_misc_charging(void *opaque, int n, int level)
 {
-switch (line) {
-case 0:
-zaurus_printf("Charging %s.\n", level ? "off" : "on");
-break;
-case 1:
-zaurus_printf("Discharging %s.\n", level ? "on" : "off");
-break;
-case 2:
-zaurus_printf("Green LED %s.\n", level ? "on" : "off");
-break;
-case 3:
-zaurus_printf("Orange LED %s.\n", level ? "on" : "off");
-break;
-case 6:
-spitz_adc_temp_on(opaque, line, level);
-break;
-default:
-g_assert_not_reached();
-}
+zaurus_printf("Charging %s.\n", level ? "off" : "on");
+}
+
+static void spitz_misc_discharging(void *opaque, int n, int level)
+{
+zaurus_printf("Discharging %s.\n", level ? "off" : "on");
+}
+
+static void spitz_misc_green_led(void *opaque, int n, int level)
+{
+zaurus_printf("Green LED %s.\n", level ? "off" : "on");
+}
+
+static void spitz_misc_orange_led(void *opaque, int n, int level)
+{
+zaurus_printf("Orange LED %s.\n", level ? "off" : "on");
+}
+
+static void spitz_misc_adc_temp(void *opaque, int n, int level)
+{
+SpitzMiscGPIOState *s = SPITZ_MISC_GPIO(opaque);
+int batt_temp = level ? SPITZ_BATTERY_TEMP : 0;
+
+qemu_set_irq(s->adc_value, batt_temp);
+}
+
+static void spitz_misc_gpio_init(Object *obj)
+{
+SpitzMiscGPIOState *s = SPITZ_MISC_GPIO(obj);
+DeviceState *dev = DEVICE(obj);
+
+qdev_init_gpio_in_named(dev, spitz_misc_charging, "charging", 1);
+qdev_init_gpio_in_named(dev, spitz_misc_discharging, "discharging", 1);
+qdev_init_gpio_in_named(dev, spitz_misc_green_led, "green-led", 1);
+qdev_init_gpio_in_name

[PATCH 11/17] hw/misc/max111x: Create header file for documentation, TYPE_ macros

2020-06-28 Thread Peter Maydell
Create a header file for the hw/misc/max111x device, in the
usual modern style for QOM devices:
 * definition of the TYPE_ constants and macros
 * definition of the device's state struct so that it can
   be embedded in other structs if desired
 * documentation of the interface

This allows us to use TYPE_MAX_ in the spitz.c code rather
than the string "max".

Signed-off-by: Peter Maydell 
---
To be honest the main driver here is that I wanted a header
file to put the documentation comment in :-)
---
 include/hw/misc/max111x.h | 57 +++
 hw/arm/spitz.c|  3 ++-
 hw/misc/max111x.c | 25 +
 MAINTAINERS   |  1 +
 4 files changed, 61 insertions(+), 25 deletions(-)
 create mode 100644 include/hw/misc/max111x.h

diff --git a/include/hw/misc/max111x.h b/include/hw/misc/max111x.h
new file mode 100644
index 000..337ba63d588
--- /dev/null
+++ b/include/hw/misc/max111x.h
@@ -0,0 +1,57 @@
+/*
+ * Maxim MAX1110/ ADC chip emulation.
+ *
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Written by Andrzej Zaborowski 
+ *
+ * This code is licensed under the GNU GPLv2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#ifndef HW_MISC_MAX111X_H
+#define HW_MISC_MAX111X_H
+
+#include "hw/ssi/ssi.h"
+#include "hw/irq.h"
+
+/*
+ * This is a model of the Maxim MAX1110/ ADC chip, which for QEMU
+ * is an SSI slave device. It has either 4 (max1110) or 8 (max)
+ * 8-bit ADC channels.
+ *
+ * QEMU interface:
+ *  + GPIO inputs 0..3 (for max1110) or 0..7 (for max): set the value
+ *of each ADC input, as an unsigned 8-bit value
+ *  + GPIO output 0: interrupt line
+ *  + Properties "input0" to "input3" (max1110) or "input0" to "input7"
+ *(max): initial reset values for ADC inputs.
+ *
+ * Known bugs:
+ *  + the interrupt line is not correctly implemented, and will never
+ *be lowered once it has been asserted.
+ */
+typedef struct {
+SSISlave parent_obj;
+
+qemu_irq interrupt;
+/* Values of inputs at system reset (settable by QOM property) */
+uint8_t reset_input[8];
+
+uint8_t tb1, rb2, rb3;
+int cycle;
+
+uint8_t input[8];
+int inputs, com;
+} MAX111xState;
+
+#define TYPE_MAX_111X "max111x"
+
+#define MAX_111X(obj) \
+OBJECT_CHECK(MAX111xState, (obj), TYPE_MAX_111X)
+
+#define TYPE_MAX_1110 "max1110"
+#define TYPE_MAX_ "max"
+
+#endif
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index fa592aad6d6..1400a56729d 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -29,6 +29,7 @@
 #include "audio/audio.h"
 #include "hw/boards.h"
 #include "hw/sysbus.h"
+#include "hw/misc/max111x.h"
 #include "migration/vmstate.h"
 #include "exec/address-spaces.h"
 #include "cpu.h"
@@ -732,7 +733,7 @@ static void spitz_ssp_attach(SpitzMachineState *sms)
   qdev_get_gpio_in(sms->mpu->gpio, SPITZ_GPIO_TP_INT));
 
 bus = qdev_get_child_bus(sms->mux, "ssi2");
-sms->max = qdev_new("max");
+sms->max = qdev_new(TYPE_MAX_);
 max = sms->max;
 qdev_prop_set_uint8(sms->max, "input1" /* BATT_VOLT */,
 SPITZ_BATTERY_VOLT);
diff --git a/hw/misc/max111x.c b/hw/misc/max111x.c
index 3a5cb838445..d41cfd92a8d 100644
--- a/hw/misc/max111x.c
+++ b/hw/misc/max111x.c
@@ -11,34 +11,11 @@
  */
 
 #include "qemu/osdep.h"
-#include "hw/irq.h"
-#include "hw/ssi/ssi.h"
+#include "hw/misc/max111x.h"
 #include "migration/vmstate.h"
 #include "qemu/module.h"
 #include "hw/qdev-properties.h"
 
-typedef struct {
-SSISlave parent_obj;
-
-qemu_irq interrupt;
-/* Values of inputs at system reset (settable by QOM property) */
-uint8_t reset_input[8];
-
-uint8_t tb1, rb2, rb3;
-int cycle;
-
-uint8_t input[8];
-int inputs, com;
-} MAX111xState;
-
-#define TYPE_MAX_111X "max111x"
-
-#define MAX_111X(obj) \
-OBJECT_CHECK(MAX111xState, (obj), TYPE_MAX_111X)
-
-#define TYPE_MAX_1110 "max1110"
-#define TYPE_MAX_ "max"
-
 /* Control-byte bitfields */
 #define CB_PD0 (1 << 0)
 #define CB_PD1 (1 << 1)
diff --git a/MAINTAINERS b/MAINTAINERS
index 1b40446c739..550844d1514 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -787,6 +787,7 @@ F: hw/gpio/max7310.c
 F: hw/gpio/zaurus.c
 F: hw/misc/mst_fpga.c
 F: hw/misc/max111x.c
+F: include/hw/misc/max111x.h
 F: include/hw/arm/pxa.h
 F: include/hw/arm/sharpsl.h
 F: include/hw/display/tc6393xb.h
-- 
2.20.1




[PATCH 06/17] hw/misc/max111x: provide QOM properties for setting initial values

2020-06-28 Thread Peter Maydell
Add some QOM properties to the max111x ADC device to allow the
initial values to be configured. Currently this is done by
board code calling max111x_set_input() after it creates the
device, which doesn't work on system reset.

This requires us to implement a reset method for this device,
so while we're doing that make sure we reset the other parts
of the device state.

Signed-off-by: Peter Maydell 
---
 hw/misc/max111x.c | 57 ++-
 1 file changed, 47 insertions(+), 10 deletions(-)

diff --git a/hw/misc/max111x.c b/hw/misc/max111x.c
index 2b87bdee5b7..d0e5534e4f5 100644
--- a/hw/misc/max111x.c
+++ b/hw/misc/max111x.c
@@ -15,11 +15,15 @@
 #include "hw/ssi/ssi.h"
 #include "migration/vmstate.h"
 #include "qemu/module.h"
+#include "hw/qdev-properties.h"
 
 typedef struct {
 SSISlave parent_obj;
 
 qemu_irq interrupt;
+/* Values of inputs at system reset (settable by QOM property) */
+uint8_t reset_input[8];
+
 uint8_t tb1, rb2, rb3;
 int cycle;
 
@@ -135,16 +139,6 @@ static int max111x_init(SSISlave *d, int inputs)
 qdev_init_gpio_out(dev, &s->interrupt, 1);
 
 s->inputs = inputs;
-/* TODO: add a user interface for setting these */
-s->input[0] = 0xf0;
-s->input[1] = 0xe0;
-s->input[2] = 0xd0;
-s->input[3] = 0xc0;
-s->input[4] = 0xb0;
-s->input[5] = 0xa0;
-s->input[6] = 0x90;
-s->input[7] = 0x80;
-s->com = 0;
 
 vmstate_register(VMSTATE_IF(dev), VMSTATE_INSTANCE_ID_ANY,
  &vmstate_max111x, s);
@@ -168,11 +162,50 @@ void max111x_set_input(DeviceState *dev, int line, 
uint8_t value)
 s->input[line] = value;
 }
 
+static void max111x_reset(DeviceState *dev)
+{
+MAX111xState *s = MAX_111X(dev);
+int i;
+
+for (i = 0; i < s->inputs; i++) {
+s->input[i] = s->reset_input[i];
+}
+s->com = 0;
+s->tb1 = 0;
+s->rb2 = 0;
+s->rb3 = 0;
+s->cycle = 0;
+}
+
+static Property max1110_properties[] = {
+/* Reset values for ADC inputs */
+DEFINE_PROP_UINT8("input0", MAX111xState, reset_input[0], 0xf0),
+DEFINE_PROP_UINT8("input1", MAX111xState, reset_input[1], 0xe0),
+DEFINE_PROP_UINT8("input2", MAX111xState, reset_input[2], 0xd0),
+DEFINE_PROP_UINT8("input3", MAX111xState, reset_input[3], 0xc0),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static Property max_properties[] = {
+/* Reset values for ADC inputs */
+DEFINE_PROP_UINT8("input0", MAX111xState, reset_input[0], 0xf0),
+DEFINE_PROP_UINT8("input1", MAX111xState, reset_input[1], 0xe0),
+DEFINE_PROP_UINT8("input2", MAX111xState, reset_input[2], 0xd0),
+DEFINE_PROP_UINT8("input3", MAX111xState, reset_input[3], 0xc0),
+DEFINE_PROP_UINT8("input4", MAX111xState, reset_input[4], 0xb0),
+DEFINE_PROP_UINT8("input5", MAX111xState, reset_input[5], 0xa0),
+DEFINE_PROP_UINT8("input6", MAX111xState, reset_input[6], 0x90),
+DEFINE_PROP_UINT8("input7", MAX111xState, reset_input[7], 0x80),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static void max111x_class_init(ObjectClass *klass, void *data)
 {
 SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+DeviceClass *dc = DEVICE_CLASS(klass);
 
 k->transfer = max111x_transfer;
+dc->reset = max111x_reset;
 }
 
 static const TypeInfo max111x_info = {
@@ -186,8 +219,10 @@ static const TypeInfo max111x_info = {
 static void max1110_class_init(ObjectClass *klass, void *data)
 {
 SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+DeviceClass *dc = DEVICE_CLASS(klass);
 
 k->realize = max1110_realize;
+device_class_set_props(dc, max1110_properties);
 }
 
 static const TypeInfo max1110_info = {
@@ -199,8 +234,10 @@ static const TypeInfo max1110_info = {
 static void max_class_init(ObjectClass *klass, void *data)
 {
 SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+DeviceClass *dc = DEVICE_CLASS(klass);
 
 k->realize = max_realize;
+device_class_set_props(dc, max_properties);
 }
 
 static const TypeInfo max_info = {
-- 
2.20.1




[PATCH 09/17] hw/arm/spitz: Use max111x properties to set initial values

2020-06-28 Thread Peter Maydell
Use the new max111x qdev properties to set the initial input
values rather than calling max111x_set_input(); this means that
on system reset the inputs will correctly return to their initial
values.

Signed-off-by: Peter Maydell 
---
 hw/arm/spitz.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index 11e413723f4..93a25edcb5b 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -731,11 +731,14 @@ static void spitz_ssp_attach(SpitzMachineState *sms)
   qdev_get_gpio_in(sms->mpu->gpio, SPITZ_GPIO_TP_INT));
 
 bus = qdev_get_child_bus(sms->mux, "ssi2");
-sms->max = ssi_create_slave(bus, "max");
+sms->max = qdev_new("max");
 max = sms->max;
-max111x_set_input(sms->max, MAX_BATT_VOLT, SPITZ_BATTERY_VOLT);
-max111x_set_input(sms->max, MAX_BATT_TEMP, 0);
-max111x_set_input(sms->max, MAX_ACIN_VOLT, SPITZ_CHARGEON_ACIN);
+qdev_prop_set_uint8(sms->max, "input1" /* BATT_VOLT */,
+SPITZ_BATTERY_VOLT);
+qdev_prop_set_uint8(sms->max, "input2" /* BATT_TEMP */, 0);
+qdev_prop_set_uint8(sms->max, "input3" /* ACIN_VOLT */,
+SPITZ_CHARGEON_ACIN);
+ssi_realize_and_unref(sms->max, bus, &error_fatal);
 
 qdev_connect_gpio_out(sms->mpu->gpio, SPITZ_GPIO_LCDCON_CS,
 qdev_get_gpio_in(sms->mux, 0));
-- 
2.20.1




[PATCH 15/17] hw/arm/pxa2xx_pic: Use LOG_GUEST_ERROR for bad guest register accesses

2020-06-28 Thread Peter Maydell
Instead of using printf() for logging guest accesses to invalid
register offsets in the pxa2xx PIC device, use the usual
qemu_log_mask(LOG_GUEST_ERROR,...).

This was the only user of the REG_FMT macro in pxa.h, so we can
remove that.

Signed-off-by: Peter Maydell 
---
 include/hw/arm/pxa.h | 1 -
 hw/arm/pxa2xx_pic.c  | 9 +++--
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h
index f6dfb5c0cf0..8843e5f9107 100644
--- a/include/hw/arm/pxa.h
+++ b/include/hw/arm/pxa.h
@@ -184,7 +184,6 @@ struct PXA2xxI2SState {
 };
 
 # define PA_FMT"0x%08lx"
-# define REG_FMT   "0x" TARGET_FMT_plx
 
 PXA2xxState *pxa270_init(MemoryRegion *address_space, unsigned int sdram_size,
  const char *revision);
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
index 105c5e63f2f..ceee6aa48db 100644
--- a/hw/arm/pxa2xx_pic.c
+++ b/hw/arm/pxa2xx_pic.c
@@ -11,6 +11,7 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "qemu/module.h"
+#include "qemu/log.h"
 #include "cpu.h"
 #include "hw/arm/pxa.h"
 #include "hw/sysbus.h"
@@ -166,7 +167,9 @@ static uint64_t pxa2xx_pic_mem_read(void *opaque, hwaddr 
offset,
 case ICHP: /* Highest Priority register */
 return pxa2xx_pic_highest(s);
 default:
-printf("%s: Bad register offset " REG_FMT "\n", __func__, offset);
+qemu_log_mask(LOG_GUEST_ERROR,
+  "pxa2xx_pic_mem_read: bad register offset 0x%" 
HWADDR_PRIx
+  "\n", offset);
 return 0;
 }
 }
@@ -199,7 +202,9 @@ static void pxa2xx_pic_mem_write(void *opaque, hwaddr 
offset,
 s->priority[32 + ((offset - IPR32) >> 2)] = value & 0x803f;
 break;
 default:
-printf("%s: Bad register offset " REG_FMT "\n", __func__, offset);
+qemu_log_mask(LOG_GUEST_ERROR,
+  "pxa2xx_pic_mem_write: bad register offset 0x%"
+  HWADDR_PRIx "\n", offset);
 return;
 }
 pxa2xx_pic_update(opaque);
-- 
2.20.1




[PATCH 05/17] hw/arm/spitz: Implement inbound GPIO lines for bit5 and power signals

2020-06-28 Thread Peter Maydell
Currently the Spitz board uses a nasty hack for the GPIO lines
that pass "bit5" and "power" information to the LCD controller:
the lcdtg realize function sets a global variable to point to
the instance it just realized, and then the functions spitz_bl_power()
and spitz_bl_bit5() use that to find the device they are changing
the internal state of. There is a comment reading:
 FIXME: Implement GPIO properly and remove this hack.
which was added in 2009.

Implement GPIO properly and remove this hack.

Signed-off-by: Peter Maydell 
---
 hw/arm/spitz.c | 28 
 1 file changed, 12 insertions(+), 16 deletions(-)

diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index 69bc2b3fa10..11e413723f4 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -586,12 +586,9 @@ static void spitz_bl_update(SpitzLCDTG *s)
 zaurus_printf("LCD Backlight now off\n");
 }
 
-/* FIXME: Implement GPIO properly and remove this hack.  */
-static SpitzLCDTG *spitz_lcdtg;
-
 static inline void spitz_bl_bit5(void *opaque, int line, int level)
 {
-SpitzLCDTG *s = spitz_lcdtg;
+SpitzLCDTG *s = opaque;
 int prev = s->bl_intensity;
 
 if (level)
@@ -605,7 +602,7 @@ static inline void spitz_bl_bit5(void *opaque, int line, 
int level)
 
 static inline void spitz_bl_power(void *opaque, int line, int level)
 {
-SpitzLCDTG *s = spitz_lcdtg;
+SpitzLCDTG *s = opaque;
 s->bl_power = !!level;
 spitz_bl_update(s);
 }
@@ -639,13 +636,16 @@ static uint32_t spitz_lcdtg_transfer(SSISlave *dev, 
uint32_t value)
 return 0;
 }
 
-static void spitz_lcdtg_realize(SSISlave *dev, Error **errp)
+static void spitz_lcdtg_realize(SSISlave *ssi, Error **errp)
 {
-SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev);
+SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, ssi);
+DeviceState *dev = DEVICE(s);
 
-spitz_lcdtg = s;
 s->bl_power = 0;
 s->bl_intensity = 0x20;
+
+qdev_init_gpio_in_named(dev, spitz_bl_bit5, "bl_bit5", 1);
+qdev_init_gpio_in_named(dev, spitz_bl_power, "bl_power", 1);
 }
 
 /* SSP devices */
@@ -820,15 +820,11 @@ static void spitz_out_switch(void *opaque, int line, int 
level)
 case 3:
 zaurus_printf("Orange LED %s.\n", level ? "on" : "off");
 break;
-case 4:
-spitz_bl_bit5(opaque, line, level);
-break;
-case 5:
-spitz_bl_power(opaque, line, level);
-break;
 case 6:
 spitz_adc_temp_on(opaque, line, level);
 break;
+default:
+g_assert_not_reached();
 }
 }
 
@@ -858,9 +854,9 @@ static void spitz_scoop_gpio_setup(SpitzMachineState *sms)
 
 if (sms->scp1) {
 qdev_connect_gpio_out(sms->scp1, SPITZ_SCP2_BACKLIGHT_CONT,
-  outsignals[4]);
+  qdev_get_gpio_in_named(sms->lcdtg, "bl_bit5", 
0));
 qdev_connect_gpio_out(sms->scp1, SPITZ_SCP2_BACKLIGHT_ON,
-  outsignals[5]);
+  qdev_get_gpio_in_named(sms->lcdtg, "bl_power", 
0));
 }
 
 qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_ADC_TEMP_ON, outsignals[6]);
-- 
2.20.1




[PATCH 08/17] ssi: Add ssi_realize_and_unref()

2020-06-28 Thread Peter Maydell
Add an ssi_realize_and_unref(), for the benefit of callers
who want to be able to create an SSI device, set QOM properties
on it, and then do the realize-and-unref afterwards.

The API works on the same principle as the recently added
qdev_realize_and_undef(), sysbus_realize_and_undef(), etc.

Signed-off-by: Peter Maydell 
---
 include/hw/ssi/ssi.h | 26 ++
 hw/ssi/ssi.c |  7 ++-
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/include/hw/ssi/ssi.h b/include/hw/ssi/ssi.h
index 93f2b8b0beb..4be5325e654 100644
--- a/include/hw/ssi/ssi.h
+++ b/include/hw/ssi/ssi.h
@@ -79,6 +79,32 @@ extern const VMStateDescription vmstate_ssi_slave;
 }
 
 DeviceState *ssi_create_slave(SSIBus *bus, const char *name);
+/**
+ * ssi_realize_and_unref: realize and unref an SSI slave device
+ * @dev: SSI slave device to realize
+ * @bus: SSI bus to put it on
+ * @errp: error pointer
+ *
+ * Call 'realize' on @dev, put it on the specified @bus, and drop the
+ * reference to it. Errors are reported via @errp and by returning
+ * false.
+ *
+ * This function is useful if you have created @dev via qdev_new()
+ * (which takes a reference to the device it returns to you), so that
+ * you can set properties on it before realizing it. If you don't need
+ * to set properties then ssi_create_slave() is probably better (as it
+ * does the create, init and realize in one step).
+ *
+ * If you are embedding the SSI slave into another QOM device and
+ * initialized it via some variant on object_initialize_child() then
+ * do not use this function, because that family of functions arrange
+ * for the only reference to the child device to be held by the parent
+ * via the child<> property, and so the reference-count-drop done here
+ * would be incorrect.  (Instead you would want ssi_realize(), which
+ * doesn't currently exist but would be trivial to create if we had
+ * any code that wanted it.)
+ */
+bool ssi_realize_and_unref(DeviceState *dev, SSIBus *bus, Error **errp);
 
 /* Master interface.  */
 SSIBus *ssi_create_bus(DeviceState *parent, const char *name);
diff --git a/hw/ssi/ssi.c b/hw/ssi/ssi.c
index 67b48c31cd6..a35d7ebb266 100644
--- a/hw/ssi/ssi.c
+++ b/hw/ssi/ssi.c
@@ -90,11 +90,16 @@ static const TypeInfo ssi_slave_info = {
 .abstract = true,
 };
 
+bool ssi_realize_and_unref(DeviceState *dev, SSIBus *bus, Error **errp)
+{
+return qdev_realize_and_unref(dev, &bus->parent_obj, errp);
+}
+
 DeviceState *ssi_create_slave(SSIBus *bus, const char *name)
 {
 DeviceState *dev = qdev_new(name);
 
-qdev_realize_and_unref(dev, &bus->parent_obj, &error_fatal);
+ssi_realize_and_unref(dev, bus, &error_fatal);
 return dev;
 }
 
-- 
2.20.1




[PATCH 02/17] hw/arm/spitz: Create SpitzMachineClass abstract base class

2020-06-28 Thread Peter Maydell
For the four Spitz-family machines (akita, borzoi, spitz, terrier)
create a proper abstract class SpitzMachineClass which encapsulates
the common behaviour, rather than having them all derive directly
from TYPE_MACHINE:
 * instead of each machine class setting mc->init to a wrapper
   function which calls spitz_common_init() with parameters,
   put that data in the SpitzMachineClass and make spitz_common_init
   the SpitzMachineClass machine-init function
 * move the settings of mc->block_default_type and
   mc->ignore_memory_transaction_failures into the SpitzMachineClass
   class init rather than repeating them in each machine's class init

(The motivation is that we're going to want to keep some state in
the SpitzMachineState so we can connect GPIOs between devices created
in one sub-function of the machine init to devices created in a
different sub-function.)

Signed-off-by: Peter Maydell 
---
 hw/arm/spitz.c | 91 ++
 1 file changed, 55 insertions(+), 36 deletions(-)

diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index 9eaedab79b5..c70e912a33d 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -33,6 +33,26 @@
 #include "exec/address-spaces.h"
 #include "cpu.h"
 
+enum spitz_model_e { spitz, akita, borzoi, terrier };
+
+typedef struct {
+MachineClass parent;
+enum spitz_model_e model;
+int arm_id;
+} SpitzMachineClass;
+
+typedef struct {
+MachineState parent;
+} SpitzMachineState;
+
+#define TYPE_SPITZ_MACHINE "spitz-common"
+#define SPITZ_MACHINE(obj) \
+OBJECT_CHECK(SpitzMachineState, obj, TYPE_SPITZ_MACHINE)
+#define SPITZ_MACHINE_GET_CLASS(obj) \
+OBJECT_GET_CLASS(SpitzMachineClass, obj, TYPE_SPITZ_MACHINE)
+#define SPITZ_MACHINE_CLASS(klass) \
+OBJECT_CLASS_CHECK(SpitzMachineClass, klass, TYPE_SPITZ_MACHINE)
+
 #undef REG_FMT
 #define REG_FMT "0x%02lx"
 
@@ -905,8 +925,6 @@ static void spitz_gpio_setup(PXA2xxState *cpu, int slots)
 }
 
 /* Board init.  */
-enum spitz_model_e { spitz, akita, borzoi, terrier };
-
 #define SPITZ_RAM   0x0400
 #define SPITZ_ROM   0x0080
 
@@ -915,9 +933,10 @@ static struct arm_boot_info spitz_binfo = {
 .ram_size = 0x0400,
 };
 
-static void spitz_common_init(MachineState *machine,
-  enum spitz_model_e model, int arm_id)
+static void spitz_common_init(MachineState *machine)
 {
+SpitzMachineClass *smc = SPITZ_MACHINE_GET_CLASS(machine);
+enum spitz_model_e model = smc->model;
 PXA2xxState *mpu;
 DeviceState *scp0, *scp1 = NULL;
 MemoryRegion *address_space_mem = get_system_memory();
@@ -958,100 +977,100 @@ static void spitz_common_init(MachineState *machine,
 /* A 4.0 GB microdrive is permanently sitting in CF slot 0.  */
 spitz_microdrive_attach(mpu, 0);
 
-spitz_binfo.board_id = arm_id;
+spitz_binfo.board_id = smc->arm_id;
 arm_load_kernel(mpu->cpu, machine, &spitz_binfo);
 sl_bootparam_write(SL_PXA_PARAM_BASE);
 }
 
-static void spitz_init(MachineState *machine)
+static void spitz_common_class_init(ObjectClass *oc, void *data)
 {
-spitz_common_init(machine, spitz, 0x2c9);
+MachineClass *mc = MACHINE_CLASS(oc);
+
+mc->block_default_type = IF_IDE;
+mc->ignore_memory_transaction_failures = true;
+mc->init = spitz_common_init;
 }
 
-static void borzoi_init(MachineState *machine)
-{
-spitz_common_init(machine, borzoi, 0x33f);
-}
-
-static void akita_init(MachineState *machine)
-{
-spitz_common_init(machine, akita, 0x2e8);
-}
-
-static void terrier_init(MachineState *machine)
-{
-spitz_common_init(machine, terrier, 0x33f);
-}
+static const TypeInfo spitz_common_info = {
+.name = TYPE_SPITZ_MACHINE,
+.parent = TYPE_MACHINE,
+.abstract = true,
+.instance_size = sizeof(SpitzMachineState),
+.class_size = sizeof(SpitzMachineClass),
+.class_init = spitz_common_class_init,
+};
 
 static void akitapda_class_init(ObjectClass *oc, void *data)
 {
 MachineClass *mc = MACHINE_CLASS(oc);
+SpitzMachineClass *smc = SPITZ_MACHINE_CLASS(oc);
 
 mc->desc = "Sharp SL-C1000 (Akita) PDA (PXA270)";
-mc->init = akita_init;
-mc->ignore_memory_transaction_failures = true;
 mc->default_cpu_type = ARM_CPU_TYPE_NAME("pxa270-c0");
+smc->model = akita;
+smc->arm_id = 0x2e8;
 }
 
 static const TypeInfo akitapda_type = {
 .name = MACHINE_TYPE_NAME("akita"),
-.parent = TYPE_MACHINE,
+.parent = TYPE_SPITZ_MACHINE,
 .class_init = akitapda_class_init,
 };
 
 static void spitzpda_class_init(ObjectClass *oc, void *data)
 {
 MachineClass *mc = MACHINE_CLASS(oc);
+SpitzMachineClass *smc = SPITZ_MACHINE_CLASS(oc);
 
 mc->desc = "Sharp SL-C3000 (Spitz) PDA (PXA270)";
-mc->init = spitz_init;
-mc->block_default_type = IF_IDE;
-mc->ignore_memory_transaction_failures = true;
 mc->default_cpu_type = ARM_CPU_TYPE_NAME("pxa270-c0");
+smc->model = spitz;
+smc->arm_id = 0x2c9;
 }
 
 s

[PATCH 04/17] hw/arm/spitz: Keep pointers to scp0, scp1 in SpitzMachineState

2020-06-28 Thread Peter Maydell
Keep pointers to scp0, scp1 in SpitzMachineState, and just pass
that to spitz_scoop_gpio_setup().

(We'll want to use some of the other fields in SpitzMachineState
in that function in the next commit.)

Signed-off-by: Peter Maydell 
---
 hw/arm/spitz.c | 34 +++---
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index f48e966c047..69bc2b3fa10 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -48,6 +48,8 @@ typedef struct {
 DeviceState *lcdtg;
 DeviceState *ads7846;
 DeviceState *max;
+DeviceState *scp0;
+DeviceState *scp1;
 } SpitzMachineState;
 
 #define TYPE_SPITZ_MACHINE "spitz-common"
@@ -845,22 +847,23 @@ static void spitz_out_switch(void *opaque, int line, int 
level)
 #define SPITZ_SCP2_BACKLIGHT_ON 8
 #define SPITZ_SCP2_MIC_BIAS 9
 
-static void spitz_scoop_gpio_setup(PXA2xxState *cpu,
-DeviceState *scp0, DeviceState *scp1)
+static void spitz_scoop_gpio_setup(SpitzMachineState *sms)
 {
-qemu_irq *outsignals = qemu_allocate_irqs(spitz_out_switch, cpu, 8);
+qemu_irq *outsignals = qemu_allocate_irqs(spitz_out_switch, sms->mpu, 8);
 
-qdev_connect_gpio_out(scp0, SPITZ_SCP_CHRG_ON, outsignals[0]);
-qdev_connect_gpio_out(scp0, SPITZ_SCP_JK_B, outsignals[1]);
-qdev_connect_gpio_out(scp0, SPITZ_SCP_LED_GREEN, outsignals[2]);
-qdev_connect_gpio_out(scp0, SPITZ_SCP_LED_ORANGE, outsignals[3]);
+qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_CHRG_ON, outsignals[0]);
+qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_JK_B, outsignals[1]);
+qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_LED_GREEN, outsignals[2]);
+qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_LED_ORANGE, outsignals[3]);
 
-if (scp1) {
-qdev_connect_gpio_out(scp1, SPITZ_SCP2_BACKLIGHT_CONT, outsignals[4]);
-qdev_connect_gpio_out(scp1, SPITZ_SCP2_BACKLIGHT_ON, outsignals[5]);
+if (sms->scp1) {
+qdev_connect_gpio_out(sms->scp1, SPITZ_SCP2_BACKLIGHT_CONT,
+  outsignals[4]);
+qdev_connect_gpio_out(sms->scp1, SPITZ_SCP2_BACKLIGHT_ON,
+  outsignals[5]);
 }
 
-qdev_connect_gpio_out(scp0, SPITZ_SCP_ADC_TEMP_ON, outsignals[6]);
+qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_ADC_TEMP_ON, outsignals[6]);
 }
 
 #define SPITZ_GPIO_HSYNC22
@@ -943,7 +946,6 @@ static void spitz_common_init(MachineState *machine)
 SpitzMachineState *sms = SPITZ_MACHINE(machine);
 enum spitz_model_e model = smc->model;
 PXA2xxState *mpu;
-DeviceState *scp0, *scp1 = NULL;
 MemoryRegion *address_space_mem = get_system_memory();
 MemoryRegion *rom = g_new(MemoryRegion, 1);
 
@@ -962,12 +964,14 @@ static void spitz_common_init(MachineState *machine)
 
 spitz_ssp_attach(sms);
 
-scp0 = sysbus_create_simple("scoop", 0x1080, NULL);
+sms->scp0 = sysbus_create_simple("scoop", 0x1080, NULL);
 if (model != akita) {
-scp1 = sysbus_create_simple("scoop", 0x08800040, NULL);
+sms->scp1 = sysbus_create_simple("scoop", 0x08800040, NULL);
+} else {
+sms->scp1 = NULL;
 }
 
-spitz_scoop_gpio_setup(mpu, scp0, scp1);
+spitz_scoop_gpio_setup(sms);
 
 spitz_gpio_setup(mpu, (model == akita) ? 1 : 2);
 
-- 
2.20.1




[PATCH 10/17] hw/misc/max111x: Use GPIO lines rather than max111x_set_input()

2020-06-28 Thread Peter Maydell
The max111x ADC device model allows other code to set the level on
the 8 ADC inputs using the max111x_set_input() function.  Replace
this with generic qdev GPIO inputs, which also allow inputs to be set
to arbitrary values.

Using GPIO lines will make it easier for board code to wire things
up, so that if device A wants to set the ADC input it doesn't need to
have a direct pointer to the max111x but can just set that value on
its output GPIO, which is then wired up by the board to the
appropriate max111x input.

Signed-off-by: Peter Maydell 
---
 include/hw/ssi/ssi.h |  3 ---
 hw/arm/spitz.c   |  9 +
 hw/misc/max111x.c| 16 +---
 3 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/include/hw/ssi/ssi.h b/include/hw/ssi/ssi.h
index 4be5325e654..5fd411f2e4e 100644
--- a/include/hw/ssi/ssi.h
+++ b/include/hw/ssi/ssi.h
@@ -111,7 +111,4 @@ SSIBus *ssi_create_bus(DeviceState *parent, const char 
*name);
 
 uint32_t ssi_transfer(SSIBus *bus, uint32_t val);
 
-/* max111x.c */
-void max111x_set_input(DeviceState *dev, int line, uint8_t value);
-
 #endif
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index 93a25edcb5b..fa592aad6d6 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -696,13 +696,14 @@ static void corgi_ssp_gpio_cs(void *opaque, int line, int 
level)
 
 static void spitz_adc_temp_on(void *opaque, int line, int level)
 {
+int batt_temp;
+
 if (!max)
 return;
 
-if (level)
-max111x_set_input(max, MAX_BATT_TEMP, SPITZ_BATTERY_TEMP);
-else
-max111x_set_input(max, MAX_BATT_TEMP, 0);
+batt_temp = level ? SPITZ_BATTERY_TEMP : 0;
+
+qemu_set_irq(qdev_get_gpio_in(max, MAX_BATT_TEMP), batt_temp);
 }
 
 static void corgi_ssp_realize(SSISlave *d, Error **errp)
diff --git a/hw/misc/max111x.c b/hw/misc/max111x.c
index abddfa3c660..3a5cb838445 100644
--- a/hw/misc/max111x.c
+++ b/hw/misc/max111x.c
@@ -131,12 +131,21 @@ static const VMStateDescription vmstate_max111x = {
 }
 };
 
+static void max111x_input_set(void *opaque, int line, int value)
+{
+MAX111xState *s = MAX_111X(opaque);
+
+assert(line >= 0 && line < s->inputs);
+s->input[line] = value;
+}
+
 static int max111x_init(SSISlave *d, int inputs)
 {
 DeviceState *dev = DEVICE(d);
 MAX111xState *s = MAX_111X(dev);
 
 qdev_init_gpio_out(dev, &s->interrupt, 1);
+qdev_init_gpio_in(dev, max111x_input_set, inputs);
 
 s->inputs = inputs;
 
@@ -153,13 +162,6 @@ static void max_realize(SSISlave *dev, Error **errp)
 max111x_init(dev, 4);
 }
 
-void max111x_set_input(DeviceState *dev, int line, uint8_t value)
-{
-MAX111xState *s = MAX_111X(dev);
-assert(line >= 0 && line < s->inputs);
-s->input[line] = value;
-}
-
 static void max111x_reset(DeviceState *dev)
 {
 MAX111xState *s = MAX_111X(dev);
-- 
2.20.1




[PATCH 00/17] spitz: fix hacks, fix CID 1421913, various cleanups

2020-06-28 Thread Peter Maydell
This series of patches makes various cleanups to the spitz board
family code; the main driver here was fixing the minor Coverity
nit CID 1421913, which is a complaint that the call to
qemu_allocate_irqs() creates memory that is leaked.

We fix this by replacing the free-standing irq array and
callback function with a proper QOM device TYPE_SPITZ_MISC_GPIO,
which can have its own GPIO inputs and outputs which we can wire
up as appropriate. This also allows us to remove the ugly
file-scope variables that pointed to some of the devices on the
board so that the old callback function could prod them.

For this to work we need to add QOM properties and input GPIOs
to the max111x ADC devices so that we can control them that
way rather than by direct calls to max111x_set_input().
While we're in that bit of old code we take the opportunity to
get rid of its call to vmstate_register() and to give it a reset
method and a header file so we can document it a bit better.

The last few patches are unrelated cleanup that I noticed in
passing: we reduce the use of the zaurus_printf() macro in favour
of LOG_GUEST_ERROR logging for bad register accesess, and we
get rid of the old FROM_SSI_SLAVE which can be replaced with
QOM cast macros.

Patch 1 removes the hardcoded tabs in spitz.c, because they've
escaped our usual "fix as we touch a file" policy long enough,
and it's easier to do a wholesale detabify of the file before
starting.

As you review this series you might notice some other things in the
code that could also be cleaned up; so did I, but I felt that
17 patches was quite enough to be going on with :-)

thanks
-- PMM

Peter Maydell (17):
  hw/arm/spitz: Detabify
  hw/arm/spitz: Create SpitzMachineClass abstract base class
  hw/arm/spitz: Keep pointers to MPU and SSI devices in
SpitzMachineState
  hw/arm/spitz: Keep pointers to scp0, scp1 in SpitzMachineState
  hw/arm/spitz: Implement inbound GPIO lines for bit5 and power signals
  hw/misc/max111x: provide QOM properties for setting initial values
  hw/misc/max111x: Don't use vmstate_register()
  ssi: Add ssi_realize_and_unref()
  hw/arm/spitz: Use max111x properties to set initial values
  hw/misc/max111x: Use GPIO lines rather than max111x_set_input()
  hw/misc/max111x: Create header file for documentation, TYPE_ macros
  hw/arm/spitz: Encapsulate misc GPIO handling in a device
  hw/gpio/zaurus.c: Use LOG_GUEST_ERROR for bad guest register accesses
  hw/arm/spitz: Use LOG_GUEST_ERROR for bad guest register accesses
  hw/arm/pxa2xx_pic: Use LOG_GUEST_ERROR for bad guest register accesses
  hw/arm/spitz: Provide usual QOM macros for corgi-ssp and spitz-lcdtg
  Replace uses of FROM_SSI_SLAVE() macro with QOM casts

 include/hw/arm/pxa.h  |   1 -
 include/hw/arm/sharpsl.h  |   3 -
 include/hw/misc/max111x.h |  57 +
 include/hw/ssi/ssi.h  |  31 ++-
 hw/arm/pxa2xx_pic.c   |   9 +-
 hw/arm/spitz.c| 507 ++
 hw/arm/z2.c   |  11 +-
 hw/display/ads7846.c  |   9 +-
 hw/display/ssd0323.c  |  10 +-
 hw/gpio/zaurus.c  |  12 +-
 hw/misc/max111x.c |  87 ---
 hw/sd/ssi-sd.c|   4 +-
 hw/ssi/ssi.c  |   7 +-
 MAINTAINERS   |   1 +
 14 files changed, 474 insertions(+), 275 deletions(-)
 create mode 100644 include/hw/misc/max111x.h

-- 
2.20.1




[PATCH 01/17] hw/arm/spitz: Detabify

2020-06-28 Thread Peter Maydell
The spitz board has been around a long time, and still has a fair number
of hard-coded tab characters in it. We're about to do some work on
this source file, so start out by expanding out the tabs.

This commit is a pure whitespace only change.

Signed-off-by: Peter Maydell 
---
Couple of checkpatch errors due to the QUEUE_KEY macro which can
be ignored as this is just a detabify.
---
 hw/arm/spitz.c | 156 -
 1 file changed, 78 insertions(+), 78 deletions(-)

diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index fc18212e686..9eaedab79b5 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -34,25 +34,25 @@
 #include "cpu.h"
 
 #undef REG_FMT
-#define REG_FMT"0x%02lx"
+#define REG_FMT "0x%02lx"
 
 /* Spitz Flash */
-#define FLASH_BASE 0x0c00
-#define FLASH_ECCLPLB  0x00/* Line parity 7 - 0 bit */
-#define FLASH_ECCLPUB  0x04/* Line parity 15 - 8 bit */
-#define FLASH_ECCCP0x08/* Column parity 5 - 0 bit */
-#define FLASH_ECCCNTR  0x0c/* ECC byte counter */
-#define FLASH_ECCCLRR  0x10/* Clear ECC */
-#define FLASH_FLASHIO  0x14/* Flash I/O */
-#define FLASH_FLASHCTL 0x18/* Flash Control */
+#define FLASH_BASE  0x0c00
+#define FLASH_ECCLPLB   0x00/* Line parity 7 - 0 bit */
+#define FLASH_ECCLPUB   0x04/* Line parity 15 - 8 bit */
+#define FLASH_ECCCP 0x08/* Column parity 5 - 0 bit */
+#define FLASH_ECCCNTR   0x0c/* ECC byte counter */
+#define FLASH_ECCCLRR   0x10/* Clear ECC */
+#define FLASH_FLASHIO   0x14/* Flash I/O */
+#define FLASH_FLASHCTL  0x18/* Flash Control */
 
-#define FLASHCTL_CE0   (1 << 0)
-#define FLASHCTL_CLE   (1 << 1)
-#define FLASHCTL_ALE   (1 << 2)
-#define FLASHCTL_WP(1 << 3)
-#define FLASHCTL_CE1   (1 << 4)
-#define FLASHCTL_RYBY  (1 << 5)
-#define FLASHCTL_NCE   (FLASHCTL_CE0 | FLASHCTL_CE1)
+#define FLASHCTL_CE0(1 << 0)
+#define FLASHCTL_CLE(1 << 1)
+#define FLASHCTL_ALE(1 << 2)
+#define FLASHCTL_WP (1 << 3)
+#define FLASHCTL_CE1(1 << 4)
+#define FLASHCTL_RYBY   (1 << 5)
+#define FLASHCTL_NCE(FLASHCTL_CE0 | FLASHCTL_CE1)
 
 #define TYPE_SL_NAND "sl-nand"
 #define SL_NAND(obj) OBJECT_CHECK(SLNANDState, (obj), TYPE_SL_NAND)
@@ -74,12 +74,12 @@ static uint64_t sl_read(void *opaque, hwaddr addr, unsigned 
size)
 int ryby;
 
 switch (addr) {
-#define BSHR(byte, from, to)   ((s->ecc.lp[byte] >> (from - to)) & (1 << to))
+#define BSHR(byte, from, to)((s->ecc.lp[byte] >> (from - to)) & (1 << to))
 case FLASH_ECCLPLB:
 return BSHR(0, 4, 0) | BSHR(0, 5, 2) | BSHR(0, 6, 4) | BSHR(0, 7, 6) |
 BSHR(1, 4, 1) | BSHR(1, 5, 3) | BSHR(1, 6, 5) | BSHR(1, 7, 7);
 
-#define BSHL(byte, from, to)   ((s->ecc.lp[byte] << (to - from)) & (1 << to))
+#define BSHL(byte, from, to)((s->ecc.lp[byte] << (to - from)) & (1 << to))
 case FLASH_ECCLPUB:
 return BSHL(0, 0, 0) | BSHL(0, 1, 2) | BSHL(0, 2, 4) | BSHL(0, 3, 6) |
 BSHL(1, 0, 1) | BSHL(1, 1, 3) | BSHL(1, 2, 5) | BSHL(1, 3, 7);
@@ -191,8 +191,8 @@ static void sl_nand_realize(DeviceState *dev, Error **errp)
 
 /* Spitz Keyboard */
 
-#define SPITZ_KEY_STROBE_NUM   11
-#define SPITZ_KEY_SENSE_NUM7
+#define SPITZ_KEY_STROBE_NUM11
+#define SPITZ_KEY_SENSE_NUM 7
 
 static const int spitz_gpio_key_sense[SPITZ_KEY_SENSE_NUM] = {
 12, 17, 91, 34, 36, 38, 39
@@ -214,11 +214,11 @@ static int spitz_keymap[SPITZ_KEY_SENSE_NUM + 
1][SPITZ_KEY_STROBE_NUM] = {
 { 0x52, 0x43, 0x01, 0x47, 0x49,  -1 ,  -1 ,  -1 ,  -1 ,  -1 ,  -1  },
 };
 
-#define SPITZ_GPIO_AK_INT  13  /* Remote control */
-#define SPITZ_GPIO_SYNC16  /* Sync button */
-#define SPITZ_GPIO_ON_KEY  95  /* Power button */
-#define SPITZ_GPIO_SWA 97  /* Lid */
-#define SPITZ_GPIO_SWB 96  /* Tablet mode */
+#define SPITZ_GPIO_AK_INT   13  /* Remote control */
+#define SPITZ_GPIO_SYNC 16  /* Sync button */
+#define SPITZ_GPIO_ON_KEY   95  /* Power button */
+#define SPITZ_GPIO_SWA  97  /* Lid */
+#define SPITZ_GPIO_SWB  96  /* Tablet mode */
 
 /* The special buttons are mapped to unused keys */
 static const int spitz_gpiomap[5] = {
@@ -300,7 +300,7 @@ static void spitz_keyboard_keydown(SpitzKeyboardState *s, 
int keycode)
 #define SPITZ_MOD_CTRL(1 << 8)
 #define SPITZ_MOD_FN  (1 << 9)
 
-#define QUEUE_KEY(c)   s->fifo[(s->fifopos + s->fifolen ++) & 0xf] = c
+#define QUEUE_KEY(c)s->fifo[(s->fifopos + s->fifolen ++) & 0xf] = c
 
 static void spitz_keyboard_handler(void *opaque, int keycode)
 {
@@ -308,25 +308,25 @@ static void spitz_keyboard_handler(void *opaque, int

[PATCH 03/17] hw/arm/spitz: Keep pointers to MPU and SSI devices in SpitzMachineState

2020-06-28 Thread Peter Maydell
Keep pointers to the MPU and the SSI devices in SpitzMachineState.
We're going to want to make GPIO connections between some of the
SSI devices and the SCPs, so we want to keep hold of a pointer to
those; putting the MPU into the struct allows us to pass just
one thing to spitz_ssp_attach() rather than two.

We have to retain the setting of the global "max" variable
for the moment as it is used in spitz_adc_temp_on(); later in
this series of commits we will be able to remove it.

Signed-off-by: Peter Maydell 
---
 hw/arm/spitz.c | 50 --
 1 file changed, 28 insertions(+), 22 deletions(-)

diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index c70e912a33d..f48e966c047 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -43,6 +43,11 @@ typedef struct {
 
 typedef struct {
 MachineState parent;
+PXA2xxState *mpu;
+DeviceState *mux;
+DeviceState *lcdtg;
+DeviceState *ads7846;
+DeviceState *max;
 } SpitzMachineState;
 
 #define TYPE_SPITZ_MACHINE "spitz-common"
@@ -709,34 +714,33 @@ static void corgi_ssp_realize(SSISlave *d, Error **errp)
 s->bus[2] = ssi_create_bus(dev, "ssi2");
 }
 
-static void spitz_ssp_attach(PXA2xxState *cpu)
+static void spitz_ssp_attach(SpitzMachineState *sms)
 {
-DeviceState *mux;
-DeviceState *dev;
 void *bus;
 
-mux = ssi_create_slave(cpu->ssp[CORGI_SSP_PORT - 1], "corgi-ssp");
+sms->mux = ssi_create_slave(sms->mpu->ssp[CORGI_SSP_PORT - 1], 
"corgi-ssp");
 
-bus = qdev_get_child_bus(mux, "ssi0");
-ssi_create_slave(bus, "spitz-lcdtg");
+bus = qdev_get_child_bus(sms->mux, "ssi0");
+sms->lcdtg = ssi_create_slave(bus, "spitz-lcdtg");
 
-bus = qdev_get_child_bus(mux, "ssi1");
-dev = ssi_create_slave(bus, "ads7846");
-qdev_connect_gpio_out(dev, 0,
-  qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_TP_INT));
+bus = qdev_get_child_bus(sms->mux, "ssi1");
+sms->ads7846 = ssi_create_slave(bus, "ads7846");
+qdev_connect_gpio_out(sms->ads7846, 0,
+  qdev_get_gpio_in(sms->mpu->gpio, SPITZ_GPIO_TP_INT));
 
-bus = qdev_get_child_bus(mux, "ssi2");
-max = ssi_create_slave(bus, "max");
-max111x_set_input(max, MAX_BATT_VOLT, SPITZ_BATTERY_VOLT);
-max111x_set_input(max, MAX_BATT_TEMP, 0);
-max111x_set_input(max, MAX_ACIN_VOLT, SPITZ_CHARGEON_ACIN);
+bus = qdev_get_child_bus(sms->mux, "ssi2");
+sms->max = ssi_create_slave(bus, "max");
+max = sms->max;
+max111x_set_input(sms->max, MAX_BATT_VOLT, SPITZ_BATTERY_VOLT);
+max111x_set_input(sms->max, MAX_BATT_TEMP, 0);
+max111x_set_input(sms->max, MAX_ACIN_VOLT, SPITZ_CHARGEON_ACIN);
 
-qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_LCDCON_CS,
-qdev_get_gpio_in(mux, 0));
-qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_ADS7846_CS,
-qdev_get_gpio_in(mux, 1));
-qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_MAX_CS,
-qdev_get_gpio_in(mux, 2));
+qdev_connect_gpio_out(sms->mpu->gpio, SPITZ_GPIO_LCDCON_CS,
+qdev_get_gpio_in(sms->mux, 0));
+qdev_connect_gpio_out(sms->mpu->gpio, SPITZ_GPIO_ADS7846_CS,
+qdev_get_gpio_in(sms->mux, 1));
+qdev_connect_gpio_out(sms->mpu->gpio, SPITZ_GPIO_MAX_CS,
+qdev_get_gpio_in(sms->mux, 2));
 }
 
 /* CF Microdrive */
@@ -936,6 +940,7 @@ static struct arm_boot_info spitz_binfo = {
 static void spitz_common_init(MachineState *machine)
 {
 SpitzMachineClass *smc = SPITZ_MACHINE_GET_CLASS(machine);
+SpitzMachineState *sms = SPITZ_MACHINE(machine);
 enum spitz_model_e model = smc->model;
 PXA2xxState *mpu;
 DeviceState *scp0, *scp1 = NULL;
@@ -945,6 +950,7 @@ static void spitz_common_init(MachineState *machine)
 /* Setup CPU & memory */
 mpu = pxa270_init(address_space_mem, spitz_binfo.ram_size,
   machine->cpu_type);
+sms->mpu = mpu;
 
 sl_flash_register(mpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
 
@@ -954,7 +960,7 @@ static void spitz_common_init(MachineState *machine)
 /* Setup peripherals */
 spitz_keyboard_register(mpu);
 
-spitz_ssp_attach(mpu);
+spitz_ssp_attach(sms);
 
 scp0 = sysbus_create_simple("scoop", 0x1080, NULL);
 if (model != akita) {
-- 
2.20.1




[PATCH 07/17] hw/misc/max111x: Don't use vmstate_register()

2020-06-28 Thread Peter Maydell
The max111x is a proper qdev device; we can use dc->vmsd rather than
directly calling vmstate_register().

It's possible that this is a migration compat break, but the only
boards that use this device are the spitz-family ('akita', 'borzoi',
'spitz', 'terrier').

Signed-off-by: Peter Maydell 
---
 hw/misc/max111x.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/hw/misc/max111x.c b/hw/misc/max111x.c
index d0e5534e4f5..abddfa3c660 100644
--- a/hw/misc/max111x.c
+++ b/hw/misc/max111x.c
@@ -140,8 +140,6 @@ static int max111x_init(SSISlave *d, int inputs)
 
 s->inputs = inputs;
 
-vmstate_register(VMSTATE_IF(dev), VMSTATE_INSTANCE_ID_ANY,
- &vmstate_max111x, s);
 return 0;
 }
 
@@ -206,6 +204,7 @@ static void max111x_class_init(ObjectClass *klass, void 
*data)
 
 k->transfer = max111x_transfer;
 dc->reset = max111x_reset;
+dc->vmsd = &vmstate_max111x;
 }
 
 static const TypeInfo max111x_info = {
-- 
2.20.1




Re: Building in Solaris 11.4

2020-06-28 Thread Peter Tribble
On Sun, Jun 28, 2020 at 2:23 PM Peter Maydell 
wrote:

> On Sat, 27 Jun 2020 at 23:05, Michele Denber 
> wrote:
> >
> > Well I removed the "static" from the line
> >
> > static int openpty(int *amaster, int *aslave, char *name,
> >struct termios *termp, struct winsize *winp)
> >
> > in util/qemu-openpty.c.  I odn't know if that was the right thing to do
> but it did allow it to compile.
>
> No, that doesn't sound right. The code in qemu-openpty.c
> for Solaris assumes that solaris does not provide
> openpty(), and so it provides its own implementation.
> This is a very old bit of portability-workaround. It
> sounds like at least some Solaris versions do provide
> a system openpty() in termios.h (in libc, or perhaps
> needing an extra -lsomething?), in which case we want
> to detect that and use it (not compiling the QEMU
> code for solaris-without-openpty).
>
> The first thing to do here would be to find out which
> versions of Solaris provide openpty(), and which header
> and library need to be used to compile code that uses it.
> The gnulib docs think it is missing on Solaris 11.3:
> do we care about supporting that as a host OS?
> https://www.gnu.org/software/gnulib/manual/html_node/openpty.html
>

I think you need to support older versions that don't ship openpty(),
as 11.4 dropped support for a lot of older hardware so people with
existing (older but working) hardware won't be able to upgrade to it.

Also, illumos doesn't (yet) have openpty.


> Then you'd need to improve configure so that it looked for
> "does the system provide openpty() via termios.h" and defined
> CONFIG_OPENPTY_IN_TERMIOS to indicate that; then if that is
> set we qemu-openpty.c can make solaris use the "system has
> openpty()" codepath rather than "system doesn't have that".
> If it turns out that all Solaris versions new enough that we
> might care about them do have openpty() we could also delete
> the handling code for systems that don't.
>
> > CC  monitor/trace.o
> > util/drm.c: In function 'qemu_drm_rendernode_open':
> > util/drm.c:41:16: error: 'struct dirent' has no member named 'd_type';
> did you mean 'd_name'?
> >  if (e->d_type != DT_CHR) {
> > ^~
> > d_name
> > util/drm.c:41:26: error: 'DT_CHR' undeclared (first use in this
> function); did you mean 'TH_CWR'?
> >  if (e->d_type != DT_CHR) {
> >   ^~
> >   TH_CWR
> > util/drm.c:41:26: note: each undeclared identifier is reported only once
> for each function it appears in
> > gmake: *** [/export/home/denber/qemu-5.0.0/rules.mak:69: util/drm.o]
> Error 1
> >
> > This looks like more "not in Solaris" POSIX stuff.
>
> Ah, the Haiku folks just ran into exactly this issue.
> Their fix should also be good for Solaris:
> https://lists.gnu.org/archive/html/qemu-devel/2020-06/msg08800.html
> (This whole file is for using a Linux-specific feature so there's
> no point even compiling it for other OSes.)
>
> thanks
> -- PMM
>
>

-- 
-Peter Tribble
http://www.petertribble.co.uk/ - http://ptribble.blogspot.com/


Re: [PATCH v5 09/11] macio: Add dummy screamer register area

2020-06-28 Thread BALATON Zoltan

Here it is with --enable-debug and additional screamer debug:

SCREAMER: screamer_read: addr  -> 0
SCREAMER: screamer_write: addr  val 11
SCREAMER: screamer_control_write: val 17
SCREAMER: basic rate: 44100
DBDMA[10]: writel 0x080c <= 0x0010
DBDMA[10]: channel 0x10 reg 0x3
DBDMA[10]: dbdma_cmdptr_load 0x0010
DBDMA[10]: writel 0x0800 <= 0xf000
DBDMA[10]: channel 0x10 reg 0x0
DBDMA[10]:  Clearing RUN !
DBDMA[10]:  clearing PAUSE !
DBDMA[10]:   -> ACTIVE down !
DBDMA[10]:  new status=0x
SCREAMER: DMA TX flush!
DBDMA[10]: readl 0x0804 => 0x
DBDMA[10]: channel 0x10 reg 0x1
DBDMA[10]: writel 0x0800 <= 0xf0008000
DBDMA[10]: channel 0x10 reg 0x0
DBDMA[10]:  Setting RUN !
DBDMA[10]:  clearing PAUSE !
DBDMA[10]:  -> ACTIVE up !
DBDMA[10]:  new status=0x8400
DBDMA[10]: readl 0x0804 => 0x8400
DBDMA[10]: channel 0x10 reg 0x1
DBDMA: -> DBDMA_run_bh
DBDMA[10]: channel_run
DBDMA[10]: dbdma_cmd 0x56aac340
DBDMA[10]: req_count 0x8000
DBDMA[10]: command 0x
DBDMA[10]: phy_addr 0x0100
DBDMA[10]: cmd_dep 0x
DBDMA[10]: res_count 0x
DBDMA[10]: xfer_status 0x
DBDMA[10]: * OUTPUT_MORE *
DBDMA[10]: start_output
DBDMA[10]: addr 0x100 key 0x0
SCREAMER: DMA TX defer interrupt!
DBDMA: <- DBDMA_run_bh
SCREAMER: Processing deferred buffer
SCREAMER: DMA TX transfer: addr 100 len: 8000  bpos: 0

Thread 1 "qemu-system-ppc" received signal SIGSEGV, Segmentation fault.
0x94ff7c19 in ?? ()

(gdb) bt
#0  0x94ff7c19 in  ()
#1  0x55acb1e2 in pmac_screamer_tx_transfer (io=0x56ab1a98) at 
hw/audio/screamer.c:79
#2  0x55acb4dd in screamerspk_callback (opaque=0x56aad630, 
avail=16384) at hw/audio/screamer.c:155
#3  0x55a6af3d in audio_run_out (s=0x56b12bd0) at audio/audio.c:1181
#4  0x55a6b886 in audio_run (s=0x56b12bd0, msg=0x5609d4a9 "alsa run 
(prepared)") at audio/audio.c:1372
#5  0x55d00ce9 in alsa_poll_handler (opaque=0x57959c60) at 
audio/alsaaudio.c:199
#6  0x55e57079 in aio_dispatch_handler (ctx=0x567257f0, 
node=0x57a0c6b0) at util/aio-posix.c:328
#7  0x55e57232 in aio_dispatch_handlers (ctx=0x567257f0) at 
util/aio-posix.c:371
#8  0x55e57288 in aio_dispatch (ctx=0x567257f0) at 
util/aio-posix.c:381
#9  0x55e6d373 in aio_ctx_dispatch (source=0x567257f0, 
callback=0x0, user_data=0x0) at util/async.c:306
#10 0x77cc6665 in g_main_context_dispatch () at /lib64/libglib-2.0.so.0
#11 0x55e74898 in glib_pollfds_poll () at util/main-loop.c:219
#12 0x55e74912 in os_host_main_loop_wait (timeout=28915159) at 
util/main-loop.c:242
#13 0x55e74a17 in main_loop_wait (nonblocking=0) at util/main-loop.c:518
#14 0x55981d35 in qemu_main_loop () at qemu/softmmu/vl.c:1664
#15 0x55df59dc in main (argc=17, argv=0x7fffdf28, 
envp=0x7fffdfb8) at qemu/softmmu/main.c:49
(gdb) up
#1  0x55acb1e2 in pmac_screamer_tx_transfer (io=0x56ab1a98) at 
hw/audio/screamer.c:79
79  io->dma_end(io);
(gdb) p/x *io
$1 = {opaque = 0xa2140923, channel = 0x79130821, addr = 0x14137e1f, len = 0x0, 
is_last = 0x0, is_dma_out = 0x3408f81a, dma_end = 0x94ff7c19, processing = 
0x19,  dma_mem = 0x53f5351b, dma_len = 0xc7f99f1e, dir = 0x21fbe921}

Looks like dma_end is not pointing to the expected end procedure. Maybe 
something has overwritten it?

Regards,
BALATON Zoltan



Re: [PULL 0/6] MIPS + TCG Continuous Benchmarking queue for June 27th, 2020

2020-06-28 Thread Peter Maydell
On Sat, 27 Jun 2020 at 20:51, Aleksandar Markovic
 wrote:
>
> The following changes since commit 553cf5d7c47bee05a3dec9461c1f8430316d516b:
>
>   Merge remote-tracking branch 
> 'remotes/pmaydell/tags/pull-target-arm-20200626' into staging (2020-06-26 
> 18:22:36 +0100)
>
> are available in the git repository at:
>
>   https://github.com/AMarkovic/qemu tags/mips-gsoc-queue-jun-27-2020
>
> for you to fetch changes up to 53fb8bfb93487c0fd88b0babb9a52ec8d67cff7b:
>
>   MAINTAINERS: Add 'Performance Tools and Tests' subsection (2020-06-27 
> 20:15:07 +0200)
>
> 
>
> MIPS + TCG Continuous Benchmarking queue for June 27th, 2020
>
>Highlights:
>
>  - add two additional elements of Loongson-3 support
>  - add first two Python scripts as a part of a GSoC project
>
>Notes:
>
>  - several checkpatch warnings on updating MAINTAINERS should be ignored
>
> 


Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/5.1
for any user-visible changes.

-- PMM



Re: Building in Solaris 11.4

2020-06-28 Thread Peter Maydell
On Sat, 27 Jun 2020 at 23:05, Michele Denber  wrote:
>
> Well I removed the "static" from the line
>
> static int openpty(int *amaster, int *aslave, char *name,
>struct termios *termp, struct winsize *winp)
>
> in util/qemu-openpty.c.  I odn't know if that was the right thing to do but 
> it did allow it to compile.

No, that doesn't sound right. The code in qemu-openpty.c
for Solaris assumes that solaris does not provide
openpty(), and so it provides its own implementation.
This is a very old bit of portability-workaround. It
sounds like at least some Solaris versions do provide
a system openpty() in termios.h (in libc, or perhaps
needing an extra -lsomething?), in which case we want
to detect that and use it (not compiling the QEMU
code for solaris-without-openpty).

The first thing to do here would be to find out which
versions of Solaris provide openpty(), and which header
and library need to be used to compile code that uses it.
The gnulib docs think it is missing on Solaris 11.3:
do we care about supporting that as a host OS?
https://www.gnu.org/software/gnulib/manual/html_node/openpty.html

Then you'd need to improve configure so that it looked for
"does the system provide openpty() via termios.h" and defined
CONFIG_OPENPTY_IN_TERMIOS to indicate that; then if that is
set we qemu-openpty.c can make solaris use the "system has
openpty()" codepath rather than "system doesn't have that".
If it turns out that all Solaris versions new enough that we
might care about them do have openpty() we could also delete
the handling code for systems that don't.

> CC  monitor/trace.o
> util/drm.c: In function 'qemu_drm_rendernode_open':
> util/drm.c:41:16: error: 'struct dirent' has no member named 'd_type'; did 
> you mean 'd_name'?
>  if (e->d_type != DT_CHR) {
> ^~
> d_name
> util/drm.c:41:26: error: 'DT_CHR' undeclared (first use in this function); 
> did you mean 'TH_CWR'?
>  if (e->d_type != DT_CHR) {
>   ^~
>   TH_CWR
> util/drm.c:41:26: note: each undeclared identifier is reported only once for 
> each function it appears in
> gmake: *** [/export/home/denber/qemu-5.0.0/rules.mak:69: util/drm.o] Error 1
>
> This looks like more "not in Solaris" POSIX stuff.

Ah, the Haiku folks just ran into exactly this issue.
Their fix should also be good for Solaris:
https://lists.gnu.org/archive/html/qemu-devel/2020-06/msg08800.html
(This whole file is for using a Linux-specific feature so there's
no point even compiling it for other OSes.)

thanks
-- PMM



[RFC PATCH] WIP macio/cuda: Attempt to add i2c support

2020-06-28 Thread BALATON Zoltan



This is a non-working RFC patch attempt to implement i2c bus in CUDA
needed for firmware to access SPD data of installed RAM. The skeleton
is there but actual operation fails because I don't know how this is
supposed to work and the i2c bus state becomes invalid quickly. Also
sending back results may be missing or wrong. Help fixing and
finishing this is welcome, I don't plan to spend more time with this
so just submitted it for whoever picks this up.

Signed-off-by: BALATON Zoltan 
---
This is still RFC and only for testing but with this the ROM seems to 
detect some RAM now:


cuda_packet_receive length 5
cuda_packet_receive_data [0] 0x01
cuda_packet_receive_data [1] 0x25
cuda_packet_receive_data [2] 0xa0
cuda_packet_receive_data [3] 0x02
cuda_packet_receive_data [4] 0xa1
cuda_receive_packet_cmd handling command COMBINED_FORMAT_IIC
i2c_event start(addr:0x50)
smbus(50): Incoming data
i2c_send send(addr:0x50) data:0x02
smbus(50): Write data 02
i2c_event finish(addr:0x50)
smbus(50): Command 2 len 1
eeprom_write_byte: addr=0x50 cmd=0x02 val=0x00
i2c_event start(addr:0x50)
smbus(50): Read mode
eeprom_receive_byte: addr=0x50 val=0x04
smbus(50): Read data 04
i2c_recv recv(addr:0x50) data:0x04
eeprom_receive_byte: addr=0x50 val=0x0d
smbus(50): Read data 0d
i2c_recv recv(addr:0x50) data:0x0d
eeprom_receive_byte: addr=0x50 val=0x0a
smbus(50): Read data 0a
i2c_recv recv(addr:0x50) data:0x0a
eeprom_receive_byte: addr=0x50 val=0x02
smbus(50): Read data 02
i2c_recv recv(addr:0x50) data:0x02
eeprom_receive_byte: addr=0x50 val=0x40
smbus(50): Read data 40
i2c_recv recv(addr:0x50) data:0x40
i2c_event finish(addr:0x50)
smbus(50): Quick Command 1
cuda_packet_send length 8
cuda_packet_send_data [0] 0x01
cuda_packet_send_data [1] 0x00
cuda_packet_send_data [2] 0x25
cuda_packet_send_data [3] 0x04
cuda_packet_send_data [4] 0x0d
cuda_packet_send_data [5] 0x0a
cuda_packet_send_data [6] 0x02
cuda_packet_send_data [7] 0x40
cuda_delay_set_sr_int
cuda_data_recv recv: 0x01
cuda_delay_set_sr_int
cuda_data_recv recv: 0x00
cuda_delay_set_sr_int
cuda_data_recv recv: 0x25
cuda_delay_set_sr_int
cuda_data_recv recv: 0x04
cuda_delay_set_sr_int
cuda_data_recv recv: 0x0d
cuda_delay_set_sr_int
cuda_data_recv recv: 0x0a
cuda_delay_set_sr_int
cuda_data_recv recv: 0x02
cuda_delay_set_sr_int
cuda_data_recv recv: 0x40
cuda_delay_set_sr_int
cuda_delay_set_sr_int
cuda_delay_set_sr_int
cuda_delay_set_sr_int
cuda_data_send send: 0x01
cuda_delay_set_sr_int
cuda_data_send send: 0x25
cuda_delay_set_sr_int
cuda_data_send send: 0xa2
cuda_delay_set_sr_int
cuda_data_send send: 0x02
cuda_delay_set_sr_int
cuda_data_send send: 0xa3
cuda_delay_set_sr_int
cuda_delay_set_sr_int
cuda_packet_receive length 5
cuda_packet_receive_data [0] 0x01
cuda_packet_receive_data [1] 0x25
cuda_packet_receive_data [2] 0xa2
cuda_packet_receive_data [3] 0x02
cuda_packet_receive_data [4] 0xa3
cuda_receive_packet_cmd handling command COMBINED_FORMAT_IIC
CUDA: COMBINED_FORMAT_IIC: wrong parameters 4
[...]
pci_cfg_write grackle 00:0 @0x80 <- 0x8000
pci_cfg_write grackle 00:0 @0x88 <- 0x
pci_cfg_write grackle 00:0 @0x90 <- 0xff7f
pci_cfg_write grackle 00:0 @0x98 <- 0x

^^^ these were all 0x before

pci_cfg_write grackle 00:0 @0x84 <- 0x
pci_cfg_write grackle 00:0 @0x8c <- 0x
pci_cfg_write grackle 00:0 @0x94 <- 0x
pci_cfg_write grackle 00:0 @0x9c <- 0x
pci_cfg_write grackle 00:0 @0xa0 <- 0x3
pci_cfg_read grackle 00:0 @0xf0 -> 0x1290
pci_cfg_write grackle 00:0 @0xf0 <- 0x1295
pci_cfg_read grackle 00:0 @0x8 -> 0x6000140
pci_cfg_read grackle 00:0 @0xf0 -> 0x1295
pci_cfg_write grackle 00:0 @0xf0 <- 0x12940005
pci_cfg_write grackle 00:0 @0xf0 <- 0x12940005
pci_cfg_write grackle 00:0 @0xf4 <- 0x40010fe4
pci_cfg_write grackle 00:0 @0xf8 <- 0x7302293
pci_cfg_write grackle 00:0 @0xfc <- 0x25302220
pci_cfg_read grackle 00:0 @0xa0 -> 0x3
pci_cfg_write grackle 00:0 @0xa0 <- 0x6703
pci_cfg_read grackle 00:0 @0xf0 -> 0x12940005
pci_cfg_write grackle 00:0 @0xf0 <- 0x129c0005

In my understanding after an I2C command CUDA should enter in a mode 
whereby reading the SR reg will return bytes from the I2C device but not 
sure what terminates that mode and how to model it correctly so I just 
return the expected number of bytes in this patch to make the ROM go 
further so I can test what else is needed. Then it crashes in screamer.


 hw/misc/macio/cuda.c | 76 +++-
 include/hw/misc/macio/cuda.h |  1 +
 2 files changed, 76 insertions(+), 1 deletion(-)

diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c
index 5bbc7770fa..3fc9773717 100644
--- a/hw/misc/macio/cuda.c
+++ b/hw/misc/macio/cuda.c
@@ -28,6 +28,7 @@
 #include "hw/ppc/mac.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
+#include "hw/i2c/i2c.h"
 #include "hw/input/adb.h"
 #include "hw/misc/mos6522.h"
 #include "hw/misc/macio/cuda.h"
@@ -370,6 +371,75 @@ static bool cuda_cmd_set_time(CUDAState *s,
 return

Re: [PATCH v5 09/11] macio: Add dummy screamer register area

2020-06-28 Thread BALATON Zoltan

On Fri, 26 Jun 2020, Mark Cave-Ayland wrote:

Again I'm wary of adding empty devices here as the main issue around the 
screamer
code (and why it has not been submitted upstream) is that it can cause random 
hangs
for MacOS on startup. Does it regress any MacOS 9 through 10.5 boot tests?

FWIW I've rebased the latest version of my screamer branch at
https://github.com/mcayland/qemu/commits/screamer to git master if you want to 
see if
any noise comes out.


It seems the dummy screamer patch is not enough so I've tried on top of 
your screamer branch now. It does not make sound but it crashes (this is 
with --audio-drv-list=alsa in case that matters):


17609@1593346435.329466:cuda_packet_receive length 5
17609@1593346435.329467:cuda_packet_receive_data [0] 0x01
17609@1593346435.329469:cuda_packet_receive_data [1] 0x22
17609@1593346435.329470:cuda_packet_receive_data [2] 0x8a
17609@1593346435.329471:cuda_packet_receive_data [3] 0x01
17609@1593346435.329472:cuda_packet_receive_data [4] 0x29
17609@1593346435.329473:cuda_receive_packet_cmd handling command GET_SET_IIC
CUDA: unimplemented GET_SET_IIC write 0x45 3
17609@1593346435.329476:i2c_event start(addr:0x50)
smbus: error: Unexpected send start condition in state -1
17609@1593346435.329478:cuda_packet_send length 3
17609@1593346435.329479:cuda_packet_send_data [0] 0x01
17609@1593346435.329480:cuda_packet_send_data [1] 0x00
17609@1593346435.329482:cuda_packet_send_data [2] 0x22
17609@1593346435.329483:cuda_delay_set_sr_int
17609@1593346435.329514:cuda_data_recv recv: 0x01
17609@1593346435.329516:cuda_delay_set_sr_int
17609@1593346435.329548:cuda_data_recv recv: 0x00
17609@1593346435.329550:cuda_delay_set_sr_int
17609@1593346435.329588:cuda_data_recv recv: 0x22
17609@1593346435.329590:cuda_delay_set_sr_int
17609@1593346435.366095:cuda_delay_set_sr_int
DBDMA[10]: writel 0x080c <= 0xffe40020
DBDMA[10]: channel 0x10 reg 0x3
DBDMA[10]: dbdma_cmdptr_load 0xffe40020
DBDMA[10]: writel 0x0800 <= 0xf000
DBDMA[10]: channel 0x10 reg 0x0
DBDMA[10]:  Clearing RUN !
DBDMA[10]:  clearing PAUSE !
DBDMA[10]:   -> ACTIVE down !
DBDMA[10]:  new status=0x
DBDMA[10]: readl 0x0804 => 0x
DBDMA[10]: channel 0x10 reg 0x1
DBDMA[10]: writel 0x0800 <= 0xf0008000
DBDMA[10]: channel 0x10 reg 0x0
DBDMA[10]:  Setting RUN !
DBDMA[10]:  clearing PAUSE !
DBDMA[10]:  -> ACTIVE up !
DBDMA[10]:  new status=0x8400
DBDMA[10]: readl 0x0804 => 0x8400
DBDMA[10]: channel 0x10 reg 0x1
DBDMA: -> DBDMA_run_bh
DBDMA[10]: channel_run
DBDMA[10]: dbdma_cmd 0x56802c50
DBDMA[10]: req_count 0x6238
DBDMA[10]: command 0x1000
DBDMA[10]: phy_addr 0xffe32c00
DBDMA[10]: cmd_dep 0x
DBDMA[10]: res_count 0x
DBDMA[10]: xfer_status 0x
DBDMA[10]: * OUTPUT_LAST *
DBDMA[10]: start_output
DBDMA[10]: addr 0xffe32c00 key 0x0
DBDMA: <- DBDMA_run_bh

Thread 1 "qemu-system-ppc" received signal SIGSEGV, Segmentation fault.
0x55a13216 in pmac_screamer_tx_transfer (io=0x568083a8) at 
hw/audio/screamer.c:79

79  io->dma_end(io);

#0  0x55a13216 in pmac_screamer_tx_transfer (io=0x568083a8) at 
hw/audio/screamer.c:79
#1  0x559dc7bb in audio_run_out (s=0x56868dc0) at audio/audio.c:1181
#2  0x559dc7bb in audio_run (s=0x56868dc0, msg=msg@entry=0x55e69664 
"alsa run (prepared)") at audio/audio.c:1372
#3  0x55bab458 in alsa_poll_handler (opaque=0x5770eb50) at 
audio/alsaaudio.c:199
#4  0x55cad63b in aio_dispatch_handler (ctx=ctx@entry=0x56487860, 
node=0x5770e700) at util/aio-posix.c:328
#5  0x55cadf0c in aio_dispatch_handlers (ctx=0x56487860) at 
util/aio-posix.c:371
#6  0x55cadf0c in aio_dispatch (ctx=0x56487860) at 
util/aio-posix.c:381
#7  0x55cbe60e in aio_ctx_dispatch (source=, callback=, user_data=) at util/async.c:306
#8  0x77cc6665 in g_main_context_dispatch () at /lib64/libglib-2.0.so.0
#9  0x55cc3938 in glib_pollfds_poll () at util/main-loop.c:219
#10 0x55cc3938 in os_host_main_loop_wait (timeout=) at 
util/main-loop.c:242
#11 0x55cc3938 in main_loop_wait (nonblocking=nonblocking@entry=0) at 
util/main-loop.c:518
#12 0x55932a49 in qemu_main_loop () at qemu/softmmu/vl.c:1664
#13 0x5585138e in main (argc=, argv=, 
envp=) at qemu/softmmu/main.c:49

Does the same on master with your patches and my series.

Regards,
BALATON Zoltan



Re: [PATCH] ftgmac100: fix dblac write test

2020-06-28 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20200628114057.-1-erik.lucas.s...@gmail.com/



Hi,

This series failed the docker-mingw@fedora build test. Please find the testing 
commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

=== TEST SCRIPT BEGIN ===
#! /bin/bash
export ARCH=x86_64
make docker-image-fedora V=1 NETWORK=1
time make docker-test-mingw@fedora J=14 NETWORK=1
=== TEST SCRIPT END ===

  BUILD   pc-bios/optionrom/linuxboot.raw
In file included from /tmp/qemu-test/src/hw/net/ftgmac100.c:19:
/tmp/qemu-test/src/hw/net/ftgmac100.c: In function 'ftgmac100_write':
/tmp/qemu-test/src/hw/net/ftgmac100.c:815:27: error: format '%ld' expects 
argument of type 'long int', but argument 3 has type 'uint64_t' {aka 'long long 
unsigned int'} [-Werror=format=]
  815 |   "%s: transmit descriptor too small : %ld 
bytes\n",
  |   
^
/tmp/qemu-test/src/include/qemu/log.h:120:22: note: in definition of macro 
'qemu_log_mask'
---
  |  long 
int
  |%lld
In file included from /tmp/qemu-test/src/hw/net/ftgmac100.c:19:
/tmp/qemu-test/src/hw/net/ftgmac100.c:821:27: error: format '%ld' expects 
argument of type 'long int', but argument 3 has type 'uint64_t' {aka 'long long 
unsigned int'} [-Werror=format=]
  821 |   "%s: receive descriptor too small : %ld 
bytes\n",
  |   
^~~~
/tmp/qemu-test/src/include/qemu/log.h:120:22: note: in definition of macro 
'qemu_log_mask'
---
  | long int
  |   %lld
cc1: all warnings being treated as errors
make: *** [/tmp/qemu-test/src/rules.mak:69: hw/net/ftgmac100.o] Error 1
make: *** Waiting for unfinished jobs
  BUILD   pc-bios/optionrom/linuxboot_dma.raw
  BUILD   pc-bios/optionrom/kvmvapic.raw
---
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sudo', '-n', 'docker', 'run', 
'--label', 'com.qemu.instance.uuid=2dd03a1068f74da08c7abd42679f0f27', '-u', 
'1001', '--security-opt', 'seccomp=unconfined', '--rm', '-e', 'TARGET_LIST=', 
'-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=14', '-e', 'DEBUG=', '-e', 
'SHOW_ENV=', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', 
'/home/patchew/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', 
'/var/tmp/patchew-tester-tmp-jgbwf7wz/src/docker-src.2020-06-28-07.46.16.21026:/var/tmp/qemu:z,ro',
 'qemu:fedora', '/var/tmp/qemu/run', 'test-mingw']' returned non-zero exit 
status 2.
filter=--filter=label=com.qemu.instance.uuid=2dd03a1068f74da08c7abd42679f0f27
make[1]: *** [docker-run] Error 1
make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-jgbwf7wz/src'
make: *** [docker-run-test-mingw@fedora] Error 2

real3m51.351s
user0m8.836s


The full log is available at
http://patchew.org/logs/20200628114057.-1-erik.lucas.s...@gmail.com/testing.docker-mingw@fedora/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-de...@redhat.com

[PATCH] ftgmac100: fix dblac write test

2020-06-28 Thread erik-smit
The test of the write of the dblac register was testing the old value
instead of the new value. This would accept the write of an invalid value
but subsequently refuse any following valid writes.

Signed-off-by: erik-smit 
---
 hw/net/ftgmac100.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
index 043ba61b86..9db0d27ea6 100644
--- a/hw/net/ftgmac100.c
+++ b/hw/net/ftgmac100.c
@@ -810,16 +810,16 @@ static void ftgmac100_write(void *opaque, hwaddr addr,
 s->phydata = value & 0x;
 break;
 case FTGMAC100_DBLAC: /* DMA Burst Length and Arbitration Control */
-if (FTGMAC100_DBLAC_TXDES_SIZE(s->dblac) < sizeof(FTGMAC100Desc)) {
+if (FTGMAC100_DBLAC_TXDES_SIZE(value) < sizeof(FTGMAC100Desc)) {
 qemu_log_mask(LOG_GUEST_ERROR,
-  "%s: transmit descriptor too small : %d bytes\n",
-  __func__, FTGMAC100_DBLAC_TXDES_SIZE(s->dblac));
+  "%s: transmit descriptor too small : %ld bytes\n",
+  __func__, FTGMAC100_DBLAC_TXDES_SIZE(value));
 break;
 }
-if (FTGMAC100_DBLAC_RXDES_SIZE(s->dblac) < sizeof(FTGMAC100Desc)) {
+if (FTGMAC100_DBLAC_RXDES_SIZE(value) < sizeof(FTGMAC100Desc)) {
 qemu_log_mask(LOG_GUEST_ERROR,
-  "%s: receive descriptor too small : %d bytes\n",
-  __func__, FTGMAC100_DBLAC_RXDES_SIZE(s->dblac));
+  "%s: receive descriptor too small : %ld bytes\n",
+  __func__, FTGMAC100_DBLAC_RXDES_SIZE(value));
 break;
 }
 s->dblac = value;
-- 
2.25.1




Re: [PATCH v2 1/2] Introduce (x86) CPU model deprecation API

2020-06-28 Thread Robert Hoo
Hi, Ping for comments:)
On Thu, 2020-06-11 at 10:47 +0800, Robert Hoo wrote:
> Complement versioned CPU model framework with the ability of marking
> some
> versions deprecated. When that CPU model is chosen, get some warning.
> The
> warning message is customized, e.g. telling in which future QEMU
> version will
> it be obsoleted.
> The deprecation message will also appear by x86_cpu_list_entry(),
> e.g. '-cpu
> help'.
> QMP 'query-cpu-definitions' will also return a bool value indicating
> the
> deprecation status.
> 
> Changes in v2:
> Move deprecation check from parse_cpu_option() to
> machine_run_board_init(), so
> that it can cover implicit cpu_type assignment cases.
> Add qapi new member documentation. Thanks Eric for comment and
> guidance on qapi.
> 
> Signed-off-by: Robert Hoo 
> ---
>  hw/core/machine.c| 11 +--
>  include/hw/core/cpu.h|  1 +
>  qapi/machine-target.json |  7 ++-
>  target/i386/cpu.c| 45
> +++--
>  4 files changed, 59 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/core/machine.c b/hw/core/machine.c
> index bb3a7b1..9318964 100644
> --- a/hw/core/machine.c
> +++ b/hw/core/machine.c
> @@ -1083,6 +1083,8 @@ MemoryRegion
> *machine_consume_memdev(MachineState *machine,
>  void machine_run_board_init(MachineState *machine)
>  {
>  MachineClass *machine_class = MACHINE_GET_CLASS(machine);
> +ObjectClass *oc = object_class_by_name(machine->cpu_type);
> +CPUClass *cc;
>  
>  if (machine->ram_memdev_id) {
>  Object *o;
> @@ -1102,11 +1104,10 @@ void machine_run_board_init(MachineState
> *machine)
>   * specified a CPU with -cpu check here that the user CPU is
> supported.
>   */
>  if (machine_class->valid_cpu_types && machine->cpu_type) {
> -ObjectClass *class = object_class_by_name(machine-
> >cpu_type);
>  int i;
>  
>  for (i = 0; machine_class->valid_cpu_types[i]; i++) {
> -if (object_class_dynamic_cast(class,
> +if (object_class_dynamic_cast(oc,
>machine_class-
> >valid_cpu_types[i])) {
>  /* The user specificed CPU is in the valid field, we
> are
>   * good to go.
> @@ -1129,6 +1130,12 @@ void machine_run_board_init(MachineState
> *machine)
>  }
>  }
>  
> +/* Check if CPU type is deprecated and warn if so */
> +cc = CPU_CLASS(oc);
> +if (cc->deprecation_check) {
> +cc->deprecation_check(oc);
> +}
> +
>  machine_class->init(machine);
>  }
>  
> diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
> index 497600c..1ca47dc 100644
> --- a/include/hw/core/cpu.h
> +++ b/include/hw/core/cpu.h
> @@ -218,6 +218,7 @@ typedef struct CPUClass {
>  void (*disas_set_info)(CPUState *cpu, disassemble_info *info);
>  vaddr (*adjust_watchpoint_address)(CPUState *cpu, vaddr addr,
> int len);
>  void (*tcg_initialize)(void);
> +void (*deprecation_check)(ObjectClass *oc);
>  
>  /* Keep non-pointer data at the end to minimize holes.  */
>  int gdb_num_core_regs;
> diff --git a/qapi/machine-target.json b/qapi/machine-target.json
> index f2c8294..c24f506 100644
> --- a/qapi/machine-target.json
> +++ b/qapi/machine-target.json
> @@ -285,6 +285,10 @@
>  #in the VM configuration, because aliases may stop being
>  #migration-safe in the future (since 4.1)
>  #
> +# @deprecated: If true, this CPU model is deprecated and may be
> removed in
> +#  in some future version of QEMU according to the QEMU
> deprecation
> +#  policy. (since 5.1)
> +#
>  # @unavailable-features is a list of QOM property names that
>  # represent CPU model attributes that prevent the CPU from running.
>  # If the QOM property is read-only, that means there's no known
> @@ -309,7 +313,8 @@
>  'static': 'bool',
>  '*unavailable-features': [ 'str' ],
>  'typename': 'str',
> -'*alias-of' : 'str' },
> +'*alias-of' : 'str',
> +'deprecated' : 'bool' },
>'if': 'defined(TARGET_PPC) || defined(TARGET_ARM) ||
> defined(TARGET_I386) || defined(TARGET_S390X) ||
> defined(TARGET_MIPS)' }
>  
>  ##
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index ba05da3..0d8638a 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -1599,6 +1599,7 @@ typedef struct X86CPUVersionDefinition {
>  const char *alias;
>  const char *note;
>  PropValue *props;
> +bool   deprecated;
>  } X86CPUVersionDefinition;
>  
>  /* Base definition for a CPU model */
> @@ -1638,6 +1639,11 @@ struct X86CPUModel {
>   * This matters only for "-cpu help" and query-cpu-definitions
>   */
>  bool is_alias;
> +/*
> + * If true, this model is deprecated, and may be removed in the
> future.
> + * Trying to use it now will cause a warning.
> + */
> +bool deprecated;
>  };
>  
>  /* Get full model nam

[PATCH v9 31/34] qcow2: Add the 'extended_l2' option and the QCOW2_INCOMPAT_EXTL2 bit

2020-06-28 Thread Alberto Garcia
Now that the implementation of subclusters is complete we can finally
add the necessary options to create and read images with this feature,
which we call "extended L2 entries".

Signed-off-by: Alberto Garcia 
Reviewed-by: Eric Blake 
---
 qapi/block-core.json |   7 +++
 block/qcow2.h|   8 ++-
 include/block/block_int.h|   1 +
 block/qcow2.c|  74 --
 tests/qemu-iotests/031.out   |   8 +--
 tests/qemu-iotests/036.out   |   4 +-
 tests/qemu-iotests/049.out   | 102 +++
 tests/qemu-iotests/060.out   |   1 +
 tests/qemu-iotests/061.out   |  20 +++---
 tests/qemu-iotests/065   |  12 ++--
 tests/qemu-iotests/082.out   |  48 ---
 tests/qemu-iotests/085.out   |  38 ++--
 tests/qemu-iotests/144.out   |   4 +-
 tests/qemu-iotests/182.out   |   2 +-
 tests/qemu-iotests/185.out   |   8 +--
 tests/qemu-iotests/198.out   |   2 +
 tests/qemu-iotests/206.out   |   4 ++
 tests/qemu-iotests/242.out   |   5 ++
 tests/qemu-iotests/255.out   |   8 +--
 tests/qemu-iotests/274.out   |  49 ---
 tests/qemu-iotests/280.out   |   2 +-
 tests/qemu-iotests/291.out   |   6 +-
 tests/qemu-iotests/common.filter |   1 +
 23 files changed, 272 insertions(+), 142 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 0e1c6a59f2..24e002ebae 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -66,6 +66,9 @@
 # standalone (read-only) raw image without looking at qcow2
 # metadata (since: 4.0)
 #
+# @extended-l2: true if the image has extended L2 entries; only valid for
+#   compat >= 1.1 (since 5.1)
+#
 # @lazy-refcounts: on or off; only valid for compat >= 1.1
 #
 # @corrupt: true if the image has been marked corrupt; only valid for
@@ -87,6 +90,7 @@
   'compat': 'str',
   '*data-file': 'str',
   '*data-file-raw': 'bool',
+  '*extended-l2': 'bool',
   '*lazy-refcounts': 'bool',
   '*corrupt': 'bool',
   'refcount-bits': 'int',
@@ -4318,6 +4322,8 @@
 # @data-file-raw: True if the external data file must stay valid as a
 # standalone (read-only) raw image without looking at qcow2
 # metadata (default: false; since: 4.0)
+# @extended-l2  True to make the image have extended L2 entries
+#   (default: false; since 5.1)
 # @size: Size of the virtual disk in bytes
 # @version: Compatibility level (default: v3)
 # @backing-file: File name of the backing file if a backing file
@@ -4338,6 +4344,7 @@
   'data': { 'file': 'BlockdevRef',
 '*data-file':   'BlockdevRef',
 '*data-file-raw':   'bool',
+'*extended-l2': 'bool',
 'size': 'size',
 '*version': 'BlockdevQcow2Version',
 '*backing-file':'str',
diff --git a/block/qcow2.h b/block/qcow2.h
index f3499e53bf..065ec3df0b 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -246,15 +246,18 @@ enum {
 QCOW2_INCOMPAT_CORRUPT_BITNR= 1,
 QCOW2_INCOMPAT_DATA_FILE_BITNR  = 2,
 QCOW2_INCOMPAT_COMPRESSION_BITNR = 3,
+QCOW2_INCOMPAT_EXTL2_BITNR  = 4,
 QCOW2_INCOMPAT_DIRTY= 1 << QCOW2_INCOMPAT_DIRTY_BITNR,
 QCOW2_INCOMPAT_CORRUPT  = 1 << QCOW2_INCOMPAT_CORRUPT_BITNR,
 QCOW2_INCOMPAT_DATA_FILE= 1 << QCOW2_INCOMPAT_DATA_FILE_BITNR,
 QCOW2_INCOMPAT_COMPRESSION  = 1 << QCOW2_INCOMPAT_COMPRESSION_BITNR,
+QCOW2_INCOMPAT_EXTL2= 1 << QCOW2_INCOMPAT_EXTL2_BITNR,
 
 QCOW2_INCOMPAT_MASK = QCOW2_INCOMPAT_DIRTY
 | QCOW2_INCOMPAT_CORRUPT
 | QCOW2_INCOMPAT_DATA_FILE
-| QCOW2_INCOMPAT_COMPRESSION,
+| QCOW2_INCOMPAT_COMPRESSION
+| QCOW2_INCOMPAT_EXTL2,
 };
 
 /* Compatible feature bits */
@@ -581,8 +584,7 @@ typedef enum QCow2MetadataOverlap {
 
 static inline bool has_subclusters(BDRVQcow2State *s)
 {
-/* FIXME: Return false until this feature is complete */
-return false;
+return s->incompatible_features & QCOW2_INCOMPAT_EXTL2;
 }
 
 static inline size_t l2_entry_size(BDRVQcow2State *s)
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 791de6a59c..36e1993788 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -58,6 +58,7 @@
 #define BLOCK_OPT_DATA_FILE "data_file"
 #define BLOCK_OPT_DATA_FILE_RAW "data_file_raw"
 #define BLOCK_OPT_COMPRESSION_TYPE  "compression_type"
+#define BLOCK_OPT_EXTL2 "extended_l2"
 
 #define BLOCK_PROBE_BUF_SIZE512
 
diff --git a/block/qcow2.c b/block/qcow2.c
index 003f166024..37bfae823c 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1438,6 +1438,12 @@ static in

[PATCH v9 14/34] qcow2: Add QCow2SubclusterType and qcow2_get_subcluster_type()

2020-06-28 Thread Alberto Garcia
This patch adds QCow2SubclusterType, which is the subcluster-level
version of QCow2ClusterType. All QCOW2_SUBCLUSTER_* values have the
the same meaning as their QCOW2_CLUSTER_* equivalents (when they
exist). See below for details and caveats.

In images without extended L2 entries clusters are treated as having
exactly one subcluster so it is possible to replace one data type with
the other while keeping the exact same semantics.

With extended L2 entries there are new possible values, and every
subcluster in the same cluster can obviously have a different
QCow2SubclusterType so functions need to be adapted to work on the
subcluster level.

There are several things that have to be taken into account:

  a) QCOW2_SUBCLUSTER_COMPRESSED means that the whole cluster is
 compressed. We do not support compression at the subcluster
 level.

  b) There are two different values for unallocated subclusters:
 QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN which means that the whole
 cluster is unallocated, and QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC
 which means that the cluster is allocated but the subcluster is
 not. The latter can only happen in images with extended L2
 entries.

  c) QCOW2_SUBCLUSTER_INVALID is used to detect the cases where an L2
 entry has a value that violates the specification. The caller is
 responsible for handling these situations.

 To prevent compatibility problems with images that have invalid
 values but are currently being read by QEMU without causing side
 effects, QCOW2_SUBCLUSTER_INVALID is only returned for images
 with extended L2 entries.

qcow2_cluster_to_subcluster_type() is added as a separate function
from qcow2_get_subcluster_type(), but this is only temporary and both
will be merged in a subsequent patch.

Signed-off-by: Alberto Garcia 
Reviewed-by: Eric Blake 
---
 block/qcow2.h | 126 +-
 1 file changed, 125 insertions(+), 1 deletion(-)

diff --git a/block/qcow2.h b/block/qcow2.h
index 82b86f6cec..3aec6f452a 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -80,6 +80,21 @@
 
 #define QCOW_EXTL2_SUBCLUSTERS_PER_CLUSTER 32
 
+/* The subcluster X [0..31] is allocated */
+#define QCOW_OFLAG_SUB_ALLOC(X)   (1ULL << (X))
+/* The subcluster X [0..31] reads as zeroes */
+#define QCOW_OFLAG_SUB_ZERO(X)(QCOW_OFLAG_SUB_ALLOC(X) << 32)
+/* Subclusters [X, Y) (0 <= X <= Y <= 32) are allocated */
+#define QCOW_OFLAG_SUB_ALLOC_RANGE(X, Y) \
+(QCOW_OFLAG_SUB_ALLOC(Y) - QCOW_OFLAG_SUB_ALLOC(X))
+/* Subclusters [X, Y) (0 <= X <= Y <= 32) read as zeroes */
+#define QCOW_OFLAG_SUB_ZERO_RANGE(X, Y) \
+(QCOW_OFLAG_SUB_ALLOC_RANGE(X, Y) << 32)
+/* L2 entry bitmap with all allocation bits set */
+#define QCOW_L2_BITMAP_ALL_ALLOC  (QCOW_OFLAG_SUB_ALLOC_RANGE(0, 32))
+/* L2 entry bitmap with all "read as zeroes" bits set */
+#define QCOW_L2_BITMAP_ALL_ZEROES (QCOW_OFLAG_SUB_ZERO_RANGE(0, 32))
+
 /* Size of normal and extended L2 entries */
 #define L2E_SIZE_NORMAL   (sizeof(uint64_t))
 #define L2E_SIZE_EXTENDED (sizeof(uint64_t) * 2)
@@ -462,6 +477,33 @@ typedef struct QCowL2Meta
 QLIST_ENTRY(QCowL2Meta) next_in_flight;
 } QCowL2Meta;
 
+/*
+ * In images with standard L2 entries all clusters are treated as if
+ * they had one subcluster so QCow2ClusterType and QCow2SubclusterType
+ * can be mapped to each other and have the exact same meaning
+ * (QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC cannot happen in these images).
+ *
+ * In images with extended L2 entries QCow2ClusterType refers to the
+ * complete cluster and QCow2SubclusterType to each of the individual
+ * subclusters, so there are several possible combinations:
+ *
+ * |--+---|
+ * | Cluster type | Possible subcluster types |
+ * |--+---|
+ * | UNALLOCATED  | UNALLOCATED_PLAIN |
+ * |  |ZERO_PLAIN |
+ * |--+---|
+ * | NORMAL   | UNALLOCATED_ALLOC |
+ * |  |ZERO_ALLOC |
+ * |  |NORMAL |
+ * |--+---|
+ * | COMPRESSED   |COMPRESSED |
+ * |--+---|
+ *
+ * QCOW2_SUBCLUSTER_INVALID means that the L2 entry is incorrect and
+ * the image should be marked corrupt.
+ */
+
 typedef enum QCow2ClusterType {
 QCOW2_CLUSTER_UNALLOCATED,
 QCOW2_CLUSTER_ZERO_PLAIN,
@@ -470,6 +512,16 @@ typedef enum QCow2ClusterType {
 QCOW2_CLUSTER_COMPRESSED,
 } QCow2ClusterType;
 
+typedef enum QCow2SubclusterType {
+QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN,
+QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC,
+QCOW2_SUBCLUSTER_ZERO_PLAIN,
+QCOW2_SUBCLUSTER_ZERO_ALLOC,
+QCOW2_SUBCLUSTER_NORMAL,
+QCOW2_SUBCLUSTER_COMPRESSED,
+QCOW2_SUBCLUSTER_INVALID,
+} QCow2SubclusterType;
+
 typedef enum QCow2MetadataOverlap {
  

[PATCH v9 28/34] qcow2: Add subcluster support to qcow2_co_pwrite_zeroes()

2020-06-28 Thread Alberto Garcia
This works now at the subcluster level and pwrite_zeroes_alignment is
updated accordingly.

qcow2_cluster_zeroize() is turned into qcow2_subcluster_zeroize() with
the following changes:

   - The request can now be subcluster-aligned.

   - The cluster-aligned body of the request is still zeroized using
 zero_in_l2_slice() as before.

   - The subcluster-aligned head and tail of the request are zeroized
 with the new zero_l2_subclusters() function.

There is just one thing to take into account for a possible future
improvement: compressed clusters cannot be partially zeroized so
zero_l2_subclusters() on the head or the tail can return -ENOTSUP.
This makes the caller repeat the *complete* request and write actual
zeroes to disk. This is sub-optimal because

   1) if the head area was compressed we would still be able to use
  the fast path for the body and possibly the tail.

   2) if the tail area was compressed we are writing zeroes to the
  head and the body areas, which are already zeroized.

Signed-off-by: Alberto Garcia 
Reviewed-by: Eric Blake 
---
 block/qcow2.h |  4 +--
 block/qcow2-cluster.c | 80 +++
 block/qcow2.c | 27 ---
 3 files changed, 90 insertions(+), 21 deletions(-)

diff --git a/block/qcow2.h b/block/qcow2.h
index 4fad40b96b..4ef4ae4ab0 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -898,8 +898,8 @@ void qcow2_alloc_cluster_abort(BlockDriverState *bs, 
QCowL2Meta *m);
 int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
   uint64_t bytes, enum qcow2_discard_type type,
   bool full_discard);
-int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
-  uint64_t bytes, int flags);
+int qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset,
+ uint64_t bytes, int flags);
 
 int qcow2_expand_zero_clusters(BlockDriverState *bs,
BlockDriverAmendStatusCB *status_cb,
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index deff838fe8..1641976028 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -2015,12 +2015,58 @@ static int zero_in_l2_slice(BlockDriverState *bs, 
uint64_t offset,
 return nb_clusters;
 }
 
-int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
-  uint64_t bytes, int flags)
+static int zero_l2_subclusters(BlockDriverState *bs, uint64_t offset,
+   unsigned nb_subclusters)
+{
+BDRVQcow2State *s = bs->opaque;
+uint64_t *l2_slice;
+uint64_t old_l2_bitmap, l2_bitmap;
+int l2_index, ret, sc = offset_to_sc_index(s, offset);
+
+/* For full clusters use zero_in_l2_slice() instead */
+assert(nb_subclusters > 0 && nb_subclusters < s->subclusters_per_cluster);
+assert(sc + nb_subclusters <= s->subclusters_per_cluster);
+
+ret = get_cluster_table(bs, offset, &l2_slice, &l2_index);
+if (ret < 0) {
+return ret;
+}
+
+switch (qcow2_get_cluster_type(bs, get_l2_entry(s, l2_slice, l2_index))) {
+case QCOW2_CLUSTER_COMPRESSED:
+ret = -ENOTSUP; /* We cannot partially zeroize compressed clusters */
+goto out;
+case QCOW2_CLUSTER_NORMAL:
+case QCOW2_CLUSTER_UNALLOCATED:
+break;
+default:
+g_assert_not_reached();
+}
+
+old_l2_bitmap = l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index);
+
+l2_bitmap |=  QCOW_OFLAG_SUB_ZERO_RANGE(sc, sc + nb_subclusters);
+l2_bitmap &= ~QCOW_OFLAG_SUB_ALLOC_RANGE(sc, sc + nb_subclusters);
+
+if (old_l2_bitmap != l2_bitmap) {
+set_l2_bitmap(s, l2_slice, l2_index, l2_bitmap);
+qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
+}
+
+ret = 0;
+out:
+qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
+
+return ret;
+}
+
+int qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset,
+ uint64_t bytes, int flags)
 {
 BDRVQcow2State *s = bs->opaque;
 uint64_t end_offset = offset + bytes;
 uint64_t nb_clusters;
+unsigned head, tail;
 int64_t cleared;
 int ret;
 
@@ -2035,8 +2081,8 @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t 
offset,
 }
 
 /* Caller must pass aligned values, except at image end */
-assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
-assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) ||
+assert(offset_into_subcluster(s, offset) == 0);
+assert(offset_into_subcluster(s, end_offset) == 0 ||
end_offset >= bs->total_sectors << BDRV_SECTOR_BITS);
 
 /* The zero flag is only supported by version 3 and newer */
@@ -2044,11 +2090,26 @@ int qcow2_cluster_zeroize(BlockDriverState *bs, 
uint64_t offset,
 return -ENOTSUP;
 }
 
-/* Each L2 slice is handled by its own loop iteration */
-nb_clusters = size_to_clusters(s, bytes);
+head = MIN(end_offset,

[PATCH v9 15/34] qcow2: Add qcow2_get_subcluster_range_type()

2020-06-28 Thread Alberto Garcia
There are situations in which we want to know how many contiguous
subclusters of the same type there are in a given cluster. This can be
done by simply iterating over the subclusters and repeatedly calling
qcow2_get_subcluster_type() for each one of them.

However once we determined the type of a subcluster we can check the
rest efficiently by counting the number of adjacent ones (or zeroes)
in the bitmap. This is what this function does.

Signed-off-by: Alberto Garcia 
Reviewed-by: Eric Blake 
---
 block/qcow2-cluster.c | 51 +++
 1 file changed, 51 insertions(+)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 8b2fc550b7..32dc6e75e3 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -375,6 +375,57 @@ fail:
 return ret;
 }
 
+/*
+ * For a given L2 entry, count the number of contiguous subclusters of
+ * the same type starting from @sc_from. Compressed clusters are
+ * treated as if they were divided into subclusters of size
+ * s->subcluster_size.
+ *
+ * Return the number of contiguous subclusters and set @type to the
+ * subcluster type.
+ *
+ * If the L2 entry is invalid return -errno and set @type to
+ * QCOW2_SUBCLUSTER_INVALID.
+ */
+G_GNUC_UNUSED
+static int qcow2_get_subcluster_range_type(BlockDriverState *bs,
+   uint64_t l2_entry,
+   uint64_t l2_bitmap,
+   unsigned sc_from,
+   QCow2SubclusterType *type)
+{
+BDRVQcow2State *s = bs->opaque;
+uint32_t val;
+
+*type = qcow2_get_subcluster_type(bs, l2_entry, l2_bitmap, sc_from);
+
+if (*type == QCOW2_SUBCLUSTER_INVALID) {
+return -EINVAL;
+} else if (!has_subclusters(s) || *type == QCOW2_SUBCLUSTER_COMPRESSED) {
+return s->subclusters_per_cluster - sc_from;
+}
+
+switch (*type) {
+case QCOW2_SUBCLUSTER_NORMAL:
+val = l2_bitmap | QCOW_OFLAG_SUB_ALLOC_RANGE(0, sc_from);
+return cto32(val) - sc_from;
+
+case QCOW2_SUBCLUSTER_ZERO_PLAIN:
+case QCOW2_SUBCLUSTER_ZERO_ALLOC:
+val = (l2_bitmap | QCOW_OFLAG_SUB_ZERO_RANGE(0, sc_from)) >> 32;
+return cto32(val) - sc_from;
+
+case QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN:
+case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC:
+val = ((l2_bitmap >> 32) | l2_bitmap)
+& ~QCOW_OFLAG_SUB_ALLOC_RANGE(0, sc_from);
+return ctz32(val) - sc_from;
+
+default:
+g_assert_not_reached();
+}
+}
+
 /*
  * Checks how many clusters in a given L2 slice are contiguous in the image
  * file. As soon as one of the flags in the bitmask stop_flags changes compared
-- 
2.20.1




[PATCH v9 18/34] qcow2: Replace QCOW2_CLUSTER_* with QCOW2_SUBCLUSTER_*

2020-06-28 Thread Alberto Garcia
In order to support extended L2 entries some functions of the qcow2
driver need to start dealing with subclusters instead of clusters.

qcow2_get_host_offset() is modified to return the subcluster type
instead of the cluster type, and all callers are updated to replace
all values of QCow2ClusterType with their QCow2SubclusterType
equivalents.

This patch only changes the data types, there are no semantic changes.

Signed-off-by: Alberto Garcia 
Reviewed-by: Max Reitz 
Reviewed-by: Vladimir Sementsov-Ogievskiy 
---
 block/qcow2.h |  2 +-
 block/qcow2-cluster.c | 10 +++
 block/qcow2.c | 70 ++-
 3 files changed, 42 insertions(+), 40 deletions(-)

diff --git a/block/qcow2.h b/block/qcow2.h
index 74f65793bd..5df761edc3 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -894,7 +894,7 @@ int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t 
sector_num,
 
 int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
   unsigned int *bytes, uint64_t *host_offset,
-  QCow2ClusterType *cluster_type);
+  QCow2SubclusterType *subcluster_type);
 int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
unsigned int *bytes, uint64_t *host_offset,
QCowL2Meta **m);
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 1e5681b0c6..ed7b92dbb2 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -564,15 +564,15 @@ static int coroutine_fn 
do_perform_cow_write(BlockDriverState *bs,
  * offset that we are interested in.
  *
  * On exit, *bytes is the number of bytes starting at offset that have the same
- * cluster type and (if applicable) are stored contiguously in the image file.
- * The cluster type is stored in *cluster_type.
- * Compressed clusters are always returned one by one.
+ * subcluster type and (if applicable) are stored contiguously in the image
+ * file. The subcluster type is stored in *subcluster_type.
+ * Compressed clusters are always processed one by one.
  *
  * Returns 0 on success, -errno in error cases.
  */
 int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
   unsigned int *bytes, uint64_t *host_offset,
-  QCow2ClusterType *cluster_type)
+  QCow2SubclusterType *subcluster_type)
 {
 BDRVQcow2State *s = bs->opaque;
 unsigned int l2_index;
@@ -713,7 +713,7 @@ out:
 assert(bytes_available - offset_in_cluster <= UINT_MAX);
 *bytes = bytes_available - offset_in_cluster;
 
-*cluster_type = type;
+*subcluster_type = qcow2_cluster_to_subcluster_type(type);
 
 return 0;
 
diff --git a/block/qcow2.c b/block/qcow2.c
index 89e17bdaba..2f7a2a7c7a 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2033,7 +2033,7 @@ static int coroutine_fn 
qcow2_co_block_status(BlockDriverState *bs,
 BDRVQcow2State *s = bs->opaque;
 uint64_t host_offset;
 unsigned int bytes;
-QCow2ClusterType type;
+QCow2SubclusterType type;
 int ret, status = 0;
 
 qemu_co_mutex_lock(&s->lock);
@@ -2053,15 +2053,16 @@ static int coroutine_fn 
qcow2_co_block_status(BlockDriverState *bs,
 
 *pnum = bytes;
 
-if ((type == QCOW2_CLUSTER_NORMAL || type == QCOW2_CLUSTER_ZERO_ALLOC) &&
-!s->crypto) {
+if ((type == QCOW2_SUBCLUSTER_NORMAL ||
+ type == QCOW2_SUBCLUSTER_ZERO_ALLOC) && !s->crypto) {
 *map = host_offset;
 *file = s->data_file->bs;
 status |= BDRV_BLOCK_OFFSET_VALID;
 }
-if (type == QCOW2_CLUSTER_ZERO_PLAIN || type == QCOW2_CLUSTER_ZERO_ALLOC) {
+if (type == QCOW2_SUBCLUSTER_ZERO_PLAIN ||
+type == QCOW2_SUBCLUSTER_ZERO_ALLOC) {
 status |= BDRV_BLOCK_ZERO;
-} else if (type != QCOW2_CLUSTER_UNALLOCATED) {
+} else if (type != QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN) {
 status |= BDRV_BLOCK_DATA;
 }
 if (s->metadata_preallocation && (status & BDRV_BLOCK_DATA) &&
@@ -2158,7 +2159,7 @@ typedef struct Qcow2AioTask {
 AioTask task;
 
 BlockDriverState *bs;
-QCow2ClusterType cluster_type; /* only for read */
+QCow2SubclusterType subcluster_type; /* only for read */
 uint64_t host_offset; /* or full descriptor in compressed clusters */
 uint64_t offset;
 uint64_t bytes;
@@ -2171,7 +2172,7 @@ static coroutine_fn int 
qcow2_co_preadv_task_entry(AioTask *task);
 static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
AioTaskPool *pool,
AioTaskFunc func,
-   QCow2ClusterType cluster_type,
+   QCow2SubclusterType subcluster_type,
uint64_t host_offset,
uint64_t offset,
uint64_t bytes,
@@ -2185,

[PATCH v9 33/34] qcow2: Assert that expand_zero_clusters_in_l1() does not support subclusters

2020-06-28 Thread Alberto Garcia
This function is only used by qcow2_expand_zero_clusters() to
downgrade a qcow2 image to a previous version. This would require
transforming all extended L2 entries into normal L2 entries but this
is not a simple task and there are no plans to implement this at the
moment.

Signed-off-by: Alberto Garcia 
Reviewed-by: Eric Blake 
---
 block/qcow2-cluster.c  | 8 +++-
 tests/qemu-iotests/061 | 6 ++
 tests/qemu-iotests/061.out | 5 +
 3 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index c8217081f2..e8bb1f32f3 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -2157,6 +2157,9 @@ static int expand_zero_clusters_in_l1(BlockDriverState 
*bs, uint64_t *l1_table,
 int ret;
 int i, j;
 
+/* qcow2_downgrade() is not allowed in images with subclusters */
+assert(!has_subclusters(s));
+
 slice_size2 = s->l2_slice_size * l2_entry_size(s);
 n_slices = s->cluster_size / slice_size2;
 
@@ -2225,7 +2228,8 @@ static int expand_zero_clusters_in_l1(BlockDriverState 
*bs, uint64_t *l1_table,
 if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN) {
 if (!bs->backing) {
 /* not backed; therefore we can simply deallocate the
- * cluster */
+ * cluster. No need to call set_l2_bitmap(), this
+ * function doesn't support images with subclusters. */
 set_l2_entry(s, l2_slice, j, 0);
 l2_dirty = true;
 continue;
@@ -2296,6 +2300,8 @@ static int expand_zero_clusters_in_l1(BlockDriverState 
*bs, uint64_t *l1_table,
 } else {
 set_l2_entry(s, l2_slice, j, offset);
 }
+/* No need to call set_l2_bitmap() after set_l2_entry() because
+ * this function doesn't support images with subclusters. */
 l2_dirty = true;
 }
 
diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
index 10eb243164..23add2dfe3 100755
--- a/tests/qemu-iotests/061
+++ b/tests/qemu-iotests/061
@@ -303,6 +303,12 @@ $QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
 _img_info --format-specific
 _check_test_img
 
+echo
+echo "=== Testing version downgrade with extended L2 entries ==="
+echo
+_make_test_img -o "compat=1.1,extended_l2=on" 64M
+$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
+
 echo
 echo "=== Try changing the external data file ==="
 echo
diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out
index f618259d47..a139d4f1fe 100644
--- a/tests/qemu-iotests/061.out
+++ b/tests/qemu-iotests/061.out
@@ -528,6 +528,11 @@ Format specific information:
 extended l2: false
 No errors were found on the image.
 
+=== Testing version downgrade with extended L2 entries ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+qemu-img: Cannot downgrade an image with incompatible features 0x10 set
+
 === Try changing the external data file ===
 
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-- 
2.20.1




[PATCH v9 21/34] qcow2: Add subcluster support to qcow2_get_host_offset()

2020-06-28 Thread Alberto Garcia
The logic of this function remains pretty much the same, except that
it uses count_contiguous_subclusters(), which combines the logic of
count_contiguous_clusters() / count_contiguous_clusters_unallocated()
and checks individual subclusters.

qcow2_cluster_to_subcluster_type() is not necessary as a separate
function anymore so it's inlined into its caller.

Signed-off-by: Alberto Garcia 
Reviewed-by: Eric Blake 
---
 block/qcow2.h |  38 ---
 block/qcow2-cluster.c | 150 ++
 2 files changed, 92 insertions(+), 96 deletions(-)

diff --git a/block/qcow2.h b/block/qcow2.h
index 5df761edc3..4fad40b96b 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -710,29 +710,6 @@ static inline QCow2ClusterType 
qcow2_get_cluster_type(BlockDriverState *bs,
 }
 }
 
-/*
- * For an image without extended L2 entries, return the
- * QCow2SubclusterType equivalent of a given QCow2ClusterType.
- */
-static inline
-QCow2SubclusterType qcow2_cluster_to_subcluster_type(QCow2ClusterType type)
-{
-switch (type) {
-case QCOW2_CLUSTER_COMPRESSED:
-return QCOW2_SUBCLUSTER_COMPRESSED;
-case QCOW2_CLUSTER_ZERO_PLAIN:
-return QCOW2_SUBCLUSTER_ZERO_PLAIN;
-case QCOW2_CLUSTER_ZERO_ALLOC:
-return QCOW2_SUBCLUSTER_ZERO_ALLOC;
-case QCOW2_CLUSTER_NORMAL:
-return QCOW2_SUBCLUSTER_NORMAL;
-case QCOW2_CLUSTER_UNALLOCATED:
-return QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN;
-default:
-g_assert_not_reached();
-}
-}
-
 /*
  * In an image without subsclusters @l2_bitmap is ignored and
  * @sc_index must be 0.
@@ -776,7 +753,20 @@ QCow2SubclusterType 
qcow2_get_subcluster_type(BlockDriverState *bs,
 g_assert_not_reached();
 }
 } else {
-return qcow2_cluster_to_subcluster_type(type);
+switch (type) {
+case QCOW2_CLUSTER_COMPRESSED:
+return QCOW2_SUBCLUSTER_COMPRESSED;
+case QCOW2_CLUSTER_ZERO_PLAIN:
+return QCOW2_SUBCLUSTER_ZERO_PLAIN;
+case QCOW2_CLUSTER_ZERO_ALLOC:
+return QCOW2_SUBCLUSTER_ZERO_ALLOC;
+case QCOW2_CLUSTER_NORMAL:
+return QCOW2_SUBCLUSTER_NORMAL;
+case QCOW2_CLUSTER_UNALLOCATED:
+return QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN;
+default:
+g_assert_not_reached();
+}
 }
 }
 
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 59dd9bda29..2f3bd3a882 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -426,66 +426,66 @@ static int 
qcow2_get_subcluster_range_type(BlockDriverState *bs,
 }
 
 /*
- * Checks how many clusters in a given L2 slice are contiguous in the image
- * file. As soon as one of the flags in the bitmask stop_flags changes compared
- * to the first cluster, the search is stopped and the cluster is not counted
- * as contiguous. (This allows it, for example, to stop at the first compressed
- * cluster which may require a different handling)
+ * Return the number of contiguous subclusters of the exact same type
+ * in a given L2 slice, starting from cluster @l2_index, subcluster
+ * @sc_index. Allocated subclusters are required to be contiguous in
+ * the image file.
+ * At most @nb_clusters are checked (note that this means clusters,
+ * not subclusters).
+ * Compressed clusters are always processed one by one but for the
+ * purpose of this count they are treated as if they were divided into
+ * subclusters of size s->subcluster_size.
+ * On failure return -errno and update @l2_index to point to the
+ * invalid entry.
  */
-static int count_contiguous_clusters(BlockDriverState *bs, int nb_clusters,
-int cluster_size, uint64_t *l2_slice, int l2_index, uint64_t 
stop_flags)
+static int count_contiguous_subclusters(BlockDriverState *bs, int nb_clusters,
+unsigned sc_index, uint64_t *l2_slice,
+unsigned *l2_index)
 {
 BDRVQcow2State *s = bs->opaque;
-int i;
-QCow2ClusterType first_cluster_type;
-uint64_t mask = stop_flags | L2E_OFFSET_MASK | QCOW_OFLAG_COMPRESSED;
-uint64_t first_entry = get_l2_entry(s, l2_slice, l2_index);
-uint64_t offset = first_entry & mask;
+int i, count = 0;
+bool check_offset;
+uint64_t expected_offset;
+QCow2SubclusterType expected_type, type;
 
-first_cluster_type = qcow2_get_cluster_type(bs, first_entry);
-if (first_cluster_type == QCOW2_CLUSTER_UNALLOCATED) {
-return 0;
-}
-
-/* must be allocated */
-assert(first_cluster_type == QCOW2_CLUSTER_NORMAL ||
-   first_cluster_type == QCOW2_CLUSTER_ZERO_ALLOC);
+assert(*l2_index + nb_clusters <= s->l2_size);
 
 for (i = 0; i < nb_clusters; i++) {
-uint64_t l2_entry = get_l2_entry(s, l2_slice, l2_index + i) & mask;
-if (offset + (uint64_t) i * cluster_size != l2_entry) {
+unsigned first_sc = (i == 0) ? sc_index : 0;
+uint64_t l2_entry = get_l2

[PATCH v9 30/34] qcow2: Add prealloc field to QCowL2Meta

2020-06-28 Thread Alberto Garcia
This field allows us to indicate that the L2 metadata update does not
come from a write request with actual data but from a preallocation
request.

For traditional images this does not make any difference, but for
images with extended L2 entries this means that the clusters are
allocated normally in the L2 table but individual subclusters are
marked as unallocated.

This will allow preallocating images that have a backing file.

There is one special case: when we resize an existing image we can
also request that the new clusters are preallocated. If the image
already had a backing file then we have to hide any possible stale
data and zero out the new clusters (see commit 955c7d6687 for more
details).

In this case the subclusters cannot be left as unallocated so the L2
bitmap must be updated.

Signed-off-by: Alberto Garcia 
Reviewed-by: Eric Blake 
---
 block/qcow2.h | 8 
 block/qcow2-cluster.c | 2 +-
 block/qcow2.c | 6 ++
 3 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/block/qcow2.h b/block/qcow2.h
index 4ef4ae4ab0..f3499e53bf 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -463,6 +463,14 @@ typedef struct QCowL2Meta
  */
 bool skip_cow;
 
+/**
+ * Indicates that this is not a normal write request but a preallocation.
+ * If the image has extended L2 entries this means that no new individual
+ * subclusters will be marked as allocated in the L2 bitmap (but any
+ * existing contents of that bitmap will be kept).
+ */
+bool prealloc;
+
 /**
  * The I/O vector with the data from the actual guest write request.
  * If non-NULL, this is meant to be merged together with the data
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 1641976028..c8217081f2 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1066,7 +1066,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, 
QCowL2Meta *m)
 set_l2_entry(s, l2_slice, l2_index + i, offset | QCOW_OFLAG_COPIED);
 
 /* Update bitmap with the subclusters that were just written */
-if (has_subclusters(s)) {
+if (has_subclusters(s) && !m->prealloc) {
 uint64_t l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index + i);
 unsigned written_from = m->cow_start.offset;
 unsigned written_to = m->cow_end.offset + m->cow_end.nb_bytes ?:
diff --git a/block/qcow2.c b/block/qcow2.c
index 72bd25e774..003f166024 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2086,6 +2086,7 @@ static coroutine_fn int 
qcow2_handle_l2meta(BlockDriverState *bs,
 QCowL2Meta *next;
 
 if (link_l2) {
+assert(!l2meta->prealloc);
 ret = qcow2_alloc_cluster_link_l2(bs, l2meta);
 if (ret) {
 goto out;
@@ -3131,6 +3132,7 @@ static int coroutine_fn preallocate_co(BlockDriverState 
*bs, uint64_t offset,
 
 while (meta) {
 QCowL2Meta *next = meta->next;
+meta->prealloc = true;
 
 ret = qcow2_alloc_cluster_link_l2(bs, meta);
 if (ret < 0) {
@@ -4224,6 +4226,7 @@ static int coroutine_fn 
qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
 int64_t clusters_allocated;
 int64_t old_file_size, last_cluster, new_file_size;
 uint64_t nb_new_data_clusters, nb_new_l2_tables;
+bool subclusters_need_allocation = false;
 
 /* With a data file, preallocation means just allocating the metadata
  * and forwarding the truncate request to the data file */
@@ -4305,6 +4308,8 @@ static int coroutine_fn 
qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
BDRV_REQ_ZERO_WRITE, NULL);
 if (ret >= 0) {
 flags &= ~BDRV_REQ_ZERO_WRITE;
+/* Ensure that we read zeroes and not backing file data */
+subclusters_need_allocation = true;
 }
 } else {
 ret = -1;
@@ -4343,6 +4348,7 @@ static int coroutine_fn 
qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
 .offset   = nb_clusters << s->cluster_bits,
 .nb_bytes = 0,
 },
+.prealloc = !subclusters_need_allocation,
 };
 qemu_co_queue_init(&allocation.dependent_requests);
 
-- 
2.20.1




[PATCH v9 23/34] qcow2: Add subcluster support to discard_in_l2_slice()

2020-06-28 Thread Alberto Garcia
Two things need to be taken into account here:

1) With full_discard == true the L2 entry must be cleared completely.
   This also includes the L2 bitmap if the image has extended L2
   entries.

2) With full_discard == false we have to make the discarded cluster
   read back as zeroes. With normal L2 entries this is done with the
   QCOW_OFLAG_ZERO bit, whereas with extended L2 entries this is done
   with the individual 'all zeroes' bits for each subcluster.

   Note however that QCOW_OFLAG_ZERO is not supported in v2 qcow2
   images so, if there is a backing file, discard cannot guarantee
   that the image will read back as zeroes. If this is important for
   the caller it should forbid it as qcow2_co_pdiscard() does (see
   80f5c01183 for more details).

Signed-off-by: Alberto Garcia 
Reviewed-by: Eric Blake 
---
 block/qcow2-cluster.c | 52 +++
 1 file changed, 23 insertions(+), 29 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 4e59bbd545..edfc8ea91c 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1847,11 +1847,17 @@ static int discard_in_l2_slice(BlockDriverState *bs, 
uint64_t offset,
 assert(nb_clusters <= INT_MAX);
 
 for (i = 0; i < nb_clusters; i++) {
-uint64_t old_l2_entry;
-
-old_l2_entry = get_l2_entry(s, l2_slice, l2_index + i);
+uint64_t old_l2_entry = get_l2_entry(s, l2_slice, l2_index + i);
+uint64_t old_l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index + i);
+uint64_t new_l2_entry = old_l2_entry;
+uint64_t new_l2_bitmap = old_l2_bitmap;
+QCow2ClusterType cluster_type =
+qcow2_get_cluster_type(bs, old_l2_entry);
 
 /*
+ * If full_discard is true, the cluster should not read back as zeroes,
+ * but rather fall through to the backing file.
+ *
  * If full_discard is false, make sure that a discarded area reads back
  * as zeroes for v3 images (we cannot do it for v2 without actually
  * writing a zero-filled buffer). We can skip the operation if the
@@ -1860,40 +1866,28 @@ static int discard_in_l2_slice(BlockDriverState *bs, 
uint64_t offset,
  *
  * TODO We might want to use bdrv_block_status(bs) here, but we're
  * holding s->lock, so that doesn't work today.
- *
- * If full_discard is true, the sector should not read back as zeroes,
- * but rather fall through to the backing file.
  */
-switch (qcow2_get_cluster_type(bs, old_l2_entry)) {
-case QCOW2_CLUSTER_UNALLOCATED:
-if (full_discard || !bs->backing) {
-continue;
+if (full_discard) {
+new_l2_entry = new_l2_bitmap = 0;
+} else if (bs->backing || qcow2_cluster_is_allocated(cluster_type)) {
+if (has_subclusters(s)) {
+new_l2_entry = 0;
+new_l2_bitmap = QCOW_L2_BITMAP_ALL_ZEROES;
+} else {
+new_l2_entry = s->qcow_version >= 3 ? QCOW_OFLAG_ZERO : 0;
 }
-break;
+}
 
-case QCOW2_CLUSTER_ZERO_PLAIN:
-if (!full_discard) {
-continue;
-}
-break;
-
-case QCOW2_CLUSTER_ZERO_ALLOC:
-case QCOW2_CLUSTER_NORMAL:
-case QCOW2_CLUSTER_COMPRESSED:
-break;
-
-default:
-abort();
+if (old_l2_entry == new_l2_entry && old_l2_bitmap == new_l2_bitmap) {
+continue;
 }
 
 /* First remove L2 entries */
 qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
-if (!full_discard && s->qcow_version >= 3) {
-set_l2_entry(s, l2_slice, l2_index + i, QCOW_OFLAG_ZERO);
-} else {
-set_l2_entry(s, l2_slice, l2_index + i, 0);
+set_l2_entry(s, l2_slice, l2_index + i, new_l2_entry);
+if (has_subclusters(s)) {
+set_l2_bitmap(s, l2_slice, l2_index + i, new_l2_bitmap);
 }
-
 /* Then decrease the refcount */
 qcow2_free_any_clusters(bs, old_l2_entry, 1, type);
 }
-- 
2.20.1




[PATCH v9 12/34] qcow2: Add l2_entry_size()

2020-06-28 Thread Alberto Garcia
qcow2 images with subclusters have 128-bit L2 entries. The first 64
bits contain the same information as traditional images and the last
64 bits form a bitmap with the status of each individual subcluster.

Because of that we cannot assume that L2 entries are sizeof(uint64_t)
anymore. This function returns the proper value for the image.

Signed-off-by: Alberto Garcia 
Reviewed-by: Max Reitz 
---
 block/qcow2.h  |  9 +
 block/qcow2-cluster.c  | 12 ++--
 block/qcow2-refcount.c | 14 --
 block/qcow2.c  |  8 
 4 files changed, 27 insertions(+), 16 deletions(-)

diff --git a/block/qcow2.h b/block/qcow2.h
index 4fe31adfd3..46b351229a 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -80,6 +80,10 @@
 
 #define QCOW_EXTL2_SUBCLUSTERS_PER_CLUSTER 32
 
+/* Size of normal and extended L2 entries */
+#define L2E_SIZE_NORMAL   (sizeof(uint64_t))
+#define L2E_SIZE_EXTENDED (sizeof(uint64_t) * 2)
+
 #define MIN_CLUSTER_BITS 9
 #define MAX_CLUSTER_BITS 21
 
@@ -521,6 +525,11 @@ static inline bool has_subclusters(BDRVQcow2State *s)
 return false;
 }
 
+static inline size_t l2_entry_size(BDRVQcow2State *s)
+{
+return has_subclusters(s) ? L2E_SIZE_EXTENDED : L2E_SIZE_NORMAL;
+}
+
 static inline uint64_t get_l2_entry(BDRVQcow2State *s, uint64_t *l2_slice,
 int idx)
 {
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 76fd0f3cdb..8b2fc550b7 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -208,7 +208,7 @@ static int l2_load(BlockDriverState *bs, uint64_t offset,
uint64_t l2_offset, uint64_t **l2_slice)
 {
 BDRVQcow2State *s = bs->opaque;
-int start_of_slice = sizeof(uint64_t) *
+int start_of_slice = l2_entry_size(s) *
 (offset_to_l2_index(s, offset) - offset_to_l2_slice_index(s, offset));
 
 return qcow2_cache_get(bs, s->l2_table_cache, l2_offset + start_of_slice,
@@ -281,7 +281,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index)
 
 /* allocate a new l2 entry */
 
-l2_offset = qcow2_alloc_clusters(bs, s->l2_size * sizeof(uint64_t));
+l2_offset = qcow2_alloc_clusters(bs, s->l2_size * l2_entry_size(s));
 if (l2_offset < 0) {
 ret = l2_offset;
 goto fail;
@@ -305,7 +305,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index)
 
 /* allocate a new entry in the l2 cache */
 
-slice_size2 = s->l2_slice_size * sizeof(uint64_t);
+slice_size2 = s->l2_slice_size * l2_entry_size(s);
 n_slices = s->cluster_size / slice_size2;
 
 trace_qcow2_l2_allocate_get_empty(bs, l1_index);
@@ -369,7 +369,7 @@ fail:
 }
 s->l1_table[l1_index] = old_l2_offset;
 if (l2_offset > 0) {
-qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t),
+qcow2_free_clusters(bs, l2_offset, s->l2_size * l2_entry_size(s),
 QCOW2_DISCARD_ALWAYS);
 }
 return ret;
@@ -716,7 +716,7 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t 
offset,
 
 /* Then decrease the refcount of the old table */
 if (l2_offset) {
-qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t),
+qcow2_free_clusters(bs, l2_offset, s->l2_size * l2_entry_size(s),
 QCOW2_DISCARD_OTHER);
 }
 
@@ -1913,7 +1913,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState 
*bs, uint64_t *l1_table,
 int ret;
 int i, j;
 
-slice_size2 = s->l2_slice_size * sizeof(uint64_t);
+slice_size2 = s->l2_slice_size * l2_entry_size(s);
 n_slices = s->cluster_size / slice_size2;
 
 if (!is_active_l1) {
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 04546838e8..770c5dbc83 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1254,7 +1254,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
 l2_slice = NULL;
 l1_table = NULL;
 l1_size2 = l1_size * sizeof(uint64_t);
-slice_size2 = s->l2_slice_size * sizeof(uint64_t);
+slice_size2 = s->l2_slice_size * l2_entry_size(s);
 n_slices = s->cluster_size / slice_size2;
 
 s->cache_discards = true;
@@ -1605,7 +1605,7 @@ static int check_refcounts_l2(BlockDriverState *bs, 
BdrvCheckResult *res,
 int i, l2_size, nb_csectors, ret;
 
 /* Read L2 table from disk */
-l2_size = s->l2_size * sizeof(uint64_t);
+l2_size = s->l2_size * l2_entry_size(s);
 l2_table = g_malloc(l2_size);
 
 ret = bdrv_pread(bs->file, l2_offset, l2_table, l2_size);
@@ -1680,15 +1680,16 @@ static int check_refcounts_l2(BlockDriverState *bs, 
BdrvCheckResult *res,
 fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR",
 offset);
 if (fix & BDRV_FIX_ERRORS) {
+int idx = i * (l2_entry_size(s) / sizeof(uint64_t));
 uint64_t l2e_offset =
-l2_offset + (uint64_t

[PATCH v9 09/34] qcow2: Add subcluster-related fields to BDRVQcow2State

2020-06-28 Thread Alberto Garcia
This patch adds the following new fields to BDRVQcow2State:

- subclusters_per_cluster: Number of subclusters in a cluster
- subcluster_size: The size of each subcluster, in bytes
- subcluster_bits: No. of bits so 1 << subcluster_bits = subcluster_size

Images without subclusters are treated as if they had exactly one
subcluster per cluster (i.e. subcluster_size = cluster_size).

Signed-off-by: Alberto Garcia 
Reviewed-by: Max Reitz 
Reviewed-by: Vladimir Sementsov-Ogievskiy 
---
 block/qcow2.h | 5 +
 block/qcow2.c | 5 +
 2 files changed, 10 insertions(+)

diff --git a/block/qcow2.h b/block/qcow2.h
index 2064dd3d85..eee4c8de9c 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -78,6 +78,8 @@
 /* The cluster reads as all zeros */
 #define QCOW_OFLAG_ZERO (1ULL << 0)
 
+#define QCOW_EXTL2_SUBCLUSTERS_PER_CLUSTER 32
+
 #define MIN_CLUSTER_BITS 9
 #define MAX_CLUSTER_BITS 21
 
@@ -295,6 +297,9 @@ typedef struct BDRVQcow2State {
 int cluster_bits;
 int cluster_size;
 int l2_slice_size;
+int subcluster_bits;
+int subcluster_size;
+int subclusters_per_cluster;
 int l2_bits;
 int l2_size;
 int l1_size;
diff --git a/block/qcow2.c b/block/qcow2.c
index afb00ada42..5c175a314c 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1433,6 +1433,11 @@ static int coroutine_fn qcow2_do_open(BlockDriverState 
*bs, QDict *options,
 }
 }
 
+s->subclusters_per_cluster =
+has_subclusters(s) ? QCOW_EXTL2_SUBCLUSTERS_PER_CLUSTER : 1;
+s->subcluster_size = s->cluster_size / s->subclusters_per_cluster;
+s->subcluster_bits = ctz32(s->subcluster_size);
+
 /* Check support for various header values */
 if (header.refcount_order > 6) {
 error_setg(errp, "Reference count entry width too large; may not "
-- 
2.20.1




[PATCH v9 34/34] iotests: Add tests for qcow2 images with extended L2 entries

2020-06-28 Thread Alberto Garcia
Signed-off-by: Alberto Garcia 
---
 tests/qemu-iotests/271 | 901 +
 tests/qemu-iotests/271.out | 724 +
 tests/qemu-iotests/group   |   1 +
 3 files changed, 1626 insertions(+)
 create mode 100755 tests/qemu-iotests/271
 create mode 100644 tests/qemu-iotests/271.out

diff --git a/tests/qemu-iotests/271 b/tests/qemu-iotests/271
new file mode 100755
index 00..5ef3ebb2bf
--- /dev/null
+++ b/tests/qemu-iotests/271
@@ -0,0 +1,901 @@
+#!/bin/bash
+#
+# Test qcow2 images with extended L2 entries
+#
+# Copyright (C) 2019-2020 Igalia, S.L.
+# Author: Alberto Garcia 
+#
+# 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 .
+#
+
+# creator
+owner=be...@igalia.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+status=1   # failure is the default!
+
+_cleanup()
+{
+_cleanup_test_img
+rm -f "$TEST_IMG.raw"
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt qcow2
+_supported_proto file nfs
+_supported_os Linux
+_unsupported_imgopts extended_l2 compat=0.10 cluster_size data_file
+
+l2_offset=$((0x4))
+
+_verify_img()
+{
+$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.raw" | grep -v 'Images are 
identical'
+$QEMU_IMG check "$TEST_IMG" | _filter_qemu_img_check | \
+grep -v 'No errors were found on the image'
+}
+
+# Compare the bitmap of an extended L2 entry against an expected value
+_verify_l2_bitmap()
+{
+entry_no="$1"# L2 entry number, starting from 0
+expected_alloc="$alloc"  # Space-separated list of allocated subcluster 
indexes
+expected_zero="$zero"# Space-separated list of zero subcluster indexes
+
+offset=$(($l2_offset + $entry_no * 16))
+entry=$(peek_file_be "$TEST_IMG" $offset 8)
+offset=$(($offset + 8))
+bitmap=$(peek_file_be "$TEST_IMG" $offset 8)
+
+expected_bitmap=0
+for bit in $expected_alloc; do
+expected_bitmap=$(($expected_bitmap | (1 << $bit)))
+done
+for bit in $expected_zero; do
+expected_bitmap=$(($expected_bitmap | (1 << (32 + $bit
+done
+printf -v expected_bitmap "%llu" $expected_bitmap # Convert to unsigned
+
+printf "L2 entry #%d: 0x%016lx %016lx\n" "$entry_no" "$entry" "$bitmap"
+if [ "$bitmap" != "$expected_bitmap" ]; then
+printf "ERROR: expecting bitmap   0x%016lx\n" "$expected_bitmap"
+fi
+}
+
+# This should be called as _run_test c=XXX sc=XXX off=XXX len=XXX cmd=XXX
+# c:   cluster number (0 if unset)
+# sc:  subcluster number inside cluster @c (0 if unset)
+# off: offset inside subcluster @sc, in kilobytes (0 if unset)
+# len: request length, passed directly to qemu-io (e.g: 256, 4k, 1M, ...)
+# cmd: the command to pass to qemu-io, must be one of
+#  write-> write
+#  zero -> write -z
+#  unmap-> write -z -u
+#  compress -> write -c
+#  discard  -> discard
+_run_test()
+{
+unset c sc off len cmd
+for var in "$@"; do eval "$var"; done
+case "${cmd:-write}" in
+zero)
+cmd="write -q -z";;
+unmap)
+cmd="write -q -z -u";;
+compress)
+pat=$((${pat:-0} + 1))
+cmd="write -q -c -P ${pat}";;
+write)
+pat=$((${pat:-0} + 1))
+cmd="write -q -P ${pat}";;
+discard)
+cmd="discard -q";;
+*)
+echo "Unknown option $cmd"
+exit 1;;
+esac
+c="${c:-0}"
+sc="${sc:-0}"
+off="${off:-0}"
+offset="$(($c * 64 + $sc * 2 + $off))"
+[ "$offset" != 0 ] && offset="${offset}k"
+cmd="$cmd ${offset} ${len}"
+raw_cmd=$(echo $cmd | sed s/-c//) # Raw images don't support -c
+echo $cmd | sed 's/-P [0-9][0-9]\?/-P PATTERN/'
+$QEMU_IO -c "$cmd" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "$raw_cmd" -f raw "$TEST_IMG.raw" | _filter_qemu_io
+_verify_img
+_verify_l2_bitmap "$c"
+}
+
+_reset_img()
+{
+size="$1"
+$QEMU_IMG create -f raw "$TEST_IMG.raw" "$size" | _filter_img_create
+if [ "$use_backing_file" = "yes" ]; then
+$QEMU_IMG create -f raw "$TEST_IMG.base" "$size" | _filter_img_create
+$QEMU_IO -c "write -q -P 0xFF 0 $size" -f raw "$TEST_IMG.base" | 
_filter_qemu_io
+$QEMU_IO -c "write -q -P 0xFF 0 $size" -f raw "$TEST_IMG.raw" 

[PATCH v9 32/34] qcow2: Allow preallocation and backing files if extended_l2 is set

2020-06-28 Thread Alberto Garcia
Traditional qcow2 images don't allow preallocation if a backing file
is set. This is because once a cluster is allocated there is no way to
tell that its data should be read from the backing file.

Extended L2 entries have individual allocation bits for each
subcluster, and therefore it is perfectly possible to have an
allocated cluster with all its subclusters unallocated.

Signed-off-by: Alberto Garcia 
Reviewed-by: Eric Blake 
---
 block/qcow2.c  | 7 ---
 tests/qemu-iotests/206.out | 2 +-
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 37bfae823c..1ea8d3b87e 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -3451,10 +3451,11 @@ qcow2_co_create(BlockdevCreateOptions *create_options, 
Error **errp)
 qcow2_opts->preallocation = PREALLOC_MODE_OFF;
 }
 if (qcow2_opts->has_backing_file &&
-qcow2_opts->preallocation != PREALLOC_MODE_OFF)
+qcow2_opts->preallocation != PREALLOC_MODE_OFF &&
+!qcow2_opts->extended_l2)
 {
-error_setg(errp, "Backing file and preallocation cannot be used at "
-   "the same time");
+error_setg(errp, "Backing file and preallocation can only be used at "
+   "the same time if extended_l2 is on");
 ret = -EINVAL;
 goto out;
 }
diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out
index 363c5abe35..a100849fcb 100644
--- a/tests/qemu-iotests/206.out
+++ b/tests/qemu-iotests/206.out
@@ -203,7 +203,7 @@ Job failed: Different refcount widths than 16 bits require 
compatibility level 1
 === Invalid backing file options ===
 {"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": 
{"backing-file": "/dev/null", "driver": "qcow2", "file": "node0", 
"preallocation": "full", "size": 67108864}}}
 {"return": {}}
-Job failed: Backing file and preallocation cannot be used at the same time
+Job failed: Backing file and preallocation can only be used at the same time 
if extended_l2 is on
 {"execute": "job-dismiss", "arguments": {"id": "job0"}}
 {"return": {}}
 
-- 
2.20.1




[PATCH v9 25/34] qcow2: Update L2 bitmap in qcow2_alloc_cluster_link_l2()

2020-06-28 Thread Alberto Garcia
The L2 bitmap needs to be updated after each write to indicate what
new subclusters are now allocated. This needs to happen even if the
cluster was already allocated and the L2 entry was otherwise valid.

In some cases however a write operation doesn't need change the L2
bitmap (because all affected subclusters were already allocated). This
is detected in calculate_l2_meta(), and qcow2_alloc_cluster_link_l2()
is never called in those cases.

Signed-off-by: Alberto Garcia 
Reviewed-by: Eric Blake 
---
 block/qcow2-cluster.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index edfc8ea91c..2276cee6d6 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1061,6 +1061,24 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, 
QCowL2Meta *m)
 assert((offset & L2E_OFFSET_MASK) == offset);
 
 set_l2_entry(s, l2_slice, l2_index + i, offset | QCOW_OFLAG_COPIED);
+
+/* Update bitmap with the subclusters that were just written */
+if (has_subclusters(s)) {
+uint64_t l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index + i);
+unsigned written_from = m->cow_start.offset;
+unsigned written_to = m->cow_end.offset + m->cow_end.nb_bytes ?:
+m->nb_clusters << s->cluster_bits;
+int first_sc, last_sc;
+/* Narrow written_from and written_to down to the current cluster 
*/
+written_from = MAX(written_from, i << s->cluster_bits);
+written_to   = MIN(written_to, (i + 1) << s->cluster_bits);
+assert(written_from < written_to);
+first_sc = offset_to_sc_index(s, written_from);
+last_sc  = offset_to_sc_index(s, written_to - 1);
+l2_bitmap |= QCOW_OFLAG_SUB_ALLOC_RANGE(first_sc, last_sc + 1);
+l2_bitmap &= ~QCOW_OFLAG_SUB_ZERO_RANGE(first_sc, last_sc + 1);
+set_l2_bitmap(s, l2_slice, l2_index + i, l2_bitmap);
+}
  }
 
 
-- 
2.20.1




[PATCH v9 22/34] qcow2: Add subcluster support to zero_in_l2_slice()

2020-06-28 Thread Alberto Garcia
The QCOW_OFLAG_ZERO bit that indicates that a cluster reads as
zeroes is only used in standard L2 entries. Extended L2 entries use
individual 'all zeroes' bits for each subcluster.

This must be taken into account when updating the L2 entry and also
when deciding that an existing entry does not need to be updated.

Signed-off-by: Alberto Garcia 
Reviewed-by: Eric Blake 
---
 block/qcow2-cluster.c | 36 +++-
 1 file changed, 19 insertions(+), 17 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 2f3bd3a882..4e59bbd545 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1956,7 +1956,6 @@ static int zero_in_l2_slice(BlockDriverState *bs, 
uint64_t offset,
 int l2_index;
 int ret;
 int i;
-bool unmap = !!(flags & BDRV_REQ_MAY_UNMAP);
 
 ret = get_cluster_table(bs, offset, &l2_slice, &l2_index);
 if (ret < 0) {
@@ -1968,28 +1967,31 @@ static int zero_in_l2_slice(BlockDriverState *bs, 
uint64_t offset,
 assert(nb_clusters <= INT_MAX);
 
 for (i = 0; i < nb_clusters; i++) {
-uint64_t old_offset;
-QCow2ClusterType cluster_type;
+uint64_t old_l2_entry = get_l2_entry(s, l2_slice, l2_index + i);
+uint64_t old_l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index + i);
+QCow2ClusterType type = qcow2_get_cluster_type(bs, old_l2_entry);
+bool unmap = (type == QCOW2_CLUSTER_COMPRESSED) ||
+((flags & BDRV_REQ_MAY_UNMAP) && qcow2_cluster_is_allocated(type));
+uint64_t new_l2_entry = unmap ? 0 : old_l2_entry;
+uint64_t new_l2_bitmap = old_l2_bitmap;
 
-old_offset = get_l2_entry(s, l2_slice, l2_index + i);
+if (has_subclusters(s)) {
+new_l2_bitmap = QCOW_L2_BITMAP_ALL_ZEROES;
+} else {
+new_l2_entry |= QCOW_OFLAG_ZERO;
+}
 
-/*
- * Minimize L2 changes if the cluster already reads back as
- * zeroes with correct allocation.
- */
-cluster_type = qcow2_get_cluster_type(bs, old_offset);
-if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN ||
-(cluster_type == QCOW2_CLUSTER_ZERO_ALLOC && !unmap)) {
+if (old_l2_entry == new_l2_entry && old_l2_bitmap == new_l2_bitmap) {
 continue;
 }
 
 qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
-if (cluster_type == QCOW2_CLUSTER_COMPRESSED || unmap) {
-set_l2_entry(s, l2_slice, l2_index + i, QCOW_OFLAG_ZERO);
-qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST);
-} else {
-uint64_t entry = get_l2_entry(s, l2_slice, l2_index + i);
-set_l2_entry(s, l2_slice, l2_index + i, entry | QCOW_OFLAG_ZERO);
+if (unmap) {
+qcow2_free_any_clusters(bs, old_l2_entry, 1, 
QCOW2_DISCARD_REQUEST);
+}
+set_l2_entry(s, l2_slice, l2_index + i, new_l2_entry);
+if (has_subclusters(s)) {
+set_l2_bitmap(s, l2_slice, l2_index + i, new_l2_bitmap);
 }
 }
 
-- 
2.20.1




[PATCH v9 20/34] qcow2: Add subcluster support to calculate_l2_meta()

2020-06-28 Thread Alberto Garcia
If an image has subclusters then there are more copy-on-write
scenarios that we need to consider. Let's say we have a write request
from the middle of subcluster #3 until the end of the cluster:

1) If we are writing to a newly allocated cluster then we need
   copy-on-write. The previous contents of subclusters #0 to #3 must
   be copied to the new cluster. We can optimize this process by
   skipping all leading unallocated or zero subclusters (the status of
   those skipped subclusters will be reflected in the new L2 bitmap).

2) If we are overwriting an existing cluster:

   2.1) If subcluster #3 is unallocated or has the all-zeroes bit set
then we need copy-on-write (on subcluster #3 only).

   2.2) If subcluster #3 was already allocated then there is no need
for any copy-on-write. However we still need to update the L2
bitmap to reflect possible changes in the allocation status of
subclusters #4 to #31. Because of this, this function checks
if all the overwritten subclusters are already allocated and
in this case it returns without creating a new QCowL2Meta
structure.

After all these changes l2meta_cow_start() and l2meta_cow_end()
are not necessarily cluster-aligned anymore. We need to update the
calculation of old_start and old_end in handle_dependencies() to
guarantee that no two requests try to write on the same cluster.

Signed-off-by: Alberto Garcia 
Reviewed-by: Eric Blake 
---
 block/qcow2-cluster.c | 163 +-
 1 file changed, 131 insertions(+), 32 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index ed7b92dbb2..59dd9bda29 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -387,7 +387,6 @@ fail:
  * If the L2 entry is invalid return -errno and set @type to
  * QCOW2_SUBCLUSTER_INVALID.
  */
-G_GNUC_UNUSED
 static int qcow2_get_subcluster_range_type(BlockDriverState *bs,
uint64_t l2_entry,
uint64_t l2_bitmap,
@@ -1110,56 +1109,148 @@ void qcow2_alloc_cluster_abort(BlockDriverState *bs, 
QCowL2Meta *m)
  * If @keep_old is true it means that the clusters were already
  * allocated and will be overwritten. If false then the clusters are
  * new and we have to decrease the reference count of the old ones.
+ *
+ * Returns 0 on success, -errno on failure.
  */
-static void calculate_l2_meta(BlockDriverState *bs,
-  uint64_t host_cluster_offset,
-  uint64_t guest_offset, unsigned bytes,
-  uint64_t *l2_slice, QCowL2Meta **m, bool 
keep_old)
+static int calculate_l2_meta(BlockDriverState *bs, uint64_t 
host_cluster_offset,
+ uint64_t guest_offset, unsigned bytes,
+ uint64_t *l2_slice, QCowL2Meta **m, bool keep_old)
 {
 BDRVQcow2State *s = bs->opaque;
-int l2_index = offset_to_l2_slice_index(s, guest_offset);
-uint64_t l2_entry;
+int sc_index, l2_index = offset_to_l2_slice_index(s, guest_offset);
+uint64_t l2_entry, l2_bitmap;
 unsigned cow_start_from, cow_end_to;
 unsigned cow_start_to = offset_into_cluster(s, guest_offset);
 unsigned cow_end_from = cow_start_to + bytes;
 unsigned nb_clusters = size_to_clusters(s, cow_end_from);
 QCowL2Meta *old_m = *m;
-QCow2ClusterType type;
+QCow2SubclusterType type;
+int i;
+bool skip_cow = keep_old;
 
 assert(nb_clusters <= s->l2_slice_size - l2_index);
 
-/* Return if there's no COW (all clusters are normal and we keep them) */
-if (keep_old) {
-int i;
-for (i = 0; i < nb_clusters; i++) {
-l2_entry = get_l2_entry(s, l2_slice, l2_index + i);
-if (qcow2_get_cluster_type(bs, l2_entry) != QCOW2_CLUSTER_NORMAL) {
-break;
+/* Check the type of all affected subclusters */
+for (i = 0; i < nb_clusters; i++) {
+l2_entry = get_l2_entry(s, l2_slice, l2_index + i);
+l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index + i);
+if (skip_cow) {
+unsigned write_from = MAX(cow_start_to, i << s->cluster_bits);
+unsigned write_to = MIN(cow_end_from, (i + 1) << s->cluster_bits);
+int first_sc = offset_to_sc_index(s, write_from);
+int last_sc = offset_to_sc_index(s, write_to - 1);
+int cnt = qcow2_get_subcluster_range_type(bs, l2_entry, l2_bitmap,
+  first_sc, &type);
+/* Is any of the subclusters of type != QCOW2_SUBCLUSTER_NORMAL ? 
*/
+if (type != QCOW2_SUBCLUSTER_NORMAL || first_sc + cnt <= last_sc) {
+skip_cow = false;
 }
+} else {
+/* If we can't skip the cow we can still look for invalid entries 
*/
+type = qcow2_get_subcluster_type(bs, l2_entry, l2_bitmap, 0);
 }
-

[PATCH v9 00/34] Add subcluster allocation to qcow2

2020-06-28 Thread Alberto Garcia
Hi,

here's the new version of the patches to add subcluster allocation
support to qcow2.

Please refer to the cover letter of the first version for a full
description of the patches:

   https://lists.gnu.org/archive/html/qemu-block/2019-10/msg00983.html

The important change from v8 is patch 24. This patch fixes unaligned
offsets in ZERO_ALLOC clusters, but the previous implementation was
not working for images with extended L2 entries and was simply adding
dead code. The new implementation works properly.

If you want to test this series make sure to apply this patch first:

   https://lists.gnu.org/archive/html/qemu-block/2020-06/msg00504.html

Berto

Based-on: <20200610094600.4029-1-be...@igalia.com>

v9:
- Patch 24: Change the algorithm so it actually does something in
  images with extended L2 entries.
- Patch 31: Update expected test results after rebase
- Patch 34: Fix a couple of typos.
Add a new test for the changes in patch 24.
Test concurrent requests on different subclusters of the
same cluster.

v8: https://lists.gnu.org/archive/html/qemu-block/2020-06/msg00546.html
v7: https://lists.gnu.org/archive/html/qemu-block/2020-05/msg01683.html
v6: https://lists.gnu.org/archive/html/qemu-block/2020-05/msg01583.html
v5: https://lists.gnu.org/archive/html/qemu-block/2020-05/msg00251.html
v4: https://lists.gnu.org/archive/html/qemu-block/2020-03/msg00966.html
v3: https://lists.gnu.org/archive/html/qemu-block/2019-12/msg00587.html
v2: https://lists.gnu.org/archive/html/qemu-block/2019-10/msg01642.html
v1: https://lists.gnu.org/archive/html/qemu-block/2019-10/msg00983.html

Output of git backport-diff against v8:

Key:
[] : patches are identical
[] : number of functional differences between upstream/downstream patch
[down] : patch is downstream-only
The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively

001/34:[] [--] 'qcow2: Make Qcow2AioTask store the full host offset'
002/34:[] [--] 'qcow2: Convert qcow2_get_cluster_offset() into 
qcow2_get_host_offset()'
003/34:[] [--] 'qcow2: Add calculate_l2_meta()'
004/34:[] [--] 'qcow2: Split cluster_needs_cow() out of 
count_cow_clusters()'
005/34:[] [--] 'qcow2: Process QCOW2_CLUSTER_ZERO_ALLOC clusters in 
handle_copied()'
006/34:[] [--] 'qcow2: Add get_l2_entry() and set_l2_entry()'
007/34:[] [--] 'qcow2: Document the Extended L2 Entries feature'
008/34:[] [--] 'qcow2: Add dummy has_subclusters() function'
009/34:[] [--] 'qcow2: Add subcluster-related fields to BDRVQcow2State'
010/34:[] [--] 'qcow2: Add offset_to_sc_index()'
011/34:[] [--] 'qcow2: Add offset_into_subcluster() and 
size_to_subclusters()'
012/34:[] [--] 'qcow2: Add l2_entry_size()'
013/34:[] [--] 'qcow2: Update get/set_l2_entry() and add 
get/set_l2_bitmap()'
014/34:[] [--] 'qcow2: Add QCow2SubclusterType and 
qcow2_get_subcluster_type()'
015/34:[] [--] 'qcow2: Add qcow2_get_subcluster_range_type()'
016/34:[] [--] 'qcow2: Add qcow2_cluster_is_allocated()'
017/34:[] [--] 'qcow2: Add cluster type parameter to 
qcow2_get_host_offset()'
018/34:[] [--] 'qcow2: Replace QCOW2_CLUSTER_* with QCOW2_SUBCLUSTER_*'
019/34:[] [--] 'qcow2: Handle QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC'
020/34:[] [--] 'qcow2: Add subcluster support to calculate_l2_meta()'
021/34:[] [--] 'qcow2: Add subcluster support to qcow2_get_host_offset()'
022/34:[] [--] 'qcow2: Add subcluster support to zero_in_l2_slice()'
023/34:[] [--] 'qcow2: Add subcluster support to discard_in_l2_slice()'
024/34:[0025] [FC] 'qcow2: Add subcluster support to check_refcounts_l2()'
025/34:[] [--] 'qcow2: Update L2 bitmap in qcow2_alloc_cluster_link_l2()'
026/34:[] [--] 'qcow2: Clear the L2 bitmap when allocating a compressed 
cluster'
027/34:[] [--] 'qcow2: Add subcluster support to handle_alloc_space()'
028/34:[] [--] 'qcow2: Add subcluster support to qcow2_co_pwrite_zeroes()'
029/34:[] [--] 'qcow2: Add subcluster support to qcow2_measure()'
030/34:[] [--] 'qcow2: Add prealloc field to QCowL2Meta'
031/34:[0004] [FC] 'qcow2: Add the 'extended_l2' option and the 
QCOW2_INCOMPAT_EXTL2 bit'
032/34:[] [--] 'qcow2: Allow preallocation and backing files if extended_l2 
is set'
033/34:[] [--] 'qcow2: Assert that expand_zero_clusters_in_l1() does not 
support subclusters'
034/34:[0152] [FC] 'iotests: Add tests for qcow2 images with extended L2 
entries'

Alberto Garcia (34):
  qcow2: Make Qcow2AioTask store the full host offset
  qcow2: Convert qcow2_get_cluster_offset() into qcow2_get_host_offset()
  qcow2: Add calculate_l2_meta()
  qcow2: Split cluster_needs_cow() out of count_cow_clusters()
  qcow2: Process QCOW2_CLUSTER_ZERO_ALLOC clusters in handle_copied()
  qcow2: Add get_l2_entry() and set_l2_entry()
  qcow2: Document the Extended L2 Entries feature
  qcow2: Add dummy has_subclusters() function
  qcow2: Add subcluster-related fields to BDRVQcow2State
  qcow2: Add o

[PATCH v9 29/34] qcow2: Add subcluster support to qcow2_measure()

2020-06-28 Thread Alberto Garcia
Extended L2 entries are bigger than normal L2 entries so this has an
impact on the amount of metadata needed for a qcow2 file.

Signed-off-by: Alberto Garcia 
Reviewed-by: Max Reitz 
---
 block/qcow2.c | 20 +---
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 4edc3c72b9..72bd25e774 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -3233,28 +3233,31 @@ int64_t qcow2_refcount_metadata_size(int64_t clusters, 
size_t cluster_size,
  * @total_size: virtual disk size in bytes
  * @cluster_size: cluster size in bytes
  * @refcount_order: refcount bits power-of-2 exponent
+ * @extended_l2: true if the image has extended L2 entries
  *
  * Returns: Total number of bytes required for the fully allocated image
  * (including metadata).
  */
 static int64_t qcow2_calc_prealloc_size(int64_t total_size,
 size_t cluster_size,
-int refcount_order)
+int refcount_order,
+bool extended_l2)
 {
 int64_t meta_size = 0;
 uint64_t nl1e, nl2e;
 int64_t aligned_total_size = ROUND_UP(total_size, cluster_size);
+size_t l2e_size = extended_l2 ? L2E_SIZE_EXTENDED : L2E_SIZE_NORMAL;
 
 /* header: 1 cluster */
 meta_size += cluster_size;
 
 /* total size of L2 tables */
 nl2e = aligned_total_size / cluster_size;
-nl2e = ROUND_UP(nl2e, cluster_size / sizeof(uint64_t));
-meta_size += nl2e * sizeof(uint64_t);
+nl2e = ROUND_UP(nl2e, cluster_size / l2e_size);
+meta_size += nl2e * l2e_size;
 
 /* total size of L1 tables */
-nl1e = nl2e * sizeof(uint64_t) / cluster_size;
+nl1e = nl2e * l2e_size / cluster_size;
 nl1e = ROUND_UP(nl1e, cluster_size / sizeof(uint64_t));
 meta_size += nl1e * sizeof(uint64_t);
 
@@ -4845,6 +4848,8 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, 
BlockDriverState *in_bs,
 PreallocMode prealloc;
 bool has_backing_file;
 bool has_luks;
+bool extended_l2 = false; /* Set to false until the option is added */
+size_t l2e_size;
 
 /* Parse image creation options */
 cluster_size = qcow2_opt_get_cluster_size_del(opts, &local_err);
@@ -4910,8 +4915,9 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, 
BlockDriverState *in_bs,
 virtual_size = ROUND_UP(virtual_size, cluster_size);
 
 /* Check that virtual disk size is valid */
+l2e_size = extended_l2 ? L2E_SIZE_EXTENDED : L2E_SIZE_NORMAL;
 l2_tables = DIV_ROUND_UP(virtual_size / cluster_size,
- cluster_size / sizeof(uint64_t));
+ cluster_size / l2e_size);
 if (l2_tables * sizeof(uint64_t) > QCOW_MAX_L1_SIZE) {
 error_setg(&local_err, "The image size is too large "
"(try using a larger cluster size)");
@@ -4974,9 +4980,9 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, 
BlockDriverState *in_bs,
 }
 
 info = g_new0(BlockMeasureInfo, 1);
-info->fully_allocated =
+info->fully_allocated = luks_payload_size +
 qcow2_calc_prealloc_size(virtual_size, cluster_size,
- ctz32(refcount_bits)) + luks_payload_size;
+ ctz32(refcount_bits), extended_l2);
 
 /*
  * Remove data clusters that are not required.  This overestimates the
-- 
2.20.1




[PATCH v9 01/34] qcow2: Make Qcow2AioTask store the full host offset

2020-06-28 Thread Alberto Garcia
The file_cluster_offset field of Qcow2AioTask stores a cluster-aligned
host offset. In practice this is not very useful because all users(*)
of this structure need the final host offset into the cluster, which
they calculate using

   host_offset = file_cluster_offset + offset_into_cluster(s, offset)

There is no reason why Qcow2AioTask cannot store host_offset directly
and that is what this patch does.

(*) compressed clusters are the exception: in this case what
file_cluster_offset was storing was the full compressed cluster
descriptor (offset + size). This does not change with this patch
but it is documented now.

Signed-off-by: Alberto Garcia 
Reviewed-by: Eric Blake 
Reviewed-by: Max Reitz 
Reviewed-by: Vladimir Sementsov-Ogievskiy 
---
 block/qcow2.c  | 69 ++
 block/trace-events |  2 +-
 2 files changed, 34 insertions(+), 37 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index e20590c3b7..d792137af6 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -74,7 +74,7 @@ typedef struct {
 
 static int coroutine_fn
 qcow2_co_preadv_compressed(BlockDriverState *bs,
-   uint64_t file_cluster_offset,
+   uint64_t cluster_descriptor,
uint64_t offset,
uint64_t bytes,
QEMUIOVector *qiov,
@@ -2103,7 +2103,7 @@ out:
 
 static coroutine_fn int
 qcow2_co_preadv_encrypted(BlockDriverState *bs,
-   uint64_t file_cluster_offset,
+   uint64_t host_offset,
uint64_t offset,
uint64_t bytes,
QEMUIOVector *qiov,
@@ -2130,16 +2130,12 @@ qcow2_co_preadv_encrypted(BlockDriverState *bs,
 }
 
 BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
-ret = bdrv_co_pread(s->data_file,
-file_cluster_offset + offset_into_cluster(s, offset),
-bytes, buf, 0);
+ret = bdrv_co_pread(s->data_file, host_offset, bytes, buf, 0);
 if (ret < 0) {
 goto fail;
 }
 
-if (qcow2_co_decrypt(bs,
- file_cluster_offset + offset_into_cluster(s, offset),
- offset, buf, bytes) < 0)
+if (qcow2_co_decrypt(bs, host_offset, offset, buf, bytes) < 0)
 {
 ret = -EIO;
 goto fail;
@@ -2157,7 +2153,7 @@ typedef struct Qcow2AioTask {
 
 BlockDriverState *bs;
 QCow2ClusterType cluster_type; /* only for read */
-uint64_t file_cluster_offset;
+uint64_t host_offset; /* or full descriptor in compressed clusters */
 uint64_t offset;
 uint64_t bytes;
 QEMUIOVector *qiov;
@@ -2170,7 +2166,7 @@ static coroutine_fn int qcow2_add_task(BlockDriverState 
*bs,
AioTaskPool *pool,
AioTaskFunc func,
QCow2ClusterType cluster_type,
-   uint64_t file_cluster_offset,
+   uint64_t host_offset,
uint64_t offset,
uint64_t bytes,
QEMUIOVector *qiov,
@@ -2185,7 +2181,7 @@ static coroutine_fn int qcow2_add_task(BlockDriverState 
*bs,
 .bs = bs,
 .cluster_type = cluster_type,
 .qiov = qiov,
-.file_cluster_offset = file_cluster_offset,
+.host_offset = host_offset,
 .offset = offset,
 .bytes = bytes,
 .qiov_offset = qiov_offset,
@@ -2194,7 +2190,7 @@ static coroutine_fn int qcow2_add_task(BlockDriverState 
*bs,
 
 trace_qcow2_add_task(qemu_coroutine_self(), bs, pool,
  func == qcow2_co_preadv_task_entry ? "read" : "write",
- cluster_type, file_cluster_offset, offset, bytes,
+ cluster_type, host_offset, offset, bytes,
  qiov, qiov_offset);
 
 if (!pool) {
@@ -2208,13 +2204,12 @@ static coroutine_fn int qcow2_add_task(BlockDriverState 
*bs,
 
 static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
  QCow2ClusterType cluster_type,
- uint64_t file_cluster_offset,
+ uint64_t host_offset,
  uint64_t offset, uint64_t bytes,
  QEMUIOVector *qiov,
  size_t qiov_offset)
 {
 BDRVQcow2State *s = bs->opaque;
-int offset_in_cluster = offset_into_cluster(s, offset);
 
 switch (cluster_type) {
 case QCOW2_CLUSTER_ZERO_PLAIN:
@@ -2230,19 +2225,17 @@ static coroutine_fn int 
qcow2_co_preadv_task(BlockDriverState *bs,
qiov, qiov_offs

  1   2   >