Re: [PATCH v5 21/45] block: add bdrv_try_set_aio_context_tran transaction action

2022-06-13 Thread Hanna Reitz

On 09.06.22 16:56, Vladimir Sementsov-Ogievskiy wrote:

On 6/8/22 14:49, Hanna Reitz wrote:

On 30.03.22 23:28, Vladimir Sementsov-Ogievskiy wrote:

To be used in further commit.

Signed-off-by: Vladimir Sementsov-Ogievskiy 
---
  block.c | 48 
  1 file changed, 48 insertions(+)


Looking at bdrv_child_try_set_aio_context(), it looks like 
bdrv_can_set_aio_context() were supposed to be the .prepare action, 
and bdrv_set_aio_context_ignore() should be the .commit action.  Can 
we not use it that way?






The difference is that we want the whole action be done in .prepare 
stage, not only the check. It's generally better: when do several 
actions in a transaction, actions usually depend on result of previous 
actions.


Ah, yes.

And I think it's necessary for graph update. Graph relations are 
changed during other actions .prepare phases, so I can't imagine how 
to postpone aio-context update to .commit phase.


OK, sounds good.

But I agree, that having both _can_ / _set_  and *tran APIs don't look 
good. May be we can refactor it.. But not in this series I think)





Re: [PATCH v5 21/45] block: add bdrv_try_set_aio_context_tran transaction action

2022-06-13 Thread Hanna Reitz

On 30.03.22 23:28, Vladimir Sementsov-Ogievskiy wrote:

To be used in further commit.

Signed-off-by: Vladimir Sementsov-Ogievskiy 
---
  block.c | 48 
  1 file changed, 48 insertions(+)

diff --git a/block.c b/block.c
index be19964f89..1900cdf277 100644
--- a/block.c
+++ b/block.c
@@ -2907,6 +2907,54 @@ static void bdrv_child_free(BdrvChild *child)
  g_free(child);
  }
  
+typedef struct BdrvTrySetAioContextState {

+BlockDriverState *bs;
+AioContext *old_ctx;
+} BdrvTrySetAioContextState;
+
+static void bdrv_try_set_aio_context_abort(void *opaque)
+{
+BdrvTrySetAioContextState *s = opaque;
+
+if (bdrv_get_aio_context(s->bs) != s->old_ctx) {
+bdrv_try_set_aio_context(s->bs, s->old_ctx, &error_abort);


As far as I understand, users of this transaction will need to do a bit 
of AioContext lock shuffling: To set the context, they need to hold 
old_ctx, but not new_ctx; but in case of abort, they need to release 
old_ctx and acquire new_ctx before the abort handlers are called.  (Due 
to the constraints on bdrv_set_aio_context_ignore().)


If that’s true, I think that should be documented somewhere.


+}
+}
+





[PATCH v2] ui: move 'pc-bios/keymaps' to 'ui/keymaps'

2022-06-13 Thread Daniel P . Berrangé
The 'keymaps' directory contents is nothing to do with the firmware
blobs. The 'pc-bios/keymaps' directory appears to have been used
previously as a convenience for getting the files installed into
a subdir of the firmware install dir, as well as to make it easier
to launch QEMU directly from the build tree. These requirements
do not need to be reflected in the source tree arrangement. The
keymaps logically belong with the UI code, and meson can install
them into the right place. For in-tree execution, we merely need
a suitable symlink from the source tree to the build tree.

Signed-off-by: Daniel P. Berrangé 
---

Changed in v2:

  - Make configure symlink ui/keymaps to $BUILD/pc-bios
so in-tree build execution works. (Thanks Volker)

 configure   | 4 
 pc-bios/meson.build | 1 -
 {pc-bios => ui}/keymaps/ar  | 0
 {pc-bios => ui}/keymaps/bepo| 0
 {pc-bios => ui}/keymaps/cz  | 0
 {pc-bios => ui}/keymaps/da  | 0
 {pc-bios => ui}/keymaps/de  | 0
 {pc-bios => ui}/keymaps/de-ch   | 0
 {pc-bios => ui}/keymaps/en-gb   | 0
 {pc-bios => ui}/keymaps/en-us   | 0
 {pc-bios => ui}/keymaps/es  | 0
 {pc-bios => ui}/keymaps/et  | 0
 {pc-bios => ui}/keymaps/fi  | 0
 {pc-bios => ui}/keymaps/fo  | 0
 {pc-bios => ui}/keymaps/fr  | 0
 {pc-bios => ui}/keymaps/fr-be   | 0
 {pc-bios => ui}/keymaps/fr-ca   | 0
 {pc-bios => ui}/keymaps/fr-ch   | 0
 {pc-bios => ui}/keymaps/hr  | 0
 {pc-bios => ui}/keymaps/hu  | 0
 {pc-bios => ui}/keymaps/is  | 0
 {pc-bios => ui}/keymaps/it  | 0
 {pc-bios => ui}/keymaps/ja  | 0
 {pc-bios => ui}/keymaps/lt  | 0
 {pc-bios => ui}/keymaps/lv  | 0
 {pc-bios => ui}/keymaps/meson.build | 0
 {pc-bios => ui}/keymaps/mk  | 0
 {pc-bios => ui}/keymaps/nl  | 0
 {pc-bios => ui}/keymaps/no  | 0
 {pc-bios => ui}/keymaps/pl  | 0
 {pc-bios => ui}/keymaps/pt  | 0
 {pc-bios => ui}/keymaps/pt-br   | 0
 {pc-bios => ui}/keymaps/ru  | 0
 {pc-bios => ui}/keymaps/sl  | 0
 {pc-bios => ui}/keymaps/sv  | 0
 {pc-bios => ui}/keymaps/th  | 0
 {pc-bios => ui}/keymaps/tr  | 0
 ui/meson.build  | 1 +
 38 files changed, 5 insertions(+), 1 deletion(-)
 rename {pc-bios => ui}/keymaps/ar (100%)
 rename {pc-bios => ui}/keymaps/bepo (100%)
 rename {pc-bios => ui}/keymaps/cz (100%)
 rename {pc-bios => ui}/keymaps/da (100%)
 rename {pc-bios => ui}/keymaps/de (100%)
 rename {pc-bios => ui}/keymaps/de-ch (100%)
 rename {pc-bios => ui}/keymaps/en-gb (100%)
 rename {pc-bios => ui}/keymaps/en-us (100%)
 rename {pc-bios => ui}/keymaps/es (100%)
 rename {pc-bios => ui}/keymaps/et (100%)
 rename {pc-bios => ui}/keymaps/fi (100%)
 rename {pc-bios => ui}/keymaps/fo (100%)
 rename {pc-bios => ui}/keymaps/fr (100%)
 rename {pc-bios => ui}/keymaps/fr-be (100%)
 rename {pc-bios => ui}/keymaps/fr-ca (100%)
 rename {pc-bios => ui}/keymaps/fr-ch (100%)
 rename {pc-bios => ui}/keymaps/hr (100%)
 rename {pc-bios => ui}/keymaps/hu (100%)
 rename {pc-bios => ui}/keymaps/is (100%)
 rename {pc-bios => ui}/keymaps/it (100%)
 rename {pc-bios => ui}/keymaps/ja (100%)
 rename {pc-bios => ui}/keymaps/lt (100%)
 rename {pc-bios => ui}/keymaps/lv (100%)
 rename {pc-bios => ui}/keymaps/meson.build (100%)
 rename {pc-bios => ui}/keymaps/mk (100%)
 rename {pc-bios => ui}/keymaps/nl (100%)
 rename {pc-bios => ui}/keymaps/no (100%)
 rename {pc-bios => ui}/keymaps/pl (100%)
 rename {pc-bios => ui}/keymaps/pt (100%)
 rename {pc-bios => ui}/keymaps/pt-br (100%)
 rename {pc-bios => ui}/keymaps/ru (100%)
 rename {pc-bios => ui}/keymaps/sl (100%)
 rename {pc-bios => ui}/keymaps/sv (100%)
 rename {pc-bios => ui}/keymaps/th (100%)
 rename {pc-bios => ui}/keymaps/tr (100%)

diff --git a/configure b/configure
index e69537c756..77c6864251 100755
--- a/configure
+++ b/configure
@@ -2226,6 +2226,10 @@ for f in $LINKS ; do
 fi
 done
 
+# Keymaps needs slightly different location in build
+# dir as we are simulating the installed data dir layout
+symlink "$source_path/ui/keymaps" "pc-bios/keymaps"
+
 # Mac OS X ships with a broken assembler
 roms=
 probe_target_compilers i386 x86_64
diff --git a/pc-bios/meson.build b/pc-bios/meson.build
index 41ba1c0ec7..e49c0e5f56 100644
--- a/pc-bios/meson.build
+++ b/pc-bios/meson.build
@@ -97,4 +97,3 @@ foreach f : blobs
 endforeach
 
 subdir('descriptors')
-subdir('keymaps')
diff --git a/pc-bios/keymaps/ar b/ui/keymaps/ar
similarity index 100%
rename from pc-bios/keymaps/ar
rename to ui/keymaps/ar
diff --git a/pc-bios/keymaps/bepo b/ui/keymaps/bepo
similarity index 100%
rename from pc-bios/keymaps/bepo
rename to ui/keymaps/bepo
diff --git a/pc-bios/keymaps/cz b/ui/keymaps/cz
similarity index 100%
rename from pc-bios/keymaps/cz
rename to ui/keymaps/cz
diff --git a/pc-bios/keymaps/da b/ui/keymaps/da
similarity index 100%
rename from pc-bios/keymap

[PATCH 0/7] crypto: Introduce ECDSA algorithm

2022-06-13 Thread Lei He
This patch introduced ECDSA algorithm for crypto:
1. make the built-in ASN.1 decoder support more ASN.1 types.
2. support ECDSA key and signature parsing.
3. implement the ECDSA algorithm using nettle and gcrypt respectively.

Lei He (7):
  crypto: Introduce ECDSA algorithm API
  crypto: Support more ASN.1 types
  crypto: remove "qemu/osdep.h" in rsakey.h
  crypto: Add ECDSA key parser
  crypto: Implement ECDSA algorithm by hogweed
  crypto: Implement ECDSA algorithm by gcrypt
  crypto: Add test suite for ECDSA algorithm

 crypto/akcipher-gcrypt.c.inc  | 400 ++
 crypto/akcipher-nettle.c.inc  | 268 +
 crypto/der.c  | 174 +++--
 crypto/der.h  | 128 +++-
 crypto/ecdsakey-builtin.c.inc | 248 +++
 crypto/ecdsakey.c | 118 +++
 crypto/ecdsakey.h |  66 +++
 crypto/meson.build|   1 +
 crypto/rsakey.c   |   1 +
 crypto/rsakey.h   |   1 -
 qapi/crypto.json  |  28 ++-
 tests/unit/test-crypto-akcipher.c | 227 +++--
 tests/unit/test-crypto-der.c  | 126 +---
 13 files changed, 1722 insertions(+), 64 deletions(-)
 create mode 100644 crypto/ecdsakey-builtin.c.inc
 create mode 100644 crypto/ecdsakey.c
 create mode 100644 crypto/ecdsakey.h

-- 
2.11.0




[PATCH 1/7] crypto: Introduce ECDSA algorithm API

2022-06-13 Thread Lei He
Introduce ECDSA related structures to qapi-crypto.

Signed-off-by: lei he 
---
 qapi/crypto.json | 28 ++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/qapi/crypto.json b/qapi/crypto.json
index 653e6e3f3d..c2fcdaa13a 100644
--- a/qapi/crypto.json
+++ b/qapi/crypto.json
@@ -545,7 +545,7 @@
 ##
 { 'enum': 'QCryptoAkCipherAlgorithm',
   'prefix': 'QCRYPTO_AKCIPHER_ALG',
-  'data': ['rsa']}
+  'data': ['rsa', 'ecdsa']}
 
 ##
 # @QCryptoAkCipherKeyType:
@@ -587,6 +587,29 @@
 'padding-alg': 'QCryptoRSAPaddingAlgorithm'}}
 
 ##
+# @QCryptoCurveID:
+#
+# The known curved for ECC algorithms.
+#
+# Since: 7.1
+##
+{ 'enum': 'QCryptoCurveID',
+  'prefix': 'QCRYPTO_CURVE_ID',
+  'data': ['nist-p192', 'nist-p256', 'nist-p384']}
+
+##
+# @QCryptoAkCipherOptionsECDSA:
+#
+# Specific parameters for ECDSA algorithm.
+#
+# @curve-id: QCryptoCurveId
+#
+# Since: 7.1
+##
+{ 'struct': 'QCryptoAkCipherOptionsECDSA',
+  'data': { 'curve-id':'QCryptoCurveID' }}
+
+##
 # @QCryptoAkCipherOptions:
 #
 # The options that are available for all asymmetric key algorithms
@@ -597,4 +620,5 @@
 { 'union': 'QCryptoAkCipherOptions',
   'base': { 'alg': 'QCryptoAkCipherAlgorithm' },
   'discriminator': 'alg',
-  'data': { 'rsa': 'QCryptoAkCipherOptionsRSA' }}
+  'data': { 'rsa': 'QCryptoAkCipherOptionsRSA',
+'ecdsa': 'QCryptoAkCipherOptionsECDSA' }}
-- 
2.11.0




[PATCH 6/7] crypto: Implement ECDSA algorithm by gcrypt

2022-06-13 Thread Lei He
Implement ECDSA algorithm by gcrypt

Signed-off-by: lei he 
---
 crypto/akcipher-gcrypt.c.inc | 400 +++
 1 file changed, 400 insertions(+)

diff --git a/crypto/akcipher-gcrypt.c.inc b/crypto/akcipher-gcrypt.c.inc
index abb1fb272e..24377bbec6 100644
--- a/crypto/akcipher-gcrypt.c.inc
+++ b/crypto/akcipher-gcrypt.c.inc
@@ -28,6 +28,7 @@
 #include "qapi/error.h"
 #include "sysemu/cryptodev.h"
 #include "rsakey.h"
+#include "ecdsakey.h"
 
 typedef struct QCryptoGcryptRSA {
 QCryptoAkCipher akcipher;
@@ -36,6 +37,13 @@ typedef struct QCryptoGcryptRSA {
 QCryptoHashAlgorithm hash_alg;
 } QCryptoGcryptRSA;
 
+typedef struct QCryptoGcryptECDSA {
+QCryptoAkCipher akcipher;
+gcry_sexp_t key;
+QCryptoCurveID curve_id;
+const char *curve_name;
+} QCryptoGcryptECDSA;
+
 static void qcrypto_gcrypt_rsa_free(QCryptoAkCipher *akcipher)
 {
 QCryptoGcryptRSA *rsa = (QCryptoGcryptRSA *)akcipher;
@@ -53,6 +61,12 @@ static QCryptoGcryptRSA *qcrypto_gcrypt_rsa_new(
 const uint8_t *key,  size_t keylen,
 Error **errp);
 
+static QCryptoGcryptECDSA *qcrypto_gcrypt_ecdsa_new(
+const QCryptoAkCipherOptionsECDSA *opts,
+QCryptoAkCipherKeyType type,
+const uint8_t *key, size_t keylen,
+Error **errp);
+
 QCryptoAkCipher *qcrypto_akcipher_new(const QCryptoAkCipherOptions *opts,
   QCryptoAkCipherKeyType type,
   const uint8_t *key, size_t keylen,
@@ -63,6 +77,10 @@ QCryptoAkCipher *qcrypto_akcipher_new(const 
QCryptoAkCipherOptions *opts,
 return (QCryptoAkCipher *)qcrypto_gcrypt_rsa_new(
 &opts->u.rsa, type, key, keylen, errp);
 
+case QCRYPTO_AKCIPHER_ALG_ECDSA:
+return (QCryptoAkCipher *)qcrypto_gcrypt_ecdsa_new(
+&opts->u.ecdsa, type, key, keylen, errp);
+
 default:
 error_setg(errp, "Unsupported algorithm: %u", opts->alg);
 return NULL;
@@ -564,6 +582,377 @@ error:
 return NULL;
 }
 
+static int qcrypto_gcrypt_parse_curve_id(QCryptoGcryptECDSA *ecdsa,
+const QCryptoAkCipherOptionsECDSA *opts, Error **errp)
+{
+/* ECDSA algorithm can't used for encryption */
+ecdsa->akcipher.max_plaintext_len = 0;
+ecdsa->akcipher.max_ciphertext_len = 0;
+
+switch (opts->curve_id) {
+case QCRYPTO_CURVE_ID_NIST_P192:
+ecdsa->curve_name = "nistp192";
+ecdsa->akcipher.max_signature_len =
+qcrypto_akcipher_ecdsasig_x9_62_size(192 / 8);
+ecdsa->akcipher.max_dgst_len = 192 / 8;
+break;
+
+case QCRYPTO_CURVE_ID_NIST_P256:
+ecdsa->curve_name = "nistp256";
+ecdsa->akcipher.max_signature_len =
+qcrypto_akcipher_ecdsasig_x9_62_size(256 / 8);
+ecdsa->akcipher.max_dgst_len = 256 / 8;
+break;
+
+case QCRYPTO_CURVE_ID_NIST_P384:
+ecdsa->curve_name = "nistp384";
+ecdsa->akcipher.max_signature_len =
+qcrypto_akcipher_ecdsasig_x9_62_size(384 / 8);
+ecdsa->akcipher.max_dgst_len = 256 / 8;
+break;
+
+default:
+error_setg(errp, "Unknown curve id: %d", opts->curve_id);
+return -1;
+}
+
+return 0;
+}
+
+static int qcrypto_gcrypt_parse_ecdsa_private_key(
+QCryptoGcryptECDSA *ecdsa, const char *curve_name,
+const uint8_t *key, size_t keylen,
+Error **errp)
+{
+g_autoptr(QCryptoAkCipherECDSAKey) ecdsa_key =
+qcrypto_akcipher_ecdsakey_parse(QCRYPTO_AKCIPHER_KEY_TYPE_PRIVATE,
+key, keylen, errp);
+gcry_mpi_t d = NULL;
+gcry_error_t err;
+int ret = -1;
+
+if (!ecdsa_key) {
+return ret;
+}
+
+err = gcry_mpi_scan(&d, GCRYMPI_FMT_USG, ecdsa_key->priv.data,
+ecdsa_key->priv.len, NULL);
+if (gcry_err_code(err) != 0) {
+error_setg(errp, "Failed to parse ECDSA parivate key: %s/%s",
+   gcry_strsource(err), gcry_strerror(err));
+return ret;
+}
+
+err = gcry_sexp_build(&ecdsa->key, NULL,
+"(private-key (ecc (curve %s) (d %m)))", curve_name, d);
+if (gcry_err_code(err) != 0) {
+error_setg(errp, "Failed to build ECDSA parivate key: %s/%s",
+   gcry_strsource(err), gcry_strerror(err));
+goto cleanup;
+}
+
+ret = 0;
+
+cleanup:
+gcry_mpi_release(d);
+return ret;
+}
+
+static int qcrypto_gcrypt_parse_ecdsa_public_key(
+QCryptoGcryptECDSA *ecdsa, const char *curve_name,
+const uint8_t *key, size_t keylen,
+Error **errp)
+{
+gcry_mpi_t q = NULL;
+gcry_error_t err;
+int ret = -1;
+
+err = gcry_mpi_scan(&q, GCRYMPI_FMT_USG, key, keylen, NULL);
+if (gcry_err_code(err) != 0) {
+error_setg(errp, "Failed to scan public point: %s/%s",
+   gcry_strsource(err), gcry_strerror(err));
+return -1;
+}
+
+err = gcry_sexp_build(&ecdsa->key, NULL,
+"(public-key (ecc (curve %s) (q %m)))", curve_nam

Re: [PULL 00/17] Kraxel 20220610 patches

2022-06-13 Thread Daniel P . Berrangé
On Sat, Jun 11, 2022 at 06:34:28PM +0200, Volker Rümelin wrote:
> Am 10.06.22 um 22:16 schrieb Richard Henderson:
> > On 6/10/22 02:20, Gerd Hoffmann wrote:
> > > The following changes since commit
> > > 9cc1bf1ebca550f8d90f967ccd2b6d2e00e81387:
> > > 
> > >    Merge tag 'pull-xen-20220609' of
> > > https://xenbits.xen.org/git-http/people/aperard/qemu-dm into staging
> > > (2022-06-09 08:25:17 -0700)
> > > 
> > > are available in the Git repository at:
> > > 
> > >    git://git.kraxel.org/qemu tags/kraxel-20220610-pull-request
> > > 
> > > for you to fetch changes up to 02319a4d67d3f19039127b8dc9ca9478b6d6ccd8:
> > > 
> > >    virtio-gpu: Respect UI refresh rate for EDID (2022-06-10 11:11:44
> > > +0200)
> > > 
> > > 
> > > usb: add CanoKey device, fixes for ehci + redir
> > > ui: fixes for gtk and cocoa, move keymaps, rework refresh rate
> > > virtio-gpu: scanout flush fix
> > 
> > This introduces regressions:
> > 
> > https://gitlab.com/qemu-project/qemu/-/jobs/2576157660
> > https://gitlab.com/qemu-project/qemu/-/jobs/2576151565
> > https://gitlab.com/qemu-project/qemu/-/jobs/2576154539
> > https://gitlab.com/qemu-project/qemu/-/jobs/2575867208
> > 
> > 
> >  (27/43)
> > tests/avocado/vnc.py:Vnc.test_change_password_requires_a_password:
> > ERROR: ConnectError: Failed to establish session: EOFError\n Exit code:
> > 1\n    Command: ./qemu-system-x86_64 -display none -vga none -chardev 
> > socket,id=mon,path=/var/tmp/avo_qemu_sock_4nrz0r37/qemu-2912538-7f732e94e0f0-monitor.sock
> > -mon chardev=mon,mode=control -node... (0.09 s)
> >  (28/43) tests/avocado/vnc.py:Vnc.test_change_password:  ERROR:
> > ConnectError: Failed to establish session: EOFError\n    Exit code:
> > 1\n    Command: ./qemu-system-x86_64 -display none -vga none -chardev 
> > socket,id=mon,path=/var/tmp/avo_qemu_sock_yhpzy5c3/qemu-2912543-7f732e94b438-monitor.sock
> > -mon chardev=mon,mode=control -node... (0.09 s)
> >  (29/43)
> > tests/avocado/vnc.py:Vnc.test_change_password_requires_a_password:
> > ERROR: ConnectError: Failed to establish session: EOFError\n Exit code:
> > 1\n    Command: ./qemu-system-x86_64 -display none -vga none -chardev 
> > socket,id=mon,path=/var/tmp/avo_qemu_sock_tk3pfmt2/qemu-2912548-7f732e93d7b8-monitor.sock
> > -mon chardev=mon,mode=control -node... (0.09 s)
> > 
> > 
> > r~
> > 
> 
> This is caused by [PATCH 14/17] ui: move 'pc-bios/keymaps' to 'ui/keymaps'.
> After this patch QEMU no longer finds it's keymaps if started directly from
> the build directory.

I just sent Gerd an update version which adds a symlink from the source
tree to the build dir to solve this problem, along with updated commit
message to reflect this need

With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




[PATCH 4/7] crypto: Add ECDSA key parser

2022-06-13 Thread Lei He
Add ECDSA key parser and ECDSA signautre parser.

Signed-off-by: lei he 
---
 crypto/ecdsakey-builtin.c.inc | 248 ++
 crypto/ecdsakey.c | 118 
 crypto/ecdsakey.h |  66 +++
 crypto/meson.build|   1 +
 4 files changed, 433 insertions(+)
 create mode 100644 crypto/ecdsakey-builtin.c.inc
 create mode 100644 crypto/ecdsakey.c
 create mode 100644 crypto/ecdsakey.h

diff --git a/crypto/ecdsakey-builtin.c.inc b/crypto/ecdsakey-builtin.c.inc
new file mode 100644
index 00..5da317ec44
--- /dev/null
+++ b/crypto/ecdsakey-builtin.c.inc
@@ -0,0 +1,248 @@
+/*
+ * QEMU Crypto akcipher algorithms
+ *
+ * Copyright (c) 2022 Bytedance
+ * Author: lei he 
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ *
+ */
+
+#include "der.h"
+#include "ecdsakey.h"
+
+#define QCRYPTO_ECDSA_PUBKEY_FMT_UNCOMPRESSED 0x04
+
+static int extract_mpi(void *ctx, const uint8_t *value,
+   size_t vlen, Error **errp)
+{
+QCryptoAkCipherMPI *mpi = (QCryptoAkCipherMPI *)ctx;
+if (vlen == 0) {
+error_setg(errp, "Empty mpi field");
+return -1;
+}
+mpi->data = g_memdup2(value, vlen);
+mpi->len = vlen;
+return 0;
+}
+
+static int extract_version(void *ctx, const uint8_t *value,
+   size_t vlen, Error **errp)
+{
+uint8_t *version = (uint8_t *)ctx;
+if (vlen != 1 || *value > 1) {
+error_setg(errp, "Invalid rsakey version");
+return -1;
+}
+*version = *value;
+return 0;
+}
+
+static int extract_cons_content(void *ctx, const uint8_t *value,
+size_t vlen, Error **errp)
+{
+const uint8_t **content = (const uint8_t **)ctx;
+if (vlen == 0) {
+error_setg(errp, "Empty sequence");
+return -1;
+}
+*content = value;
+return 0;
+}
+
+static int __qcrypto_akcipher_builtin_ecdsa_pubkey_parse(
+QCryptoAkCipherECDSAKey *ecdsa,
+const uint8_t *key, size_t keylen, Error **errp);
+
+static int extract_pubkey(void *ctx, const uint8_t *value,
+  size_t vlen, Error **errp)
+{
+QCryptoAkCipherECDSAKey *ecdsa = (QCryptoAkCipherECDSAKey *)ctx;
+if (vlen < 4) {
+error_setg(errp, "Public key part too short");
+return -1;
+}
+/* Skip meta bit of BIT STRING */
+value++;
+vlen--;
+return __qcrypto_akcipher_builtin_ecdsa_pubkey_parse(
+ecdsa, value, vlen, errp);
+}
+
+/**
+ *
+ *ECDSASignature ::= SEQUENCE {
+ * r   INTEGER
+ * s   INTEGER
+ * }
+ */
+QCryptoAkCipherECDSASig *qcrypto_akcipher_ecdsasig_parse(
+const uint8_t *signature, size_t len, Error **errp)
+{
+QCryptoAkCipherECDSASig *sig = g_new0(QCryptoAkCipherECDSASig, 1);
+const uint8_t *seq;
+size_t seq_length;
+int decode_ret;
+
+decode_ret = qcrypto_der_decode_seq(&signature, &len,
+extract_cons_content, &seq, errp);
+
+if (decode_ret < 0 || len != 0) {
+goto error;
+}
+seq_length = decode_ret;
+
+if (qcrypto_der_decode_int(&seq, &seq_length, extract_mpi,
+   &sig->r, errp) < 0 ||
+qcrypto_der_decode_int(&seq, &seq_length, extract_mpi,
+   &sig->s, errp) < 0) {
+goto error;
+}
+if (seq_length != 0) {
+goto error;
+}
+
+return sig;
+
+error:
+if (errp && !*errp) {
+error_setg(errp, "Invalid RSA public key");
+}
+qcrypto_akcipher_ecdsasig_free(sig);
+return NULL;
+}
+
+/**
+ *   ECDSAPublicKey: compress-format | x coordinate | y coordinate
+ */
+static int __qcrypto_akcipher_builtin_ecdsa_pubkey_parse(
+QCryptoAkCipherECDSAKey *ecdsa,
+const uint8_t *key, size_t keylen, Error **errp)
+{
+if (keylen < 3) {
+error_setg(errp, "keylen is too short: %zu", keylen);
+return -1;
+}
+if (key[0] != QCRYPTO_ECDSA_PUBKEY_FMT_UNCOMPRESSED) {
+error_setg(errp, "Only uncompressed ECDSA public key is supported");
+return -1;
+}
+
+/* Skip format byte */
+key++;
+keylen--;
+if (keylen % 2 != 0) {
+error_setg(errp, "ECDSA public key's length must be odd");
+return -1;
+}
+
+ecdsa->pub_x.data 

[PATCH 2/7] crypto: Support more ASN.1 types

2022-06-13 Thread Lei He
1. support decoding of 'bit string','octet string',
'object id', and 'context specific tag' for DER decoder.
2. support encoding of int and sequence for DER decoder.
3. add test suites for the above changes.

Signed-off-by: lei he 
---
 crypto/der.c | 174 +--
 crypto/der.h | 128 ++-
 tests/unit/test-crypto-der.c | 126 +--
 3 files changed, 382 insertions(+), 46 deletions(-)

diff --git a/crypto/der.c b/crypto/der.c
index f877390bbb..edf2c6c313 100644
--- a/crypto/der.c
+++ b/crypto/der.c
@@ -27,15 +27,68 @@ enum QCryptoDERTypeTag {
 QCRYPTO_DER_TYPE_TAG_INT = 0x2,
 QCRYPTO_DER_TYPE_TAG_BIT_STR = 0x3,
 QCRYPTO_DER_TYPE_TAG_OCT_STR = 0x4,
-QCRYPTO_DER_TYPE_TAG_OCT_NULL = 0x5,
-QCRYPTO_DER_TYPE_TAG_OCT_OID = 0x6,
+QCRYPTO_DER_TYPE_TAG_NULL = 0x5,
+QCRYPTO_DER_TYPE_TAG_OID = 0x6,
 QCRYPTO_DER_TYPE_TAG_SEQ = 0x10,
 QCRYPTO_DER_TYPE_TAG_SET = 0x11,
 };
 
-#define QCRYPTO_DER_CONSTRUCTED_MASK 0x20
+enum QCryptoDERTagClass {
+QCRYPTO_DER_TAG_CLASS_UNIV = 0x0,
+QCRYPTO_DER_TAG_CLASS_APPL = 0x1,
+QCRYPTO_DER_TAG_CLASS_CONT = 0x2,
+QCRYPTO_DER_TAG_CLASS_PRIV = 0x3,
+};
+
+enum QCryptoDERTagEnc {
+QCRYPTO_DER_TAG_ENC_PRIM = 0x0,
+QCRYPTO_DER_TAG_ENC_CONS = 0x1,
+};
+
+#define QCRYPTO_DER_TAG_ENC_MASK 0x20
+#define QCRYPTO_DER_TAG_ENC_SHIFT 5
+
+#define QCRYPTO_DER_TAG_CLASS_MASK 0xc0
+#define QCRYPTO_DER_TAG_CLASS_SHIFT 6
+
+#define QCRYPTO_DER_TAG_VAL_MASK 0x1f
 #define QCRYPTO_DER_SHORT_LEN_MASK 0x80
 
+#define QCRYPTO_DER_TAG(class, enc, val)\
+(((class) << QCRYPTO_DER_TAG_CLASS_SHIFT) | \
+ ((enc) << QCRYPTO_DER_TAG_ENC_SHIFT) | val)
+
+static void qcrypto_der_encode_data(const uint8_t *src, size_t src_len,
+uint8_t *dst, size_t *dst_len)
+{
+size_t max_length = 0xFF;
+uint8_t length_bytes = 0, header_byte;
+
+if (src_len < QCRYPTO_DER_SHORT_LEN_MASK) {
+header_byte = src_len;
+*dst_len = src_len + 1;
+} else {
+for (length_bytes = 1; max_length < src_len;) {
+length_bytes++;
+max_length = (max_length << 8) + max_length;
+}
+header_byte = length_bytes;
+header_byte |= QCRYPTO_DER_SHORT_LEN_MASK;
+*dst_len = src_len + length_bytes + 1;
+}
+if (!dst) {
+return;
+}
+*dst++ = header_byte;
+/* Bigendian length bytes */
+while (length_bytes) {
+*dst++ = (src_len >> (length_bytes - 1) * 8);
+src_len >>= 8;
+length_bytes--;
+}
+memcpy(dst, src, src_len);
+}
+
 static uint8_t qcrypto_der_peek_byte(const uint8_t **data, size_t *dlen)
 {
 return **data;
@@ -150,40 +203,119 @@ static int qcrypto_der_extract_data(const uint8_t 
**data, size_t *dlen,
 return qcrypto_der_extract_definite_data(data, dlen, cb, ctx, errp);
 }
 
-int qcrypto_der_decode_int(const uint8_t **data, size_t *dlen,
-   QCryptoDERDecodeCb cb, void *ctx, Error **errp)
+static int qcrypto_der_decode_tlv(const uint8_t expected_tag,
+  const uint8_t **data, size_t *dlen,
+  QCryptoDERDecodeCb cb,
+  void *ctx, Error **errp)
 {
+const uint8_t *saved_data = *data;
+size_t saved_dlen = *dlen;
 uint8_t tag;
+int data_length;
+
 if (*dlen < 1) {
 error_setg(errp, "Need more data");
 return -1;
 }
 tag = qcrypto_der_cut_byte(data, dlen);
+if (tag != expected_tag) {
+error_setg(errp, "Unexpected tag: expected: %u, actual: %u",
+   expected_tag, tag);
+goto error;
+}
 
-/* INTEGER must encoded in primitive-form */
-if (tag != QCRYPTO_DER_TYPE_TAG_INT) {
-error_setg(errp, "Invalid integer type tag: %u", tag);
-return -1;
+data_length = qcrypto_der_extract_data(data, dlen, cb, ctx, errp);
+if (data_length < 0) {
+goto error;
 }
+return data_length;
+
+error:
+*data = saved_data;
+*dlen = saved_dlen;
+return -1;
+}
 
-return qcrypto_der_extract_data(data, dlen, cb, ctx, errp);
+int qcrypto_der_decode_int(const uint8_t **data, size_t *dlen,
+   QCryptoDERDecodeCb cb, void *ctx, Error **errp)
+{
+const uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
+QCRYPTO_DER_TAG_ENC_PRIM,
+QCRYPTO_DER_TYPE_TAG_INT);
+return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp);
 }
 
 int qcrypto_der_decode_seq(const uint8_t **data, size_t *dlen,
QCryptoDERDecodeCb cb, void *ctx, Error **errp)
 {
-uint8_t tag;
-if (*dlen < 1) {
-error_setg(errp, "Need more data");
-return -1;
-}
-tag = qcrypto_der_cut_byte(data, dlen);
+uint8_t tag = QCRYPTO

[PATCH 3/7] crypto: remove "qemu/osdep.h" in rsakey.h

2022-06-13 Thread Lei He
Move 'include "qemu/osdep.h"' from rsakey.h to rsakey.c.

Signed-off-by: lei he 
---
 crypto/rsakey.c | 1 +
 crypto/rsakey.h | 1 -
 2 files changed, 1 insertion(+), 1 deletion(-)

diff --git a/crypto/rsakey.c b/crypto/rsakey.c
index cc40e072f0..dcdbd9ec57 100644
--- a/crypto/rsakey.c
+++ b/crypto/rsakey.c
@@ -19,6 +19,7 @@
  *
  */
 
+#include "qemu/osdep.h"
 #include "rsakey.h"
 
 void qcrypto_akcipher_rsakey_free(QCryptoAkCipherRSAKey *rsa_key)
diff --git a/crypto/rsakey.h b/crypto/rsakey.h
index 974b76f659..ba88974d12 100644
--- a/crypto/rsakey.h
+++ b/crypto/rsakey.h
@@ -22,7 +22,6 @@
 #ifndef QCRYPTO_RSAKEY_H
 #define QCRYPTO_RSAKEY_H
 
-#include "qemu/osdep.h"
 #include "qemu/host-utils.h"
 #include "crypto/akcipher.h"
 
-- 
2.11.0




[PATCH 7/7] crypto: Add test suite for ECDSA algorithm

2022-06-13 Thread Lei He
1. add test suite for ecdsa algorithm.
2. use qcrypto_akcihper_max_xxx_len to help create buffers in
test code.

Signed-off-by: lei he 
---
 tests/unit/test-crypto-akcipher.c | 227 +++---
 1 file changed, 212 insertions(+), 15 deletions(-)

diff --git a/tests/unit/test-crypto-akcipher.c 
b/tests/unit/test-crypto-akcipher.c
index 4f1f4214dd..7b0f5ac4d4 100644
--- a/tests/unit/test-crypto-akcipher.c
+++ b/tests/unit/test-crypto-akcipher.c
@@ -314,6 +314,100 @@ static const uint8_t rsa2048_public_key[] = {
 0xed, 0x02, 0x03, 0x01, 0x00, 0x01
 };
 
+static const uint8_t ecdsa_p192_public_key[] = {
+0x04, 0xc4, 0x16, 0xb3, 0xff, 0xac, 0xd5, 0x87,
+0x98, 0xf7, 0xd9, 0x45, 0xfe, 0xd3, 0x5c, 0x17,
+0x9d, 0xb2, 0x36, 0x22, 0xcc, 0x07, 0xb3, 0x6d,
+0x3c, 0x4e, 0x04, 0x5f, 0xeb, 0xb6, 0x52, 0x58,
+0xfb, 0x36, 0x10, 0x52, 0xb7, 0x01, 0x62, 0x0e,
+0x94, 0x51, 0x1d, 0xe2, 0xef, 0x10, 0x82, 0x88,
+0x78,
+};
+
+static const uint8_t ecdsa_p192_private_key[] = {
+0x30, 0x53, 0x02, 0x01, 0x01, 0x04, 0x18, 0xcb,
+0xc8, 0x86, 0x0e, 0x66, 0x3c, 0xf7, 0x5a, 0x44,
+0x13, 0xb8, 0xef, 0xea, 0x1d, 0x7b, 0xa6, 0x1c,
+0xda, 0xf4, 0x1b, 0xc7, 0x67, 0x6b, 0x35, 0xa1,
+0x34, 0x03, 0x32, 0x00, 0x04, 0xc4, 0x16, 0xb3,
+0xff, 0xac, 0xd5, 0x87, 0x98, 0xf7, 0xd9, 0x45,
+0xfe, 0xd3, 0x5c, 0x17, 0x9d, 0xb2, 0x36, 0x22,
+0xcc, 0x07, 0xb3, 0x6d, 0x3c, 0x4e, 0x04, 0x5f,
+0xeb, 0xb6, 0x52, 0x58, 0xfb, 0x36, 0x10, 0x52,
+0xb7, 0x01, 0x62, 0x0e, 0x94, 0x51, 0x1d, 0xe2,
+0xef, 0x10, 0x82, 0x88, 0x78,
+};
+
+static const uint8_t ecdsa_p256_private_key[] = {
+0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xf6,
+0x92, 0xdd, 0x29, 0x1c, 0x6e, 0xef, 0xb6, 0xb2,
+0x73, 0x9f, 0x40, 0x1b, 0xb3, 0x2a, 0x28, 0xd2,
+0x37, 0xd6, 0x4a, 0x5b, 0xe4, 0x40, 0x4c, 0x6a,
+0x95, 0x99, 0xfa, 0xf7, 0x92, 0x49, 0xbe, 0xa0,
+0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00,
+0x04, 0xed, 0x42, 0x9c, 0x67, 0x79, 0xbe, 0x46,
+0x83, 0x88, 0x3e, 0x8c, 0xc1, 0x33, 0xf3, 0xc3,
+0xf6, 0x2c, 0xf3, 0x13, 0x6a, 0x00, 0xc2, 0xc9,
+0x3e, 0x87, 0x7f, 0x86, 0x39, 0xe6, 0xae, 0xe3,
+0xb9, 0xba, 0x2f, 0x58, 0x63, 0x32, 0x62, 0x62,
+0x54, 0x07, 0x27, 0xf9, 0x5a, 0x3a, 0xc7, 0x3a,
+0x6b, 0x5b, 0xbc, 0x0d, 0x33, 0xba, 0xbb, 0xd4,
+0xa3, 0xff, 0x4f, 0x9e, 0xdd, 0xf5, 0x59, 0xc0,
+0xf6,
+};
+
+static const uint8_t ecdsa_p256_public_key[] = {
+0x04, 0xed, 0x42, 0x9c, 0x67, 0x79, 0xbe, 0x46,
+0x83, 0x88, 0x3e, 0x8c, 0xc1, 0x33, 0xf3, 0xc3,
+0xf6, 0x2c, 0xf3, 0x13, 0x6a, 0x00, 0xc2, 0xc9,
+0x3e, 0x87, 0x7f, 0x86, 0x39, 0xe6, 0xae, 0xe3,
+0xb9, 0xba, 0x2f, 0x58, 0x63, 0x32, 0x62, 0x62,
+0x54, 0x07, 0x27, 0xf9, 0x5a, 0x3a, 0xc7, 0x3a,
+0x6b, 0x5b, 0xbc, 0x0d, 0x33, 0xba, 0xbb, 0xd4,
+0xa3, 0xff, 0x4f, 0x9e, 0xdd, 0xf5, 0x59, 0xc0,
+0xf6,
+};
+
+static const uint8_t ecdsa_p384_public_key[] = {
+0x04, 0xab, 0xd5, 0xf8, 0x87, 0x1d, 0x23, 0x9b,
+0x26, 0xb9, 0x57, 0x7e, 0x97, 0x78, 0x10, 0xcd,
+0x13, 0xe3, 0x98, 0x25, 0xa8, 0xd6, 0xab, 0x66,
+0x35, 0x26, 0x68, 0x8a, 0x0e, 0x49, 0xd9, 0x4a,
+0x91, 0x7d, 0x6c, 0x94, 0x06, 0x06, 0x99, 0xf1,
+0x8d, 0x2a, 0x25, 0x8d, 0xf9, 0xbf, 0x40, 0xfa,
+0xb7, 0xcb, 0xe1, 0x14, 0x22, 0x0a, 0xa7, 0xfb,
+0x0a, 0xb4, 0x02, 0x05, 0x8b, 0x98, 0xaa, 0x78,
+0xcd, 0x53, 0x00, 0x1e, 0xd1, 0x79, 0x6a, 0x5f,
+0x09, 0x01, 0x88, 0xb4, 0xbc, 0x32, 0x62, 0x83,
+0x92, 0x84, 0x2d, 0xc6, 0xf8, 0xda, 0xc4, 0x7f,
+0x10, 0xa3, 0x18, 0x1d, 0xae, 0x0d, 0xa4, 0x41,
+0x9f,
+};
+
+static const uint8_t ecdsa_p384_private_key[] = {
+0x30, 0x81, 0x9b, 0x02, 0x01, 0x01, 0x04, 0x30,
+0xb6, 0x04, 0xef, 0xb1, 0x2c, 0x98, 0xdf, 0xcf,
+0xd4, 0x16, 0x31, 0xd4, 0x69, 0x0c, 0x27, 0x81,
+0x4a, 0xac, 0x1a, 0x83, 0x3c, 0xe4, 0xef, 0x65,
+0xe1, 0x7a, 0x6a, 0xc6, 0xd6, 0xf7, 0xea, 0x79,
+0xbe, 0xf1, 0x00, 0x3c, 0xdf, 0x6e, 0x9d, 0x10,
+0x22, 0x61, 0x1b, 0x11, 0xcf, 0x49, 0x6e, 0x62,
+0xa1, 0x64, 0x03, 0x62, 0x00, 0x04, 0xab, 0xd5,
+0xf8, 0x87, 0x1d, 0x23, 0x9b, 0x26, 0xb9, 0x57,
+0x7e, 0x97, 0x78, 0x10, 0xcd, 0x13, 0xe3, 0x98,
+0x25, 0xa8, 0xd6, 0xab, 0x66, 0x35, 0x26, 0x68,
+0x8a, 0x0e, 0x49, 0xd9, 0x4a, 0x91, 0x7d, 0x6c,
+0x94, 0x06, 0x06, 0x99, 0xf1, 0x8d, 0x2a, 0x25,
+0x8d, 0xf9, 0xbf, 0x40, 0xfa, 0xb7, 0xcb, 0xe1,
+0x14, 0x22, 0x0a, 0xa7, 0xfb, 0x0a, 0xb4, 0x02,
+0x05, 0x8b, 0x98, 0xaa, 0x78, 0xcd, 0x53, 0x00,
+0x1e, 0xd1, 0x79, 0x6a, 0x5f, 0x09, 0x01, 0x88,
+0xb4, 0xbc, 0x32, 0x62, 0x83, 0x92, 0x84, 0x2d,
+0xc6, 0xf8, 0xda, 0xc4, 0x7f, 0x10, 0xa3, 0x18,
+0x1d, 0xae, 0x0d, 0xa4, 0x41, 0x9f,
+};
+
 static const uint8_t test_sha1_dgst[] = {
 0x3c, 0x05, 0x19, 0x34, 0x29, 0x19, 0xc7, 0xe0,
 0x87, 0xb6, 0x24, 0xf9, 0x58, 0xac, 0xa4, 0xd4,
@@ -374,6 +468,45 @@ static const uint8_t exp_signature_rsa1024_pkcs1[] = {
 0xab, 0x0d, 0

[PATCH 5/7] crypto: Implement ECDSA algorithm by hogweed

2022-06-13 Thread Lei He
Implement ECDSA algorithm by hogweed and nettle.

Signed-off-by: lei he 
---
 crypto/akcipher-nettle.c.inc | 268 +++
 1 file changed, 268 insertions(+)

diff --git a/crypto/akcipher-nettle.c.inc b/crypto/akcipher-nettle.c.inc
index 02699e6e6d..94d6e0b629 100644
--- a/crypto/akcipher-nettle.c.inc
+++ b/crypto/akcipher-nettle.c.inc
@@ -20,6 +20,8 @@
  */
 
 #include 
+#include 
+#include 
 
 #include "qemu/osdep.h"
 #include "qemu/host-utils.h"
@@ -28,6 +30,7 @@
 #include "qapi/error.h"
 #include "sysemu/cryptodev.h"
 #include "rsakey.h"
+#include "ecdsakey.h"
 
 typedef struct QCryptoNettleRSA {
 QCryptoAkCipher akcipher;
@@ -37,6 +40,33 @@ typedef struct QCryptoNettleRSA {
 QCryptoHashAlgorithm hash_alg;
 } QCryptoNettleRSA;
 
+typedef struct QCryptoNettleECDSA {
+QCryptoAkCipher akcipher;
+QCryptoCurveID curve_id;
+const struct ecc_curve *curve;
+struct ecc_point pubkey;
+struct ecc_scalar privkey;
+} QCryptoNettleECDSA;
+
+static int qcrypto_nettle_invalid_encrypt(QCryptoAkCipher *akcipher,
+  const void *data, size_t data_len,
+  void *enc, size_t enc_len,
+  Error **errp)
+{
+error_setg(errp, "Invalid operation");
+return -1;
+}
+
+
+static int qcrypto_nettle_invalid_decrypt(QCryptoAkCipher *akcipher,
+  const void *enc, size_t enc_len,
+  void *data, size_t data_len,
+  Error **errp)
+{
+error_setg(errp, "Invalid operation");
+return -1;
+}
+
 static void qcrypto_nettle_rsa_free(QCryptoAkCipher *akcipher)
 {
 QCryptoNettleRSA *rsa = (QCryptoNettleRSA *)akcipher;
@@ -55,6 +85,12 @@ static QCryptoAkCipher *qcrypto_nettle_rsa_new(
 const uint8_t *key,  size_t keylen,
 Error **errp);
 
+static QCryptoAkCipher *qcrypto_nettle_ecdsa_new(
+const QCryptoAkCipherOptionsECDSA *opts,
+QCryptoAkCipherKeyType type,
+const uint8_t *key, size_t keylen,
+Error **errp);
+
 QCryptoAkCipher *qcrypto_akcipher_new(const QCryptoAkCipherOptions *opts,
   QCryptoAkCipherKeyType type,
   const uint8_t *key, size_t keylen,
@@ -64,6 +100,10 @@ QCryptoAkCipher *qcrypto_akcipher_new(const 
QCryptoAkCipherOptions *opts,
 case QCRYPTO_AKCIPHER_ALG_RSA:
 return qcrypto_nettle_rsa_new(&opts->u.rsa, type, key, keylen, errp);
 
+case QCRYPTO_AKCIPHER_ALG_ECDSA:
+return qcrypto_nettle_ecdsa_new(&opts->u.ecdsa, type,
+key, keylen, errp);
+
 default:
 error_setg(errp, "Unsupported algorithm: %u", opts->alg);
 return NULL;
@@ -421,6 +461,223 @@ error:
 return NULL;
 }
 
+static int qcrypto_nettle_parse_curve_id(
+QCryptoNettleECDSA *ecdsa,
+const QCryptoAkCipherOptionsECDSA *opts, Error **errp)
+{
+/* ECDSA algorithm can't used for encryption */
+ecdsa->akcipher.max_plaintext_len = 0;
+ecdsa->akcipher.max_ciphertext_len = 0;
+
+switch (opts->curve_id) {
+case QCRYPTO_CURVE_ID_NIST_P192:
+ecdsa->akcipher.max_signature_len =
+qcrypto_akcipher_ecdsasig_x9_62_size(192 / 8);
+ecdsa->akcipher.max_dgst_len = 192 / 8;
+ecdsa->curve = nettle_get_secp_192r1();
+break;
+
+case QCRYPTO_CURVE_ID_NIST_P256:
+ecdsa->akcipher.max_signature_len =
+qcrypto_akcipher_ecdsasig_x9_62_size(256 / 8);
+ecdsa->akcipher.max_dgst_len = 256 / 8;
+ecdsa->curve = nettle_get_secp_256r1();
+break;
+
+case QCRYPTO_CURVE_ID_NIST_P384:
+ecdsa->akcipher.max_signature_len =
+qcrypto_akcipher_ecdsasig_x9_62_size(384 / 8);
+ecdsa->akcipher.max_dgst_len = 256 / 8;
+ecdsa->curve = nettle_get_secp_384r1();
+break;
+
+default:
+error_setg(errp, "Unknown curve id: %d", opts->curve_id);
+return -1;
+}
+
+return 0;
+}
+
+static void qcrypto_nettle_ecdsa_free(QCryptoAkCipher *akcipher)
+{
+QCryptoNettleECDSA *ecdsa = (QCryptoNettleECDSA *)akcipher;
+if (!ecdsa) {
+return;
+}
+ecc_point_clear(&ecdsa->pubkey);
+ecc_scalar_clear(&ecdsa->privkey);
+g_free(ecdsa);
+}
+
+static int qcrypt_nettle_parse_ecdsa_private_key(
+QCryptoNettleECDSA *ecdsa,
+const uint8_t *key,
+size_t keylen,
+Error **errp)
+{
+g_autoptr(QCryptoAkCipherECDSAKey) ecdsa_key =
+qcrypto_akcipher_ecdsakey_parse(QCRYPTO_AKCIPHER_KEY_TYPE_PRIVATE,
+key, keylen, errp);
+mpz_t scalar;
+int ret = -1;
+
+if (!ecdsa_key) {
+return ret;
+}
+nettle_mpz_init_set_str_256_u(
+scalar, ecdsa_key->priv.len, ecdsa_key->priv.data);
+if (ecc_scalar_set(&ecdsa->privkey, scalar) != 1) {
+goto cleanup;
+

Re: [PATCH v2 1/1] Fix the coredump when memory backend id conflicts with default_ram_id

2022-06-13 Thread Li Zhang
On Thu, Jun 9, 2022 at 5:59 PM Igor Mammedov  wrote:
>
> On Fri, 20 May 2022 11:56:02 +0200
> Li Zhang  wrote:
>
> > When no memory backend is specified in machine options,
> > a default memory device will be added with default_ram_id.
> > However, if a memory backend object is added in QEMU options
> > and id is the same as default_ram_id, a coredump happens.
> >
> > Command line:
> > qemu-system-x86_64 -name guest=vmtest,debug-threads=on \
> > -machine pc-q35-6.0,accel=kvm,usb=off,vmport=off \
> > -smp 16,sockets=16,cores=1,threads=1 \
> > -m 4G \
> > -object memory-backend-ram,id=pc.ram,size=4G \
> > -no-user-config -nodefaults -nographic
> >
> > Stack trace of thread 16903:
> > #0  0x7fb109a9318b raise (libc.so.6 + 0x3a18b)
> > #1  0x7fb109a94585 abort (libc.so.6 + 0x3b585)
> > #2  0x558c34bc89be error_handle_fatal (qemu-system-x86_64 + 
> > 0x9c89be)
> > #3  0x558c34bc8aee error_setv (qemu-system-x86_64 + 0x9c8aee)
> > #4  0x558c34bc8ccf error_setg_internal (qemu-system-x86_64 + 
> > 0x9c8ccf)
> > #5  0x558c349f6899 object_property_try_add (qemu-system-x86_64 + 
> > 0x7f6899)
> > #6  0x558c349f7df8 object_property_try_add_child 
> > (qemu-system-x86_64 + 0x7f7df8)
> > #7  0x558c349f7e91 object_property_add_child (qemu-system-x86_64 + 
> > 0x7f7e91)
> > #8  0x558c3454686d create_default_memdev (qemu-system-x86_64 + 
> > 0x34686d)
> > #9  0x558c34546f58 qemu_init_board (qemu-system-x86_64 + 0x346f58)
> > #10 0x558c345471b9 qmp_x_exit_preconfig (qemu-system-x86_64 + 
> > 0x3471b9)
> > #11 0x558c345497d9 qemu_init (qemu-system-x86_64 + 0x3497d9)
> > #12 0x558c344e54c2 main (qemu-system-x86_64 + 0x2e54c2)
> > #13 0x7fb109a7e34d __libc_start_main (libc.so.6 + 0x2534d)
> > #14 0x558c344e53ba _start (qemu-system-x86_64 + 0x2e53ba)
> >
> > Signed-off-by: Li Zhang 
> > ---
> >  hw/core/machine.c | 8 
> >  1 file changed, 8 insertions(+)
> >
> > diff --git a/hw/core/machine.c b/hw/core/machine.c
> > index b03d9192ba..3867af7a8a 100644
> > --- a/hw/core/machine.c
> > +++ b/hw/core/machine.c
> > @@ -1290,9 +1290,17 @@ MemoryRegion *machine_consume_memdev(MachineState 
> > *machine,
> >  static bool create_default_memdev(MachineState *ms, const char *path, 
> > Error **errp)
> >  {
> >  Object *obj;
> > +ObjectProperty *prop;
> >  MachineClass *mc = MACHINE_GET_CLASS(ms);
> >  bool r = false;
> >
> > +prop = object_property_find(object_get_objects_root(), 
> > mc->default_ram_id);
> > +if (prop) {
> > +error_report("Memory backend id conflicts with default_ram_id %s",
> > + mc->default_ram_id);
>
> maybe something like this would be better:
>  A memory backend with id '%s' already exists, cannot create default RAM 
> backend with the same id.
>  Either change id of the offending backend or provide system RAM backend 
> explicitly using
>  '-machine memory-backend' option.
>

Thanks, I will modify it.

>
> > +exit(EXIT_FAILURE);
> > +}
> > +
> >  obj = object_new(path ? TYPE_MEMORY_BACKEND_FILE : 
> > TYPE_MEMORY_BACKEND_RAM);
> >  if (path) {
> >  if (!object_property_set_str(obj, "mem-path", path, errp)) {
>
>


-- 

Best Regards
-Li



Re: [PATCH v5 22/45] block: implemet bdrv_unref_tran()

2022-06-13 Thread Hanna Reitz

On 30.03.22 23:28, Vladimir Sementsov-Ogievskiy wrote:

Now nodes are removed during block-graph update transactions now? Look
at bdrv_replace_child_tran: bdrv_unref() is simply postponed to commit
phase.

What is the problem with it?

We want to make copy-before-write permissions strict: it should unshare
write always, not only when it has at least one parent.


Looking over this patch in not too much detail (because I find it rather 
complicated), it looks OK to me; but this reason for why we need it 
doesn’t really satisfy me.  What is the problem with how CBW permissions 
work?  Is that really the only reason for this patch?



But if so, we
can't neither insert the filter nor remove it:

To insert the filter, we should first do blockdev-add, and filter will
unshare write on the child, so, blockdev-add will fail if disk is in
use by guest.

To remove the filter, we should first do a replace operations, which
again leads to situation when the filter and old parent share one
child, and all parent want write permission when the filter unshare it.

The solution is first do both graph-modifying operations (add &
replace, or replace & remove) and only then update permissions. But
that is not possible with current method to transactionally remove the
block node: if we just postpone bdrv_unref() to commit phase, than on
prepare phase the node is not removed, and it still keep all
permissions on its children.

What to do? In general, I don't know. But it's possible to solve the
problem for the block drivers that doesn't need access to their
children on .bdrv_close(). For such drivers we can detach their
children on prepare stage (still, postponing bdrv_close() call to
commit phase). For this to work we of course should effectively reduce
bs->refcnt on prepare phase as well.

So, the logic of new bdrv_unref_tran() is:

prepare:
   decrease refcnt and detach children if possible (and if refcnt is 0)

commit:
   do bdrv_delete() if refcnt is 0

abort:
   restore children and refcnt

What's the difficulty with it? If we want to transactionally (and with
no permission change) remove nodes, we should understand that some
nodes may be removed recursively, and finally we get several possible
not deleted leaves, where permissions should be updated. How caller
will know what to update? That leads to additional transaction-wide
refresh_list variable, which is filled by various graph modifying
function. So, user should declare referesh_list variable and do one or
several block-graph modifying operations (that may probably remove some
nodes), then user call bdrv_list_refresh_perms on resulting
refresh_list.

Signed-off-by: Vladimir Sementsov-Ogievskiy 





Re: [PATCH 2/3] hw/acpi/aml-build: Fix {socket, cluster, core} IDs in PPTT

2022-06-13 Thread Gavin Shan

Hi Igor,

On 6/10/22 12:00 AM, Igor Mammedov wrote:

On Thu, 26 May 2022 22:40:05 +0800
Gavin Shan  wrote:

On 5/26/22 8:25 PM, Igor Mammedov wrote:

On Wed, 18 May 2022 17:21:40 +0800
Gavin Shan  wrote:
   

The {socket, cluster, core} IDs detected from Linux guest aren't
matching with what have been provided in PPTT. The flag used for
'ACPI Processor ID valid' is missed for {socket, cluster, core}
nodes.


To permit this flag set  on no leaf nodes we have to have
a corresponding containers built for them in DSDT so that
'ACPI Processor ID' could be matched with containers '_UID's.
If we don not build such containers then setting this flag is
not correct. And I don't recall QEMU building CPU hierarchy
in DSDT.
   


It's true that we don't have containers in DSDT. In Linux implementation,
the corresponding IDs are fetched if 'ACPI Processor ID valid' is set in
PPTT node (entry), without checking DSDT table.


linux can makeup container IDs and it is fine as long as it
does that consistently



Ok. I think it's fine except that the container IDs aren't readable, because
the offset of PPTT entries are taken as the container IDs.


I don't know how the PPTT entry is linked to DSDT for _UID, after rechecking
ACPI specification. I was thinking 'Private Resources' fields are used for
the linking, but I should be wrong after checking PPTT tables on my host.
I'm not sure if you have idea how PPTT entry (node) is linked with one
specific device in DSDT table?


from spec description of 'ACPI Processor ID valid' flag:
"
For non-leaf entries in the processor topology, the ACPI Pro-
cessor ID entry can relate to a Processor container in the
namespace. The processor container will have a matching ID
value returned through the _UID method. As not every pro-
cessor hierarchy node structure in PPTT may have a matching
processor container, this flag indicates whether the ACPI pro-
cessor ID points to valid entry.
"

i.e. nothing to do with private resources
on can set this flag for a container only if there is
a container device in DSDT with _UID matching 'ACPI Processor ID'
in PPTT entry. Other possibility for setting this flag
is that processor is described in MADT (which is unlikely for
for a container)



Agreed. I don't think the private resources are relevant to
the IDs. However, I don't understand how the DSDT is linked with
PPTT in regard of the container IDs.


On my host, one of the cluster node resides at offset 10B0h and it's ID
has been marked as valid. The 'Private Resources' fields point to the
type-1 cache structures, which resides in PPTT table either. The cluster
ID ('0x109') isn't appearing in DSDT table.


looks like they are cheating or spec is wrong

PS:
one of the reasons we added PPTT table is to avoid building
CPU topology hierarchy in DSDT.



Yes, I don't think the spec is clear enough in this regard. Anyway,
I checked PPTT table on my host, where the container IDs are specified
by PPTT table entries without corresponding entries in DSDT.



[C9Ch 3228   1]Subtable Type : 01 [Cache Type]
[C9Dh 3229   1]   Length : 18
[C9Eh 3230   2] Reserved : 
[CA0h 3232   4]Flags (decoded below) : 005F
Size valid : 1
  Number of Sets valid : 1
   Associativity valid : 1
 Allocation Type valid : 1
  Cache Type valid : 1
Write Policy valid : 0
   Line Size valid : 1
Cache ID valid : 0
 :
 :
[CB4h 3252   1]Subtable Type : 01 [Cache Type]
[CB5h 3253   1]   Length : 18
[CB6h 3254   2] Reserved : 
[CB8h 3256   4]Flags (decoded below) : 007F
Size valid : 1
  Number of Sets valid : 1
   Associativity valid : 1
 Allocation Type valid : 1
  Cache Type valid : 1
Write Policy valid : 1
   Line Size valid : 1
Cache ID valid : 0
[CBCh 3260   4]  Next Level of Cache : 0CCC
   :
   :
[10B0h 4272   1]Subtable Type : 00 [Processor Hierarchy Node]
[10B1h 4273   1]   Length : 1C
[10B2h 4274   2] Reserved : 
[10B4h 4276   4]Flags (decoded below) : 0002
  Physical package : 0
   ACPI Processor ID valid : 1
 Processor is a thread : 0
Node is a leaf : 0
  Identical Implementation : 0
[10B8h 4280   4]   

Re: [RFC v1] Adding block layer APIs resembling Linux ZoneBlockDevice ioctls.

2022-06-13 Thread Sam Li
Damien Le Moal  于2022年6月13日周一 14:24写道:
>
> On 6/13/22 13:09, Sam Li wrote:
> > By adding zone management operations in BlockDriver, storage
> > controller emulation can use the new block layer APIs including
> > zone_report, zone_reset, zone_open, zone_close, and zone_finish.
>
> Like a real review, commenting inline below.
>
> >
> > Signed-off-by: Sam Li 
> > ---
> >  block/block-backend.c |  20 
> >  block/coroutines.h|   6 ++
> >  block/file-posix.c| 174 ++
> >  block/io.c|  26 +
> >  include/block/block-common.h  |   8 ++
> >  include/block/block-io.h  |  11 ++
> >  include/block/block_int-common.h  |   6 ++
> >  qemu-io-cmds.c|  66 
> >  tests/qemu-iotests/tests/zoned.sh |  47 
> >  9 files changed, 364 insertions(+)
> >  create mode 100644 tests/qemu-iotests/tests/zoned.sh
> >
> > diff --git a/block/block-backend.c b/block/block-backend.c
> > index e0e1aff4b1..4695e5f9fe 100644
> > --- a/block/block-backend.c
> > +++ b/block/block-backend.c
> > @@ -104,6 +104,8 @@ typedef struct BlockBackendAIOCB {
> >  int ret;
> >  } BlockBackendAIOCB;
> >
> > +
> > +
>
> No need for these extra blank line.
>
> >  static const AIOCBInfo block_backend_aiocb_info = {
> >  .get_aio_context = blk_aiocb_get_aio_context,
> >  .aiocb_size = sizeof(BlockBackendAIOCB),
> > @@ -1810,6 +1812,23 @@ int blk_flush(BlockBackend *blk)
> >  return ret;
> >  }
> >
> > +int blk_co_zone_report(BlockBackend *blk)
> > +{
> > +int ret;
> > +ret = bdrv_co_zone_report(blk->root->bs, NULL, 0, 0, 0, 0);
> > +
> > +return ret;
>
> Simplify:
>
> return bdrv_co_zone_report(blk->root->bs, NULL, 0, 0, 0, 0);
>
> But I can see that this code is temporary anyway :)
>
> > +}
> > +
> > +int blk_co_zone_mgmt(BlockBackend *blk, enum zone_op op)
> > +{
> > +int ret;
> > +ret = bdrv_co_zone_mgmt(blk->root->bs, op, 0, 100);
> > +
> > +return ret;
> > +}
> > +
> > +
> >  void blk_drain(BlockBackend *blk)
> >  {
> >  BlockDriverState *bs = blk_bs(blk);
> > @@ -2634,3 +2653,4 @@ int blk_make_empty(BlockBackend *blk, Error **errp)
> >
> >  return bdrv_make_empty(blk->root, errp);
> >  }
> > +
>
> Please do not randomly add blank lines.
>
> > diff --git a/block/coroutines.h b/block/coroutines.h
> > index 830ecaa733..e29222a68a 100644
> > --- a/block/coroutines.h
> > +++ b/block/coroutines.h
> > @@ -81,6 +81,10 @@ blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, 
> > int64_t bytes);
> >
> >  int coroutine_fn blk_co_do_flush(BlockBackend *blk);
> >
> > +int coroutine_fn blk_co_zone_report(BlockBackend *blk);
> > +
> > +int coroutine_fn blk_co_zone_mgmt(BlockBackend *blk, enum zone_op op);
> > +
> >
> >  /*
> >   * "I/O or GS" API functions. These functions can run without
> > @@ -129,4 +133,6 @@ blk_do_pdiscard(BlockBackend *blk, int64_t offset, 
> > int64_t bytes);
> >
> >  int generated_co_wrapper blk_do_flush(BlockBackend *blk);
> >
> > +
> > +
>
> No need for these blank lines.
>
> >  #endif /* BLOCK_COROUTINES_H */
> > diff --git a/block/file-posix.c b/block/file-posix.c
> > index 48cd096624..42646acc4e 100644
> > --- a/block/file-posix.c
> > +++ b/block/file-posix.c
> > @@ -73,6 +73,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #ifdef __s390__
> >  #include 
> >  #endif
> > @@ -178,6 +179,167 @@ typedef struct BDRVRawReopenState {
> >  bool check_cache_dropped;
> >  } BDRVRawReopenState;
> >
> > +
>
> Another extra blank line not needed.
>
> > +enum zone_type {
> > +BLK_ZT_CONV = BLK_ZONE_TYPE_CONVENTIONAL,
> > +BLK_ZT_SWR = BLK_ZONE_TYPE_SEQWRITE_REQ,
> > +BLK_ZT_SWP = BLK_ZONE_TYPE_SEQWRITE_PREF,
> > +};
> > +
> > +enum zone_cond {
> > +BLK_ZS_NOT_WP = BLK_ZONE_COND_NOT_WP,
> > +BLK_ZS_EMPTY = BLK_ZONE_COND_EMPTY,
> > +BLK_ZS_IOPEN = BLK_ZONE_COND_IMP_OPEN,
> > +BLK_ZS_EOPEN = BLK_ZONE_COND_EXP_OPEN,
> > +BLK_ZS_CLOSED = BLK_ZONE_COND_CLOSED,
> > +BLK_ZS_RDONLY = BLK_ZONE_COND_READONLY,
> > +BLK_ZS_FULL = BLK_ZONE_COND_FULL,
> > +BLK_ZS_OFFLINE = BLK_ZONE_COND_OFFLINE,
> > +};
> > +
> > +/*
> > + * Zone descriptor data structure.
> > + * Provide information on a zone with all position and size values in 
> > bytes.
> > + */
> > +struct BlockZoneDescriptor {
> > +uint64_t start;
> > +uint32_t length;
> > +uint32_t cap;
> > +uint64_t wp;
> > +enum zone_type type;
> > +enum zone_cond cond;
> > +};
> > +
> > +enum zone_model {
> > +ZBD_HOST_MANAGED,
> > +ZBD_HOST_AWARE,
>
> Please stay consistent with the macro prefixes. Use BLK_Zxxx here too.
> Likely BLK_ZM_HOST_MANAGED and BLK_ZM_HOST_AWARE.
>
> All of the above definitions should not be in block/file-posix.c because
> they must be common to the entire block layer backend (regardless of the
> driver implementing the zone operations). So these need to go into some
> common .h header file so 

Re: [RFC v1] Adding block layer APIs resembling Linux ZoneBlockDevice ioctls.

2022-06-13 Thread Damien Le Moal
On 6/13/22 18:12, Sam Li wrote:
[...]
>>> +};
>>> +
>>> +/**
>>> + * Zone device information data structure.
>>> + * Provide information on a device.
>>> + */
>>> +typedef struct zbd_dev {
>>> +enum zone_model model;
>>> +uint32_t block_size;
>>> +uint32_t write_granularity;
>>> +uint32_t nr_zones;
>>> +struct BlockZoneDescriptor *zones; /* array of zones */
>>> +uint32_t max_nr_open_zones; /* maximum number of explicitly open zones 
>>> */
>>> +uint32_t max_nr_active_zones;
>>> +} zbd_dev;
>>> +
>>> +/**
>>> + * zone report - Get a zone block device's information in the
>>> + * form of an array of zone descriptors.
>>> + *
>>> + * @param bs: passing zone block device file descriptor
>>> + * @param zones: Space to hold zone information on reply
>>> + * @param offset: the location in the zone block device
>>> + * @param len: the length of reported zone information*
>>> + * @param partial: if partial has zero value, it is the number
>>> + * of zones that can be reported; else, set the nr_zones to the
>>> + * number of fully transferred zone descriptors in the data buffer.
>>> + * @return 0 on success, -1 on failure
>>> + */
>>> +static int raw_co_zone_report(BlockDriverState *bs,
>>> +   struct BlockZoneDescriptor *zones, uint32_t 
>>> *nr_zones,
>>> +   int64_t offset, int64_t len, uint8_t partial) {
>>
>> Remove the partial argument from this interface. We have decided to drop
>> it from the virtio specs and linux ioctl do not need it. Also, it is
>> generally good practice to have the first arguments of a function be the
>> "inputs" and the last ones the outputs. So:
>>
>> static int raw_co_zone_report(BlockDriverState *bs,
>>   int64_t offset, int64_t len,
>>   uint32_t *nr_zones,
>>   struct BlockZoneDescriptor *zones)
>>
>> would be better, I think.
>> In any case, this function interface needs rethinking. E.g., what are the
>> inputs and the outputs ?
>>
>> * Option (1)
>>
>> Input: (a) the offset where to start the report from, (b) the array of
>> zones to fill up and (c) the maximum number of zones that the caller wants
>> (which may be just 1).
>> Ouput: (a) the array of zones filled up and (b) the number of zone
>> decriptors that were filled in the array of zones, which can be LESS than
>> what the caller requested.
>>
>> The interface then is:
>>
>> static int raw_co_zone_report(BlockDriverState *bs,
>>   int64_t offset, uint32_t *nr_zones,
>>   struct BlockZoneDescriptor *zones);
>>
>> * Option (2)
>>
>> Input: (a) the offset where to start the report from, (b) the maximum
>> number of zones that the caller wants (which may be just 1).
>> Ouput: (a) an allocated and filled array of zones and (b) the number of
>> zone decriptors that were filled in the allocated array of zones, which
>> can be LESS than what the caller requested.
>>
>> The interface then is:
>>
>> static int raw_co_zone_report(BlockDriverState *bs,
>>   int64_t offset, uint32_t *nr_zones,
>>   struct BlockZoneDescriptor **zones);
>>
>> Note the "**" since you will return an array of zones (that is, a pointer).
>>
>> For option (1), the caller will be responsible to manage the array of
>> zones and free it when it is not needed anymore. For (2), the caller will
>> still need to free the array of zones when not needed anymore BUT since
>> the caller has no idea how that array was allocated, (it may be an
>> anonymous mmap region !), you would need a "free array of zones" function 
>> too.
>>
>> So option (2) is more complicated. So I strongly suggest you go for
>> solution (1): the virtio-blk driver (or qemu-io for your test) will
>> allocate the array of zones and pass it along as an argument for this
>> function to use it and fill the array.
> 
> It's kind of like the delete_file before. I should finish solution 1
> before moving to improvements.
> 
> Thanks for reviewing. The advice is very helpful and I'll fix these
> problems as soon as possible.

As we discussed last week during the call, first do not worry about the
ioctl for report zones. Get the interface working so that you can call it
from qemu-io exactly like the virtio-blk driver would (well almost the
same), that is, with all the arguments. So for instance, pass along the
report start offset and use that to generate a single zone report with a
zone descriptor that has a start offset *equal* to the offset specified in
qemu-io. And set the other zone fields (length, capacity, wp, etc) to some
value.

With that, when you run your zone report test with qemu-io, you can print
the zone descriptor you get and check that the zone fields match. That
would mean you are passing along the data correctly between the layers.

With that in place, you can then implement the actual ioctl() call to get
the real zone info from

Re: [PATCH v5 29/45] block: introduce BDRV_O_NOPERM flag

2022-06-13 Thread Hanna Reitz

On 30.03.22 23:28, Vladimir Sementsov-Ogievskiy wrote:

Now copy-before-write filter has weak permission model: when it has no
parents, it share write permission on source. Otherwise we just can't
blockdev-add it, when existing user of source has write permission.

The situation is bad, it means that copy-before-write filter doesn't
guarantee that all write goes through it.


I don’t understand how this situation really is bad, because it sounds 
like anything else would just be a safeguard against users adding a CBW 
filter without making use of it.  Which I’d think is their own fault.


As far as I remember the actual problem is that we cannot do 
transactional graph modifications, where e.g. a CBW node is inserted and 
a bitmap is created in a single atomic transaction[1].  Which is a 
problem.  And now I just don’t quite understand how unsharing WRITE 
unconditionally would help with the actual problem.


[1] Then again, would then even be “atomic”?  For that transaction to 
work as intended, the node would need to be drained during the 
transaction (so that the bitmap stays in sync with the CBW state). It 
doesn’t look like that would be the case.


So perhaps I’m just remembering incorrectly.


And a lot better is unshare
write always. But how to insert the filter in this case?

The solution is to do blockdev-add and blockdev-replace in one
transaction, and more, update permissions only after both command.

For now, let's create a possibility to not update permission on file
child of copy-before-write filter at time of open.

New interfaces are:

- bds_tree_init() with flags argument, so that caller may pass
   additional flags, for example the new BDRV_O_NOPERM.

- bdrv_open_file_child_common() with boolean refresh_perms arguments.
   Drivers may use this function with refresh_perms = true, if they want
   to satisfy BDRV_O_NOPERM. No one such driver for now.

Signed-off-by: Vladimir Sementsov-Ogievskiy 





Re: [PATCH v17 6/8] softmmu/dirtylimit: Implement virtual CPU throttle

2022-06-13 Thread manish.mishra


On 26/05/22 8:21 am, Jason Wang wrote:

On Wed, May 25, 2022 at 11:56 PM Peter Xu  wrote:

On Wed, May 25, 2022 at 11:38:26PM +0800, Hyman Huang wrote:

2. Also this algorithm only control or limits dirty rate by guest
writes. There can be some memory dirtying done by virtio based devices
which is accounted only at qemu level so may not be accounted through
dirty rings so do we have plan for that in future? Those are not issue
for auto-converge as it slows full VM but dirty rate limit only slows
guest writes.


 From the migration point of view, time spent on migrating memory is far
greater than migrating devices emulated by qemu. I think we can do that when
migrating device costs the same magnitude time as migrating memory.

As to auto-converge, it throttle vcpu by kicking it and force it to sleep
periodically. The two seems has no much difference from the perspective of
internal method but the auto-converge is kind of "offensive" when doing
restraint. I'll read the auto-converge implementation code and figure out
the problem you point out.

This seems to be not virtio-specific, but can be applied to any device DMA
writting to guest mem (if not including vfio).  But indeed virtio can be
normally faster.

I'm also curious how fast a device DMA could dirty memories.  This could be
a question to answer to all vcpu-based throttling approaches (including the
quota based approach that was proposed on KVM list).  Maybe for kernel
virtio drivers we can have some easier estimation?

As you said below, it really depends on the speed of the backend.


  My guess is it'll be
much harder for DPDK-in-guest (aka userspace drivers) because IIUC that
could use a large chunk of guest mem.

Probably, for vhost-user backend, it could be ~20Mpps or even higher.


Sorry for late response on this. We did experiment with IO on virtio-scsi based 
disk.

We could see dirty rate of ~500MBps on my system and most of that was not 
tracked

as kvm_dirty_log. Also for reference i am attaching test we used to avoid 
tacking

in KVM. (as attached file).



Thanks


[copy Jason too]

--
Peter Xu
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define PAGE_SIZE 4096
#define GB (1024 * 1024 * 1024)

int main()
{
char *buff;
size_t size;
struct stat stat;
// Take file of size atleast double of RAM size to
// achieve max dirty rate possible.
const char * file_name = "file_10_gb";
int fd;
size_t i = 0, count = 0;
struct timespec ts1, ts0;
double time_diff;

fd = open(file_name, O_RDONLY);
if (fd == -1) {
   perror("Error opening file");
   exit(1);
}

fstat (fd, &stat);
size = stat.st_size;
printf("File size %ld\n", (long)size);

buff = (char *)mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0);
if (buff == MAP_FAILED) {
   perror("Mmap Error");
   exit(1);
}

(void)clock_gettime(CLOCK_MONOTONIC, &ts0);

while(1) {
   char c;

   i = (i + PAGE_SIZE) % size;
   c = buff[i];
   count++;
   // Check on every 10K pages for rate.
   if (count % 1 == 0) {
  (void)clock_gettime(CLOCK_MONOTONIC, &ts1);
  time_diff = ((double)ts1.tv_sec  + ts1.tv_nsec * 1.0e-9) 
-((double)ts0.tv_sec + ts0.tv_nsec * 1.0e-9);
  printf("Expected Dirty rate %f\n", (1.0 * PAGE_SIZE) / GB / 
time_diff);
  ts0 = ts1;
   }
}

close(fd);
return 0;
}


Re: [PATCH 2/3] hw/usb/canokey: fix compatibility of qemu-xhci

2022-06-13 Thread Gerd Hoffmann
  Hi,

>  case CANOKEY_EP_IN_WAIT:
>  /* NAK for early INTR IN */
>  p->status = USB_RET_NAK;
> +/* store pointer here for later emu_transmit wakeup */
> +key->ep_in_pointer[ep_in] = p->ep;

There is no need to fish the ep pointer out of usb packets.
You can just use usb_ep_get() instead.

take care,
  Gerd




[PATCH v3 1/1] Fix the coredump when memory backend id conflicts with default_ram_id

2022-06-13 Thread Li Zhang
When no memory backend is specified in machine options,
a default memory device will be added with default_ram_id.
However, if a memory backend object is added in QEMU options
and id is the same as default_ram_id, a coredump happens.

Command line:
qemu-system-x86_64 -name guest=vmtest,debug-threads=on \
-machine pc-q35-6.0,accel=kvm,usb=off,vmport=off \
-smp 16,sockets=16,cores=1,threads=1 \
-m 4G \
-object memory-backend-ram,id=pc.ram,size=4G \
-no-user-config -nodefaults -nographic

Stack trace of thread 16903:
#0  0x7fb109a9318b raise (libc.so.6 + 0x3a18b)
#1  0x7fb109a94585 abort (libc.so.6 + 0x3b585)
#2  0x558c34bc89be error_handle_fatal (qemu-system-x86_64 + 0x9c89be)
#3  0x558c34bc8aee error_setv (qemu-system-x86_64 + 0x9c8aee)
#4  0x558c34bc8ccf error_setg_internal (qemu-system-x86_64 + 0x9c8ccf)
#5  0x558c349f6899 object_property_try_add (qemu-system-x86_64 + 
0x7f6899)
#6  0x558c349f7df8 object_property_try_add_child (qemu-system-x86_64 + 
0x7f7df8)
#7  0x558c349f7e91 object_property_add_child (qemu-system-x86_64 + 
0x7f7e91)
#8  0x558c3454686d create_default_memdev (qemu-system-x86_64 + 0x34686d)
#9  0x558c34546f58 qemu_init_board (qemu-system-x86_64 + 0x346f58)
#10 0x558c345471b9 qmp_x_exit_preconfig (qemu-system-x86_64 + 0x3471b9)
#11 0x558c345497d9 qemu_init (qemu-system-x86_64 + 0x3497d9)
#12 0x558c344e54c2 main (qemu-system-x86_64 + 0x2e54c2)
#13 0x7fb109a7e34d __libc_start_main (libc.so.6 + 0x2534d)
#14 0x558c344e53ba _start (qemu-system-x86_64 + 0x2e53ba)

Signed-off-by: Li Zhang 
---
 hw/core/machine.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index a673302cce..9ede63b01c 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -1265,9 +1265,21 @@ MemoryRegion *machine_consume_memdev(MachineState 
*machine,
 static bool create_default_memdev(MachineState *ms, const char *path, Error 
**errp)
 {
 Object *obj;
+ObjectProperty *prop;
 MachineClass *mc = MACHINE_GET_CLASS(ms);
 bool r = false;
 
+prop = object_property_find(object_get_objects_root(), mc->default_ram_id);
+if (prop) {
+error_report("A memory backend with id '%s' already exists, "
+ "cannot create default RAM backend with the same id. "
+ "Either change id of the offending backend or "
+ "provide system RAM backend explicitly using "
+ "'-machine memory-backend' option. " ,
+ mc->default_ram_id);
+exit(EXIT_FAILURE);
+}
+
 obj = object_new(path ? TYPE_MEMORY_BACKEND_FILE : 
TYPE_MEMORY_BACKEND_RAM);
 if (path) {
 if (!object_property_set_str(obj, "mem-path", path, errp)) {
-- 
2.34.1




Re: [PATCH] hw/openrisc: pass random seed to fdt

2022-06-13 Thread Jason A. Donenfeld
On 6/13/22, Stafford Horne  wrote:
> On Sun, Jun 12, 2022 at 11:59:49PM +0200, Jason A. Donenfeld wrote:
>> If the FDT contains /chosen/rng-seed, then the Linux RNG will use it to
>> initialize early. Set this using the usual guest random number
>> generation function. This is confirmed to successfully initialize the
>> RNG on Linux 5.19-rc2.
>>
>> Cc: Stafford Horne 
>> Signed-off-by: Jason A. Donenfeld 
>> ---
>>  hw/openrisc/openrisc_sim.c | 6 ++
>>  1 file changed, 6 insertions(+)
>>
>> diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
>> index 35adce17ac..41821b5f30 100644
>> --- a/hw/openrisc/openrisc_sim.c
>> +++ b/hw/openrisc/openrisc_sim.c
>> @@ -20,6 +20,7 @@
>>
>>  #include "qemu/osdep.h"
>>  #include "qemu/error-report.h"
>> +#include "qemu/guest-random.h"
>>  #include "qapi/error.h"
>>  #include "cpu.h"
>>  #include "hw/irq.h"
>> @@ -115,6 +116,7 @@ static void openrisc_create_fdt(Or1ksimState *state,
>>  int cpu;
>>  char *nodename;
>>  int pic_ph;
>> +uint8_t rng_seed[32];
>>
>>  fdt = state->fdt = create_device_tree(&state->fdt_size);
>>  if (!fdt) {
>> @@ -165,6 +167,10 @@ static void openrisc_create_fdt(Or1ksimState *state,
>>  qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
>>  }
>>
>> +/* Pass seed to RNG. */
>> +qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));
>> +qemu_fdt_setprop(fdt, "/chosen", "rng-seed", rng_seed,
>> sizeof(rng_seed));
>> +
>>  /* Create aliases node for use by devices. */
>>  qemu_fdt_add_subnode(fdt, "/aliases");
>>  }
>
> This all looks fine to me.  I will queue it with my current changes.  Since
> this
> is only applying to openrisc_sim I would like to also apply it to virt.  To
> do
> that I need to have a common core openrisc system creation api.  That way I
> don't end up copying and pasting this to every platform.

Sure. Or just do it on the virt board only if that's easier.

Jason



Re: [PATCH RFC 4/5] cpu: Allow cpu_synchronize_all_post_init() to take an errp

2022-06-13 Thread Dr. David Alan Gilbert
* Peter Xu (pet...@redhat.com) wrote:
> On Thu, Jun 09, 2022 at 05:02:29PM -0400, Peter Xu wrote:
> > On Wed, Jun 08, 2022 at 06:05:28PM +0100, Dr. David Alan Gilbert wrote:
> > > > @@ -2005,7 +2005,17 @@ static void loadvm_postcopy_handle_run_bh(void 
> > > > *opaque)
> > > >  /* TODO we should move all of this lot into postcopy_ram.c or a 
> > > > shared code
> > > >   * in migration.c
> > > >   */
> > > > -cpu_synchronize_all_post_init();
> > > > +cpu_synchronize_all_post_init(&local_err);
> > > > +if (local_err) {
> > > > +/*
> > > > + * TODO: a better way to do this is to tell the src that we 
> > > > cannot
> > > > + * run the VM here so hopefully we can keep the VM running on 
> > > > src
> > > > + * and immediately halt the switch-over.  But that needs work.
> > > 
> > > Yes, I think it is possible; unlike some of the later errors in the same
> > > function, in this case we know no disks/network/etc have been touched,
> > > so we should be able to recover.
> > > I wonder if we can move the postcopy_state_set(POSTCOPY_INCOMING_RUNNING)
> > > out of loadvm_postcopy_handle_run to after this point.
> > > 
> > > We've already got the return path, so we should be able to signal the
> > > failure unless we're very unlucky.
> > 
> > Right.  It's just that for the new ACK we may need to modify the return
> > path protocol for sure, because none of the existing ones can notify such
> > an information.
> > 
> > One idea is to reuse MIG_RP_MSG_RESUME_ACK, it was only used for postcopy
> > recovery before to do the final handshake with offload=1 only (which is
> > defined as MIGRATION_RESUME_ACK_VALUE).  We could try to fill in the
> > payload with some !1 value, to tell the source that we NACK the migration
> > then src fails the migration as long as possible?
> > 
> > That seems to be even compatibile with one old qemu migrating to a new qemu
> > scenario, because when the old qemu notices the MIG_RP_MSG_RESUME_ACK
> > message with !1 payload, it'll mark the rp bad:
> 
> Oh it won't be compatible..  The clean way to do this is we need to modify
> the src qemu to halt in postcopy_start() to wait for that ack before
> continue.  That may need another cap/param to enable.

OK; I was wondering aobut sending a RP_MSG_SHUT with a failure; but if
you'd need to change the source it's still a problem.

> The thing is I'm not very sure whether this will be worth it.
> 
> Non-compatible migrations should be rare on put register failures.  For the
> issue I was working on, it was actually a kernel bug that triggered it but
> it's just hard to figure out where's wrong.  With properly working kernels
> and matching hosts they should just not really heppen.  I'm worried adding
> too much complexity could over-engineer things without much benefits.

OK that makes sense.

> In that case, I'd think it proper if we start with what this patchset
> provides, which at least allows us to fail in a crystal clear way?

Yes, the clear error is important.

Dave

> > 
> >   if (migrate_handle_rp_resume_ack(ms, tmp32)) {
> >   mark_source_rp_bad(ms);
> >   goto out;
> >   }
> > 
> >   static int migrate_handle_rp_resume_ack(MigrationState *s, uint32_t value)
> >   {
> >   trace_source_return_path_thread_resume_ack(value);
> >   
> >   if (value != MIGRATION_RESUME_ACK_VALUE) {
> >   error_report("%s: illegal resume_ack value %"PRIu32,
> >__func__, value);
> >   return -1;
> >   }
> >   ...
> >   }
> > 
> > If it looks generally good, I can try with such a change in v2.
> > 
> > Thanks,
> > 
> > -- 
> > Peter Xu
> 
> -- 
> Peter Xu
> 
-- 
Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK




Re: [PATCH v2 00/11] vfio/migration: Implement VFIO migration protocol v2

2022-06-13 Thread Avihai Horon



On 6/8/2022 12:32 AM, Alex Williamson wrote:

External email: Use caution opening links or attachments


On Tue, 7 Jun 2022 20:44:23 +0300
Avihai Horon  wrote:


On 5/30/2022 8:07 PM, Avihai Horon wrote:

Hello,

Following VFIO migration protocol v2 acceptance in kernel, this series
implements VFIO migration according to the new v2 protocol and replaces
the now deprecated v1 implementation.

The main differences between v1 and v2 migration protocols are:
1. VFIO device state is represented as a finite state machine instead of
 a bitmap.

2. The migration interface with kernel is done using VFIO_DEVICE_FEATURE
 ioctl and normal read() and write() instead of the migration region
 used in v1.

3. Migration protocol v2 currently doesn't support the pre-copy phase of
 migration.

Full description of the v2 protocol and the differences from v1 can be
found here [1].

Patches 1-3 are prep patches fixing bugs and adding QEMUFile function
that will be used later.

Patches 4-6 refactor v1 protocol code to make it easier to add v2
protocol.

Patches 7-11 implement v2 protocol and remove v1 protocol.

Thanks.

[1]
https://lore.kernel.org/all/20220224142024.147653-10-yish...@nvidia.com/

Changes from v1: 
https://lore.kernel.org/all/20220512154320.19697-1-avih...@nvidia.com/
- Split the big patch that replaced v1 with v2 into several patches as
suggested by Joao, to make review easier.
- Change warn_report to warn_report_once when container doesn't support
dirty tracking.
- Add Reviewed-by tag.

Avihai Horon (11):
vfio/migration: Fix NULL pointer dereference bug
vfio/migration: Skip pre-copy if dirty page tracking is not supported
migration/qemu-file: Add qemu_file_get_to_fd()
vfio/common: Change vfio_devices_all_running_and_saving() logic to
  equivalent one
vfio/migration: Move migration v1 logic to vfio_migration_init()
vfio/migration: Rename functions/structs related to v1 protocol
vfio/migration: Implement VFIO migration protocol v2
vfio/migration: Remove VFIO migration protocol v1
vfio/migration: Reset device if setting recover state fails
vfio: Alphabetize migration section of VFIO trace-events file
docs/devel: Align vfio-migration docs to VFIO migration v2

   docs/devel/vfio-migration.rst |  77 ++--
   hw/vfio/common.c  |  21 +-
   hw/vfio/migration.c   | 640 --
   hw/vfio/trace-events  |  25 +-
   include/hw/vfio/vfio-common.h |   8 +-
   migration/migration.c |   5 +
   migration/migration.h |   3 +
   migration/qemu-file.c |  34 ++
   migration/qemu-file.h |   1 +
   9 files changed, 252 insertions(+), 562 deletions(-)


Ping.

Based on the changelog, this seems like a mostly cosmetic spin and I
don't see that all of the discussion threads from v1 were resolved to
everyone's satisfaction.  I'm certainly still uncomfortable with the
pre-copy behavior and I thought there were still some action items to
figure out whether an SLA is present and vet the solution with
management tools.  Thanks,


Yes.
OK, so let's clear things up and reach an agreement before I prepare the 
v3 series.


There are three topics that came up in previous discussion:

1. [PATCH v2 01/11] vfio/migration: Fix NULL pointer dereference bug.
   Juan gave his Reviewed-by but he wasn't sure about qemu_file_* usage
   outside migration thread.
   This code existed before and I fixed a NULL pointer dereference that
   I encountered.
   I suggested that later we can refactor VMChangeStateHandler to
   return error.
   I prefer not to do this refactor right now because I am not sure
   it's as straightforward change as it might seem - if some notifier
   fails and we abort do_vm_stop/vm_prepare_start in the middle, can
   this leave the VM in some unstable state?
   We plan to leave it as is and not do the refactor as part of this
   series.
   Are you ok with this?

2. [PATCH v2 02/11] vfio/migration: Skip pre-copy if dirty page
   tracking is not supported.
   As previously discussed, this patch doesn't consider the configured
   downtime limit.
   One way to fix it is to allow such migration only when "no SLA" (no
   downtime limit) is set. AFAIK today there is no way that one can set
   "no SLA".
   If we go with this option, we change normal flow of migration
   (skipping pre-copy) and might need to change management tools.

Instead, what about letting QEMU VFIO code mark all pages dirty (instead 
of kernel)?
This way we don’t skip pre-copy and we get the same behavior we have now 
of perpetual dirtying all RAM, which respects SLA.
If we go with this option, do we need to block migration when IOMMU is 
sPAPR TCE?
Until now migration would be blocked because sPAPR TCE doesn't report 
dirty_pages_supported cap, but going with this option we will allow 
migration even when dirty_pages_supported cap is not set (and let QEMU 
dirty all pages).


3. [PATCH v2 03/11] migration/qemu-f

Re: [PATCH 1/1] block: use 'unsigned' for in_flight field on driver state

2022-06-13 Thread Denis V. Lunev

On 30.05.2022 12:39, Denis V. Lunev wrote:

This patch makes in_flight field 'unsigned' for BDRVNBDState and
MirrorBlockJob. This matches the definition of this field on BDS
and is generically correct - we should never get negative value here.

Signed-off-by: Denis V. Lunev 
CC: John Snow 
CC: Vladimir Sementsov-Ogievskiy 
CC: Kevin Wolf 
CC: Hanna Reitz 
CC: Eric Blake 
---
  block/mirror.c | 2 +-
  block/nbd.c| 2 +-
  2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/block/mirror.c b/block/mirror.c
index d8ecb9efa2..3c4ab1159d 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -73,7 +73,7 @@ typedef struct MirrorBlockJob {
  
  uint64_t last_pause_ns;

  unsigned long *in_flight_bitmap;
-int in_flight;
+unsigned in_flight;
  int64_t bytes_in_flight;
  QTAILQ_HEAD(, MirrorOp) ops_in_flight;
  int ret;
diff --git a/block/nbd.c b/block/nbd.c
index 6085ab1d2c..512a53bf73 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -77,7 +77,7 @@ typedef struct BDRVNBDState {
  QemuMutex requests_lock;
  NBDClientState state;
  CoQueue free_sema;
-int in_flight;
+unsigned in_flight;
  NBDClientRequest requests[MAX_NBD_REQUESTS];
  QEMUTimer *reconnect_delay_timer;
  

ping v2



Re: [PATCH v2 1/1] nbd: trace long NBD operations

2022-06-13 Thread Denis V. Lunev

On 30.05.2022 12:39, Denis V. Lunev wrote:

At the moment there are 2 sources of lengthy operations if configured:
* open connection, which could retry inside and
* reconnect of already opened connection
These operations could be quite lengthy and cumbersome to catch thus
it would be quite natural to add trace points for them.

This patch is based on the original downstream work made by Vladimir.

Signed-off-by: Denis V. Lunev 
CC: Eric Blake 
CC: Vladimir Sementsov-Ogievskiy 
CC: Kevin Wolf 
CC: Hanna Reitz 
CC: Paolo Bonzini 
---
  block/nbd.c | 6 +-
  block/trace-events  | 2 ++
  nbd/client-connection.c | 2 ++
  nbd/trace-events| 3 +++
  4 files changed, 12 insertions(+), 1 deletion(-)

Changes from v1:
- %d -> %u for in_flights
- renamed open trace-point + fixed timeout type
- moved trace_nbd_reconnect_attempt_result above

diff --git a/block/nbd.c b/block/nbd.c
index 512a53bf73..19e773d602 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -371,6 +371,7 @@ static bool nbd_client_connecting(BDRVNBDState *s)
  /* Called with s->requests_lock taken.  */
  static coroutine_fn void nbd_reconnect_attempt(BDRVNBDState *s)
  {
+int ret;
  bool blocking = s->state == NBD_CLIENT_CONNECTING_WAIT;
  
  /*

@@ -380,6 +381,8 @@ static coroutine_fn void nbd_reconnect_attempt(BDRVNBDState 
*s)
  assert(nbd_client_connecting(s));
  assert(s->in_flight == 1);
  
+trace_nbd_reconnect_attempt(s->bs->in_flight);

+
  if (blocking && !s->reconnect_delay_timer) {
  /*
   * It's the first reconnect attempt after switching to
@@ -401,7 +404,8 @@ static coroutine_fn void nbd_reconnect_attempt(BDRVNBDState 
*s)
  }
  
  qemu_mutex_unlock(&s->requests_lock);

-nbd_co_do_establish_connection(s->bs, blocking, NULL);
+ret = nbd_co_do_establish_connection(s->bs, blocking, NULL);
+trace_nbd_reconnect_attempt_result(ret, s->bs->in_flight);
  qemu_mutex_lock(&s->requests_lock);
  
  /*

diff --git a/block/trace-events b/block/trace-events
index 549090d453..48dbf10c66 100644
--- a/block/trace-events
+++ b/block/trace-events
@@ -172,6 +172,8 @@ nbd_read_reply_entry_fail(int ret, const char *err) "ret = %d, 
err: %s"
  nbd_co_request_fail(uint64_t from, uint32_t len, uint64_t handle, uint16_t flags, uint16_t type, const char *name, int ret, const char 
*err) "Request failed { .from = %" PRIu64", .len = %" PRIu32 ", .handle = %" PRIu64 ", .flags = 
0x%" PRIx16 ", .type = %" PRIu16 " (%s) } ret = %d, err: %s"
  nbd_client_handshake(const char *export_name) "export '%s'"
  nbd_client_handshake_success(const char *export_name) "export '%s'"
+nbd_reconnect_attempt(unsigned in_flight) "in_flight %u"
+nbd_reconnect_attempt_result(int ret, unsigned in_flight) "ret %d in_flight %u"
  
  # ssh.c

  ssh_restart_coroutine(void *co) "co=%p"
diff --git a/nbd/client-connection.c b/nbd/client-connection.c
index 2a632931c3..0c5f917efa 100644
--- a/nbd/client-connection.c
+++ b/nbd/client-connection.c
@@ -23,6 +23,7 @@
   */
  
  #include "qemu/osdep.h"

+#include "trace.h"
  
  #include "block/nbd.h"
  
@@ -210,6 +211,7 @@ static void *connect_thread_func(void *opaque)

  object_unref(OBJECT(conn->sioc));
  conn->sioc = NULL;
  if (conn->do_retry && !conn->detached) {
+trace_nbd_connect_thread_sleep(timeout);
  qemu_mutex_unlock(&conn->mutex);
  
  sleep(timeout);

diff --git a/nbd/trace-events b/nbd/trace-events
index c4919a2dd5..b7032ca277 100644
--- a/nbd/trace-events
+++ b/nbd/trace-events
@@ -73,3 +73,6 @@ nbd_co_receive_request_decode_type(uint64_t handle, uint16_t 
type, const char *n
  nbd_co_receive_request_payload_received(uint64_t handle, uint32_t len) "Payload received: 
handle = %" PRIu64 ", len = %" PRIu32
  nbd_co_receive_align_compliance(const char *op, uint64_t from, uint32_t len, uint32_t align) "client 
sent non-compliant unaligned %s request: from=0x%" PRIx64 ", len=0x%" PRIx32 ", 
align=0x%" PRIx32
  nbd_trip(void) "Reading request"
+
+# client-connection.c
+nbd_connect_thread_sleep(uint64_t timeout) "timeout %" PRIu64

ping v2



[PULL 00/16] Kraxel 20220613 patches

2022-06-13 Thread Gerd Hoffmann
The following changes since commit dcb40541ebca7ec98a14d461593b3cd7282b4fac:

  Merge tag 'mips-20220611' of https://github.com/philmd/qemu into staging 
(2022-06-11 21:13:27 -0700)

are available in the Git repository at:

  git://git.kraxel.org/qemu tags/kraxel-20220613-pull-request

for you to fetch changes up to 23b87f7a3a13e93e248eef8a4b7257548855a620:

  ui: move 'pc-bios/keymaps' to 'ui/keymaps' (2022-06-13 10:59:25 +0200)


usb: add CanoKey device, fixes for ehci + redir
ui: fixes for gtk and cocoa, move keymaps (v2), rework refresh rate
virtio-gpu: scanout flush fix



Akihiko Odaki (4):
  ui/cocoa: Fix poweroff request code
  ui/console: Do not return a value with ui_info
  ui: Deliver refresh rate via QemuUIInfo
  virtio-gpu: Respect UI refresh rate for EDID

Arnout Engelen (1):
  hw/usb/hcd-ehci: fix writeback order

Daniel P. Berrangé (1):
  ui: move 'pc-bios/keymaps' to 'ui/keymaps'

Dongwon Kim (1):
  virtio-gpu: update done only on the scanout associated with rect

Hongren (Zenithal) Zheng (6):
  hw/usb: Add CanoKey Implementation
  hw/usb/canokey: Add trace events
  meson: Add CanoKey
  docs: Add CanoKey documentation
  docs/system/devices/usb: Add CanoKey to USB devices examples
  MAINTAINERS: add myself as CanoKey maintainer

Joelle van Dyne (1):
  usbredir: avoid queuing hello packet on snapshot restore

Volker Rümelin (2):
  ui/gtk-gl-area: implement GL context destruction
  ui/gtk-gl-area: create the requested GL context version

 configure   |   4 +
 meson_options.txt   |   2 +
 hw/usb/canokey.h|  69 ++
 include/hw/virtio/virtio-gpu.h  |   1 +
 include/ui/console.h|   4 +-
 include/ui/gtk.h|   2 +-
 hw/display/virtio-gpu-base.c|   7 +-
 hw/display/virtio-gpu.c |   4 +
 hw/display/virtio-vga.c |   5 +-
 hw/display/xenfb.c  |  14 +-
 hw/usb/canokey.c| 313 
 hw/usb/hcd-ehci.c   |   5 +-
 hw/usb/redirect.c   |   3 +-
 hw/vfio/display.c   |   8 +-
 ui/console.c|   6 -
 ui/gtk-egl.c|   4 +-
 ui/gtk-gl-area.c|  42 +++-
 ui/gtk.c|  45 ++--
 MAINTAINERS |   8 +
 docs/system/device-emulation.rst|   1 +
 docs/system/devices/canokey.rst | 168 +++
 docs/system/devices/usb.rst |   4 +
 hw/usb/Kconfig  |   5 +
 hw/usb/meson.build  |   5 +
 hw/usb/trace-events |  16 ++
 meson.build |   6 +
 pc-bios/meson.build |   1 -
 scripts/meson-buildoptions.sh   |   3 +
 ui/cocoa.m  |   6 +-
 {pc-bios => ui}/keymaps/ar  |   0
 {pc-bios => ui}/keymaps/bepo|   0
 {pc-bios => ui}/keymaps/cz  |   0
 {pc-bios => ui}/keymaps/da  |   0
 {pc-bios => ui}/keymaps/de  |   0
 {pc-bios => ui}/keymaps/de-ch   |   0
 {pc-bios => ui}/keymaps/en-gb   |   0
 {pc-bios => ui}/keymaps/en-us   |   0
 {pc-bios => ui}/keymaps/es  |   0
 {pc-bios => ui}/keymaps/et  |   0
 {pc-bios => ui}/keymaps/fi  |   0
 {pc-bios => ui}/keymaps/fo  |   0
 {pc-bios => ui}/keymaps/fr  |   0
 {pc-bios => ui}/keymaps/fr-be   |   0
 {pc-bios => ui}/keymaps/fr-ca   |   0
 {pc-bios => ui}/keymaps/fr-ch   |   0
 {pc-bios => ui}/keymaps/hr  |   0
 {pc-bios => ui}/keymaps/hu  |   0
 {pc-bios => ui}/keymaps/is  |   0
 {pc-bios => ui}/keymaps/it  |   0
 {pc-bios => ui}/keymaps/ja  |   0
 {pc-bios => ui}/keymaps/lt  |   0
 {pc-bios => ui}/keymaps/lv  |   0
 {pc-bios => ui}/keymaps/meson.build |   0
 {pc-bios => ui}/keymaps/mk  |   0
 {pc-bios => ui}/keymaps/nl  |   0
 {pc-bios => ui}/keymaps/no  |   0
 {pc-bios => ui}/keymaps/pl  |   0
 {pc-bios => ui}/keymaps/pt  |   0
 {pc-bios => ui}/keymaps/pt-br   |   0
 {pc-bios => ui}/keymaps/ru  |   0
 {pc-bios => ui}/keymaps/sl  |   0
 {pc-bios => ui}/keymaps/sv  |   0
 {pc-bios => ui}/keymaps/th  |   0
 {pc-bios => ui}/keymaps/tr  |   0
 ui/meson.build  |   1 +
 ui/trace-events |   2 +
 66 files changed, 712 insertions(+), 52 deletions(-)
 create mode 100644 hw/usb/canokey.h
 create mode 100644 hw/usb/canokey.c
 create mode 100644 docs/system/devices/canokey.rst
 rename {pc-bios => ui}/keymaps/ar (100%)
 rename {pc-bios => ui}/keymaps/bepo (100%)
 r

[PULL 06/16] meson: Add CanoKey

2022-06-13 Thread Gerd Hoffmann
From: "Hongren (Zenithal) Zheng" 

Signed-off-by: Hongren (Zenithal) Zheng 
Message-Id: 
Signed-off-by: Gerd Hoffmann 
---
 meson_options.txt | 2 ++
 hw/usb/Kconfig| 5 +
 hw/usb/meson.build| 5 +
 meson.build   | 6 ++
 scripts/meson-buildoptions.sh | 3 +++
 5 files changed, 21 insertions(+)

diff --git a/meson_options.txt b/meson_options.txt
index 2de94af03712..0e8197386b99 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -189,6 +189,8 @@ option('spice_protocol', type : 'feature', value : 'auto',
description: 'Spice protocol support')
 option('u2f', type : 'feature', value : 'auto',
description: 'U2F emulation support')
+option('canokey', type : 'feature', value : 'auto',
+   description: 'CanoKey support')
 option('usb_redir', type : 'feature', value : 'auto',
description: 'libusbredir support')
 option('l2tpv3', type : 'feature', value : 'auto',
diff --git a/hw/usb/Kconfig b/hw/usb/Kconfig
index 53f8283ffdc1..ce4f4339763e 100644
--- a/hw/usb/Kconfig
+++ b/hw/usb/Kconfig
@@ -119,6 +119,11 @@ config USB_U2F
 default y
 depends on USB
 
+config USB_CANOKEY
+bool
+default y
+depends on USB
+
 config IMX_USBPHY
 bool
 default y
diff --git a/hw/usb/meson.build b/hw/usb/meson.build
index de853d780dd8..793df42e2127 100644
--- a/hw/usb/meson.build
+++ b/hw/usb/meson.build
@@ -63,6 +63,11 @@ if u2f.found()
   softmmu_ss.add(when: 'CONFIG_USB_U2F', if_true: [u2f, 
files('u2f-emulated.c')])
 endif
 
+# CanoKey
+if canokey.found()
+  softmmu_ss.add(when: 'CONFIG_USB_CANOKEY', if_true: [canokey, 
files('canokey.c')])
+endif
+
 # usb redirect
 if usbredir.found()
   usbredir_ss = ss.source_set()
diff --git a/meson.build b/meson.build
index 21cd949082dc..0c2e11ff0715 100644
--- a/meson.build
+++ b/meson.build
@@ -1408,6 +1408,12 @@ if have_system
method: 'pkg-config',
kwargs: static_kwargs)
 endif
+canokey = not_found
+if have_system
+  canokey = dependency('canokey-qemu', required: get_option('canokey'),
+   method: 'pkg-config',
+   kwargs: static_kwargs)
+endif
 usbredir = not_found
 if not get_option('usb_redir').auto() or have_system
   usbredir = dependency('libusbredirparser-0.5', required: 
get_option('usb_redir'),
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
index 00ea4d8cd169..1fc1d2e2c362 100644
--- a/scripts/meson-buildoptions.sh
+++ b/scripts/meson-buildoptions.sh
@@ -73,6 +73,7 @@ meson_options_help() {
   printf "%s\n" '  bpf eBPF support'
   printf "%s\n" '  brlapi  brlapi character device driver'
   printf "%s\n" '  bzip2   bzip2 support for DMG images'
+  printf "%s\n" '  canokey CanoKey support'
   printf "%s\n" '  cap-ng  cap_ng support'
   printf "%s\n" '  capstoneWhether and how to find the capstone 
library'
   printf "%s\n" '  cloop   cloop image format support'
@@ -204,6 +205,8 @@ _meson_option_parse() {
 --disable-brlapi) printf "%s" -Dbrlapi=disabled ;;
 --enable-bzip2) printf "%s" -Dbzip2=enabled ;;
 --disable-bzip2) printf "%s" -Dbzip2=disabled ;;
+--enable-canokey) printf "%s" -Dcanokey=enabled ;;
+--disable-canokey) printf "%s" -Dcanokey=disabled ;;
 --enable-cap-ng) printf "%s" -Dcap_ng=enabled ;;
 --disable-cap-ng) printf "%s" -Dcap_ng=disabled ;;
 --enable-capstone) printf "%s" -Dcapstone=enabled ;;
-- 
2.36.1




[PULL 13/16] ui/console: Do not return a value with ui_info

2022-06-13 Thread Gerd Hoffmann
From: Akihiko Odaki 

The returned value is not used and misleading.

Signed-off-by: Akihiko Odaki 
Message-Id: <20220226115516.59830-2-akihiko.od...@gmail.com>
Signed-off-by: Gerd Hoffmann 
---
 include/ui/console.h | 2 +-
 hw/display/virtio-gpu-base.c | 6 +++---
 hw/display/virtio-vga.c  | 5 ++---
 hw/vfio/display.c| 8 +++-
 4 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/include/ui/console.h b/include/ui/console.h
index c44b28a972ca..642d6f5248cf 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -432,7 +432,7 @@ typedef struct GraphicHwOps {
 bool gfx_update_async; /* if true, calls graphic_hw_update_done() */
 void (*text_update)(void *opaque, console_ch_t *text);
 void (*update_interval)(void *opaque, uint64_t interval);
-int (*ui_info)(void *opaque, uint32_t head, QemuUIInfo *info);
+void (*ui_info)(void *opaque, uint32_t head, QemuUIInfo *info);
 void (*gl_block)(void *opaque, bool block);
 } GraphicHwOps;
 
diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c
index 790cec333c8c..b21d6e5b0be8 100644
--- a/hw/display/virtio-gpu-base.c
+++ b/hw/display/virtio-gpu-base.c
@@ -69,12 +69,12 @@ static void virtio_gpu_notify_event(VirtIOGPUBase *g, 
uint32_t event_type)
 virtio_notify_config(&g->parent_obj);
 }
 
-static int virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
+static void virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
 {
 VirtIOGPUBase *g = opaque;
 
 if (idx >= g->conf.max_outputs) {
-return -1;
+return;
 }
 
 g->req_state[idx].x = info->xoff;
@@ -92,7 +92,7 @@ static int virtio_gpu_ui_info(void *opaque, uint32_t idx, 
QemuUIInfo *info)
 
 /* send event to guest */
 virtio_gpu_notify_event(g, VIRTIO_GPU_EVENT_DISPLAY);
-return 0;
+return;
 }
 
 static void
diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c
index c206b5da384b..4dcb34c4a740 100644
--- a/hw/display/virtio-vga.c
+++ b/hw/display/virtio-vga.c
@@ -47,15 +47,14 @@ static void virtio_vga_base_text_update(void *opaque, 
console_ch_t *chardata)
 }
 }
 
-static int virtio_vga_base_ui_info(void *opaque, uint32_t idx, QemuUIInfo 
*info)
+static void virtio_vga_base_ui_info(void *opaque, uint32_t idx, QemuUIInfo 
*info)
 {
 VirtIOVGABase *vvga = opaque;
 VirtIOGPUBase *g = vvga->vgpu;
 
 if (g->hw_ops->ui_info) {
-return g->hw_ops->ui_info(g, idx, info);
+g->hw_ops->ui_info(g, idx, info);
 }
-return -1;
 }
 
 static void virtio_vga_base_gl_block(void *opaque, bool block)
diff --git a/hw/vfio/display.c b/hw/vfio/display.c
index 89bc90508fb8..78f4d82c1c35 100644
--- a/hw/vfio/display.c
+++ b/hw/vfio/display.c
@@ -106,14 +106,14 @@ err:
 return;
 }
 
-static int vfio_display_edid_ui_info(void *opaque, uint32_t idx,
- QemuUIInfo *info)
+static void vfio_display_edid_ui_info(void *opaque, uint32_t idx,
+  QemuUIInfo *info)
 {
 VFIOPCIDevice *vdev = opaque;
 VFIODisplay *dpy = vdev->dpy;
 
 if (!dpy->edid_regs) {
-return 0;
+return;
 }
 
 if (info->width && info->height) {
@@ -121,8 +121,6 @@ static int vfio_display_edid_ui_info(void *opaque, uint32_t 
idx,
 } else {
 vfio_display_edid_update(vdev, false, 0, 0);
 }
-
-return 0;
 }
 
 static void vfio_display_edid_init(VFIOPCIDevice *vdev)
-- 
2.36.1




[PULL 02/16] ui/gtk-gl-area: create the requested GL context version

2022-06-13 Thread Gerd Hoffmann
From: Volker Rümelin 

Since about 2018 virglrenderer (commit fa835b0f88 "vrend: don't
hardcode context version") tries to open the highest available GL
context version. This is done by creating the known GL context
versions from the highest to the lowest until (*create_gl_context)
returns a context != NULL.

This does not work properly with
the current QEMU gd_gl_area_create_context() function, because
gdk_gl_context_realize() on Wayland creates a version 3.0 legacy
context if the requested GL context version can't be created.

In order for virglrenderer to find the highest available GL
context version, return NULL if the created context version is
lower than the requested version.

This fixes the following error:
QEMU started with -device virtio-vga-gl -display gtk,gl=on.
Under Wayland, the guest window remains black and the following
information can be seen on the host.

gl_version 30 - compat profile
(qemu:5978): Gdk-WARNING **: 16:19:01.533:
  gdk_gl_context_set_required_version
  - GL context versions less than 3.2 are not supported.

(qemu:5978): Gdk-WARNING **: 16:19:01.537:
  gdk_gl_context_set_required_version -
  GL context versions less than 3.2 are not supported.

(qemu:5978): Gdk-WARNING **: 16:19:01.554:
  gdk_gl_context_set_required_version -
  GL context versions less than 3.2 are not supported.
vrend_renderer_fill_caps: Entering with stale GL error: 1282

To reproduce this error, an OpenGL driver is required on the host
that doesn't have the latest OpenGL extensions fully implemented.
An example for this is the Intel i965 driver on a Haswell processor.

Signed-off-by: Volker Rümelin 
Message-Id: <20220605085131.7711-2-vr_q...@t-online.de>
Signed-off-by: Gerd Hoffmann 
---
 ui/gtk-gl-area.c | 31 ++-
 ui/trace-events  |  1 +
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
index 0e20ea031d34..2e0129c28cd4 100644
--- a/ui/gtk-gl-area.c
+++ b/ui/gtk-gl-area.c
@@ -170,6 +170,23 @@ void gd_gl_area_switch(DisplayChangeListener *dcl,
 }
 }
 
+static int gd_cmp_gl_context_version(int major, int minor, QEMUGLParams 
*params)
+{
+if (major > params->major_ver) {
+return 1;
+}
+if (major < params->major_ver) {
+return -1;
+}
+if (minor > params->minor_ver) {
+return 1;
+}
+if (minor < params->minor_ver) {
+return -1;
+}
+return 0;
+}
+
 QEMUGLContext gd_gl_area_create_context(DisplayGLCtx *dgc,
 QEMUGLParams *params)
 {
@@ -177,8 +194,8 @@ QEMUGLContext gd_gl_area_create_context(DisplayGLCtx *dgc,
 GdkWindow *window;
 GdkGLContext *ctx;
 GError *err = NULL;
+int major, minor;
 
-gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area));
 window = gtk_widget_get_window(vc->gfx.drawing_area);
 ctx = gdk_window_create_gl_context(window, &err);
 if (err) {
@@ -196,6 +213,18 @@ QEMUGLContext gd_gl_area_create_context(DisplayGLCtx *dgc,
 g_clear_object(&ctx);
 return NULL;
 }
+
+gdk_gl_context_make_current(ctx);
+gdk_gl_context_get_version(ctx, &major, &minor);
+gdk_gl_context_clear_current();
+gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area));
+
+if (gd_cmp_gl_context_version(major, minor, params) == -1) {
+/* created ctx version < requested version */
+g_clear_object(&ctx);
+}
+
+trace_gd_gl_area_create_context(ctx, params->major_ver, params->minor_ver);
 return ctx;
 }
 
diff --git a/ui/trace-events b/ui/trace-events
index 1040ba0f88c7..a922f00e10b4 100644
--- a/ui/trace-events
+++ b/ui/trace-events
@@ -26,6 +26,7 @@ gd_key_event(const char *tab, int gdk_keycode, int qkeycode, 
const char *action)
 gd_grab(const char *tab, const char *device, const char *reason) "tab=%s, 
dev=%s, reason=%s"
 gd_ungrab(const char *tab, const char *device) "tab=%s, dev=%s"
 gd_keymap_windowing(const char *name) "backend=%s"
+gd_gl_area_create_context(void *ctx, int major, int minor) "ctx=%p, major=%d, 
minor=%d"
 gd_gl_area_destroy_context(void *ctx, void *current_ctx) "ctx=%p, 
current_ctx=%p"
 
 # vnc-auth-sasl.c
-- 
2.36.1




[PULL 01/16] ui/gtk-gl-area: implement GL context destruction

2022-06-13 Thread Gerd Hoffmann
From: Volker Rümelin 

The counterpart function for gd_gl_area_create_context() is
currently empty. Implement the gd_gl_area_destroy_context()
function to avoid GL context leaks.

Signed-off-by: Volker Rümelin 
Message-Id: <20220605085131.7711-1-vr_q...@t-online.de>
Signed-off-by: Gerd Hoffmann 
---
 ui/gtk-gl-area.c | 8 +++-
 ui/trace-events  | 1 +
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
index fc5a082eb846..0e20ea031d34 100644
--- a/ui/gtk-gl-area.c
+++ b/ui/gtk-gl-area.c
@@ -201,7 +201,13 @@ QEMUGLContext gd_gl_area_create_context(DisplayGLCtx *dgc,
 
 void gd_gl_area_destroy_context(DisplayGLCtx *dgc, QEMUGLContext ctx)
 {
-/* FIXME */
+GdkGLContext *current_ctx = gdk_gl_context_get_current();
+
+trace_gd_gl_area_destroy_context(ctx, current_ctx);
+if (ctx == current_ctx) {
+gdk_gl_context_clear_current();
+}
+g_clear_object(&ctx);
 }
 
 void gd_gl_area_scanout_texture(DisplayChangeListener *dcl,
diff --git a/ui/trace-events b/ui/trace-events
index f78b5e66061f..1040ba0f88c7 100644
--- a/ui/trace-events
+++ b/ui/trace-events
@@ -26,6 +26,7 @@ gd_key_event(const char *tab, int gdk_keycode, int qkeycode, 
const char *action)
 gd_grab(const char *tab, const char *device, const char *reason) "tab=%s, 
dev=%s, reason=%s"
 gd_ungrab(const char *tab, const char *device) "tab=%s, dev=%s"
 gd_keymap_windowing(const char *name) "backend=%s"
+gd_gl_area_destroy_context(void *ctx, void *current_ctx) "ctx=%p, 
current_ctx=%p"
 
 # vnc-auth-sasl.c
 # vnc-auth-vencrypt.c
-- 
2.36.1




[PULL 15/16] virtio-gpu: Respect UI refresh rate for EDID

2022-06-13 Thread Gerd Hoffmann
From: Akihiko Odaki 

Signed-off-by: Akihiko Odaki 
Message-Id: <20220226115516.59830-4-akihiko.od...@gmail.com>
Signed-off-by: Gerd Hoffmann 
---
 include/hw/virtio/virtio-gpu.h | 1 +
 hw/display/virtio-gpu-base.c   | 1 +
 hw/display/virtio-gpu.c| 1 +
 3 files changed, 3 insertions(+)

diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index afff9e158e31..2e28507efe21 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -80,6 +80,7 @@ struct virtio_gpu_scanout {
 struct virtio_gpu_requested_state {
 uint16_t width_mm, height_mm;
 uint32_t width, height;
+uint32_t refresh_rate;
 int x, y;
 };
 
diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c
index b21d6e5b0be8..a29f191aa82e 100644
--- a/hw/display/virtio-gpu-base.c
+++ b/hw/display/virtio-gpu-base.c
@@ -79,6 +79,7 @@ static void virtio_gpu_ui_info(void *opaque, uint32_t idx, 
QemuUIInfo *info)
 
 g->req_state[idx].x = info->xoff;
 g->req_state[idx].y = info->yoff;
+g->req_state[idx].refresh_rate = info->refresh_rate;
 g->req_state[idx].width = info->width;
 g->req_state[idx].height = info->height;
 g->req_state[idx].width_mm = info->width_mm;
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 55c6dd576318..20cc703dcc6e 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -217,6 +217,7 @@ virtio_gpu_generate_edid(VirtIOGPU *g, int scanout,
 .height_mm = b->req_state[scanout].height_mm,
 .prefx = b->req_state[scanout].width,
 .prefy = b->req_state[scanout].height,
+.refresh_rate = b->req_state[scanout].refresh_rate,
 };
 
 edid->size = cpu_to_le32(sizeof(edid->edid));
-- 
2.36.1




[PULL 11/16] usbredir: avoid queuing hello packet on snapshot restore

2022-06-13 Thread Gerd Hoffmann
From: Joelle van Dyne 

When launching QEMU with "-loadvm", usbredir_create_parser() should avoid
setting up the hello packet (just as with "-incoming". On the latest version
of libusbredir, usbredirparser_unserialize() will return error if the parser
is not "pristine."

Signed-off-by: Joelle van Dyne 
Message-Id: <20220507041850.98716-...@getutm.app>
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/redirect.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index fd7df599bc0b..1bd30efc3ef0 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -1280,7 +1280,8 @@ static void usbredir_create_parser(USBRedirDevice *dev)
 }
 #endif
 
-if (runstate_check(RUN_STATE_INMIGRATE)) {
+if (runstate_check(RUN_STATE_INMIGRATE) ||
+runstate_check(RUN_STATE_PRELAUNCH)) {
 flags |= usbredirparser_fl_no_hello;
 }
 usbredirparser_init(dev->parser, VERSION, caps, USB_REDIR_CAPS_SIZE,
-- 
2.36.1




[PULL 03/16] ui/cocoa: Fix poweroff request code

2022-06-13 Thread Gerd Hoffmann
From: Akihiko Odaki 

Signed-off-by: Akihiko Odaki 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20220529082508.89097-1-akihiko.od...@gmail.com>
Signed-off-by: Gerd Hoffmann 
---
 ui/cocoa.m | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/ui/cocoa.m b/ui/cocoa.m
index 09a62817f2a9..84c84e98fc5e 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -35,6 +35,7 @@
 #include "ui/kbd-state.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/runstate.h"
+#include "sysemu/runstate-action.h"
 #include "sysemu/cpu-throttle.h"
 #include "qapi/error.h"
 #include "qapi/qapi-commands-block.h"
@@ -1290,7 +1291,10 @@ - (void)applicationWillTerminate:(NSNotification 
*)aNotification
 {
 COCOA_DEBUG("QemuCocoaAppController: applicationWillTerminate\n");
 
-qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_UI);
+with_iothread_lock(^{
+shutdown_action = SHUTDOWN_ACTION_POWEROFF;
+qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_UI);
+});
 
 /*
  * Sleep here, because returning will cause OSX to kill us
-- 
2.36.1




[PULL 04/16] hw/usb: Add CanoKey Implementation

2022-06-13 Thread Gerd Hoffmann
From: "Hongren (Zenithal) Zheng" 

This commit added a new emulated device called CanoKey to QEMU.

CanoKey implements platform independent features in canokey-core
https://github.com/canokeys/canokey-core, and leaves the USB implementation
to the platform.

In this commit the USB part was implemented in QEMU using QEMU's USB APIs,
therefore the emulated CanoKey can communicate with the guest OS using USB.

Signed-off-by: Hongren (Zenithal) Zheng 
Message-Id: 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/canokey.h |  69 +++
 hw/usb/canokey.c | 300 +++
 2 files changed, 369 insertions(+)
 create mode 100644 hw/usb/canokey.h
 create mode 100644 hw/usb/canokey.c

diff --git a/hw/usb/canokey.h b/hw/usb/canokey.h
new file mode 100644
index ..24cf30420346
--- /dev/null
+++ b/hw/usb/canokey.h
@@ -0,0 +1,69 @@
+/*
+ * CanoKey QEMU device header.
+ *
+ * Copyright (c) 2021-2022 Canokeys.org 
+ * Written by Hongren (Zenithal) Zheng 
+ *
+ * This code is licensed under the Apache-2.0.
+ */
+
+#ifndef CANOKEY_H
+#define CANOKEY_H
+
+#include "hw/qdev-core.h"
+
+#define TYPE_CANOKEY "canokey"
+#define CANOKEY(obj) \
+OBJECT_CHECK(CanoKeyState, (obj), TYPE_CANOKEY)
+
+/*
+ * State of Canokey (i.e. hw/canokey.c)
+ */
+
+/* CTRL INTR BULK */
+#define CANOKEY_EP_NUM 3
+/* BULK/INTR IN can be up to 1352 bytes, e.g. get key info */
+#define CANOKEY_EP_IN_BUFFER_SIZE 2048
+/* BULK OUT can be up to 270 bytes, e.g. PIV import cert */
+#define CANOKEY_EP_OUT_BUFFER_SIZE 512
+
+typedef enum {
+CANOKEY_EP_IN_WAIT,
+CANOKEY_EP_IN_READY,
+CANOKEY_EP_IN_STALL
+} CanoKeyEPState;
+
+typedef struct CanoKeyState {
+USBDevice dev;
+
+/* IN packets from canokey device loop */
+uint8_t ep_in[CANOKEY_EP_NUM][CANOKEY_EP_IN_BUFFER_SIZE];
+/*
+ * See canokey_emu_transmit
+ *
+ * For large INTR IN, receive multiple data from canokey device loop
+ * in this case ep_in_size would increase with every call
+ */
+uint32_t ep_in_size[CANOKEY_EP_NUM];
+/*
+ * Used in canokey_handle_data
+ * for IN larger than p->iov.size, we would do multiple handle_data()
+ *
+ * The difference between ep_in_pos and ep_in_size:
+ * We first increase ep_in_size to fill ep_in buffer in device_loop,
+ * then use ep_in_pos to submit data from ep_in buffer in handle_data
+ */
+uint32_t ep_in_pos[CANOKEY_EP_NUM];
+CanoKeyEPState ep_in_state[CANOKEY_EP_NUM];
+
+/* OUT pointer to canokey recv buffer */
+uint8_t *ep_out[CANOKEY_EP_NUM];
+uint32_t ep_out_size[CANOKEY_EP_NUM];
+/* For large BULK OUT, multiple write to ep_out is needed */
+uint8_t ep_out_buffer[CANOKEY_EP_NUM][CANOKEY_EP_OUT_BUFFER_SIZE];
+
+/* Properties */
+char *file; /* canokey-file */
+} CanoKeyState;
+
+#endif /* CANOKEY_H */
diff --git a/hw/usb/canokey.c b/hw/usb/canokey.c
new file mode 100644
index ..6cb8b7cdb089
--- /dev/null
+++ b/hw/usb/canokey.c
@@ -0,0 +1,300 @@
+/*
+ * CanoKey QEMU device implementation.
+ *
+ * Copyright (c) 2021-2022 Canokeys.org 
+ * Written by Hongren (Zenithal) Zheng 
+ *
+ * This code is licensed under the Apache-2.0.
+ */
+
+#include "qemu/osdep.h"
+#include 
+
+#include "qemu/module.h"
+#include "qapi/error.h"
+#include "hw/usb.h"
+#include "hw/qdev-properties.h"
+#include "desc.h"
+#include "canokey.h"
+
+#define CANOKEY_EP_IN(ep) ((ep) & 0x7F)
+
+#define CANOKEY_VENDOR_NUM 0x20a0
+#define CANOKEY_PRODUCT_NUM0x42d2
+
+/*
+ * placeholder, canokey-qemu implements its own usb desc
+ * Namely we do not use usb_desc_handle_contorl
+ */
+enum {
+STR_MANUFACTURER = 1,
+STR_PRODUCT,
+STR_SERIALNUMBER
+};
+
+static const USBDescStrings desc_strings = {
+[STR_MANUFACTURER] = "canokeys.org",
+[STR_PRODUCT]  = "CanoKey QEMU",
+[STR_SERIALNUMBER] = "0"
+};
+
+static const USBDescDevice desc_device_canokey = {
+.bcdUSB= 0x0,
+.bMaxPacketSize0   = 16,
+.bNumConfigurations= 0,
+.confs = NULL,
+};
+
+static const USBDesc desc_canokey = {
+.id = {
+.idVendor  = CANOKEY_VENDOR_NUM,
+.idProduct = CANOKEY_PRODUCT_NUM,
+.bcdDevice = 0x0100,
+.iManufacturer = STR_MANUFACTURER,
+.iProduct  = STR_PRODUCT,
+.iSerialNumber = STR_SERIALNUMBER,
+},
+.full = &desc_device_canokey,
+.high = &desc_device_canokey,
+.str  = desc_strings,
+};
+
+
+/*
+ * libcanokey-qemu.so side functions
+ * All functions are called from canokey_emu_device_loop
+ */
+int canokey_emu_stall_ep(void *base, uint8_t ep)
+{
+CanoKeyState *key = base;
+uint8_t ep_in = CANOKEY_EP_IN(ep); /* INTR IN has ep 129 */
+key->ep_in_size[ep_in] = 0;
+key->ep_in_state[ep_in] = CANOKEY_EP_IN_STALL;
+return 0;
+}
+
+int canokey_emu_set_address(void *base, uint8_t addr)
+{
+CanoKeyState *key = base;
+key->dev.

[PULL 07/16] docs: Add CanoKey documentation

2022-06-13 Thread Gerd Hoffmann
From: "Hongren (Zenithal) Zheng" 

Signed-off-by: Hongren (Zenithal) Zheng 
Message-Id: 
Signed-off-by: Gerd Hoffmann 
---
 docs/system/device-emulation.rst |   1 +
 docs/system/devices/canokey.rst  | 168 +++
 2 files changed, 169 insertions(+)
 create mode 100644 docs/system/devices/canokey.rst

diff --git a/docs/system/device-emulation.rst b/docs/system/device-emulation.rst
index 3b729b920d7c..05060060563f 100644
--- a/docs/system/device-emulation.rst
+++ b/docs/system/device-emulation.rst
@@ -92,3 +92,4 @@ Emulated Devices
devices/vhost-user.rst
devices/virtio-pmem.rst
devices/vhost-user-rng.rst
+   devices/canokey.rst
diff --git a/docs/system/devices/canokey.rst b/docs/system/devices/canokey.rst
new file mode 100644
index ..169f99b8eb82
--- /dev/null
+++ b/docs/system/devices/canokey.rst
@@ -0,0 +1,168 @@
+.. _canokey:
+
+CanoKey QEMU
+
+
+CanoKey [1]_ is an open-source secure key with supports of
+
+* U2F / FIDO2 with Ed25519 and HMAC-secret
+* OpenPGP Card V3.4 with RSA4096, Ed25519 and more [2]_
+* PIV (NIST SP 800-73-4)
+* HOTP / TOTP
+* NDEF
+
+All these platform-independent features are in canokey-core [3]_.
+
+For different platforms, CanoKey has different implementations,
+including both hardware implementions and virtual cards:
+
+* CanoKey STM32 [4]_
+* CanoKey Pigeon [5]_
+* (virt-card) CanoKey USB/IP
+* (virt-card) CanoKey FunctionFS
+
+In QEMU, yet another CanoKey virt-card is implemented.
+CanoKey QEMU exposes itself as a USB device to the guest OS.
+
+With the same software configuration as a hardware key,
+the guest OS can use all the functionalities of a secure key as if
+there was actually an hardware key plugged in.
+
+CanoKey QEMU provides much convenience for debuging:
+
+* libcanokey-qemu supports debuging output thus developers can
+  inspect what happens inside a secure key
+* CanoKey QEMU supports trace event thus event
+* QEMU USB stack supports pcap thus USB packet between the guest
+  and key can be captured and analysed
+
+Then for developers:
+
+* For developers on software with secure key support (e.g. FIDO2, OpenPGP),
+  they can see what happens inside the secure key
+* For secure key developers, USB packets between guest OS and CanoKey
+  can be easily captured and analysed
+
+Also since this is a virtual card, it can be easily used in CI for testing
+on code coping with secure key.
+
+Building
+
+
+libcanokey-qemu is required to use CanoKey QEMU.
+
+.. code-block:: shell
+
+git clone https://github.com/canokeys/canokey-qemu
+mkdir canokey-qemu/build
+pushd canokey-qemu/build
+
+If you want to install libcanokey-qemu in a different place,
+add ``-DCMAKE_INSTALL_PREFIX=/path/to/your/place`` to cmake below.
+
+.. code-block:: shell
+
+cmake ..
+make
+make install # may need sudo
+popd
+
+Then configuring and building:
+
+.. code-block:: shell
+
+# depending on your env, lib/pkgconfig can be lib64/pkgconfig
+export PKG_CONFIG_PATH=/path/to/your/place/lib/pkgconfig:$PKG_CONFIG_PATH
+./configure --enable-canokey && make
+
+Using CanoKey QEMU
+==
+
+CanoKey QEMU stores all its data on a file of the host specified by the 
argument
+when invoking qemu.
+
+.. parsed-literal::
+
+|qemu_system| -usb -device canokey,file=$HOME/.canokey-file
+
+Note: you should keep this file carefully as it may contain your private key!
+
+The first time when the file is used, it is created and initialized by CanoKey,
+afterwards CanoKey QEMU would just read this file.
+
+After the guest OS boots, you can check that there is a USB device.
+
+For example, If the guest OS is an Linux machine. You may invoke lsusb
+and find CanoKey QEMU there:
+
+.. code-block:: shell
+
+$ lsusb
+Bus 001 Device 002: ID 20a0:42d4 Clay Logic CanoKey QEMU
+
+You may setup the key as guided in [6]_. The console for the key is at [7]_.
+
+Debuging
+
+
+CanoKey QEMU consists of two parts, ``libcanokey-qemu.so`` and ``canokey.c``,
+the latter of which resides in QEMU. The former provides core functionality
+of a secure key while the latter provides platform-dependent functions:
+USB packet handling.
+
+If you want to trace what happens inside the secure key, when compiling
+libcanokey-qemu, you should add ``-DQEMU_DEBUG_OUTPUT=ON`` in cmake command
+line:
+
+.. code-block:: shell
+
+cmake .. -DQEMU_DEBUG_OUTPUT=ON
+
+If you want to trace events happened in canokey.c, use
+
+.. parsed-literal::
+
+|qemu_system| --trace "canokey_*" \\
+-usb -device canokey,file=$HOME/.canokey-file
+
+If you want to capture USB packets between the guest and the host, you can:
+
+.. parsed-literal::
+
+|qemu_system| -usb -device canokey,file=$HOME/.canokey-file,pcap=key.pcap
+
+Limitations
+===
+
+Currently libcanokey-qemu.so has dozens of global variables as it was 
originally
+designed for embedded systems. Thus one qemu instance can not have
+multiple CanoKey QEMU runn

[PULL 10/16] hw/usb/hcd-ehci: fix writeback order

2022-06-13 Thread Gerd Hoffmann
From: Arnout Engelen 

The 'active' bit passes control over a qTD between the guest and the
controller: set to 1 by guest to enable execution by the controller,
and the controller sets it to '0' to hand back control to the guest.

ehci_state_writeback write two dwords to main memory using DMA:
the third dword of the qTD (containing dt, total bytes to transfer,
cpage, cerr and status) and the fourth dword of the qTD (containing
the offset).

This commit makes sure the fourth dword is written before the third,
avoiding a race condition where a new offset written into the qTD
by the guest after it observed the status going to go to '0' gets
overwritten by a 'late' DMA writeback of the previous offset.

This race condition could lead to 'cpage out of range (5)' errors,
and reproduced by:

./qemu-system-x86_64 -enable-kvm -bios $SEABIOS/bios.bin -m 4096 -device 
usb-ehci -blockdev 
driver=file,read-only=on,filename=/home/aengelen/Downloads/openSUSE-Tumbleweed-DVD-i586-Snapshot20220428-Media.iso,node-name=iso
 -device usb-storage,drive=iso,bootindex=0 -chardev 
pipe,id=shell,path=/tmp/pipe -device virtio-serial -device 
virtconsole,chardev=shell -device virtio-rng-pci -serial mon:stdio -nographic

(press a key, select 'Installation' (2), and accept the default
values. On my machine the 'cpage out of range' is reproduced while
loading the Linux Kernel about once per 7 attempts. With the fix in
this commit it no longer fails)

This problem was previously reported as a seabios problem in
https://mail.coreboot.org/hyperkitty/list/seab...@seabios.org/thread/OUTHT5ISSQJGXPNTUPY3O5E5EPZJCHM3/
and as a nixos CI build failure in
https://github.com/NixOS/nixpkgs/issues/170803

Signed-off-by: Arnout Engelen 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/hcd-ehci.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 33a8a377bd95..d4da8dcb8d15 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -2011,7 +2011,10 @@ static int ehci_state_writeback(EHCIQueue *q)
 ehci_trace_qtd(q, NLPTR_GET(p->qtdaddr), (EHCIqtd *) &q->qh.next_qtd);
 qtd = (uint32_t *) &q->qh.next_qtd;
 addr = NLPTR_GET(p->qtdaddr);
-put_dwords(q->ehci, addr + 2 * sizeof(uint32_t), qtd + 2, 2);
+/* First write back the offset */
+put_dwords(q->ehci, addr + 3 * sizeof(uint32_t), qtd + 3, 1);
+/* Then write back the token, clearing the 'active' bit */
+put_dwords(q->ehci, addr + 2 * sizeof(uint32_t), qtd + 2, 1);
 ehci_free_packet(p);
 
 /*
-- 
2.36.1




[PATCH] hw/riscv: virt: pass random seed to fdt

2022-06-13 Thread Jason A. Donenfeld
If the FDT contains /chosen/rng-seed, then the Linux RNG will use it to
initialize early. Set this using the usual guest random number
generation function. This is confirmed to successfully initialize the
RNG on Linux 5.19-rc2.

Cc: Alistair Francis 
Signed-off-by: Jason A. Donenfeld 
---
 hw/riscv/virt.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index bc424dd2f5..368a723bf6 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -21,6 +21,7 @@
 #include "qemu/osdep.h"
 #include "qemu/units.h"
 #include "qemu/error-report.h"
+#include "qemu/guest-random.h"
 #include "qapi/error.h"
 #include "hw/boards.h"
 #include "hw/loader.h"
@@ -998,6 +999,7 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry 
*memmap,
 MachineState *mc = MACHINE(s);
 uint32_t phandle = 1, irq_mmio_phandle = 1, msi_pcie_phandle = 1;
 uint32_t irq_pcie_phandle = 1, irq_virtio_phandle = 1;
+uint8_t rng_seed[32];
 
 if (mc->dtb) {
 mc->fdt = load_device_tree(mc->dtb, &s->fdt_size);
@@ -1046,6 +1048,10 @@ update_bootargs:
 if (cmdline && *cmdline) {
 qemu_fdt_setprop_string(mc->fdt, "/chosen", "bootargs", cmdline);
 }
+
+/* Pass seed to RNG. */
+qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));
+qemu_fdt_setprop(mc->fdt, "/chosen", "rng-seed", rng_seed, 
sizeof(rng_seed));
 }
 
 static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem,
-- 
2.35.1




[PULL 12/16] virtio-gpu: update done only on the scanout associated with rect

2022-06-13 Thread Gerd Hoffmann
From: Dongwon Kim 

It only needs to update the scanouts containing the rect area
coming with the resource-flush request from the guest.

Cc: Gerd Hoffmann 
Cc: Vivek Kasireddy 
Signed-off-by: Dongwon Kim 
Message-Id: <20220505214030.4261-1-dongwon@intel.com>
Signed-off-by: Gerd Hoffmann 
---
 hw/display/virtio-gpu.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index cd4a56056fd9..55c6dd576318 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -514,6 +514,9 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
 for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
 scanout = &g->parent_obj.scanout[i];
 if (scanout->resource_id == res->resource_id &&
+rf.r.x >= scanout->x && rf.r.y >= scanout->y &&
+rf.r.x + rf.r.width <= scanout->x + scanout->width &&
+rf.r.y + rf.r.height <= scanout->y + scanout->height &&
 console_has_gl(scanout->con)) {
 dpy_gl_update(scanout->con, 0, 0, scanout->width,
   scanout->height);
-- 
2.36.1




[PULL 05/16] hw/usb/canokey: Add trace events

2022-06-13 Thread Gerd Hoffmann
From: "Hongren (Zenithal) Zheng" 

Signed-off-by: Hongren (Zenithal) Zheng 
Message-Id: 
Signed-off-by: Gerd Hoffmann 
---
 hw/usb/canokey.c| 13 +
 hw/usb/trace-events | 16 
 2 files changed, 29 insertions(+)

diff --git a/hw/usb/canokey.c b/hw/usb/canokey.c
index 6cb8b7cdb089..4a08b1cbd776 100644
--- a/hw/usb/canokey.c
+++ b/hw/usb/canokey.c
@@ -14,6 +14,7 @@
 #include "qapi/error.h"
 #include "hw/usb.h"
 #include "hw/qdev-properties.h"
+#include "trace.h"
 #include "desc.h"
 #include "canokey.h"
 
@@ -66,6 +67,7 @@ static const USBDesc desc_canokey = {
  */
 int canokey_emu_stall_ep(void *base, uint8_t ep)
 {
+trace_canokey_emu_stall_ep(ep);
 CanoKeyState *key = base;
 uint8_t ep_in = CANOKEY_EP_IN(ep); /* INTR IN has ep 129 */
 key->ep_in_size[ep_in] = 0;
@@ -75,6 +77,7 @@ int canokey_emu_stall_ep(void *base, uint8_t ep)
 
 int canokey_emu_set_address(void *base, uint8_t addr)
 {
+trace_canokey_emu_set_address(addr);
 CanoKeyState *key = base;
 key->dev.addr = addr;
 return 0;
@@ -83,6 +86,7 @@ int canokey_emu_set_address(void *base, uint8_t addr)
 int canokey_emu_prepare_receive(
 void *base, uint8_t ep, uint8_t *pbuf, uint16_t size)
 {
+trace_canokey_emu_prepare_receive(ep, size);
 CanoKeyState *key = base;
 key->ep_out[ep] = pbuf;
 key->ep_out_size[ep] = size;
@@ -92,6 +96,7 @@ int canokey_emu_prepare_receive(
 int canokey_emu_transmit(
 void *base, uint8_t ep, const uint8_t *pbuf, uint16_t size)
 {
+trace_canokey_emu_transmit(ep, size);
 CanoKeyState *key = base;
 uint8_t ep_in = CANOKEY_EP_IN(ep); /* INTR IN has ep 129 */
 memcpy(key->ep_in[ep_in] + key->ep_in_size[ep_in],
@@ -125,6 +130,7 @@ uint32_t canokey_emu_get_rx_data_size(void *base, uint8_t 
ep)
  */
 static void canokey_handle_reset(USBDevice *dev)
 {
+trace_canokey_handle_reset();
 CanoKeyState *key = CANOKEY(dev);
 for (int i = 0; i != CANOKEY_EP_NUM; ++i) {
 key->ep_in_state[i] = CANOKEY_EP_IN_WAIT;
@@ -137,6 +143,7 @@ static void canokey_handle_reset(USBDevice *dev)
 static void canokey_handle_control(USBDevice *dev, USBPacket *p,
int request, int value, int index, int length, uint8_t *data)
 {
+trace_canokey_handle_control_setup(request, value, index, length);
 CanoKeyState *key = CANOKEY(dev);
 
 canokey_emu_setup(request, value, index, length);
@@ -144,6 +151,7 @@ static void canokey_handle_control(USBDevice *dev, 
USBPacket *p,
 uint32_t dir_in = request & DeviceRequest;
 if (!dir_in) {
 /* OUT */
+trace_canokey_handle_control_out();
 if (key->ep_out[0] != NULL) {
 memcpy(key->ep_out[0], data, length);
 }
@@ -163,6 +171,7 @@ static void canokey_handle_control(USBDevice *dev, 
USBPacket *p,
 case CANOKEY_EP_IN_READY:
 memcpy(data, key->ep_in[0], key->ep_in_size[0]);
 p->actual_length = key->ep_in_size[0];
+trace_canokey_handle_control_in(p->actual_length);
 /* reset state */
 key->ep_in_state[0] = CANOKEY_EP_IN_WAIT;
 key->ep_in_size[0] = 0;
@@ -182,6 +191,7 @@ static void canokey_handle_data(USBDevice *dev, USBPacket 
*p)
 uint32_t out_len;
 switch (p->pid) {
 case USB_TOKEN_OUT:
+trace_canokey_handle_data_out(ep_out, p->iov.size);
 usb_packet_copy(p, key->ep_out_buffer[ep_out], p->iov.size);
 out_pos = 0;
 while (out_pos != p->iov.size) {
@@ -226,6 +236,7 @@ static void canokey_handle_data(USBDevice *dev, USBPacket 
*p)
 key->ep_in_size[ep_in] = 0;
 key->ep_in_pos[ep_in] = 0;
 }
+trace_canokey_handle_data_in(ep_in, in_len);
 break;
 }
 break;
@@ -237,6 +248,7 @@ static void canokey_handle_data(USBDevice *dev, USBPacket 
*p)
 
 static void canokey_realize(USBDevice *base, Error **errp)
 {
+trace_canokey_realize();
 CanoKeyState *key = CANOKEY(base);
 
 if (key->file == NULL) {
@@ -260,6 +272,7 @@ static void canokey_realize(USBDevice *base, Error **errp)
 
 static void canokey_unrealize(USBDevice *base)
 {
+trace_canokey_unrealize();
 }
 
 static Property canokey_properties[] = {
diff --git a/hw/usb/trace-events b/hw/usb/trace-events
index 9773cb53300d..914ca7166829 100644
--- a/hw/usb/trace-events
+++ b/hw/usb/trace-events
@@ -345,3 +345,19 @@ usb_serial_set_baud(int bus, int addr, int baud) "dev 
%d:%u baud rate %d"
 usb_serial_set_data(int bus, int addr, int parity, int data, int stop) "dev 
%d:%u parity %c, data bits %d, stop bits %d"
 usb_serial_set_flow_control(int bus, int addr, int index) "dev %d:%u flow 
control %d"
 usb_serial_set_xonxoff(int bus, int addr, uint8_t xon, uint8_t xoff) "dev 
%d:%u xon 0x%x xoff 0x%x"
+
+# canokey.c
+canokey_emu_stall_ep(uint8_t ep) "ep %d"
+canokey_emu_set_address(uint8_t addr) "addr %d"
+canokey_emu_prepare_receive(uint8_t ep, uint16_t size) "ep %d size %d"
+canokey_emu_transmit(uint8_t e

Re: [PATCH v2] ui: move 'pc-bios/keymaps' to 'ui/keymaps'

2022-06-13 Thread Gerd Hoffmann
On Mon, Jun 13, 2022 at 09:44:56AM +0100, Daniel P. Berrangé wrote:
> The 'keymaps' directory contents is nothing to do with the firmware
> blobs. The 'pc-bios/keymaps' directory appears to have been used
> previously as a convenience for getting the files installed into
> a subdir of the firmware install dir, as well as to make it easier
> to launch QEMU directly from the build tree. These requirements
> do not need to be reflected in the source tree arrangement. The
> keymaps logically belong with the UI code, and meson can install
> them into the right place. For in-tree execution, we merely need
> a suitable symlink from the source tree to the build tree.
> 
> Signed-off-by: Daniel P. Berrangé 
> ---
> 
> Changed in v2:
> 
>   - Make configure symlink ui/keymaps to $BUILD/pc-bios
> so in-tree build execution works. (Thanks Volker)

Replaced patch, v2 pull req sent.

thanks,
  Gerd




[PULL 09/16] MAINTAINERS: add myself as CanoKey maintainer

2022-06-13 Thread Gerd Hoffmann
From: "Hongren (Zenithal) Zheng" 

Signed-off-by: Hongren (Zenithal) Zheng 
Message-Id: 
Signed-off-by: Gerd Hoffmann 
---
 MAINTAINERS | 8 
 1 file changed, 8 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 0df25ed4b0a3..4cf6174f9f37 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2427,6 +2427,14 @@ F: hw/intc/s390_flic*.c
 F: include/hw/s390x/s390_flic.h
 L: qemu-s3...@nongnu.org
 
+CanoKey
+M: Hongren (Zenithal) Zheng 
+S: Maintained
+R: Canokeys.org 
+F: hw/usb/canokey.c
+F: hw/usb/canokey.h
+F: docs/system/devices/canokey.rst
+
 Subsystems
 --
 Overall Audio backends
-- 
2.36.1




[PULL 14/16] ui: Deliver refresh rate via QemuUIInfo

2022-06-13 Thread Gerd Hoffmann
From: Akihiko Odaki 

This change adds a new member, refresh_rate to QemuUIInfo in
include/ui/console.h. It represents the refresh rate of the
physical display backend, and it is more appropriate than
GUI update interval as the refresh rate which the emulated device
reports:
- sdl may set GUI update interval shorter than the refresh rate
  of the physical display to respond to user-generated events.
- sdl and vnc aggressively changes GUI update interval, but
  a guests is typically not designed to respond to frequent
  refresh rate changes, or frequent "display mode" changes in
  general. The frequency of refresh rate changes of the physical
  display backend matches better to the guest's expectation.

QemuUIInfo also has other members representing "display mode",
which makes it suitable for refresh rate representation. It has
a throttling of update notifications, and prevents frequent changes
of the display mode.

Signed-off-by: Akihiko Odaki 
Message-Id: <20220226115516.59830-3-akihiko.od...@gmail.com>
Signed-off-by: Gerd Hoffmann 
---
 include/ui/console.h |  2 +-
 include/ui/gtk.h |  2 +-
 hw/display/xenfb.c   | 14 +++---
 ui/console.c |  6 --
 ui/gtk-egl.c |  4 ++--
 ui/gtk-gl-area.c |  3 +--
 ui/gtk.c | 45 +---
 7 files changed, 42 insertions(+), 34 deletions(-)

diff --git a/include/ui/console.h b/include/ui/console.h
index 642d6f5248cf..b64d82436097 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -139,6 +139,7 @@ typedef struct QemuUIInfo {
 int   yoff;
 uint32_t  width;
 uint32_t  height;
+uint32_t  refresh_rate;
 } QemuUIInfo;
 
 /* cursor data format is 32bit RGBA */
@@ -431,7 +432,6 @@ typedef struct GraphicHwOps {
 void (*gfx_update)(void *opaque);
 bool gfx_update_async; /* if true, calls graphic_hw_update_done() */
 void (*text_update)(void *opaque, console_ch_t *text);
-void (*update_interval)(void *opaque, uint64_t interval);
 void (*ui_info)(void *opaque, uint32_t head, QemuUIInfo *info);
 void (*gl_block)(void *opaque, bool block);
 } GraphicHwOps;
diff --git a/include/ui/gtk.h b/include/ui/gtk.h
index 101b147d1b98..ae0f53740d19 100644
--- a/include/ui/gtk.h
+++ b/include/ui/gtk.h
@@ -155,7 +155,7 @@ extern bool gtk_use_gl_area;
 
 /* ui/gtk.c */
 void gd_update_windowsize(VirtualConsole *vc);
-int gd_monitor_update_interval(GtkWidget *widget);
+void gd_update_monitor_refresh_rate(VirtualConsole *vc, GtkWidget *widget);
 void gd_hw_gl_flushed(void *vc);
 
 /* ui/gtk-egl.c */
diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c
index cea10fe3c780..50857cd97a0b 100644
--- a/hw/display/xenfb.c
+++ b/hw/display/xenfb.c
@@ -777,16 +777,24 @@ static void xenfb_update(void *opaque)
 xenfb->up_fullscreen = 0;
 }
 
-static void xenfb_update_interval(void *opaque, uint64_t interval)
+static void xenfb_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
 {
 struct XenFB *xenfb = opaque;
+uint32_t refresh_rate;
 
 if (xenfb->feature_update) {
 #ifdef XENFB_TYPE_REFRESH_PERIOD
 if (xenfb_queue_full(xenfb)) {
 return;
 }
-xenfb_send_refresh_period(xenfb, interval);
+
+refresh_rate = info->refresh_rate;
+if (!refresh_rate) {
+refresh_rate = 75;
+}
+
+/* T = 1 / f = 1 [s*Hz] / f = 1000*1000 [ms*mHz] / f */
+xenfb_send_refresh_period(xenfb, 1000 * 1000 / refresh_rate);
 #endif
 }
 }
@@ -983,5 +991,5 @@ struct XenDevOps xen_framebuffer_ops = {
 static const GraphicHwOps xenfb_ops = {
 .invalidate  = xenfb_invalidate,
 .gfx_update  = xenfb_update,
-.update_interval = xenfb_update_interval,
+.ui_info = xenfb_ui_info,
 };
diff --git a/ui/console.c b/ui/console.c
index 36c80cd1de85..9331b85203a0 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -160,7 +160,6 @@ static void gui_update(void *opaque)
 uint64_t dcl_interval;
 DisplayState *ds = opaque;
 DisplayChangeListener *dcl;
-QemuConsole *con;
 
 ds->refreshing = true;
 dpy_refresh(ds);
@@ -175,11 +174,6 @@ static void gui_update(void *opaque)
 }
 if (ds->update_interval != interval) {
 ds->update_interval = interval;
-QTAILQ_FOREACH(con, &consoles, next) {
-if (con->hw_ops->update_interval) {
-con->hw_ops->update_interval(con->hw, interval);
-}
-}
 trace_console_refresh(interval);
 }
 ds->last_update = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
index e3bd4bc27431..b5bffbab2522 100644
--- a/ui/gtk-egl.c
+++ b/ui/gtk-egl.c
@@ -140,8 +140,8 @@ void gd_egl_refresh(DisplayChangeListener *dcl)
 {
 VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
 
-vc->gfx.dcl.update_interval = gd_monitor_update_interval(
-vc->window ? vc->window : vc->gfx.drawing_area);
+gd_update_monitor_refresh_rate(
+vc, v

[PULL 16/16] ui: move 'pc-bios/keymaps' to 'ui/keymaps'

2022-06-13 Thread Gerd Hoffmann
From: Daniel P. Berrangé 

The 'keymaps' directory contents is nothing to do with the firmware
blobs. The 'pc-bios/keymaps' directory appears to have been used
previously as a convenience for getting the files installed into
a subdir of the firmware install dir, as well as to make it easier
to launch QEMU directly from the build tree. These requirements
do not need to be reflected in the source tree arrangement. The
keymaps logically belong with the UI code, and meson can install
them into the right place. For in-tree execution, we merely need
a suitable symlink from the source tree to the build tree.

Signed-off-by: Daniel P. Berrangé 
Message-Id: <20220613084456.470068-1-berra...@redhat.com>
Signed-off-by: Gerd Hoffmann 
---
 configure   | 4 
 pc-bios/meson.build | 1 -
 {pc-bios => ui}/keymaps/ar  | 0
 {pc-bios => ui}/keymaps/bepo| 0
 {pc-bios => ui}/keymaps/cz  | 0
 {pc-bios => ui}/keymaps/da  | 0
 {pc-bios => ui}/keymaps/de  | 0
 {pc-bios => ui}/keymaps/de-ch   | 0
 {pc-bios => ui}/keymaps/en-gb   | 0
 {pc-bios => ui}/keymaps/en-us   | 0
 {pc-bios => ui}/keymaps/es  | 0
 {pc-bios => ui}/keymaps/et  | 0
 {pc-bios => ui}/keymaps/fi  | 0
 {pc-bios => ui}/keymaps/fo  | 0
 {pc-bios => ui}/keymaps/fr  | 0
 {pc-bios => ui}/keymaps/fr-be   | 0
 {pc-bios => ui}/keymaps/fr-ca   | 0
 {pc-bios => ui}/keymaps/fr-ch   | 0
 {pc-bios => ui}/keymaps/hr  | 0
 {pc-bios => ui}/keymaps/hu  | 0
 {pc-bios => ui}/keymaps/is  | 0
 {pc-bios => ui}/keymaps/it  | 0
 {pc-bios => ui}/keymaps/ja  | 0
 {pc-bios => ui}/keymaps/lt  | 0
 {pc-bios => ui}/keymaps/lv  | 0
 {pc-bios => ui}/keymaps/meson.build | 0
 {pc-bios => ui}/keymaps/mk  | 0
 {pc-bios => ui}/keymaps/nl  | 0
 {pc-bios => ui}/keymaps/no  | 0
 {pc-bios => ui}/keymaps/pl  | 0
 {pc-bios => ui}/keymaps/pt  | 0
 {pc-bios => ui}/keymaps/pt-br   | 0
 {pc-bios => ui}/keymaps/ru  | 0
 {pc-bios => ui}/keymaps/sl  | 0
 {pc-bios => ui}/keymaps/sv  | 0
 {pc-bios => ui}/keymaps/th  | 0
 {pc-bios => ui}/keymaps/tr  | 0
 ui/meson.build  | 1 +
 38 files changed, 5 insertions(+), 1 deletion(-)
 rename {pc-bios => ui}/keymaps/ar (100%)
 rename {pc-bios => ui}/keymaps/bepo (100%)
 rename {pc-bios => ui}/keymaps/cz (100%)
 rename {pc-bios => ui}/keymaps/da (100%)
 rename {pc-bios => ui}/keymaps/de (100%)
 rename {pc-bios => ui}/keymaps/de-ch (100%)
 rename {pc-bios => ui}/keymaps/en-gb (100%)
 rename {pc-bios => ui}/keymaps/en-us (100%)
 rename {pc-bios => ui}/keymaps/es (100%)
 rename {pc-bios => ui}/keymaps/et (100%)
 rename {pc-bios => ui}/keymaps/fi (100%)
 rename {pc-bios => ui}/keymaps/fo (100%)
 rename {pc-bios => ui}/keymaps/fr (100%)
 rename {pc-bios => ui}/keymaps/fr-be (100%)
 rename {pc-bios => ui}/keymaps/fr-ca (100%)
 rename {pc-bios => ui}/keymaps/fr-ch (100%)
 rename {pc-bios => ui}/keymaps/hr (100%)
 rename {pc-bios => ui}/keymaps/hu (100%)
 rename {pc-bios => ui}/keymaps/is (100%)
 rename {pc-bios => ui}/keymaps/it (100%)
 rename {pc-bios => ui}/keymaps/ja (100%)
 rename {pc-bios => ui}/keymaps/lt (100%)
 rename {pc-bios => ui}/keymaps/lv (100%)
 rename {pc-bios => ui}/keymaps/meson.build (100%)
 rename {pc-bios => ui}/keymaps/mk (100%)
 rename {pc-bios => ui}/keymaps/nl (100%)
 rename {pc-bios => ui}/keymaps/no (100%)
 rename {pc-bios => ui}/keymaps/pl (100%)
 rename {pc-bios => ui}/keymaps/pt (100%)
 rename {pc-bios => ui}/keymaps/pt-br (100%)
 rename {pc-bios => ui}/keymaps/ru (100%)
 rename {pc-bios => ui}/keymaps/sl (100%)
 rename {pc-bios => ui}/keymaps/sv (100%)
 rename {pc-bios => ui}/keymaps/th (100%)
 rename {pc-bios => ui}/keymaps/tr (100%)

diff --git a/configure b/configure
index e69537c7566c..77c68642514b 100755
--- a/configure
+++ b/configure
@@ -2226,6 +2226,10 @@ for f in $LINKS ; do
 fi
 done
 
+# Keymaps needs slightly different location in build
+# dir as we are simulating the installed data dir layout
+symlink "$source_path/ui/keymaps" "pc-bios/keymaps"
+
 # Mac OS X ships with a broken assembler
 roms=
 probe_target_compilers i386 x86_64
diff --git a/pc-bios/meson.build b/pc-bios/meson.build
index 41ba1c0ec7ba..e49c0e5f56de 100644
--- a/pc-bios/meson.build
+++ b/pc-bios/meson.build
@@ -97,4 +97,3 @@ foreach f : blobs
 endforeach
 
 subdir('descriptors')
-subdir('keymaps')
diff --git a/pc-bios/keymaps/ar b/ui/keymaps/ar
similarity index 100%
rename from pc-bios/keymaps/ar
rename to ui/keymaps/ar
diff --git a/pc-bios/keymaps/bepo b/ui/keymaps/bepo
similarity index 100%
rename from pc-bios/keymaps/bepo
rename to ui/keymaps/bepo
diff --git a/pc-bios/keymaps/cz b/ui/keymaps/cz
similarity index 100%
rename from pc-bios/keymaps/cz
rename to ui/keymaps/cz
diff --git a/pc-bios/keymaps/da b/ui/keymaps/da
similarity index 100%
rename from pc-bios/keymaps/da

[PULL 08/16] docs/system/devices/usb: Add CanoKey to USB devices examples

2022-06-13 Thread Gerd Hoffmann
From: "Hongren (Zenithal) Zheng" 

Signed-off-by: Hongren (Zenithal) Zheng 
Message-Id: 
Signed-off-by: Gerd Hoffmann 
---
 docs/system/devices/usb.rst | 4 
 1 file changed, 4 insertions(+)

diff --git a/docs/system/devices/usb.rst b/docs/system/devices/usb.rst
index afb7d6c2268d..872d9167589b 100644
--- a/docs/system/devices/usb.rst
+++ b/docs/system/devices/usb.rst
@@ -199,6 +199,10 @@ option or the ``device_add`` monitor command. Available 
devices are:
 ``u2f-{emulated,passthru}``
Universal Second Factor device
 
+``canokey``
+   An Open-source Secure Key implementing FIDO2, OpenPGP, PIV and more.
+   For more information, see :ref:`canokey`.
+
 Physical port addressing
 
 
-- 
2.36.1




[Bug] Take more 150s to boot qemu on ARM64

2022-06-13 Thread chenxiang (M)

Hi all,

I encounter a issue with kernel 5.19-rc1 on a ARM64 board:  it takes 
about 150s between beginning to run qemu command and beginng to boot 
Linux kernel ("EFI stub: Booting Linux Kernel...").


But in kernel 5.18-rc4, it only takes about 5s. I git bisect the kernel 
code and it finds c2445d387850 ("srcu: Add contention check to 
call_srcu() srcu_data ->lock acquisition").


The qemu (qemu version is 6.2.92) command i run is :

./qemu-system-aarch64 -m 4G,slots=4,maxmem=8g \
--trace "kvm*" \
-cpu host \
-machine virt,accel=kvm,gic-version=3  \
-machine smp.cpus=2,smp.sockets=2 \
-no-reboot \
-nographic \
-monitor unix:/home/cx/qmp-test,server,nowait \
-bios /home/cx/boot/QEMU_EFI.fd \
-kernel /home/cx/boot/Image  \
-device 
pcie-root-port,port=0x8,chassis=1,id=net1,bus=pcie.0,multifunction=on,addr=0x1 
\

-device vfio-pci,host=7d:01.3,id=net0 \
-device virtio-blk-pci,drive=drive0,id=virtblk0,num-queues=4  \
-drive file=/home/cx/boot/boot_ubuntu.img,if=none,id=drive0 \
-append "rdinit=init console=ttyAMA0 root=/dev/vda rootfstype=ext4 rw " \
-net none \
-D /home/cx/qemu_log.txt

I am not familiar with rcu code, and don't know how it causes the issue. 
Do you have any idea about this issue?



Best Regard,

Xiang Chen





[PATCH v2 0/3] CanoKey: Fix xHCI compatibility and CCID ZLP

2022-06-13 Thread Hongren (Zenithal) Zheng
In patch v5 [1] of Introduce CanoKey QEMU I said that canokey-qemu
was incompatible with qemu-xhci.

kraxel kindly suggested[2] that it should be the problem of usb_wakeup
So I fixed it in this patch set.

Now that the v5 patch has been in the process of git PULL [3],
I think it would be better to post a new patch set instead
of sending out v6, which would make maintainer's tree back and forth.

This patch should be applied after [1].

As for the CCID ZLP issue, it is described in the comment and commit
message.

I added a commit in https://github.com/canokeys/canokey-qemu
to export the EP num in the header, so hw/usb/canokey.c in qemu
could use it for CTAPHID quirks. If you want to compile
this version when --enable-canokey, make sure to use the latest
libcanokey-qemu.so

The CI result for this PATCH is at [4]. The failure for
amd64-debian-container seems irrelevent to this patchset.

[1] https://lore.kernel.org/qemu-devel/YoY5k0PQny8WtAHi@Sun/
[2] 
https://lore.kernel.org/qemu-devel/20220609095659.ulgk64bx3nlqz...@sirius.home.kraxel.org/
[3] 
https://lore.kernel.org/qemu-devel/20220610092043.1874654-1-kra...@redhat.com/
[4] https://gitlab.com/ZenithalHourlyRate/qemu/-/pipelines/561801062

---
v2: 
  * use usb_ep_get instead of recording ep_in_pointer
  as suggested by kraxel
  * CI result for v2 is at
https://gitlab.com/ZenithalHourlyRate/qemu/-/pipelines/562306905

Hongren (Zenithal) Zheng (3):
  hw/usb/canokey: Fix CCID ZLP
  hw/usb/canokey: fix compatibility of qemu-xhci
  docs/system/devices/usb/canokey: remove limitations on qemu-xhci

 docs/system/devices/canokey.rst | 10 --
 hw/usb/canokey.c| 30 ++
 2 files changed, 26 insertions(+), 14 deletions(-)

-- 
2.35.1




[PATCH v2 2/3] hw/usb/canokey: fix compatibility of qemu-xhci

2022-06-13 Thread Hongren (Zenithal) Zheng
XHCI wont poll interrupt IN endpoint if NAKed, and needs wakeup

Suggested-by: Gerd Hoffmann 
Signed-off-by: Hongren (Zenithal) Zheng 
---
 hw/usb/canokey.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/hw/usb/canokey.c b/hw/usb/canokey.c
index 86548923eb..8da0d65556 100644
--- a/hw/usb/canokey.c
+++ b/hw/usb/canokey.c
@@ -103,6 +103,13 @@ int canokey_emu_transmit(
 pbuf, size);
 key->ep_in_size[ep_in] += size;
 key->ep_in_state[ep_in] = CANOKEY_EP_IN_READY;
+/*
+ * wake up controller if we NAKed IN token before
+ * Note: this is a quirk for CanoKey CTAPHID
+ */
+if (ep_in == CANOKEY_EMU_EP_CTAPHID) {
+usb_wakeup(usb_ep_get(&key->dev, USB_TOKEN_IN, ep_in), 0);
+}
 /*
  * ready for more data in device loop
  *
@@ -208,6 +215,22 @@ static void canokey_handle_data(USBDevice *dev, USBPacket 
*p)
 key->ep_out_size[ep_out] = out_len;
 canokey_emu_data_out(ep_out, NULL);
 }
+/*
+ * Note: this is a quirk for CanoKey CTAPHID
+ *
+ * There is one code path that uses this device loop
+ * INTR IN -> useful data_in and useless device_loop -> NAKed
+ * INTR OUT -> useful device loop -> transmit -> wakeup
+ *   (useful thanks to both data_in and data_out having been called)
+ * the next INTR IN -> actual data to guest
+ *
+ * if there is no such device loop, there would be no further
+ * INTR IN, no device loop, no transmit hence no usb_wakeup
+ * then qemu would hang
+ */
+if (ep_in == CANOKEY_EMU_EP_CTAPHID) {
+canokey_emu_device_loop(); /* may call transmit multiple times */
+}
 break;
 case USB_TOKEN_IN:
 if (key->ep_in_pos[ep_in] == 0) { /* first time IN */
-- 
2.35.1




[PATCH] po: add ukrainian translation

2022-06-13 Thread Andrij Mizyk
Signed-off-by: Andrij Mizyk 
---
 po/LINGUAS |  1 +
 po/uk.po   | 75 ++
 2 files changed, 76 insertions(+)
 create mode 100644 po/uk.po

diff --git a/po/LINGUAS b/po/LINGUAS
index cc4b5c3b36..9b33a3659f 100644
--- a/po/LINGUAS
+++ b/po/LINGUAS
@@ -5,4 +5,5 @@ hu
 it
 sv
 tr
+uk
 zh_CN
diff --git a/po/uk.po b/po/uk.po
new file mode 100644
index 00..ff037808bf
--- /dev/null
+++ b/po/uk.po
@@ -0,0 +1,75 @@
+# Ukrainian translation for QEMU.
+# This file is put in the public domain.
+# Andrij Mizyk , 2022.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: QEMU 1.4.50\n"
+"Report-Msgid-Bugs-To: qemu-devel@nongnu.org\n"
+"POT-Creation-Date: 2018-07-18 07:56+0200\n"
+"PO-Revision-Date: 2022-06-13 01:33+0300\n"
+"Last-Translator: Andrij Mizyk \n"
+"Language-Team: Ukrainian\n"
+"Language: uk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: Gtranslator 2.91.6\n"
+
+msgid " - Press Ctrl+Alt+G to release grab"
+msgstr " - Натисніть Ctrl+Alt+G, щоб відпустити захоплення"
+
+msgid " [Paused]"
+msgstr " [Призупинено]"
+
+msgid "_Pause"
+msgstr "_Призупинити"
+
+msgid "_Reset"
+msgstr "_Скинути"
+
+msgid "Power _Down"
+msgstr "Вимкнути _живлення"
+
+msgid "_Quit"
+msgstr "_Вийти"
+
+msgid "_Fullscreen"
+msgstr "Повний _екран"
+
+msgid "_Copy"
+msgstr "_Копіювати"
+
+msgid "Zoom _In"
+msgstr "_Збільшити"
+
+msgid "Zoom _Out"
+msgstr "З_меншити"
+
+msgid "Best _Fit"
+msgstr "Найкращий _розмір"
+
+msgid "Zoom To _Fit"
+msgstr "Збільшити до _розміру"
+
+msgid "Grab On _Hover"
+msgstr "Захопити при _наведенні"
+
+msgid "_Grab Input"
+msgstr "Захопити _введення"
+
+msgid "Show _Tabs"
+msgstr "Показувати _вкладки"
+
+msgid "Detach Tab"
+msgstr "Відʼєднати вкладку"
+
+msgid "Show Menubar"
+msgstr "Показувати рядок меню"
+
+msgid "_Machine"
+msgstr "_Машина"
+
+msgid "_View"
+msgstr "_Вигляд"
-- 
2.30.2




[PATCH v2 1/3] hw/usb/canokey: Fix CCID ZLP

2022-06-13 Thread Hongren (Zenithal) Zheng
CCID could send zero-length packet (ZLP)
if we invoke two data_in, two packets would be concated
and we could not distinguish them.

The CANOKEY_EMU_EP_CTAPHID is imported from canokey-qemu.h

Reported-by: MkfsSion 
Signed-off-by: Hongren (Zenithal) Zheng 
---
 hw/usb/canokey.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/hw/usb/canokey.c b/hw/usb/canokey.c
index 4a08b1cbd7..86548923eb 100644
--- a/hw/usb/canokey.c
+++ b/hw/usb/canokey.c
@@ -109,11 +109,10 @@ int canokey_emu_transmit(
  * Note: this is a quirk for CanoKey CTAPHID
  * because it calls multiple emu_transmit in one device_loop
  * but w/o data_in it would stuck in device_loop
- * This has no side effect for CCID as it is strictly
- * OUT then IN transfer
- * However it has side effect for Control transfer
+ * This has side effect for CCID since CCID can send ZLP
+ * This also has side effect for Control transfer
  */
-if (ep_in != 0) {
+if (ep_in == CANOKEY_EMU_EP_CTAPHID) {
 canokey_emu_data_in(ep_in);
 }
 return 0;
-- 
2.35.1




[PATCH 1/5] libvduse: Fix resources leak in vduse_dev_destroy()

2022-06-13 Thread Xie Yongji
This fixes resource leak when the fd is zero in
vduse_dev_destroy().

Fixes: 8dbd281c1675 ("libvduse: Add VDUSE (vDPA Device in Userspace) library")
Signed-off-by: Xie Yongji 
---
 subprojects/libvduse/libvduse.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/subprojects/libvduse/libvduse.c b/subprojects/libvduse/libvduse.c
index 78bb777402..e781bfa907 100644
--- a/subprojects/libvduse/libvduse.c
+++ b/subprojects/libvduse/libvduse.c
@@ -1374,11 +1374,11 @@ int vduse_dev_destroy(VduseDev *dev)
 free(dev->vqs[i].resubmit_list);
 }
 free(dev->vqs);
-if (dev->fd > 0) {
+if (dev->fd >= 0) {
 close(dev->fd);
 dev->fd = -1;
 }
-if (dev->ctrl_fd > 0) {
+if (dev->ctrl_fd >= 0) {
 if (ioctl(dev->ctrl_fd, VDUSE_DESTROY_DEV, dev->name)) {
 ret = -errno;
 }
-- 
2.20.1




[PATCH v2 3/3] docs/system/devices/usb/canokey: remove limitations on qemu-xhci

2022-06-13 Thread Hongren (Zenithal) Zheng
Signed-off-by: Hongren (Zenithal) Zheng 
---
 docs/system/devices/canokey.rst | 10 --
 1 file changed, 10 deletions(-)

diff --git a/docs/system/devices/canokey.rst b/docs/system/devices/canokey.rst
index 169f99b8eb..c2c58ae3e7 100644
--- a/docs/system/devices/canokey.rst
+++ b/docs/system/devices/canokey.rst
@@ -146,16 +146,6 @@ multiple CanoKey QEMU running, namely you can not
 Also, there is no lock on canokey-file, thus two CanoKey QEMU instance
 can not read one canokey-file at the same time.
 
-Another limitation is that this device is not compatible with ``qemu-xhci``,
-in that this device would hang when there are FIDO2 packets (traffic on
-interrupt endpoints). If you do not use FIDO2 then it works as intended,
-but for full functionality you should use old uhci/ehci bus and attach canokey
-to it, for example
-
-.. parsed-literal::
-
-   |qemu_system| -device piix3-usb-uhci,id=uhci -device canokey,bus=uhci.0
-
 References
 ==
 
-- 
2.35.1




[PATCH 2/5] vduse-blk: Don't unlink the reconnect file if device exists

2022-06-13 Thread Xie Yongji
We should not unlink the reconnect file if vduse_dev_destroy()
fails with -EBUSY which means the VDUSE device has not been
removed from the vDPA bus. Otherwise, we might fail on
the reconnection later.

Fixes: 730abef0e873 ("libvduse: Add support for reconnecting")
Signed-off-by: Xie Yongji 
---
 block/export/vduse-blk.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/block/export/vduse-blk.c b/block/export/vduse-blk.c
index 3b10349173..c3a89894ae 100644
--- a/block/export/vduse-blk.c
+++ b/block/export/vduse-blk.c
@@ -316,12 +316,15 @@ static int vduse_blk_exp_create(BlockExport *exp, 
BlockExportOptions *opts,
 static void vduse_blk_exp_delete(BlockExport *exp)
 {
 VduseBlkExport *vblk_exp = container_of(exp, VduseBlkExport, export);
+int ret;
 
 blk_remove_aio_context_notifier(exp->blk, blk_aio_attached, blk_aio_detach,
 vblk_exp);
 blk_set_dev_ops(exp->blk, NULL, NULL);
-vduse_dev_destroy(vblk_exp->dev);
-unlink(vblk_exp->recon_file);
+ret = vduse_dev_destroy(vblk_exp->dev);
+if (ret != -EBUSY) {
+unlink(vblk_exp->recon_file);
+}
 g_free(vblk_exp->recon_file);
 }
 
-- 
2.20.1




Re: [PATCH 1/3] target/riscv: Remove the redundant initialization of env->misa_mxl

2022-06-13 Thread Bin Meng
On Mon, Jun 13, 2022 at 8:33 AM Alistair Francis  wrote:
>
> On Thu, Jun 9, 2022 at 11:08 AM Bin Meng  wrote:
> >
> > env->misa_mxl was already set in the RISC-V cpu init routine, and
> > validated at the beginning of riscv_cpu_realize(). There is no need
> > to do a redundant initialization later.
> >
> > Signed-off-by: Bin Meng 
> > ---
> >
> >  target/riscv/cpu.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index a91253d4bd..61d1737741 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -752,7 +752,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
> > **errp)
> >  ext |= RVJ;
> >  }
> >
> > -set_misa(env, env->misa_mxl, ext);
> > +env->misa_ext_mask = env->misa_ext = ext;
>
> You're right that we don't need to set `misa_mxl`, but isn't it
> cleaner calling the helper function here instead of manually assigning
> it?
>

There is no helper for assigning misa_ext only. Do you want a new
helper for that?

Regards,
Bin



[PATCH 5/5] vduse-blk: Add name option

2022-06-13 Thread Xie Yongji
Currently we use 'id' option as the name of VDUSE device.
It's a bit confusing since we use one value for two different
purposes: the ID to identfy the export within QEMU (must be
distinct from any other exports in the same QEMU process, but
can overlap with names used by other processes), and the VDUSE
name to uniquely identify it on the host (must be distinct from
other VDUSE devices on the same host, but can overlap with other
export types like NBD in the same process). To make it clear,
this patch adds a separate 'name' option to specify the VDUSE
name for the vduse-blk export instead.

Signed-off-by: Xie Yongji 
---
 block/export/vduse-blk.c | 4 ++--
 docs/tools/qemu-storage-daemon.rst   | 5 +++--
 qapi/block-export.json   | 7 ---
 storage-daemon/qemu-storage-daemon.c | 8 
 4 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/block/export/vduse-blk.c b/block/export/vduse-blk.c
index 066e088b00..f101c24c3f 100644
--- a/block/export/vduse-blk.c
+++ b/block/export/vduse-blk.c
@@ -300,7 +300,7 @@ static int vduse_blk_exp_create(BlockExport *exp, 
BlockExportOptions *opts,
 features |= 1ULL << VIRTIO_BLK_F_RO;
 }
 
-vblk_exp->dev = vduse_dev_create(exp->id, VIRTIO_ID_BLOCK, 0,
+vblk_exp->dev = vduse_dev_create(vblk_opts->name, VIRTIO_ID_BLOCK, 0,
  features, num_queues,
  sizeof(struct virtio_blk_config),
  (char *)&config, &vduse_blk_ops,
@@ -312,7 +312,7 @@ static int vduse_blk_exp_create(BlockExport *exp, 
BlockExportOptions *opts,
 }
 
 vblk_exp->recon_file = g_strdup_printf("%s/vduse-blk-%s",
-   g_get_tmp_dir(), exp->id);
+   g_get_tmp_dir(), vblk_opts->name);
 if (vduse_set_reconnect_log_file(vblk_exp->dev, vblk_exp->recon_file)) {
 error_setg(errp, "failed to set reconnect log file");
 ret = -EINVAL;
diff --git a/docs/tools/qemu-storage-daemon.rst 
b/docs/tools/qemu-storage-daemon.rst
index 034f2809a6..ea00149a63 100644
--- a/docs/tools/qemu-storage-daemon.rst
+++ b/docs/tools/qemu-storage-daemon.rst
@@ -77,7 +77,7 @@ Standard options:
   --export 
[type=]vhost-user-blk,id=,node-name=,addr.type=unix,addr.path=[,writable=on|off][,logical-block-size=][,num-queues=]
   --export 
[type=]vhost-user-blk,id=,node-name=,addr.type=fd,addr.str=[,writable=on|off][,logical-block-size=][,num-queues=]
   --export 
[type=]fuse,id=,node-name=,mountpoint=[,growable=on|off][,writable=on|off][,allow-other=on|off|auto]
-  --export 
[type=]vduse-blk,id=,node-name=[,writable=on|off][,num-queues=][,queue-size=][,logical-block-size=][,serial=]
+  --export 
[type=]vduse-blk,id=,node-name=,name=[,writable=on|off][,num-queues=][,queue-size=][,logical-block-size=][,serial=]
 
   is a block export definition. ``node-name`` is the block node that should be
   exported. ``writable`` determines whether or not the export allows write
@@ -111,7 +111,8 @@ Standard options:
   ``allow-other`` to auto (the default) will try enabling this option, and on
   error fall back to disabling it.
 
-  The ``vduse-blk`` export type uses the ``id`` as the VDUSE device name.
+  The ``vduse-blk`` export type takes a ``name`` (must be unique across the 
host)
+  to create the VDUSE device.
   ``num-queues`` sets the number of virtqueues (the default is 1).
   ``queue-size`` sets the virtqueue descriptor table size (the default is 256).
 
diff --git a/qapi/block-export.json b/qapi/block-export.json
index d7aeb1fbf7..81ef1e3dcd 100644
--- a/qapi/block-export.json
+++ b/qapi/block-export.json
@@ -182,6 +182,7 @@
 #
 # A vduse-blk block export.
 #
+# @name: the name of VDUSE device (must be unique across the host).
 # @num-queues: the number of virtqueues. Defaults to 1.
 # @queue-size: the size of virtqueue. Defaults to 256.
 # @logical-block-size: Logical block size in bytes. Range [512, PAGE_SIZE]
@@ -191,7 +192,8 @@
 # Since: 7.1
 ##
 { 'struct': 'BlockExportOptionsVduseBlk',
-  'data': { '*num-queues': 'uint16',
+  'data': { 'name': 'str',
+'*num-queues': 'uint16',
 '*queue-size': 'uint16',
 '*logical-block-size': 'size',
 '*serial': 'str' } }
@@ -316,8 +318,7 @@
 # Describes a block export, i.e. how single node should be exported on an
 # external interface.
 #
-# @id: A unique identifier for the block export (across the host for vduse-blk
-#  export type or across all export types for other types)
+# @id: A unique identifier for the block export (across all export types)
 #
 # @node-name: The node name of the block node to be exported (since: 5.2)
 #
diff --git a/storage-daemon/qemu-storage-daemon.c 
b/storage-daemon/qemu-storage-daemon.c
index 4e18d3fc85..b8e910f220 100644
--- a/storage-daemon/qemu-storage-daemon.c
+++ b/storage-daemon/qemu-storage-daemon.c
@@ -123,12 +123,12 @@ static void help(void)
 #endif /* CO

[PATCH 0/5] Some fixes and improvements for vduse-blk

2022-06-13 Thread Xie Yongji
This series includes few fixes and improvements for the
vduse-blk export.

Patch 1 fixes resources leak when vduse fd is zero.

Patch 2, 3 fixes two bugs which could be triggered
by force deleting a vduse-blk export with high I/O loads.

Patch 4, 5 adds two new options for vduse-blk export.

Xie Yongji (5):
  libvduse: Fix resources leak in vduse_dev_destroy()
  vduse-blk: Don't unlink the reconnect file if device exists
  vduse-blk: Don't delete the export until all inflight I/Os completed
  vduse-blk: Add serial option
  vduse-blk: Add name option

 block/export/vduse-blk.c | 53 ++--
 block/export/vhost-user-blk-server.c |  4 ++-
 block/export/virtio-blk-handler.h|  2 +-
 docs/tools/qemu-storage-daemon.rst   |  5 +--
 qapi/block-export.json   | 11 +++---
 storage-daemon/qemu-storage-daemon.c |  9 ++---
 subprojects/libvduse/libvduse.c  |  4 +--
 7 files changed, 64 insertions(+), 24 deletions(-)

-- 
2.20.1




[PATCH 4/5] vduse-blk: Add serial option

2022-06-13 Thread Xie Yongji
Add a 'serial' option to allow user to specify this value
explicitly. And the default value is changed to an empty
string as what we did in "hw/block/virtio-blk.c".

Signed-off-by: Xie Yongji 
---
 block/export/vduse-blk.c | 20 ++--
 block/export/vhost-user-blk-server.c |  4 +++-
 block/export/virtio-blk-handler.h|  2 +-
 docs/tools/qemu-storage-daemon.rst   |  2 +-
 qapi/block-export.json   |  4 +++-
 storage-daemon/qemu-storage-daemon.c |  1 +
 6 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/block/export/vduse-blk.c b/block/export/vduse-blk.c
index 251d73c841..066e088b00 100644
--- a/block/export/vduse-blk.c
+++ b/block/export/vduse-blk.c
@@ -235,7 +235,7 @@ static int vduse_blk_exp_create(BlockExport *exp, 
BlockExportOptions *opts,
 Error *local_err = NULL;
 struct virtio_blk_config config = { 0 };
 uint64_t features;
-int i;
+int i, ret;
 
 if (vblk_opts->has_num_queues) {
 num_queues = vblk_opts->num_queues;
@@ -265,7 +265,8 @@ static int vduse_blk_exp_create(BlockExport *exp, 
BlockExportOptions *opts,
 }
 vblk_exp->num_queues = num_queues;
 vblk_exp->handler.blk = exp->blk;
-vblk_exp->handler.serial = exp->id;
+vblk_exp->handler.serial = g_strdup(vblk_opts->has_serial ?
+vblk_opts->serial : "");
 vblk_exp->handler.logical_block_size = logical_block_size;
 vblk_exp->handler.writable = opts->writable;
 
@@ -306,16 +307,16 @@ static int vduse_blk_exp_create(BlockExport *exp, 
BlockExportOptions *opts,
  vblk_exp);
 if (!vblk_exp->dev) {
 error_setg(errp, "failed to create vduse device");
-return -ENOMEM;
+ret = -ENOMEM;
+goto err_dev;
 }
 
 vblk_exp->recon_file = g_strdup_printf("%s/vduse-blk-%s",
g_get_tmp_dir(), exp->id);
 if (vduse_set_reconnect_log_file(vblk_exp->dev, vblk_exp->recon_file)) {
 error_setg(errp, "failed to set reconnect log file");
-vduse_dev_destroy(vblk_exp->dev);
-g_free(vblk_exp->recon_file);
-return -EINVAL;
+ret = -EINVAL;
+goto err;
 }
 
 for (i = 0; i < num_queues; i++) {
@@ -331,6 +332,12 @@ static int vduse_blk_exp_create(BlockExport *exp, 
BlockExportOptions *opts,
 blk_set_dev_ops(exp->blk, &vduse_block_ops, exp);
 
 return 0;
+err:
+vduse_dev_destroy(vblk_exp->dev);
+g_free(vblk_exp->recon_file);
+err_dev:
+g_free(vblk_exp->handler.serial);
+return ret;
 }
 
 static void vduse_blk_exp_delete(BlockExport *exp)
@@ -346,6 +353,7 @@ static void vduse_blk_exp_delete(BlockExport *exp)
 unlink(vblk_exp->recon_file);
 }
 g_free(vblk_exp->recon_file);
+g_free(vblk_exp->handler.serial);
 }
 
 static void vduse_blk_exp_request_shutdown(BlockExport *exp)
diff --git a/block/export/vhost-user-blk-server.c 
b/block/export/vhost-user-blk-server.c
index c9c290cc4c..3409d9e02e 100644
--- a/block/export/vhost-user-blk-server.c
+++ b/block/export/vhost-user-blk-server.c
@@ -282,7 +282,7 @@ static int vu_blk_exp_create(BlockExport *exp, 
BlockExportOptions *opts,
 return -EINVAL;
 }
 vexp->handler.blk = exp->blk;
-vexp->handler.serial = "vhost_user_blk";
+vexp->handler.serial = g_strdup("vhost_user_blk");
 vexp->handler.logical_block_size = logical_block_size;
 vexp->handler.writable = opts->writable;
 
@@ -296,6 +296,7 @@ static int vu_blk_exp_create(BlockExport *exp, 
BlockExportOptions *opts,
  num_queues, &vu_blk_iface, errp)) {
 blk_remove_aio_context_notifier(exp->blk, blk_aio_attached,
 blk_aio_detach, vexp);
+g_free(vexp->handler.serial);
 return -EADDRNOTAVAIL;
 }
 
@@ -308,6 +309,7 @@ static void vu_blk_exp_delete(BlockExport *exp)
 
 blk_remove_aio_context_notifier(exp->blk, blk_aio_attached, blk_aio_detach,
 vexp);
+g_free(vexp->handler.serial);
 }
 
 const BlockExportDriver blk_exp_vhost_user_blk = {
diff --git a/block/export/virtio-blk-handler.h 
b/block/export/virtio-blk-handler.h
index 1c7a5e32ad..150d44cff2 100644
--- a/block/export/virtio-blk-handler.h
+++ b/block/export/virtio-blk-handler.h
@@ -23,7 +23,7 @@
 
 typedef struct {
 BlockBackend *blk;
-const char *serial;
+char *serial;
 uint32_t logical_block_size;
 bool writable;
 } VirtioBlkHandler;
diff --git a/docs/tools/qemu-storage-daemon.rst 
b/docs/tools/qemu-storage-daemon.rst
index fbeaf76954..034f2809a6 100644
--- a/docs/tools/qemu-storage-daemon.rst
+++ b/docs/tools/qemu-storage-daemon.rst
@@ -77,7 +77,7 @@ Standard options:
   --export 
[type=]vhost-user-blk,id=,node-name=,addr.type=unix,addr.path=[,writable=on|off][,logical-block-size=][,num-queues=]
   --export 
[type=]vhost-user-blk,id=,node-name=,addr.type=fd,addr.str=[,writable=on|of

[PATCH 3/5] vduse-blk: Don't delete the export until all inflight I/Os completed

2022-06-13 Thread Xie Yongji
Don't delete the export until all inflight I/Os completed.
Otherwise, it might lead to a use-after-free.

Fixes: cc241b5505b2 ("vduse-blk: Implement vduse-blk export")
Signed-off-by: Xie Yongji 
---
 block/export/vduse-blk.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/block/export/vduse-blk.c b/block/export/vduse-blk.c
index c3a89894ae..251d73c841 100644
--- a/block/export/vduse-blk.c
+++ b/block/export/vduse-blk.c
@@ -31,6 +31,7 @@ typedef struct VduseBlkExport {
 VduseDev *dev;
 uint16_t num_queues;
 char *recon_file;
+unsigned int inflight;
 } VduseBlkExport;
 
 typedef struct VduseBlkReq {
@@ -38,6 +39,18 @@ typedef struct VduseBlkReq {
 VduseVirtq *vq;
 } VduseBlkReq;
 
+static void vduse_blk_inflight_inc(VduseBlkExport *vblk_exp)
+{
+vblk_exp->inflight++;
+}
+
+static void vduse_blk_inflight_dec(VduseBlkExport *vblk_exp)
+{
+if (--vblk_exp->inflight == 0) {
+aio_wait_kick();
+}
+}
+
 static void vduse_blk_req_complete(VduseBlkReq *req, size_t in_len)
 {
 vduse_queue_push(req->vq, &req->elem, in_len);
@@ -68,10 +81,13 @@ static void coroutine_fn vduse_blk_virtio_process_req(void 
*opaque)
 }
 
 vduse_blk_req_complete(req, in_len);
+vduse_blk_inflight_dec(vblk_exp);
 }
 
 static void vduse_blk_vq_handler(VduseDev *dev, VduseVirtq *vq)
 {
+VduseBlkExport *vblk_exp = vduse_dev_get_priv(dev);
+
 while (1) {
 VduseBlkReq *req;
 
@@ -83,6 +99,8 @@ static void vduse_blk_vq_handler(VduseDev *dev, VduseVirtq 
*vq)
 
 Coroutine *co =
 qemu_coroutine_create(vduse_blk_virtio_process_req, req);
+
+vduse_blk_inflight_inc(vblk_exp);
 qemu_coroutine_enter(co);
 }
 }
@@ -168,6 +186,8 @@ static void vduse_blk_detach_ctx(VduseBlkExport *vblk_exp)
 }
 aio_set_fd_handler(vblk_exp->export.ctx, vduse_dev_get_fd(vblk_exp->dev),
true, NULL, NULL, NULL, NULL, NULL);
+
+AIO_WAIT_WHILE(vblk_exp->export.ctx, vblk_exp->inflight > 0);
 }
 
 
@@ -332,7 +352,9 @@ static void vduse_blk_exp_request_shutdown(BlockExport *exp)
 {
 VduseBlkExport *vblk_exp = container_of(exp, VduseBlkExport, export);
 
+aio_context_acquire(vblk_exp->export.ctx);
 vduse_blk_detach_ctx(vblk_exp);
+aio_context_acquire(vblk_exp->export.ctx);
 }
 
 const BlockExportDriver blk_exp_vduse_blk = {
-- 
2.20.1




[PATCH v2 02/17] test/avocado/machine_aspeed.py: Move OpenBMC tests

2022-06-13 Thread Cédric Le Goater
It's easier to run. Keep test_arm_ast2600_debian() under the
boot_linux_console.py file because it requires the extract_from_deb()
helper. We could remove it when we have tests for the AST2600.

Signed-off-by: Cédric Le Goater 
---
 tests/avocado/boot_linux_console.py | 43 -
 tests/avocado/machine_aspeed.py | 50 +
 2 files changed, 50 insertions(+), 43 deletions(-)

diff --git a/tests/avocado/boot_linux_console.py 
b/tests/avocado/boot_linux_console.py
index 45a2ceda2227..6b1533c17c8b 100644
--- a/tests/avocado/boot_linux_console.py
+++ b/tests/avocado/boot_linux_console.py
@@ -1043,49 +1043,6 @@ def test_arm_vexpressa9(self):
 self.vm.add_args('-dtb', self.workdir + '/day16/vexpress-v2p-ca9.dtb')
 self.do_test_advcal_2018('16', tar_hash, 'winter.zImage')
 
-def test_arm_ast2400_palmetto_openbmc_v2_9_0(self):
-"""
-:avocado: tags=arch:arm
-:avocado: tags=machine:palmetto-bmc
-"""
-
-image_url = 
('https://github.com/openbmc/openbmc/releases/download/2.9.0/'
- 'obmc-phosphor-image-palmetto.static.mtd')
-image_hash = 
('3e13bbbc28e424865dc42f35ad672b10f2e82cdb11846bb28fa625b48beafd0d')
-image_path = self.fetch_asset(image_url, asset_hash=image_hash,
-  algorithm='sha256')
-
-self.do_test_arm_aspeed(image_path)
-
-def test_arm_ast2500_romulus_openbmc_v2_9_0(self):
-"""
-:avocado: tags=arch:arm
-:avocado: tags=machine:romulus-bmc
-"""
-
-image_url = 
('https://github.com/openbmc/openbmc/releases/download/2.9.0/'
- 'obmc-phosphor-image-romulus.static.mtd')
-image_hash = 
('820341076803f1955bc31e647a512c79f9add4f5233d0697678bab4604c7bb25')
-image_path = self.fetch_asset(image_url, asset_hash=image_hash,
-  algorithm='sha256')
-
-self.do_test_arm_aspeed(image_path)
-
-def do_test_arm_aspeed(self, image):
-self.vm.set_console()
-self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw',
- '-net', 'nic')
-self.vm.launch()
-
-self.wait_for_console_pattern("U-Boot 2016.07")
-self.wait_for_console_pattern("## Loading kernel from FIT Image at 
2008")
-self.wait_for_console_pattern("Starting kernel ...")
-self.wait_for_console_pattern("Booting Linux on physical CPU 0x0")
-self.wait_for_console_pattern(
-"aspeed-smc 1e62.spi: read control register: 203b0641")
-self.wait_for_console_pattern("ftgmac100 1e66.ethernet eth0: irq ")
-self.wait_for_console_pattern("systemd[1]: Set hostname to")
-
 def test_arm_ast2600_debian(self):
 """
 :avocado: tags=arch:arm
diff --git a/tests/avocado/machine_aspeed.py b/tests/avocado/machine_aspeed.py
index 33090af19940..89bfad307661 100644
--- a/tests/avocado/machine_aspeed.py
+++ b/tests/avocado/machine_aspeed.py
@@ -34,3 +34,53 @@ def test_ast1030_zephyros(self):
 wait_for_console_pattern(self, "Booting Zephyr OS")
 exec_command_and_wait_for_pattern(self, "help",
   "Available commands")
+
+class AST2x00Machine(QemuSystemTest):
+
+def wait_for_console_pattern(self, success_message, vm=None):
+wait_for_console_pattern(self, success_message,
+ failure_message='Kernel panic - not syncing',
+ vm=vm)
+
+def do_test_arm_aspeed(self, image):
+self.vm.set_console()
+self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw',
+ '-net', 'nic')
+self.vm.launch()
+
+self.wait_for_console_pattern("U-Boot 2016.07")
+self.wait_for_console_pattern("## Loading kernel from FIT Image at 
2008")
+self.wait_for_console_pattern("Starting kernel ...")
+self.wait_for_console_pattern("Booting Linux on physical CPU 0x0")
+wait_for_console_pattern(self,
+"aspeed-smc 1e62.spi: read control register: 203b0641")
+self.wait_for_console_pattern("ftgmac100 1e66.ethernet eth0: irq ")
+self.wait_for_console_pattern("systemd[1]: Set hostname to")
+
+def test_arm_ast2400_palmetto_openbmc_v2_9_0(self):
+"""
+:avocado: tags=arch:arm
+:avocado: tags=machine:palmetto-bmc
+"""
+
+image_url = 
('https://github.com/openbmc/openbmc/releases/download/2.9.0/'
+ 'obmc-phosphor-image-palmetto.static.mtd')
+image_hash = 
('3e13bbbc28e424865dc42f35ad672b10f2e82cdb11846bb28fa625b48beafd0d')
+image_path = self.fetch_asset(image_url, asset_hash=image_hash,
+  algorithm='sha256')
+
+self.do_test_arm_aspeed(image_path)
+
+def test_arm_ast2500_romulus_openbmc_v2_9_0(self):

[PATCH v2 00/17] aspeed: Extend ast2600 I2C model with new mode

2022-06-13 Thread Cédric Le Goater
Hello,

Here is a series aggregating recent changes proposed on the Aspeed
ast2600 I2C controller model. 

First comes a large set of changes converting the model to use the
registerfield interface and adding the I2C new register mode
(Joe). Since this is complex to review, extra tests are added to the
acceptance test suite to check that I2C devices are still functional
in the ast2600-evb machine. These tests use small buildroot images
available on GH.

The ast1030 and ast2600 SoC share the same I2C logic. This series adds
I2C support to the ast1030 now that new register mode is supported.
There was a previous proposal from Troy doing the same but Joe's
patchset covers the same need (and converts the model to registerfield)

Klaus made a proposal to add support for multi master in the I2C core
and the Aspeed I2C model. The last patches add the required bits to
let this happen.  

Thanks,

C.

Changes in v2:

 - reworked I2C avocado tests
 - dropped ctrl_global_rsvd property
 - removed support for multiple masters from Klaus. this change should
   come in its own series.
  

Cédric Le Goater (8):
  aspeed: Remove fake RTC device on ast2500-evb
  test/avocado/machine_aspeed.py: Move OpenBMC tests
  test/avocado/machine_aspeed.py: Add tests using buildroot images
  test/avocado/machine_aspeed.py: Add I2C tests to ast2500-evb
  test/avocado/machine_aspeed.py: Add I2C tests to ast2600-evb
  test/avocado/machine_aspeed.py: Add an I2C RTC test
  aspeed/i2c: Add ast1030 controller models
  aspeed/i2c: Enable SLAVE_ADDR_RX_MATCH always

Joe Komlodi (6):
  hw/registerfields: Add shared fields macros
  aspeed: i2c: Migrate to registerfields API
  aspeed: i2c: Use reg array instead of individual vars
  aspeed: i2c: Add new mode support
  aspeed: i2c: Add PKT_DONE IRQ to trace
  aspeed: i2c: Move regs and helpers to header file

Klaus Jensen (2):
  hw/i2c/aspeed: rework raise interrupt trace event
  hw/i2c/aspeed: add DEV_ADDR in old register mode

Troy Lee (1):
  aspeed: Add I2C buses to AST1030 model

 include/hw/i2c/aspeed_i2c.h | 289 +-
 include/hw/registerfields.h |  70 +++
 hw/arm/aspeed.c |  17 +-
 hw/arm/aspeed_ast10x0.c |  18 +
 hw/i2c/aspeed_i2c.c | 820 +---
 hw/i2c/trace-events |   2 +-
 tests/avocado/boot_linux_console.py |  43 --
 tests/avocado/machine_aspeed.py | 136 +
 8 files changed, 1030 insertions(+), 365 deletions(-)

-- 
2.35.3




[PATCH v2 01/17] aspeed: Remove fake RTC device on ast2500-evb

2022-06-13 Thread Cédric Le Goater
The board has no such device. It might have been useful for some tests
in the past, it's not anymore and the same can be achieved on the
command line.

Signed-off-by: Cédric Le Goater 
---
 hw/arm/aspeed.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 98dc185acd9a..c49772e2eb59 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -519,10 +519,6 @@ static void ast2500_evb_i2c_init(AspeedMachineState *bmc)
 /* The AST2500 EVB expects a LM75 but a TMP105 is compatible */
 i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7),
  TYPE_TMP105, 0x4d);
-
-/* The AST2500 EVB does not have an RTC. Let's pretend that one is
- * plugged on the I2C bus header */
-i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), "ds1338", 0x32);
 }
 
 static void ast2600_evb_i2c_init(AspeedMachineState *bmc)
-- 
2.35.3




[PATCH v2 06/17] test/avocado/machine_aspeed.py: Add an I2C RTC test

2022-06-13 Thread Cédric Le Goater
Add an RTC device and check that the output of the hwclock command
matches the current year.

Reviewed-by: Joel Stanley 
Signed-off-by: Cédric Le Goater 
---
 tests/avocado/machine_aspeed.py | 8 
 1 file changed, 8 insertions(+)

diff --git a/tests/avocado/machine_aspeed.py b/tests/avocado/machine_aspeed.py
index 0a1ceec13eb1..3b8f784a57b6 100644
--- a/tests/avocado/machine_aspeed.py
+++ b/tests/avocado/machine_aspeed.py
@@ -149,6 +149,8 @@ def test_arm_ast2600_evb_builroot(self):
 
 self.vm.add_args('-device',
  
'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test');
+self.vm.add_args('-device',
+ 'ds1338,bus=aspeed.i2c.bus.3,address=0x32');
 self.do_test_arm_aspeed_buidroot_start(image_path, '0xf00')
 
 exec_command_and_wait_for_pattern(self,
@@ -161,4 +163,10 @@ def test_arm_ast2600_evb_builroot(self):
 exec_command_and_wait_for_pattern(self,
  'cat /sys/class/hwmon/hwmon0/temp1_input', 
'18000')
 
+exec_command_and_wait_for_pattern(self,
+ 'echo ds1307 0x32 > /sys/class/i2c-dev/i2c-3/device/new_device',
+ 'i2c i2c-3: new_device: Instantiated device ds1307 at 0x32');
+year = time.strftime("%Y")
+exec_command_and_wait_for_pattern(self, 'hwclock -f /dev/rtc1', year);
+
 self.do_test_arm_aspeed_buidroot_poweroff()
-- 
2.35.3




[PATCH v2 04/17] test/avocado/machine_aspeed.py: Add I2C tests to ast2500-evb

2022-06-13 Thread Cédric Le Goater
Create a named I2C temperature sensor device on the command line,
instantiate device from Linux since it is not part of the device tree,
and check the temperature is correctly reported under sysfs.

Signed-off-by: Cédric Le Goater 
---
 tests/avocado/machine_aspeed.py | 13 +
 1 file changed, 13 insertions(+)

diff --git a/tests/avocado/machine_aspeed.py b/tests/avocado/machine_aspeed.py
index 31a0fb6cd865..4d2766e1d44d 100644
--- a/tests/avocado/machine_aspeed.py
+++ b/tests/avocado/machine_aspeed.py
@@ -119,7 +119,20 @@ def test_arm_ast2500_evb_builroot(self):
 image_path = self.fetch_asset(image_url, asset_hash=image_hash,
   algorithm='sha256')
 
+self.vm.add_args('-device',
+ 
'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test');
 self.do_test_arm_aspeed_buidroot_start(image_path, '0x0')
+
+exec_command_and_wait_for_pattern(self,
+ 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-3/device/new_device',
+ 'i2c i2c-3: new_device: Instantiated device lm75 at 0x4d');
+exec_command_and_wait_for_pattern(self,
+ 'cat /sys/class/hwmon/hwmon1/temp1_input', '0')
+self.vm.command('qom-set', path='/machine/peripheral/tmp-test',
+property='temperature', value=18000);
+exec_command_and_wait_for_pattern(self,
+ 'cat /sys/class/hwmon/hwmon1/temp1_input', 
'18000')
+
 self.do_test_arm_aspeed_buidroot_poweroff()
 
 def test_arm_ast2600_evb_builroot(self):
-- 
2.35.3




[PATCH v2 03/17] test/avocado/machine_aspeed.py: Add tests using buildroot images

2022-06-13 Thread Cédric Le Goater
Buildroot images are smaller than the OpenBMC images and faster to
run. Built from source using :

  http://patchwork.ozlabs.org/project/buildroot/list/?series=303465

Signed-off-by: Cédric Le Goater 
---
 tests/avocado/machine_aspeed.py | 52 +
 1 file changed, 52 insertions(+)

diff --git a/tests/avocado/machine_aspeed.py b/tests/avocado/machine_aspeed.py
index 89bfad307661..31a0fb6cd865 100644
--- a/tests/avocado/machine_aspeed.py
+++ b/tests/avocado/machine_aspeed.py
@@ -5,8 +5,11 @@
 # This work is licensed under the terms of the GNU GPL, version 2 or
 # later.  See the COPYING file in the top-level directory.
 
+import time
+
 from avocado_qemu import QemuSystemTest
 from avocado_qemu import wait_for_console_pattern
+from avocado_qemu import exec_command
 from avocado_qemu import exec_command_and_wait_for_pattern
 from avocado.utils import archive
 
@@ -84,3 +87,52 @@ def test_arm_ast2500_romulus_openbmc_v2_9_0(self):
   algorithm='sha256')
 
 self.do_test_arm_aspeed(image_path)
+
+def do_test_arm_aspeed_buidroot_start(self, image, cpu_id):
+self.vm.set_console()
+self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw',
+ '-net', 'nic', '-net', 'user')
+self.vm.launch()
+
+self.wait_for_console_pattern('U-Boot 2019.04')
+self.wait_for_console_pattern('## Loading kernel from FIT Image')
+self.wait_for_console_pattern('Starting kernel ...')
+self.wait_for_console_pattern('Booting Linux on physical CPU ' + 
cpu_id)
+self.wait_for_console_pattern('lease of 10.0.2.15')
+self.wait_for_console_pattern('Aspeed EVB')
+exec_command(self, 'root')
+time.sleep(0.1)
+
+def do_test_arm_aspeed_buidroot_poweroff(self):
+exec_command_and_wait_for_pattern(self, 'poweroff',
+  'reboot: System halted');
+
+def test_arm_ast2500_evb_builroot(self):
+"""
+:avocado: tags=arch:arm
+:avocado: tags=machine:ast2500-evb
+"""
+
+image_url = ('https://github.com/legoater/qemu-aspeed-boot/raw/master/'
+ 'images/ast2500-evb/buildroot-2022.05/flash.img')
+image_hash = 
('549db6e9d8cdaf4367af21c36385a68bb465779c18b5e37094fc7343decccd3f')
+image_path = self.fetch_asset(image_url, asset_hash=image_hash,
+  algorithm='sha256')
+
+self.do_test_arm_aspeed_buidroot_start(image_path, '0x0')
+self.do_test_arm_aspeed_buidroot_poweroff()
+
+def test_arm_ast2600_evb_builroot(self):
+"""
+:avocado: tags=arch:arm
+:avocado: tags=machine:ast2600-evb
+"""
+
+image_url = ('https://github.com/legoater/qemu-aspeed-boot/raw/master/'
+ 'images/ast2600-evb/buildroot-2022.05/flash.img')
+image_hash = 
('6cc9e7d128fd4fa1fd01c883af67593cae8072c3239a0b8b6ace857f3538a92d')
+image_path = self.fetch_asset(image_url, asset_hash=image_hash,
+  algorithm='sha256')
+
+self.do_test_arm_aspeed_buidroot_start(image_path, '0xf00')
+self.do_test_arm_aspeed_buidroot_poweroff()
-- 
2.35.3




[PATCH v2 07/17] hw/registerfields: Add shared fields macros

2022-06-13 Thread Cédric Le Goater
From: Joe Komlodi 

Occasionally a peripheral will have different operating modes, where the
MMIO layout changes, but some of the register fields have the same offsets
and behaviors.

To help support this, we add SHARED_FIELD_XX macros that create SHIFT,
LENGTH, and MASK macros for the fields that are shared across registers,
and accessors for these fields.

An example use may look as follows:
There is a peripheral with registers REG_MODE1 and REG_MODE2 at
different addreses, and both have a field FIELD1 initialized by
SHARED_FIELD().

Depending on what mode the peripheral is operating in, the user could
extract FIELD1 via
SHARED_ARRAY_FIELD_EX32(s->regs, R_REG_MODE1, FIELD1)
or
SHARED_ARRAY_FIELD_EX32(s->regs, R_REG_MODE2, FIELD1)

Signed-off-by: Joe Komlodi 
Change-Id: Id3dc53e7d2f8741c95697cbae69a81bb699fa3cb
Message-Id: <20220331043248.2237838-2-koml...@google.com>
Signed-off-by: Cédric Le Goater 
---
 include/hw/registerfields.h | 70 +
 1 file changed, 70 insertions(+)

diff --git a/include/hw/registerfields.h b/include/hw/registerfields.h
index 3a88e135d025..1330ca77de61 100644
--- a/include/hw/registerfields.h
+++ b/include/hw/registerfields.h
@@ -154,4 +154,74 @@
 #define ARRAY_FIELD_DP64(regs, reg, field, val)   \
 (regs)[R_ ## reg] = FIELD_DP64((regs)[R_ ## reg], reg, field, val);
 
+
+/*
+ * These macros can be used for defining and extracting fields that have the
+ * same bit position across multiple registers.
+ */
+
+/* Define shared SHIFT, LENGTH, and MASK constants */
+#define SHARED_FIELD(name, shift, length)   \
+enum { name ## _ ## SHIFT = (shift)};   \
+enum { name ## _ ## LENGTH = (length)}; \
+enum { name ## _ ## MASK = MAKE_64BIT_MASK(shift, length)};
+
+/* Extract a shared field */
+#define SHARED_FIELD_EX8(storage, field) \
+extract8((storage), field ## _SHIFT, field ## _LENGTH)
+
+#define SHARED_FIELD_EX16(storage, field) \
+extract16((storage), field ## _SHIFT, field ## _LENGTH)
+
+#define SHARED_FIELD_EX32(storage, field) \
+extract32((storage), field ## _SHIFT, field ## _LENGTH)
+
+#define SHARED_FIELD_EX64(storage, field) \
+extract64((storage), field ## _SHIFT, field ## _LENGTH)
+
+/* Extract a shared field from a register array */
+#define SHARED_ARRAY_FIELD_EX32(regs, offset, field) \
+SHARED_FIELD_EX32((regs)[(offset)], field)
+#define SHARED_ARRAY_FIELD_EX64(regs, offset, field) \
+SHARED_FIELD_EX64((regs)[(offset)], field)
+
+/* Deposit a shared field */
+#define SHARED_FIELD_DP8(storage, field, val) ({\
+struct {\
+unsigned int v:field ## _LENGTH;\
+} _v = { .v = val };\
+uint8_t _d; \
+_d = deposit32((storage), field ## _SHIFT, field ## _LENGTH, _v.v); \
+_d; })
+
+#define SHARED_FIELD_DP16(storage, field, val) ({   \
+struct {\
+unsigned int v:field ## _LENGTH;\
+} _v = { .v = val };\
+uint16_t _d;\
+_d = deposit32((storage), field ## _SHIFT, field ## _LENGTH, _v.v); \
+_d; })
+
+#define SHARED_FIELD_DP32(storage, field, val) ({   \
+struct {\
+unsigned int v:field ## _LENGTH;\
+} _v = { .v = val };\
+uint32_t _d;\
+_d = deposit32((storage), field ## _SHIFT, field ## _LENGTH, _v.v); \
+_d; })
+
+#define SHARED_FIELD_DP64(storage, field, val) ({   \
+struct {\
+uint64_t v:field ## _LENGTH;\
+} _v = { .v = val };\
+uint64_t _d;\
+_d = deposit64((storage), field ## _SHIFT, field ## _LENGTH, _v.v); \
+_d; })
+
+/* Deposit a shared field to a register array */
+#define SHARED_ARRAY_FIELD_DP32(regs, offset, field, val) \
+(regs)[(offset)] = SHARED_FIELD_DP32((regs)[(offset)], field, val);
+#define SHARED_ARRAY_FIELD_DP64(regs, offset, field, val) \
+(regs)[(offset)] = SHARED_FIELD_DP64((regs)[(offset)], field, val);
+
 #endif
-- 
2.35.3




[PATCH v2 05/17] test/avocado/machine_aspeed.py: Add I2C tests to ast2600-evb

2022-06-13 Thread Cédric Le Goater
Create a named I2C temperature sensor device on the command line,
instantiate device from Linux since it is not part of the device tree,
and check the temperature is correctly reported under sysfs.

Signed-off-by: Cédric Le Goater 
---
 tests/avocado/machine_aspeed.py | 13 +
 1 file changed, 13 insertions(+)

diff --git a/tests/avocado/machine_aspeed.py b/tests/avocado/machine_aspeed.py
index 4d2766e1d44d..0a1ceec13eb1 100644
--- a/tests/avocado/machine_aspeed.py
+++ b/tests/avocado/machine_aspeed.py
@@ -147,5 +147,18 @@ def test_arm_ast2600_evb_builroot(self):
 image_path = self.fetch_asset(image_url, asset_hash=image_hash,
   algorithm='sha256')
 
+self.vm.add_args('-device',
+ 
'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test');
 self.do_test_arm_aspeed_buidroot_start(image_path, '0xf00')
+
+exec_command_and_wait_for_pattern(self,
+ 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-3/device/new_device',
+ 'i2c i2c-3: new_device: Instantiated device lm75 at 0x4d');
+exec_command_and_wait_for_pattern(self,
+ 'cat /sys/class/hwmon/hwmon0/temp1_input', '0')
+self.vm.command('qom-set', path='/machine/peripheral/tmp-test',
+property='temperature', value=18000);
+exec_command_and_wait_for_pattern(self,
+ 'cat /sys/class/hwmon/hwmon0/temp1_input', 
'18000')
+
 self.do_test_arm_aspeed_buidroot_poweroff()
-- 
2.35.3




[PATCH v2 11/17] aspeed: i2c: Add PKT_DONE IRQ to trace

2022-06-13 Thread Cédric Le Goater
From: Joe Komlodi 

Signed-off-by: Joe Komlodi 
Change-Id: I566eb09f4b9016e24570572f367627f6594039f5
Message-Id: <20220331043248.2237838-7-koml...@google.com>
Signed-off-by: Cédric Le Goater 
---
 hw/i2c/aspeed_i2c.c | 3 +++
 hw/i2c/trace-events | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
index 8b6a88315a5b..0e0cd5bec8d8 100644
--- a/hw/i2c/aspeed_i2c.c
+++ b/hw/i2c/aspeed_i2c.c
@@ -305,6 +305,9 @@ static inline void 
aspeed_i2c_bus_raise_interrupt(AspeedI2CBus *bus)
 bool raise_irq;
 
 trace_aspeed_i2c_bus_raise_interrupt(bus->regs[reg_intr_sts],
+aspeed_i2c_bus_pkt_mode_en(bus) &&
+ARRAY_FIELD_EX32(bus->regs, I2CM_INTR_STS, PKT_CMD_DONE) ?
+   "pktdone|" : "",
 SHARED_ARRAY_FIELD_EX32(bus->regs, reg_intr_sts, TX_NAK) ? "nak|" : "",
 SHARED_ARRAY_FIELD_EX32(bus->regs, reg_intr_sts, TX_ACK) ? "ack|" : "",
 SHARED_ARRAY_FIELD_EX32(bus->regs, reg_intr_sts, RX_DONE) ? "done|"
diff --git a/hw/i2c/trace-events b/hw/i2c/trace-events
index 7d8907c1eede..85e4bddff936 100644
--- a/hw/i2c/trace-events
+++ b/hw/i2c/trace-events
@@ -9,7 +9,7 @@ i2c_recv(uint8_t address, uint8_t data) "recv(addr:0x%02x) 
data:0x%02x"
 # aspeed_i2c.c
 
 aspeed_i2c_bus_cmd(uint32_t cmd, const char *cmd_flags, uint32_t count, 
uint32_t intr_status) "handling cmd=0x%x %s count=%d intr=0x%x"
-aspeed_i2c_bus_raise_interrupt(uint32_t intr_status, const char *str1, const 
char *str2, const char *str3, const char *str4, const char *str5) "handled 
intr=0x%x %s%s%s%s%s"
+aspeed_i2c_bus_raise_interrupt(uint32_t intr_status, const char *str1, const 
char *str2, const char *str3, const char *str4, const char *str5, const char 
*str6) "handled intr=0x%x %s%s%s%s%s%s"
 aspeed_i2c_bus_read(uint32_t busid, uint64_t offset, unsigned size, uint64_t 
value) "bus[%d]: To 0x%" PRIx64 " of size %u: 0x%" PRIx64
 aspeed_i2c_bus_write(uint32_t busid, uint64_t offset, unsigned size, uint64_t 
value) "bus[%d]: To 0x%" PRIx64 " of size %u: 0x%" PRIx64
 aspeed_i2c_bus_send(const char *mode, int i, int count, uint8_t byte) "%s send 
%d/%d 0x%02x"
-- 
2.35.3




[PATCH v2 09/17] aspeed: i2c: Use reg array instead of individual vars

2022-06-13 Thread Cédric Le Goater
From: Joe Komlodi 

Using a register array will allow us to represent old-mode and new-mode
I2C registers by using the same underlying register array, instead of
adding an entire new set of variables to represent new mode.

As part of this, we also do additional cleanup to use ARRAY_FIELD_
macros instead of FIELD_ macros on registers.

Signed-off-by: Joe Komlodi 
Change-Id: Ib94996b17c361b8490c042b43c99d8abc69332e3
[ clg: use of memset in aspeed_i2c_bus_reset() ]
Message-Id: <20220331043248.2237838-5-koml...@google.com>
Signed-off-by: Cédric Le Goater 
---
 include/hw/i2c/aspeed_i2c.h |  11 +-
 hw/i2c/aspeed_i2c.c | 281 
 2 files changed, 128 insertions(+), 164 deletions(-)

diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h
index 4b9be09274c7..8abb013d219c 100644
--- a/include/hw/i2c/aspeed_i2c.h
+++ b/include/hw/i2c/aspeed_i2c.h
@@ -33,6 +33,7 @@ OBJECT_DECLARE_TYPE(AspeedI2CState, AspeedI2CClass, 
ASPEED_I2C)
 
 #define ASPEED_I2C_NR_BUSSES 16
 #define ASPEED_I2C_MAX_POOL_SIZE 0x800
+#define ASPEED_I2C_OLD_NUM_REG 11
 
 struct AspeedI2CState;
 
@@ -49,15 +50,7 @@ struct AspeedI2CBus {
 uint8_t id;
 qemu_irq irq;
 
-uint32_t ctrl;
-uint32_t timing[2];
-uint32_t intr_ctrl;
-uint32_t intr_status;
-uint32_t cmd;
-uint32_t buf;
-uint32_t pool_ctrl;
-uint32_t dma_addr;
-uint32_t dma_len;
+uint32_t regs[ASPEED_I2C_OLD_NUM_REG];
 };
 
 struct AspeedI2CState {
diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
index 63d35f874c99..d13866908451 100644
--- a/hw/i2c/aspeed_i2c.c
+++ b/hw/i2c/aspeed_i2c.c
@@ -133,30 +133,30 @@ REG32(I2CD_DMA_LEN, 0x28) /* DMA Transfer Length < 4KB */
 
 static inline bool aspeed_i2c_bus_is_master(AspeedI2CBus *bus)
 {
-return FIELD_EX32(bus->ctrl, I2CD_FUN_CTRL, MASTER_EN);
+return ARRAY_FIELD_EX32(bus->regs, I2CD_FUN_CTRL, MASTER_EN);
 }
 
 static inline bool aspeed_i2c_bus_is_enabled(AspeedI2CBus *bus)
 {
-return FIELD_EX32(bus->ctrl, I2CD_FUN_CTRL, MASTER_EN) ||
-   FIELD_EX32(bus->ctrl, I2CD_FUN_CTRL, SLAVE_EN);
+return ARRAY_FIELD_EX32(bus->regs, I2CD_FUN_CTRL, MASTER_EN) ||
+   ARRAY_FIELD_EX32(bus->regs, I2CD_FUN_CTRL, SLAVE_EN);
 }
 
 static inline void aspeed_i2c_bus_raise_interrupt(AspeedI2CBus *bus)
 {
 AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller);
 
-trace_aspeed_i2c_bus_raise_interrupt(bus->intr_status,
-FIELD_EX32(bus->intr_status, I2CD_INTR_STS, TX_NAK) ? "nak|" : "",
-FIELD_EX32(bus->intr_status, I2CD_INTR_STS, TX_ACK) ? "ack|" : "",
-FIELD_EX32(bus->intr_status, I2CD_INTR_STS, RX_DONE) ? "done|" : "",
-FIELD_EX32(bus->intr_status, I2CD_INTR_STS, NORMAL_STOP) ? "normal|"
- : "",
-FIELD_EX32(bus->intr_status, I2CD_INTR_STS, ABNORMAL) ? "abnormal"
-  : "");
-
-bus->intr_status &= bus->intr_ctrl;
-if (bus->intr_status) {
+trace_aspeed_i2c_bus_raise_interrupt(bus->regs[R_I2CD_INTR_STS],
+  ARRAY_FIELD_EX32(bus->regs, I2CD_INTR_STS, TX_NAK) ? "nak|" : "",
+  ARRAY_FIELD_EX32(bus->regs, I2CD_INTR_STS, TX_ACK) ? "ack|" : "",
+  ARRAY_FIELD_EX32(bus->regs, I2CD_INTR_STS, RX_DONE) ? "done|" : "",
+  ARRAY_FIELD_EX32(bus->regs, I2CD_INTR_STS, NORMAL_STOP) ? "normal|"
+  : "",
+  ARRAY_FIELD_EX32(bus->regs, I2CD_INTR_STS, ABNORMAL) ? "abnormal"
+   : "");
+
+bus->regs[R_I2CD_INTR_STS] &= bus->regs[R_I2CD_INTR_CTRL];
+if (bus->regs[R_I2CD_INTR_STS]) {
 bus->controller->intr_status |= 1 << bus->id;
 qemu_irq_raise(aic->bus_get_irq(bus));
 }
@@ -167,46 +167,33 @@ static uint64_t aspeed_i2c_bus_read(void *opaque, hwaddr 
offset,
 {
 AspeedI2CBus *bus = opaque;
 AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller);
-uint64_t value = -1;
+uint64_t value = bus->regs[offset / sizeof(*bus->regs)];
 
 switch (offset) {
 case A_I2CD_FUN_CTRL:
-value = bus->ctrl;
-break;
 case A_I2CD_AC_TIMING1:
-value = bus->timing[0];
-break;
 case A_I2CD_AC_TIMING2:
-value = bus->timing[1];
-break;
 case A_I2CD_INTR_CTRL:
-value = bus->intr_ctrl;
-break;
 case A_I2CD_INTR_STS:
-value = bus->intr_status;
-break;
 case A_I2CD_POOL_CTRL:
-value = bus->pool_ctrl;
-break;
 case A_I2CD_BYTE_BUF:
-value = bus->buf;
+/* Value is already set, don't do anything. */
 break;
 case A_I2CD_CMD:
-value = bus->cmd | (i2c_bus_busy(bus->bus) << 16);
+value = FIELD_DP32(value, I2CD_CMD, BUS_BUSY_STS,
+   i2c_bus_busy(bus->bus));
 break;
 case A_I2CD_DMA_ADDR:

[PATCH v2 13/17] aspeed/i2c: Add ast1030 controller models

2022-06-13 Thread Cédric Le Goater
Based on :

  
https://lore.kernel.org/qemu-devel/20220324100439.478317-2-troy_...@aspeedtech.com/

Cc: Troy Lee 
Cc: Jamin Lin 
Cc: Steven Lee 
Reviewed-by: Joel Stanley 
Signed-off-by: Cédric Le Goater 
---
 include/hw/i2c/aspeed_i2c.h |  1 +
 hw/i2c/aspeed_i2c.c | 24 
 2 files changed, 25 insertions(+)

diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h
index 8ea9f6671ec8..0cd245a00963 100644
--- a/include/hw/i2c/aspeed_i2c.h
+++ b/include/hw/i2c/aspeed_i2c.h
@@ -30,6 +30,7 @@
 #define TYPE_ASPEED_2400_I2C TYPE_ASPEED_I2C "-ast2400"
 #define TYPE_ASPEED_2500_I2C TYPE_ASPEED_I2C "-ast2500"
 #define TYPE_ASPEED_2600_I2C TYPE_ASPEED_I2C "-ast2600"
+#define TYPE_ASPEED_1030_I2C TYPE_ASPEED_I2C "-ast1030"
 OBJECT_DECLARE_TYPE(AspeedI2CState, AspeedI2CClass, ASPEED_I2C)
 
 #define ASPEED_I2C_NR_BUSSES 16
diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
index 1556b2da995b..4c798b70e4c3 100644
--- a/hw/i2c/aspeed_i2c.c
+++ b/hw/i2c/aspeed_i2c.c
@@ -1176,6 +1176,29 @@ static const TypeInfo aspeed_2600_i2c_info = {
 .class_init = aspeed_2600_i2c_class_init,
 };
 
+static void aspeed_1030_i2c_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+AspeedI2CClass *aic = ASPEED_I2C_CLASS(klass);
+
+dc->desc = "ASPEED 1030 I2C Controller";
+
+aic->num_busses = 14;
+aic->reg_size = 0x80;
+aic->gap = -1; /* no gap */
+aic->bus_get_irq = aspeed_2600_i2c_bus_get_irq;
+aic->pool_size = 0x200;
+aic->pool_base = 0xC00;
+aic->bus_pool_base = aspeed_2600_i2c_bus_pool_base;
+aic->has_dma = true;
+}
+
+static const TypeInfo aspeed_1030_i2c_info = {
+.name = TYPE_ASPEED_1030_I2C,
+.parent = TYPE_ASPEED_I2C,
+.class_init = aspeed_1030_i2c_class_init,
+};
+
 static void aspeed_i2c_register_types(void)
 {
 type_register_static(&aspeed_i2c_bus_info);
@@ -1183,6 +1206,7 @@ static void aspeed_i2c_register_types(void)
 type_register_static(&aspeed_2400_i2c_info);
 type_register_static(&aspeed_2500_i2c_info);
 type_register_static(&aspeed_2600_i2c_info);
+type_register_static(&aspeed_1030_i2c_info);
 }
 
 type_init(aspeed_i2c_register_types)
-- 
2.35.3




[PATCH v2 08/17] aspeed: i2c: Migrate to registerfields API

2022-06-13 Thread Cédric Le Goater
From: Joe Komlodi 

This cleans up some of the field accessing, setting, and clearing
bitwise operations, and wraps them in macros instead.

Signed-off-by: Joe Komlodi 
Change-Id: I33018d6325fa04376e7c29dc4a49ab389a8e333a
Message-Id: <20220331043248.2237838-4-koml...@google.com>
Signed-off-by: Cédric Le Goater 
---
 hw/i2c/aspeed_i2c.c | 393 ++--
 1 file changed, 196 insertions(+), 197 deletions(-)

diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
index 03a4f5a91010..63d35f874c99 100644
--- a/hw/i2c/aspeed_i2c.c
+++ b/hw/i2c/aspeed_i2c.c
@@ -28,70 +28,61 @@
 #include "hw/i2c/aspeed_i2c.h"
 #include "hw/irq.h"
 #include "hw/qdev-properties.h"
+#include "hw/registerfields.h"
 #include "trace.h"
 
 /* I2C Global Register */
-
-#define I2C_CTRL_STATUS 0x00/* Device Interrupt Status */
-#define I2C_CTRL_ASSIGN 0x08/* Device Interrupt Target
-   Assignment */
-#define I2C_CTRL_GLOBAL 0x0C/* Global Control Register */
-#define   I2C_CTRL_SRAM_EN BIT(0)
+REG32(I2C_CTRL_STATUS, 0x0) /* Device Interrupt Status */
+REG32(I2C_CTRL_ASSIGN, 0x8) /* Device Interrupt Target Assignment */
+REG32(I2C_CTRL_GLOBAL, 0xC) /* Global Control Register */
+FIELD(I2C_CTRL_GLOBAL, SRAM_EN, 0, 1)
 
 /* I2C Device (Bus) Register */
-
-#define I2CD_FUN_CTRL_REG   0x00   /* I2CD Function Control  */
-#define   I2CD_POOL_PAGE_SEL(x)(((x) >> 20) & 0x7)  /* AST2400 */
-#define   I2CD_M_SDA_LOCK_EN   (0x1 << 16)
-#define   I2CD_MULTI_MASTER_DIS(0x1 << 15)
-#define   I2CD_M_SCL_DRIVE_EN  (0x1 << 14)
-#define   I2CD_MSB_STS (0x1 << 9)
-#define   I2CD_SDA_DRIVE_1T_EN (0x1 << 8)
-#define   I2CD_M_SDA_DRIVE_1T_EN   (0x1 << 7)
-#define   I2CD_M_HIGH_SPEED_EN (0x1 << 6)
-#define   I2CD_DEF_ADDR_EN (0x1 << 5)
-#define   I2CD_DEF_ALERT_EN(0x1 << 4)
-#define   I2CD_DEF_ARP_EN  (0x1 << 3)
-#define   I2CD_DEF_GCALL_EN(0x1 << 2)
-#define   I2CD_SLAVE_EN(0x1 << 1)
-#define   I2CD_MASTER_EN   (0x1)
-
-#define I2CD_AC_TIMING_REG1 0x04   /* Clock and AC Timing Control #1 */
-#define I2CD_AC_TIMING_REG2 0x08   /* Clock and AC Timing Control #1 */
-#define I2CD_INTR_CTRL_REG  0x0c   /* I2CD Interrupt Control */
-#define I2CD_INTR_STS_REG   0x10   /* I2CD Interrupt Status */
-
-#define   I2CD_INTR_SLAVE_ADDR_MATCH   (0x1 << 31) /* 0: addr1 1: addr2 */
-#define   I2CD_INTR_SLAVE_ADDR_RX_PENDING  (0x1 << 30)
-/* bits[19-16] Reserved */
-
-/* All bits below are cleared by writing 1 */
-#define   I2CD_INTR_SLAVE_INACTIVE_TIMEOUT (0x1 << 15)
-#define   I2CD_INTR_SDA_DL_TIMEOUT (0x1 << 14)
-#define   I2CD_INTR_BUS_RECOVER_DONE   (0x1 << 13)
-#define   I2CD_INTR_SMBUS_ALERT(0x1 << 12) /* Bus [0-3] only */
-#define   I2CD_INTR_SMBUS_ARP_ADDR (0x1 << 11) /* Removed */
-#define   I2CD_INTR_SMBUS_DEV_ALERT_ADDR   (0x1 << 10) /* Removed */
-#define   I2CD_INTR_SMBUS_DEF_ADDR (0x1 << 9)  /* Removed */
-#define   I2CD_INTR_GCALL_ADDR (0x1 << 8)  /* Removed */
-#define   I2CD_INTR_SLAVE_ADDR_RX_MATCH(0x1 << 7)  /* use RX_DONE */
-#define   I2CD_INTR_SCL_TIMEOUT(0x1 << 6)
-#define   I2CD_INTR_ABNORMAL   (0x1 << 5)
-#define   I2CD_INTR_NORMAL_STOP(0x1 << 4)
-#define   I2CD_INTR_ARBIT_LOSS (0x1 << 3)
-#define   I2CD_INTR_RX_DONE(0x1 << 2)
-#define   I2CD_INTR_TX_NAK (0x1 << 1)
-#define   I2CD_INTR_TX_ACK (0x1 << 0)
-
-#define I2CD_CMD_REG0x14   /* I2CD Command/Status */
-#define   I2CD_SDA_OE  (0x1 << 28)
-#define   I2CD_SDA_O   (0x1 << 27)
-#define   I2CD_SCL_OE  (0x1 << 26)
-#define   I2CD_SCL_O   (0x1 << 25)
-#define   I2CD_TX_TIMING   (0x1 << 24)
-#define   I2CD_TX_STATUS   (0x1 << 23)
-
-#define   I2CD_TX_STATE_SHIFT  19 /* Tx State Machine */
+REG32(I2CD_FUN_CTRL, 0x0) /* I2CD Function Control  */
+FIELD(I2CD_FUN_CTRL, POOL_PAGE_SEL, 20, 3) /* AST2400 */
+FIELD(I2CD_FUN_CTRL, M_SDA_LOCK_EN, 16, 1)
+FIELD(I2CD_FUN_CTRL, MULTI_MASTER_DIS, 15, 1)
+FIELD(I2CD_FUN_CTRL, M_SCL_DRIVE_EN, 14, 1)
+FIELD(I2CD_FUN_CTRL, MSB_STS, 9, 1)
+FIELD(I2CD_FUN_CTRL, SDA_DRIVE_IT_EN, 8, 1)
+FIELD(I2CD_FUN_CTRL, M_SDA_DRIVE_IT_EN, 7, 1)
+FIELD(I2CD_FUN_CTRL, M_HIGH_SPEED_EN, 6, 1)
+FIELD(I2CD_FUN_CTRL, DEF_ADDR_EN, 5, 1)
+FIELD(I2CD_FUN_CTRL, DEF_ALERT_EN, 4, 1)
+FIELD(I2CD_FUN_CTRL, DEF_ARP_EN, 3, 1)
+FIELD(I2CD_FUN_CTRL, DEF_GCALL_EN, 2, 1)
+FIELD(I2CD_FUN_CTRL, SLAVE_EN, 1, 1)
+FIELD(I2CD_FUN_CTRL, MASTER_EN, 0, 1)
+REG32(I2CD_AC_TIMING1, 0x04) /* Clock and

[PATCH v2 14/17] aspeed: Add I2C buses to AST1030 model

2022-06-13 Thread Cédric Le Goater
From: Troy Lee 

Instantiate the I2C buses in AST1030 model and create two slave device
for ast1030-evb.

Signed-off-by: Troy Lee 
Signed-off-by: Jamin Lin 
Signed-off-by: Steven Lee 
Reviewed-by: Joel Stanley 
[ clg : - adapted to current AST1030 upstream models
- changed AST2600 to AST1030 in comment
- fixed typo in commit log ]
Message-Id: <20220324100439.478317-3-troy_...@aspeedtech.com>
Signed-off-by: Cédric Le Goater 
---
 hw/arm/aspeed.c | 13 +
 hw/arm/aspeed_ast10x0.c | 18 ++
 2 files changed, 31 insertions(+)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index c49772e2eb59..a06f7c1b62a9 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -1397,6 +1397,18 @@ static void aspeed_minibmc_machine_init(MachineState 
*machine)
AST1030_INTERNAL_FLASH_SIZE);
 }
 
+static void ast1030_evb_i2c_init(AspeedMachineState *bmc)
+{
+AspeedSoCState *soc = &bmc->soc;
+
+/* U10 24C08 connects to SDA/SCL Groupt 1 by default */
+uint8_t *eeprom_buf = g_malloc0(32 * 1024);
+smbus_eeprom_init_one(aspeed_i2c_get_bus(&soc->i2c, 0), 0x50, eeprom_buf);
+
+/* U11 LM75 connects to SDA/SCL Group 2 by default */
+i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 1), "tmp105", 0x4d);
+}
+
 static void aspeed_minibmc_machine_ast1030_evb_class_init(ObjectClass *oc,
   void *data)
 {
@@ -1408,6 +1420,7 @@ static void 
aspeed_minibmc_machine_ast1030_evb_class_init(ObjectClass *oc,
 amc->hw_strap1 = 0;
 amc->hw_strap2 = 0;
 mc->init = aspeed_minibmc_machine_init;
+amc->i2c_init = ast1030_evb_i2c_init;
 mc->default_ram_size = 0;
 mc->default_cpus = mc->min_cpus = mc->max_cpus = 1;
 amc->fmc_model = "sst25vf032b";
diff --git a/hw/arm/aspeed_ast10x0.c b/hw/arm/aspeed_ast10x0.c
index d53454168403..5df480a21f39 100644
--- a/hw/arm/aspeed_ast10x0.c
+++ b/hw/arm/aspeed_ast10x0.c
@@ -114,6 +114,9 @@ static void aspeed_soc_ast1030_init(Object *obj)
 object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu), "hw-strap1");
 object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu), "hw-strap2");
 
+snprintf(typename, sizeof(typename), "aspeed.i2c-%s", socname);
+object_initialize_child(obj, "i2c", &s->i2c, typename);
+
 snprintf(typename, sizeof(typename), "aspeed.timer-%s", socname);
 object_initialize_child(obj, "timerctrl", &s->timerctrl, typename);
 
@@ -188,6 +191,21 @@ static void aspeed_soc_ast1030_realize(DeviceState 
*dev_soc, Error **errp)
 }
 sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, sc->memmap[ASPEED_DEV_SCU]);
 
+/* I2C */
+
+object_property_set_link(OBJECT(&s->i2c), "dram", OBJECT(&s->sram),
+ &error_abort);
+if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c), errp)) {
+return;
+}
+sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, sc->memmap[ASPEED_DEV_I2C]);
+for (i = 0; i < ASPEED_I2C_GET_CLASS(&s->i2c)->num_busses; i++) {
+qemu_irq irq = qdev_get_gpio_in(DEVICE(&s->armv7m),
+sc->irqmap[ASPEED_DEV_I2C] + i);
+/* The AST1030 I2C controller has one IRQ per bus. */
+sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c.busses[i]), 0, irq);
+}
+
 /* LPC */
 if (!sysbus_realize(SYS_BUS_DEVICE(&s->lpc), errp)) {
 return;
-- 
2.35.3




[PATCH v2 15/17] hw/i2c/aspeed: rework raise interrupt trace event

2022-06-13 Thread Cédric Le Goater
From: Klaus Jensen 

Build a single string instead of having several parameters on the trace
event.

Suggested-by: Cédric Le Goater 
Signed-off-by: Klaus Jensen 
[ clg: simplified trace buffer creation ]
Message-Id: <20220601210831.67259-2-...@irrelevant.dk>
Signed-off-by: Cédric Le Goater 
---
 hw/i2c/aspeed_i2c.c | 34 ++
 hw/i2c/trace-events |  2 +-
 2 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
index 4c798b70e4c3..43ac9491ec36 100644
--- a/hw/i2c/aspeed_i2c.c
+++ b/hw/i2c/aspeed_i2c.c
@@ -21,6 +21,7 @@
 #include "qemu/osdep.h"
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
+#include "qemu/cutils.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
 #include "qemu/error-report.h"
@@ -38,23 +39,32 @@ static inline void 
aspeed_i2c_bus_raise_interrupt(AspeedI2CBus *bus)
 uint32_t intr_ctrl_reg = aspeed_i2c_bus_intr_ctrl_offset(bus);
 bool raise_irq;
 
-trace_aspeed_i2c_bus_raise_interrupt(bus->regs[reg_intr_sts],
-aspeed_i2c_bus_pkt_mode_en(bus) &&
-ARRAY_FIELD_EX32(bus->regs, I2CM_INTR_STS, PKT_CMD_DONE) ?
-   "pktdone|" : "",
-SHARED_ARRAY_FIELD_EX32(bus->regs, reg_intr_sts, TX_NAK) ? "nak|" : "",
-SHARED_ARRAY_FIELD_EX32(bus->regs, reg_intr_sts, TX_ACK) ? "ack|" : "",
-SHARED_ARRAY_FIELD_EX32(bus->regs, reg_intr_sts, RX_DONE) ? "done|"
-  : "",
-SHARED_ARRAY_FIELD_EX32(bus->regs, reg_intr_sts, NORMAL_STOP) ?
-"normal|" : "",
-SHARED_ARRAY_FIELD_EX32(bus->regs, reg_intr_sts, ABNORMAL) ? "abnormal"
-   : "");
+if (trace_event_get_state_backends(TRACE_ASPEED_I2C_BUS_RAISE_INTERRUPT)) {
+g_autofree char *buf = g_strdup_printf("%s%s%s%s%s%s",
+   aspeed_i2c_bus_pkt_mode_en(bus) &&
+   ARRAY_FIELD_EX32(bus->regs, I2CM_INTR_STS, PKT_CMD_DONE) ?
+   "pktdone|" : "",
+   SHARED_ARRAY_FIELD_EX32(bus->regs, reg_intr_sts, TX_NAK) ?
+   "nak|" : "",
+   SHARED_ARRAY_FIELD_EX32(bus->regs, reg_intr_sts, TX_ACK) ?
+   "ack|" : "",
+   SHARED_ARRAY_FIELD_EX32(bus->regs, reg_intr_sts, RX_DONE) ?
+   "done|" : "",
+   SHARED_ARRAY_FIELD_EX32(bus->regs, reg_intr_sts, NORMAL_STOP) ?
+   "normal|" : "",
+   SHARED_ARRAY_FIELD_EX32(bus->regs, reg_intr_sts, ABNORMAL) ?
+   "abnormal"  : "");
+
+   trace_aspeed_i2c_bus_raise_interrupt(bus->regs[reg_intr_sts], buf);
+}
+
 raise_irq = bus->regs[reg_intr_sts] & bus->regs[intr_ctrl_reg];
+
 /* In packet mode we don't mask off INTR_STS */
 if (!aspeed_i2c_bus_pkt_mode_en(bus)) {
 bus->regs[reg_intr_sts] &= bus->regs[intr_ctrl_reg];
 }
+
 if (raise_irq) {
 bus->controller->intr_status |= 1 << bus->id;
 qemu_irq_raise(aic->bus_get_irq(bus));
diff --git a/hw/i2c/trace-events b/hw/i2c/trace-events
index 85e4bddff936..209275ed2dc8 100644
--- a/hw/i2c/trace-events
+++ b/hw/i2c/trace-events
@@ -9,7 +9,7 @@ i2c_recv(uint8_t address, uint8_t data) "recv(addr:0x%02x) 
data:0x%02x"
 # aspeed_i2c.c
 
 aspeed_i2c_bus_cmd(uint32_t cmd, const char *cmd_flags, uint32_t count, 
uint32_t intr_status) "handling cmd=0x%x %s count=%d intr=0x%x"
-aspeed_i2c_bus_raise_interrupt(uint32_t intr_status, const char *str1, const 
char *str2, const char *str3, const char *str4, const char *str5, const char 
*str6) "handled intr=0x%x %s%s%s%s%s%s"
+aspeed_i2c_bus_raise_interrupt(uint32_t intr_status, const char *s) "handled 
intr=0x%x %s"
 aspeed_i2c_bus_read(uint32_t busid, uint64_t offset, unsigned size, uint64_t 
value) "bus[%d]: To 0x%" PRIx64 " of size %u: 0x%" PRIx64
 aspeed_i2c_bus_write(uint32_t busid, uint64_t offset, unsigned size, uint64_t 
value) "bus[%d]: To 0x%" PRIx64 " of size %u: 0x%" PRIx64
 aspeed_i2c_bus_send(const char *mode, int i, int count, uint8_t byte) "%s send 
%d/%d 0x%02x"
-- 
2.35.3




Re: [PATCH 45/50] lasips2: use qdev gpio for output IRQ

2022-06-13 Thread Philippe Mathieu-Daudé via

On 22/5/22 20:18, Mark Cave-Ayland wrote:

This enables the IRQ to be wired up using qdev_connect_gpio_out() in
lasips2_initfn().

Signed-off-by: Mark Cave-Ayland 
---
  hw/input/lasips2.c | 8 
  include/hw/input/lasips2.h | 2 ++
  2 files changed, 6 insertions(+), 4 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 



[PATCH v2 10/17] aspeed: i2c: Add new mode support

2022-06-13 Thread Cédric Le Goater
From: Joe Komlodi 

On AST2600, I2C has a secondary mode, called "new mode", which changes
the layout of registers, adds some minor behavior changes, and
introduces a new way to transfer data called "packet mode".

Most of the bit positions of the fields are the same between old and new
mode, so we use SHARED_FIELD_XX macros to reuse most of the code between
the different modes.

For packet mode, most of the command behavior is the same compared to
other modes, but there are some minor changes to how interrupts are
handled compared to other modes.

Signed-off-by: Joe Komlodi 
Change-Id: I072f8301964f623afc74af1fe50c12e5caef199e
Message-Id: <20220331043248.2237838-6-koml...@google.com>
Signed-off-by: Cédric Le Goater 
---
 include/hw/i2c/aspeed_i2c.h |   4 +-
 hw/i2c/aspeed_i2c.c | 844 +++-
 2 files changed, 653 insertions(+), 195 deletions(-)

diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h
index 8abb013d219c..8297b190a9d2 100644
--- a/include/hw/i2c/aspeed_i2c.h
+++ b/include/hw/i2c/aspeed_i2c.h
@@ -34,6 +34,7 @@ OBJECT_DECLARE_TYPE(AspeedI2CState, AspeedI2CClass, 
ASPEED_I2C)
 #define ASPEED_I2C_NR_BUSSES 16
 #define ASPEED_I2C_MAX_POOL_SIZE 0x800
 #define ASPEED_I2C_OLD_NUM_REG 11
+#define ASPEED_I2C_NEW_NUM_REG 22
 
 struct AspeedI2CState;
 
@@ -50,7 +51,7 @@ struct AspeedI2CBus {
 uint8_t id;
 qemu_irq irq;
 
-uint32_t regs[ASPEED_I2C_OLD_NUM_REG];
+uint32_t regs[ASPEED_I2C_NEW_NUM_REG];
 };
 
 struct AspeedI2CState {
@@ -61,6 +62,7 @@ struct AspeedI2CState {
 
 uint32_t intr_status;
 uint32_t ctrl_global;
+uint32_t new_clk_divider;
 MemoryRegion pool_iomem;
 uint8_t pool[ASPEED_I2C_MAX_POOL_SIZE];
 
diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
index d13866908451..8b6a88315a5b 100644
--- a/hw/i2c/aspeed_i2c.c
+++ b/hw/i2c/aspeed_i2c.c
@@ -31,141 +31,302 @@
 #include "hw/registerfields.h"
 #include "trace.h"
 
+/* Tx State Machine */
+#define   I2CD_TX_STATE_MASK  0xf
+#define I2CD_IDLE 0x0
+#define I2CD_MACTIVE  0x8
+#define I2CD_MSTART   0x9
+#define I2CD_MSTARTR  0xa
+#define I2CD_MSTOP0xb
+#define I2CD_MTXD 0xc
+#define I2CD_MRXACK   0xd
+#define I2CD_MRXD 0xe
+#define I2CD_MTXACK   0xf
+#define I2CD_SWAIT0x1
+#define I2CD_SRXD 0x4
+#define I2CD_STXACK   0x5
+#define I2CD_STXD 0x6
+#define I2CD_SRXACK   0x7
+#define I2CD_RECOVER  0x3
+
 /* I2C Global Register */
 REG32(I2C_CTRL_STATUS, 0x0) /* Device Interrupt Status */
 REG32(I2C_CTRL_ASSIGN, 0x8) /* Device Interrupt Target Assignment */
 REG32(I2C_CTRL_GLOBAL, 0xC) /* Global Control Register */
+FIELD(I2C_CTRL_GLOBAL, REG_MODE, 2, 1)
 FIELD(I2C_CTRL_GLOBAL, SRAM_EN, 0, 1)
+REG32(I2C_CTRL_NEW_CLK_DIVIDER, 0x10) /* New mode clock divider */
 
-/* I2C Device (Bus) Register */
+/* I2C Old Mode Device (Bus) Register */
 REG32(I2CD_FUN_CTRL, 0x0) /* I2CD Function Control  */
 FIELD(I2CD_FUN_CTRL, POOL_PAGE_SEL, 20, 3) /* AST2400 */
-FIELD(I2CD_FUN_CTRL, M_SDA_LOCK_EN, 16, 1)
-FIELD(I2CD_FUN_CTRL, MULTI_MASTER_DIS, 15, 1)
-FIELD(I2CD_FUN_CTRL, M_SCL_DRIVE_EN, 14, 1)
-FIELD(I2CD_FUN_CTRL, MSB_STS, 9, 1)
-FIELD(I2CD_FUN_CTRL, SDA_DRIVE_IT_EN, 8, 1)
-FIELD(I2CD_FUN_CTRL, M_SDA_DRIVE_IT_EN, 7, 1)
-FIELD(I2CD_FUN_CTRL, M_HIGH_SPEED_EN, 6, 1)
-FIELD(I2CD_FUN_CTRL, DEF_ADDR_EN, 5, 1)
-FIELD(I2CD_FUN_CTRL, DEF_ALERT_EN, 4, 1)
-FIELD(I2CD_FUN_CTRL, DEF_ARP_EN, 3, 1)
-FIELD(I2CD_FUN_CTRL, DEF_GCALL_EN, 2, 1)
-FIELD(I2CD_FUN_CTRL, SLAVE_EN, 1, 1)
-FIELD(I2CD_FUN_CTRL, MASTER_EN, 0, 1)
+SHARED_FIELD(M_SDA_LOCK_EN, 16, 1)
+SHARED_FIELD(MULTI_MASTER_DIS, 15, 1)
+SHARED_FIELD(M_SCL_DRIVE_EN, 14, 1)
+SHARED_FIELD(MSB_STS, 9, 1)
+SHARED_FIELD(SDA_DRIVE_IT_EN, 8, 1)
+SHARED_FIELD(M_SDA_DRIVE_IT_EN, 7, 1)
+SHARED_FIELD(M_HIGH_SPEED_EN, 6, 1)
+SHARED_FIELD(DEF_ADDR_EN, 5, 1)
+SHARED_FIELD(DEF_ALERT_EN, 4, 1)
+SHARED_FIELD(DEF_ARP_EN, 3, 1)
+SHARED_FIELD(DEF_GCALL_EN, 2, 1)
+SHARED_FIELD(SLAVE_EN, 1, 1)
+SHARED_FIELD(MASTER_EN, 0, 1)
 REG32(I2CD_AC_TIMING1, 0x04) /* Clock and AC Timing Control #1 */
 REG32(I2CD_AC_TIMING2, 0x08) /* Clock and AC Timing Control #2 */
 REG32(I2CD_INTR_CTRL, 0x0C)  /* I2CD Interrupt Control */
 REG32(I2CD_INTR_STS, 0x10)   /* I2CD Interrupt Status */
-FIELD(I2CD_INTR_STS, SLAVE_ADDR_MATCH, 31, 1)/* 0: addr1 1: addr2 */
-FIELD(I2CD_INTR_STS, SLAVE_ADDR_RX_PENDING, 29, 1)
-FIELD(I2CD_INTR_STS, SLAVE_INACTIVE_TIMEOUT, 15, 1)
-FIELD(I2CD_INTR_STS, SDA_DL_TIMEOUT, 14, 1)
-FIELD(I2CD_INTR_STS, BUS_RECOVER_DONE

[PATCH v2 16/17] hw/i2c/aspeed: add DEV_ADDR in old register mode

2022-06-13 Thread Cédric Le Goater
From: Klaus Jensen 

Add support for writing and reading the device address register in old
register mode.

On the AST2400 (only 1 slave address)

  * no upper bits

On the AST2500 (2 possible slave addresses),

  * bit[31] : Slave Address match indicator
  * bit[30] : Slave Address Receiving pending

On the AST2600 (3 possible slave addresses),

  * bit[31-30] : Slave Address match indicator
  * bit[29] : Slave Address Receiving pending

The model could be more precise to take into account all fields but
since the Linux driver is masking the register value being set, it
should be fine. See commit 3fb2e2aeafb2 ("i2c: aspeed: disable
additional device addresses on ast2[56]xx") from Zeiv. This can be
addressed later.

Signed-off-by: Klaus Jensen 
[ clg: add details to commit log ]
Message-Id: <20220601210831.67259-3-...@irrelevant.dk>
Signed-off-by: Cédric Le Goater 
---
 include/hw/i2c/aspeed_i2c.h | 8 
 hw/i2c/aspeed_i2c.c | 4 ++--
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h
index 0cd245a00963..1398befc104d 100644
--- a/include/hw/i2c/aspeed_i2c.h
+++ b/include/hw/i2c/aspeed_i2c.h
@@ -295,6 +295,14 @@ static inline uint32_t 
aspeed_i2c_bus_cmd_offset(AspeedI2CBus *bus)
 return R_I2CD_CMD;
 }
 
+static inline uint32_t aspeed_i2c_bus_dev_addr_offset(AspeedI2CBus *bus)
+{
+if (aspeed_i2c_is_new_mode(bus->controller)) {
+return R_I2CS_DEV_ADDR;
+}
+return R_I2CD_DEV_ADDR;
+}
+
 static inline uint32_t aspeed_i2c_bus_intr_ctrl_offset(AspeedI2CBus *bus)
 {
 if (aspeed_i2c_is_new_mode(bus->controller)) {
diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
index 43ac9491ec36..f9fce0d84b89 100644
--- a/hw/i2c/aspeed_i2c.c
+++ b/hw/i2c/aspeed_i2c.c
@@ -83,6 +83,7 @@ static uint64_t aspeed_i2c_bus_old_read(AspeedI2CBus *bus, 
hwaddr offset,
 case A_I2CD_AC_TIMING2:
 case A_I2CD_INTR_CTRL:
 case A_I2CD_INTR_STS:
+case A_I2CD_DEV_ADDR:
 case A_I2CD_POOL_CTRL:
 case A_I2CD_BYTE_BUF:
 /* Value is already set, don't do anything. */
@@ -720,8 +721,7 @@ static void aspeed_i2c_bus_old_write(AspeedI2CBus *bus, 
hwaddr offset,
 }
 break;
 case A_I2CD_DEV_ADDR:
-qemu_log_mask(LOG_UNIMP, "%s: slave mode not implemented\n",
-  __func__);
+bus->regs[R_I2CD_DEV_ADDR] = value;
 break;
 case A_I2CD_POOL_CTRL:
 bus->regs[R_I2CD_POOL_CTRL] &= ~0xff;
-- 
2.35.3




Re: [PULL 13/27] machine: add mem compound property

2022-06-13 Thread Markus Armbruster
Paolo Bonzini  writes:

> Make -m syntactic sugar for a compound property "-machine
> mem.{size,max-size,slots}".  The new property does not have
> the magic conversion to megabytes of unsuffixed arguments,
> and also does not understand that "0" means the default size
> (you have to leave it out to get the default).  This means
> that we need to convert the QemuOpts by hand to a QDict.
>
> Signed-off-by: Paolo Bonzini 
> Message-Id: <20220414165300.555321-4-pbonz...@redhat.com>
> Signed-off-by: Paolo Bonzini 
> ---
>  hw/core/machine.c |  80 ++
>  qapi/machine.json |  18 +++
>  softmmu/vl.c  | 123 +++---
>  3 files changed, 138 insertions(+), 83 deletions(-)
>
> diff --git a/hw/core/machine.c b/hw/core/machine.c
> index 8cea94537d..46b8d0effa 100644
> --- a/hw/core/machine.c
> +++ b/hw/core/machine.c
> @@ -523,6 +523,78 @@ static void machine_set_hmat(Object *obj, bool value, 
> Error **errp)
>  ms->numa_state->hmat_enabled = value;
>  }
>  
> +static void machine_get_mem(Object *obj, Visitor *v, const char *name,
> +void *opaque, Error **errp)
> +{
> +MachineState *ms = MACHINE(obj);
> +MemorySizeConfiguration mem = {
> +.has_size = true,
> +.size = ms->ram_size,
> +.has_max_size = !!ms->ram_slots,
> +.max_size = ms->maxram_size,
> +.has_slots = !!ms->ram_slots,
> +.slots = ms->ram_slots,
> +};
> +MemorySizeConfiguration *p_mem = &mem;
> +
> +visit_type_MemorySizeConfiguration(v, name, &p_mem, &error_abort);
> +}
> +
> +static void machine_set_mem(Object *obj, Visitor *v, const char *name,
> +void *opaque, Error **errp)
> +{
> +MachineState *ms = MACHINE(obj);
> +MachineClass *mc = MACHINE_GET_CLASS(obj);
> +MemorySizeConfiguration *mem;
> +
> +ERRP_GUARD();
> +
> +if (!visit_type_MemorySizeConfiguration(v, name, &mem, errp)) {
> +return;
> +}
> +
> +if (!mem->has_size) {
> +mem->has_size = true;
> +mem->size = mc->default_ram_size;
> +}
> +mem->size = QEMU_ALIGN_UP(mem->size, 8192);
> +if (mc->fixup_ram_size) {
> +mem->size = mc->fixup_ram_size(mem->size);
> +}
> +if ((ram_addr_t)mem->size != mem->size) {
> +error_setg(errp, "ram size too large");
> +goto out_free;
> +}
> +
> +if (mem->has_max_size) {
> +if (mem->max_size < mem->size) {
> +error_setg(errp, "invalid value of maxmem: "
> +   "maximum memory size (0x%" PRIx64 ") must be at least 
> "
> +   "the initial memory size (0x%" PRIx64 ")",
> +   mem->max_size, mem->size);
> +goto out_free;
> +}
> +if (mem->has_slots && mem->slots && mem->max_size == mem->size) {
> +error_setg(errp, "invalid value of maxmem: "
> +   "memory slots were specified but maximum memory size "
> +   "(0x%" PRIx64 ") is equal to the initial memory size "
> +   "(0x%" PRIx64 ")", mem->max_size, mem->size);
> +goto out_free;
> +}
> +ms->maxram_size = mem->max_size;
> +} else {
> +if (mem->has_slots) {
> +error_setg(errp, "slots specified but no max-size");
> +goto out_free;
> +}
> +ms->maxram_size = mem->size;
> +}
> +ms->ram_size = mem->size;
> +ms->ram_slots = mem->has_slots ? mem->slots : 0;
> +out_free:
> +qapi_free_MemorySizeConfiguration(mem);
> +}
> +
>  static char *machine_get_nvdimm_persistence(Object *obj, Error **errp)
>  {
>  MachineState *ms = MACHINE(obj);
> @@ -953,6 +1025,12 @@ static void machine_class_init(ObjectClass *oc, void 
> *data)
>  object_class_property_set_description(oc, "memory-backend",
>"Set RAM backend"
>"Valid value is ID of hostmem 
> based backend");
> +
> +object_class_property_add(oc, "memory", "MemorySizeConfiguration",
> +machine_get_mem, machine_set_mem,
> +NULL, NULL);
> +object_class_property_set_description(oc, "memory",
> +"Memory size configuration");
>  }
>  
>  static void machine_class_base_init(ObjectClass *oc, void *data)
> @@ -983,6 +1061,8 @@ static void machine_initfn(Object *obj)
>  ms->mem_merge = true;
>  ms->enable_graphics = true;
>  ms->kernel_cmdline = g_strdup("");
> +ms->ram_size = mc->default_ram_size;
> +ms->maxram_size = mc->default_ram_size;
>  
>  if (mc->nvdimm_supported) {
>  Object *obj = OBJECT(ms);
> diff --git a/qapi/machine.json b/qapi/machine.json
> index e3dcf5a119..92480d4044 100644
> --- a/qapi/machine.json
> +++ b/qapi/machine.json
> @@ -1614,3 +1614,21 @@
>  ##
>  { 'enum': 'SmbiosEntryPointType',
>'data': [ '32', '64' ] }
> +
> +##
> +# @MemorySizeConfiguratio

Re: [PATCH v2] docs: add PCIe root bus for VGA compat guideline

2022-06-13 Thread Laszlo Ersek
On 06/12/22 19:32, Kevin Locke wrote:
> PCI Express devices which use legacy VGA compatibility should be placed
> on the Root Complex.  This simplifies ioport access to VGA registers,
> which requires use of a special exception bit to work across PCI(e)
> bridges.  It is also necessary for ioport access to VESA BIOS Extension
> (VBE) registers, which is not forwarded over PCI(e) bridges, even with
> the special exception bit for VGA register access.[1]
> 
> Update the PCI Express Guidelines to add these to the list of devices
> which can be placed directly on the Root Complex.
> 
> Note that the only PCI Express display devices currently supported
> (bochs-display and virtio-gpu-pci) do not offer VGA compatibility.
> Legacy PCI devices (e.g. vga, qxl-vga, virtio-vga) are already
> documented as allowed on the Root Complex by the first item in the list.
> However, this item documents an additional consideration for placing
> devices which was not previously mentioned, and may be relevant for PCIe
> devices offering VGA compatibility in the future.
> 
> [1]: 
> https://mail.coreboot.org/hyperkitty/list/seab...@seabios.org/thread/XG2RN3HKVRDEDTLA2PRELLIENIIH7II7/#XVP3I2KQVZHSTDA4SNVKOITWGRGSDU3F
> 
> Signed-off-by: Laszlo Ersek 

Please make this a "Suggested-by: Laszlo Ersek "
(concerning the text in the patch body).

The commit message looks OK to me, but I'd like Gerd and/or Alex to
approve it.

Thanks!
Laszlo

> Signed-off-by: Kevin Locke 
> ---
> Changes since v1:
>  * Replace my overly-broad exception for devices requiring ioport access
>with a list item specifically for PCI Express devices offering VGA
>Compatibility provided by Laszlo Ersek.
>  * Rewrite the commit message based on my improved understanding of the
>issue and the improved scope of the change.
> 
> P.S. Let me know if the Signed-off-by tag is not appropriate for either
> of us.  I'm not clear on the etiquette of including someone else's
> sign-off, but also don't want to misrepresent myself as the source of
> your work.
> 
>  docs/pcie.txt | 10 +++---
>  1 file changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/docs/pcie.txt b/docs/pcie.txt
> index 89e3502075..59b26817f9 100644
> --- a/docs/pcie.txt
> +++ b/docs/pcie.txt
> @@ -48,13 +48,17 @@ Place only the following kinds of devices directly on the 
> Root Complex:
>  strangely when PCI Express devices are integrated
>  with the Root Complex.
>  
> -(2) PCI Express Root Ports (ioh3420), for starting exclusively PCI 
> Express
> +(2) Assigned PCI Express GPUs that offer legacy VGA compatibility, and
> +that such compatibility is expected of (due to booting with SeaBIOS,
> +or due to UEFI driver bugs or native OS driver bugs).
> +
> +(3) PCI Express Root Ports (ioh3420), for starting exclusively PCI 
> Express
>  hierarchies.
>  
> -(3) PCI Express to PCI Bridge (pcie-pci-bridge), for starting legacy PCI
> +(4) PCI Express to PCI Bridge (pcie-pci-bridge), for starting legacy PCI
>  hierarchies.
>  
> -(4) Extra Root Complexes (pxb-pcie), if multiple PCI Express Root Buses
> +(5) Extra Root Complexes (pxb-pcie), if multiple PCI Express Root Buses
>  are needed.
>  
> pcie.0 bus
> 




[PATCH v2 12/17] aspeed: i2c: Move regs and helpers to header file

2022-06-13 Thread Cédric Le Goater
From: Joe Komlodi 

Moves register definitions and short commonly used inlined functiosn to
the header file to help tidy up the implementation file.

Signed-off-by: Joe Komlodi 
Change-Id: I34dff7485b6bbe3c9482715ccd94dbd65dc5f324
Message-Id: <20220331043248.2237838-8-koml...@google.com>
Signed-off-by: Cédric Le Goater 
---
 include/hw/i2c/aspeed_i2c.h | 267 
 hw/i2c/aspeed_i2c.c | 266 ---
 2 files changed, 267 insertions(+), 266 deletions(-)

diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h
index 8297b190a9d2..8ea9f6671ec8 100644
--- a/include/hw/i2c/aspeed_i2c.h
+++ b/include/hw/i2c/aspeed_i2c.h
@@ -23,6 +23,7 @@
 
 #include "hw/i2c/i2c.h"
 #include "hw/sysbus.h"
+#include "hw/registerfields.h"
 #include "qom/object.h"
 
 #define TYPE_ASPEED_I2C "aspeed.i2c"
@@ -36,6 +37,182 @@ OBJECT_DECLARE_TYPE(AspeedI2CState, AspeedI2CClass, 
ASPEED_I2C)
 #define ASPEED_I2C_OLD_NUM_REG 11
 #define ASPEED_I2C_NEW_NUM_REG 22
 
+/* Tx State Machine */
+#define   I2CD_TX_STATE_MASK  0xf
+#define I2CD_IDLE 0x0
+#define I2CD_MACTIVE  0x8
+#define I2CD_MSTART   0x9
+#define I2CD_MSTARTR  0xa
+#define I2CD_MSTOP0xb
+#define I2CD_MTXD 0xc
+#define I2CD_MRXACK   0xd
+#define I2CD_MRXD 0xe
+#define I2CD_MTXACK   0xf
+#define I2CD_SWAIT0x1
+#define I2CD_SRXD 0x4
+#define I2CD_STXACK   0x5
+#define I2CD_STXD 0x6
+#define I2CD_SRXACK   0x7
+#define I2CD_RECOVER  0x3
+
+/* I2C Global Register */
+REG32(I2C_CTRL_STATUS, 0x0) /* Device Interrupt Status */
+REG32(I2C_CTRL_ASSIGN, 0x8) /* Device Interrupt Target Assignment */
+REG32(I2C_CTRL_GLOBAL, 0xC) /* Global Control Register */
+FIELD(I2C_CTRL_GLOBAL, REG_MODE, 2, 1)
+FIELD(I2C_CTRL_GLOBAL, SRAM_EN, 0, 1)
+REG32(I2C_CTRL_NEW_CLK_DIVIDER, 0x10) /* New mode clock divider */
+
+/* I2C Old Mode Device (Bus) Register */
+REG32(I2CD_FUN_CTRL, 0x0) /* I2CD Function Control  */
+FIELD(I2CD_FUN_CTRL, POOL_PAGE_SEL, 20, 3) /* AST2400 */
+SHARED_FIELD(M_SDA_LOCK_EN, 16, 1)
+SHARED_FIELD(MULTI_MASTER_DIS, 15, 1)
+SHARED_FIELD(M_SCL_DRIVE_EN, 14, 1)
+SHARED_FIELD(MSB_STS, 9, 1)
+SHARED_FIELD(SDA_DRIVE_IT_EN, 8, 1)
+SHARED_FIELD(M_SDA_DRIVE_IT_EN, 7, 1)
+SHARED_FIELD(M_HIGH_SPEED_EN, 6, 1)
+SHARED_FIELD(DEF_ADDR_EN, 5, 1)
+SHARED_FIELD(DEF_ALERT_EN, 4, 1)
+SHARED_FIELD(DEF_ARP_EN, 3, 1)
+SHARED_FIELD(DEF_GCALL_EN, 2, 1)
+SHARED_FIELD(SLAVE_EN, 1, 1)
+SHARED_FIELD(MASTER_EN, 0, 1)
+REG32(I2CD_AC_TIMING1, 0x04) /* Clock and AC Timing Control #1 */
+REG32(I2CD_AC_TIMING2, 0x08) /* Clock and AC Timing Control #2 */
+REG32(I2CD_INTR_CTRL, 0x0C)  /* I2CD Interrupt Control */
+REG32(I2CD_INTR_STS, 0x10)   /* I2CD Interrupt Status */
+SHARED_FIELD(SLAVE_ADDR_MATCH, 31, 1)/* 0: addr1 1: addr2 */
+SHARED_FIELD(SLAVE_ADDR_RX_PENDING, 29, 1)
+SHARED_FIELD(SLAVE_INACTIVE_TIMEOUT, 15, 1)
+SHARED_FIELD(SDA_DL_TIMEOUT, 14, 1)
+SHARED_FIELD(BUS_RECOVER_DONE, 13, 1)
+SHARED_FIELD(SMBUS_ALERT, 12, 1)/* Bus [0-3] only */
+FIELD(I2CD_INTR_STS, SMBUS_ARP_ADDR, 11, 1) /* Removed */
+FIELD(I2CD_INTR_STS, SMBUS_DEV_ALERT_ADDR, 10, 1)   /* Removed */
+FIELD(I2CD_INTR_STS, SMBUS_DEF_ADDR, 9, 1)  /* Removed */
+FIELD(I2CD_INTR_STS, GCALL_ADDR, 8, 1)  /* Removed */
+FIELD(I2CD_INTR_STS, SLAVE_ADDR_RX_MATCH, 7, 1) /* use RX_DONE */
+SHARED_FIELD(SCL_TIMEOUT, 6, 1)
+SHARED_FIELD(ABNORMAL, 5, 1)
+SHARED_FIELD(NORMAL_STOP, 4, 1)
+SHARED_FIELD(ARBIT_LOSS, 3, 1)
+SHARED_FIELD(RX_DONE, 2, 1)
+SHARED_FIELD(TX_NAK, 1, 1)
+SHARED_FIELD(TX_ACK, 0, 1)
+REG32(I2CD_CMD, 0x14) /* I2CD Command/Status */
+SHARED_FIELD(SDA_OE, 28, 1)
+SHARED_FIELD(SDA_O, 27, 1)
+SHARED_FIELD(SCL_OE, 26, 1)
+SHARED_FIELD(SCL_O, 25, 1)
+SHARED_FIELD(TX_TIMING, 23, 2)
+SHARED_FIELD(TX_STATE, 19, 4)
+SHARED_FIELD(SCL_LINE_STS, 18, 1)
+SHARED_FIELD(SDA_LINE_STS, 17, 1)
+SHARED_FIELD(BUS_BUSY_STS, 16, 1)
+SHARED_FIELD(SDA_OE_OUT_DIR, 15, 1)
+SHARED_FIELD(SDA_O_OUT_DIR, 14, 1)
+SHARED_FIELD(SCL_OE_OUT_DIR, 13, 1)
+SHARED_FIELD(SCL_O_OUT_DIR, 12, 1)
+SHARED_FIELD(BUS_RECOVER_CMD_EN, 11, 1)
+SHARED_FIELD(S_ALT_EN, 10, 1)
+/* Command Bits */
+SHARED_FIELD(RX_DMA_EN, 9, 1)
+SHARED_FIELD(TX_DMA_EN, 8, 1)
+SHARED_FIELD(RX_BUFF_EN, 7, 1)
+SHARED_FIELD(TX_BUFF_EN, 6, 1)
+SHARED_FIELD(M_STOP_CMD, 5, 1)
+SHARED_FIELD(M_S_RX_CMD_LAST, 4, 1)
+SHARED_FIELD(M_RX_CMD, 3, 1)
+SHARED_FIELD(S_TX_CMD, 2, 1)

[PATCH v2 17/17] aspeed/i2c: Enable SLAVE_ADDR_RX_MATCH always

2022-06-13 Thread Cédric Le Goater
There is no 'slave match interrupt' enable bit in the Interrupt
Control Register. Consider it is always enabled and extend the mask
value 'bus->regs[intr_ctrl_reg]' with the SLAVE_ADDR_RX_MATCH bit when
the interrupt is raised.

Signed-off-by: Cédric Le Goater 
---
 hw/i2c/aspeed_i2c.c | 13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
index f9fce0d84b89..37ae1f2e04bd 100644
--- a/hw/i2c/aspeed_i2c.c
+++ b/hw/i2c/aspeed_i2c.c
@@ -32,15 +32,20 @@
 #include "hw/registerfields.h"
 #include "trace.h"
 
+/* Enable SLAVE_ADDR_RX_MATCH always */
+#define R_I2CD_INTR_STS_ALWAYS_ENABLE  R_I2CD_INTR_STS_SLAVE_ADDR_RX_MATCH_MASK
+
 static inline void aspeed_i2c_bus_raise_interrupt(AspeedI2CBus *bus)
 {
 AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller);
 uint32_t reg_intr_sts = aspeed_i2c_bus_intr_sts_offset(bus);
 uint32_t intr_ctrl_reg = aspeed_i2c_bus_intr_ctrl_offset(bus);
+uint32_t intr_ctrl_mask = bus->regs[intr_ctrl_reg] |
+R_I2CD_INTR_STS_ALWAYS_ENABLE;
 bool raise_irq;
 
 if (trace_event_get_state_backends(TRACE_ASPEED_I2C_BUS_RAISE_INTERRUPT)) {
-g_autofree char *buf = g_strdup_printf("%s%s%s%s%s%s",
+g_autofree char *buf = g_strdup_printf("%s%s%s%s%s%s%s",
aspeed_i2c_bus_pkt_mode_en(bus) &&
ARRAY_FIELD_EX32(bus->regs, I2CM_INTR_STS, PKT_CMD_DONE) ?
"pktdone|" : "",
@@ -50,6 +55,8 @@ static inline void 
aspeed_i2c_bus_raise_interrupt(AspeedI2CBus *bus)
"ack|" : "",
SHARED_ARRAY_FIELD_EX32(bus->regs, reg_intr_sts, RX_DONE) ?
"done|" : "",
+   ARRAY_FIELD_EX32(bus->regs, I2CD_INTR_STS, SLAVE_ADDR_RX_MATCH) 
?
+   "slave-match|" : "",
SHARED_ARRAY_FIELD_EX32(bus->regs, reg_intr_sts, NORMAL_STOP) ?
"normal|" : "",
SHARED_ARRAY_FIELD_EX32(bus->regs, reg_intr_sts, ABNORMAL) ?
@@ -58,11 +65,11 @@ static inline void 
aspeed_i2c_bus_raise_interrupt(AspeedI2CBus *bus)
trace_aspeed_i2c_bus_raise_interrupt(bus->regs[reg_intr_sts], buf);
 }
 
-raise_irq = bus->regs[reg_intr_sts] & bus->regs[intr_ctrl_reg];
+raise_irq = bus->regs[reg_intr_sts] & intr_ctrl_mask ;
 
 /* In packet mode we don't mask off INTR_STS */
 if (!aspeed_i2c_bus_pkt_mode_en(bus)) {
-bus->regs[reg_intr_sts] &= bus->regs[intr_ctrl_reg];
+bus->regs[reg_intr_sts] &= intr_ctrl_mask;
 }
 
 if (raise_irq) {
-- 
2.35.3




Re: [Bug] Take more 150s to boot qemu on ARM64

2022-06-13 Thread Paul E. McKenney
On Mon, Jun 13, 2022 at 08:26:34PM +0800, chenxiang (M) wrote:
> Hi all,
> 
> I encounter a issue with kernel 5.19-rc1 on a ARM64 board:  it takes about
> 150s between beginning to run qemu command and beginng to boot Linux kernel
> ("EFI stub: Booting Linux Kernel...").
> 
> But in kernel 5.18-rc4, it only takes about 5s. I git bisect the kernel code
> and it finds c2445d387850 ("srcu: Add contention check to call_srcu()
> srcu_data ->lock acquisition").
> 
> The qemu (qemu version is 6.2.92) command i run is :
> 
> ./qemu-system-aarch64 -m 4G,slots=4,maxmem=8g \
> --trace "kvm*" \
> -cpu host \
> -machine virt,accel=kvm,gic-version=3  \
> -machine smp.cpus=2,smp.sockets=2 \
> -no-reboot \
> -nographic \
> -monitor unix:/home/cx/qmp-test,server,nowait \
> -bios /home/cx/boot/QEMU_EFI.fd \
> -kernel /home/cx/boot/Image  \
> -device 
> pcie-root-port,port=0x8,chassis=1,id=net1,bus=pcie.0,multifunction=on,addr=0x1
> \
> -device vfio-pci,host=7d:01.3,id=net0 \
> -device virtio-blk-pci,drive=drive0,id=virtblk0,num-queues=4  \
> -drive file=/home/cx/boot/boot_ubuntu.img,if=none,id=drive0 \
> -append "rdinit=init console=ttyAMA0 root=/dev/vda rootfstype=ext4 rw " \
> -net none \
> -D /home/cx/qemu_log.txt
> 
> I am not familiar with rcu code, and don't know how it causes the issue. Do
> you have any idea about this issue?

Please see the discussion here:

https://lore.kernel.org/all/20615615-0013-5adc-584f-2b1d5c03e...@linaro.org/

Though that report requires ACPI to be forced on to get the
delay, which results in more than 9,000 back-to-back calls to
synchronize_srcu_expedited().  I cannot reproduce this on my setup, even
with an artificial tight loop invoking synchronize_srcu_expedited(),
but then again I don't have ARM hardware.

My current guess is that the following patch, but with larger values for
SRCU_MAX_NODELAY_PHASE.  Here "larger" might well be up in the hundreds,
or perhaps even larger.

If you get a chance to experiment with this, could you please reply
to the discussion at the above URL?  (Or let me know, and I can CC
you on the next message in that thread.)

Thanx, Paul



diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c
index 50ba70f019dea..0db7873f4e95b 100644
--- a/kernel/rcu/srcutree.c
+++ b/kernel/rcu/srcutree.c
@@ -513,7 +513,7 @@ static bool srcu_readers_active(struct srcu_struct *ssp)
 
 #define SRCU_INTERVAL  1   // Base delay if no expedited GPs 
pending.
 #define SRCU_MAX_INTERVAL  10  // Maximum incremental delay from slow 
readers.
-#define SRCU_MAX_NODELAY_PHASE 1   // Maximum per-GP-phase consecutive 
no-delay instances.
+#define SRCU_MAX_NODELAY_PHASE 3   // Maximum per-GP-phase consecutive 
no-delay instances.
 #define SRCU_MAX_NODELAY   100 // Maximum consecutive no-delay 
instances.
 
 /*
@@ -522,16 +522,22 @@ static bool srcu_readers_active(struct srcu_struct *ssp)
  */
 static unsigned long srcu_get_delay(struct srcu_struct *ssp)
 {
+   unsigned long gpstart;
+   unsigned long j;
unsigned long jbase = SRCU_INTERVAL;
 
if (ULONG_CMP_LT(READ_ONCE(ssp->srcu_gp_seq), 
READ_ONCE(ssp->srcu_gp_seq_needed_exp)))
jbase = 0;
-   if (rcu_seq_state(READ_ONCE(ssp->srcu_gp_seq)))
-   jbase += jiffies - READ_ONCE(ssp->srcu_gp_start);
-   if (!jbase) {
-   WRITE_ONCE(ssp->srcu_n_exp_nodelay, 
READ_ONCE(ssp->srcu_n_exp_nodelay) + 1);
-   if (READ_ONCE(ssp->srcu_n_exp_nodelay) > SRCU_MAX_NODELAY_PHASE)
-   jbase = 1;
+   if (rcu_seq_state(READ_ONCE(ssp->srcu_gp_seq))) {
+   j = jiffies - 1;
+   gpstart = READ_ONCE(ssp->srcu_gp_start);
+   if (time_after(j, gpstart))
+   jbase += j - gpstart;
+   if (!jbase) {
+   WRITE_ONCE(ssp->srcu_n_exp_nodelay, 
READ_ONCE(ssp->srcu_n_exp_nodelay) + 1);
+   if (READ_ONCE(ssp->srcu_n_exp_nodelay) > 
SRCU_MAX_NODELAY_PHASE)
+   jbase = 1;
+   }
}
return jbase > SRCU_MAX_INTERVAL ? SRCU_MAX_INTERVAL : jbase;
 }



Re: [PATCH] hw/openrisc: pass random seed to fdt

2022-06-13 Thread Philippe Mathieu-Daudé via

On 13/6/22 12:58, Jason A. Donenfeld wrote:

On 6/13/22, Stafford Horne  wrote:

On Sun, Jun 12, 2022 at 11:59:49PM +0200, Jason A. Donenfeld wrote:

If the FDT contains /chosen/rng-seed, then the Linux RNG will use it to
initialize early. Set this using the usual guest random number
generation function. This is confirmed to successfully initialize the
RNG on Linux 5.19-rc2.

Cc: Stafford Horne 
Signed-off-by: Jason A. Donenfeld 
---
  hw/openrisc/openrisc_sim.c | 6 ++
  1 file changed, 6 insertions(+)



This all looks fine to me.  I will queue it with my current changes.  Since
this
is only applying to openrisc_sim I would like to also apply it to virt.  To
do
that I need to have a common core openrisc system creation api.  That way I
don't end up copying and pasting this to every platform.


Looking at commit cb57df6f7f ("hw/arm/raspi: Make machines children of
abstract RaspiMachineClass") and around could help.



Sure. Or just do it on the virt board only if that's easier.

Jason






Re: [PATCH 3/7] crypto: remove "qemu/osdep.h" in rsakey.h

2022-06-13 Thread Philippe Mathieu-Daudé via

On 13/6/22 10:45, Lei He wrote:

Move 'include "qemu/osdep.h"' from rsakey.h to rsakey.c.

Signed-off-by: lei he 
---
  crypto/rsakey.c | 1 +
  crypto/rsakey.h | 1 -
  2 files changed, 1 insertion(+), 1 deletion(-)


Reviewed-by: Philippe Mathieu-Daudé 



[PATCH v3] docs: add PCIe root bus for VGA compat guideline

2022-06-13 Thread Kevin Locke
PCI Express devices which use legacy VGA compatibility should be placed
on the Root Complex.  This simplifies ioport access to VGA registers,
which requires use of a special exception bit to work across PCI(e)
bridges.  It is also necessary for ioport access to VESA BIOS Extension
(VBE) registers, which is not forwarded over PCI(e) bridges, even with
the special exception bit for VGA register access.[1]

Update the PCI Express Guidelines to add these to the list of devices
which can be placed directly on the Root Complex.

Note that the only PCI Express display devices currently supported
(bochs-display and virtio-gpu-pci) do not offer VGA compatibility.
Legacy PCI devices (e.g. vga, qxl-vga, virtio-vga) are already
documented as allowed on the Root Complex by the first item in the list.
However, this item documents an additional consideration for placing
devices which was not previously mentioned, and may be relevant for PCIe
devices offering VGA compatibility in the future.

[1]: 
https://mail.coreboot.org/hyperkitty/list/seab...@seabios.org/thread/XG2RN3HKVRDEDTLA2PRELLIENIIH7II7/#XVP3I2KQVZHSTDA4SNVKOITWGRGSDU3F

Suggested-by: Laszlo Ersek 
Signed-off-by: Kevin Locke 
---
Changes since v2:
 * Change Signed-off-by to Suggested-by for Laszlo Ersek, as suggested
   by Laszlo Ersek.

Changes since v1:
 * Replace my overly-broad exception for devices requiring ioport access
   with a list item specifically for PCI Express devices offering VGA
   Compatibility provided by Laszlo Ersek.
 * Rewrite the commit message based on my improved understanding of the
   issue and the improved scope of the change.

 docs/pcie.txt | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/docs/pcie.txt b/docs/pcie.txt
index 89e3502075..59b26817f9 100644
--- a/docs/pcie.txt
+++ b/docs/pcie.txt
@@ -48,13 +48,17 @@ Place only the following kinds of devices directly on the 
Root Complex:
 strangely when PCI Express devices are integrated
 with the Root Complex.
 
-(2) PCI Express Root Ports (ioh3420), for starting exclusively PCI Express
+(2) Assigned PCI Express GPUs that offer legacy VGA compatibility, and
+that such compatibility is expected of (due to booting with SeaBIOS,
+or due to UEFI driver bugs or native OS driver bugs).
+
+(3) PCI Express Root Ports (ioh3420), for starting exclusively PCI Express
 hierarchies.
 
-(3) PCI Express to PCI Bridge (pcie-pci-bridge), for starting legacy PCI
+(4) PCI Express to PCI Bridge (pcie-pci-bridge), for starting legacy PCI
 hierarchies.
 
-(4) Extra Root Complexes (pxb-pcie), if multiple PCI Express Root Buses
+(5) Extra Root Complexes (pxb-pcie), if multiple PCI Express Root Buses
 are needed.
 
pcie.0 bus
-- 
2.35.1




Re: [PATCH v3 1/1] Fix the coredump when memory backend id conflicts with default_ram_id

2022-06-13 Thread Igor Mammedov
On Mon, 13 Jun 2022 12:44:02 +0200
Li Zhang  wrote:

> When no memory backend is specified in machine options,
> a default memory device will be added with default_ram_id.
> However, if a memory backend object is added in QEMU options
> and id is the same as default_ram_id, a coredump happens.
> 
> Command line:
> qemu-system-x86_64 -name guest=vmtest,debug-threads=on \
> -machine pc-q35-6.0,accel=kvm,usb=off,vmport=off \
> -smp 16,sockets=16,cores=1,threads=1 \
> -m 4G \
> -object memory-backend-ram,id=pc.ram,size=4G \
> -no-user-config -nodefaults -nographic
> 
> Stack trace of thread 16903:
> #0  0x7fb109a9318b raise (libc.so.6 + 0x3a18b)
> #1  0x7fb109a94585 abort (libc.so.6 + 0x3b585)
> #2  0x558c34bc89be error_handle_fatal (qemu-system-x86_64 + 0x9c89be)
> #3  0x558c34bc8aee error_setv (qemu-system-x86_64 + 0x9c8aee)
> #4  0x558c34bc8ccf error_setg_internal (qemu-system-x86_64 + 0x9c8ccf)
> #5  0x558c349f6899 object_property_try_add (qemu-system-x86_64 + 
> 0x7f6899)
> #6  0x558c349f7df8 object_property_try_add_child (qemu-system-x86_64 
> + 0x7f7df8)
> #7  0x558c349f7e91 object_property_add_child (qemu-system-x86_64 + 
> 0x7f7e91)
> #8  0x558c3454686d create_default_memdev (qemu-system-x86_64 + 
> 0x34686d)
> #9  0x558c34546f58 qemu_init_board (qemu-system-x86_64 + 0x346f58)
> #10 0x558c345471b9 qmp_x_exit_preconfig (qemu-system-x86_64 + 
> 0x3471b9)
> #11 0x558c345497d9 qemu_init (qemu-system-x86_64 + 0x3497d9)
> #12 0x558c344e54c2 main (qemu-system-x86_64 + 0x2e54c2)
> #13 0x7fb109a7e34d __libc_start_main (libc.so.6 + 0x2534d)
> #14 0x558c344e53ba _start (qemu-system-x86_64 + 0x2e53ba)
> 
> Signed-off-by: Li Zhang 

Acked-by: Igor Mammedov 


CCing David as he probably would be the one to merge it

> ---
>  hw/core/machine.c | 12 
>  1 file changed, 12 insertions(+)
> 
> diff --git a/hw/core/machine.c b/hw/core/machine.c
> index a673302cce..9ede63b01c 100644
> --- a/hw/core/machine.c
> +++ b/hw/core/machine.c
> @@ -1265,9 +1265,21 @@ MemoryRegion *machine_consume_memdev(MachineState 
> *machine,
>  static bool create_default_memdev(MachineState *ms, const char *path, Error 
> **errp)
>  {
>  Object *obj;
> +ObjectProperty *prop;
>  MachineClass *mc = MACHINE_GET_CLASS(ms);
>  bool r = false;
>  
> +prop = object_property_find(object_get_objects_root(), 
> mc->default_ram_id);
> +if (prop) {
> +error_report("A memory backend with id '%s' already exists, "
> + "cannot create default RAM backend with the same id. "
> + "Either change id of the offending backend or "
> + "provide system RAM backend explicitly using "
> + "'-machine memory-backend' option. " ,
> + mc->default_ram_id);
> +exit(EXIT_FAILURE);
> +}
> +
>  obj = object_new(path ? TYPE_MEMORY_BACKEND_FILE : 
> TYPE_MEMORY_BACKEND_RAM);
>  if (path) {
>  if (!object_property_set_str(obj, "mem-path", path, errp)) {




Re: [PATCH 4/7] crypto: Add ECDSA key parser

2022-06-13 Thread Philippe Mathieu-Daudé via

On 13/6/22 10:45, Lei He wrote:

Add ECDSA key parser and ECDSA signautre parser.

Signed-off-by: lei he 
---
  crypto/ecdsakey-builtin.c.inc | 248 ++
  crypto/ecdsakey.c | 118 
  crypto/ecdsakey.h |  66 +++
  crypto/meson.build|   1 +
  4 files changed, 433 insertions(+)
  create mode 100644 crypto/ecdsakey-builtin.c.inc
  create mode 100644 crypto/ecdsakey.c
  create mode 100644 crypto/ecdsakey.h

diff --git a/crypto/ecdsakey-builtin.c.inc b/crypto/ecdsakey-builtin.c.inc
new file mode 100644
index 00..5da317ec44
--- /dev/null
+++ b/crypto/ecdsakey-builtin.c.inc
@@ -0,0 +1,248 @@
+/*
+ * QEMU Crypto akcipher algorithms
+ *
+ * Copyright (c) 2022 Bytedance
+ * Author: lei he 
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ *
+ */
+
+#include "der.h"
+#include "ecdsakey.h"
+
+#define QCRYPTO_ECDSA_PUBKEY_FMT_UNCOMPRESSED 0x04
+
+static int extract_mpi(void *ctx, const uint8_t *value,
+   size_t vlen, Error **errp)
+{
+QCryptoAkCipherMPI *mpi = (QCryptoAkCipherMPI *)ctx;
+if (vlen == 0) {
+error_setg(errp, "Empty mpi field");
+return -1;


Functions taking Error* param usually return a boolean.


+}
+mpi->data = g_memdup2(value, vlen);
+mpi->len = vlen;
+return 0;
+}
+
+static int extract_version(void *ctx, const uint8_t *value,
+   size_t vlen, Error **errp)
+{
+uint8_t *version = (uint8_t *)ctx;
+if (vlen != 1 || *value > 1) {
+error_setg(errp, "Invalid rsakey version");
+return -1;
+}
+*version = *value;
+return 0;
+}
+
+static int extract_cons_content(void *ctx, const uint8_t *value,
+size_t vlen, Error **errp)
+{
+const uint8_t **content = (const uint8_t **)ctx;
+if (vlen == 0) {
+error_setg(errp, "Empty sequence");
+return -1;
+}
+*content = value;


You need to check (vlen >= sizeof(uint8_t *)) to avoid overrun.


+return 0;
+}
+
+static int __qcrypto_akcipher_builtin_ecdsa_pubkey_parse(
+QCryptoAkCipherECDSAKey *ecdsa,
+const uint8_t *key, size_t keylen, Error **errp);


Why use the reserved __prefix?



Re: [PATCH v17 6/8] softmmu/dirtylimit: Implement virtual CPU throttle

2022-06-13 Thread Peter Xu
On Mon, Jun 13, 2022 at 03:28:34PM +0530, manish.mishra wrote:
> 
> On 26/05/22 8:21 am, Jason Wang wrote:
> > On Wed, May 25, 2022 at 11:56 PM Peter Xu  wrote:
> > > On Wed, May 25, 2022 at 11:38:26PM +0800, Hyman Huang wrote:
> > > > > 2. Also this algorithm only control or limits dirty rate by guest
> > > > > writes. There can be some memory dirtying done by virtio based devices
> > > > > which is accounted only at qemu level so may not be accounted through
> > > > > dirty rings so do we have plan for that in future? Those are not issue
> > > > > for auto-converge as it slows full VM but dirty rate limit only slows
> > > > > guest writes.
> > > > > 
> > > >  From the migration point of view, time spent on migrating memory is far
> > > > greater than migrating devices emulated by qemu. I think we can do that 
> > > > when
> > > > migrating device costs the same magnitude time as migrating memory.
> > > > 
> > > > As to auto-converge, it throttle vcpu by kicking it and force it to 
> > > > sleep
> > > > periodically. The two seems has no much difference from the perspective 
> > > > of
> > > > internal method but the auto-converge is kind of "offensive" when doing
> > > > restraint. I'll read the auto-converge implementation code and figure 
> > > > out
> > > > the problem you point out.
> > > This seems to be not virtio-specific, but can be applied to any device DMA
> > > writting to guest mem (if not including vfio).  But indeed virtio can be
> > > normally faster.
> > > 
> > > I'm also curious how fast a device DMA could dirty memories.  This could 
> > > be
> > > a question to answer to all vcpu-based throttling approaches (including 
> > > the
> > > quota based approach that was proposed on KVM list).  Maybe for kernel
> > > virtio drivers we can have some easier estimation?
> > As you said below, it really depends on the speed of the backend.
> > 
> > >   My guess is it'll be
> > > much harder for DPDK-in-guest (aka userspace drivers) because IIUC that
> > > could use a large chunk of guest mem.
> > Probably, for vhost-user backend, it could be ~20Mpps or even higher.
> 
> Sorry for late response on this. We did experiment with IO on virtio-scsi 
> based disk.

Thanks for trying this and sharing it out.

> 
> We could see dirty rate of ~500MBps on my system and most of that was not 
> tracked
> 
> as kvm_dirty_log. Also for reference i am attaching test we used to avoid 
> tacking
> 
> in KVM. (as attached file).

The number looks sane as it seems to be the sequential bandwidth for a
disk, though I'm not 100% sure it'll work as expected since you mmap()ed
the region with private pages rather than shared, so after you did I'm
wondering whether below will happen (also based on the fact that you mapped
twice the size of guest mem as you mentioned in the comment):

  (1) Swap out will start to trigger after you read a lot of data into the
  mem already, then old-read pages will be swapped out to disk (and
  hopefully the swap device does not reside on the same virtio-scsi
  disk or it'll be even more complicated scenario of mixture IOs..),
  meanwhile when you finish reading a round and start to read from
  offset 0 swap-in will start to happen too.  Swapping can slow down
  things already, and I'm wondering whether the 500MB/s was really
  caused by the swapout rather than backend disk reads.  More below.

  (2) Another attribute of private pages AFAICT is after you read it once
  it does not need to be read again from the virtio-scsi disks.  In
  other words, I'm thinking whether starting from the 2nd iteration
  your program won't trigger any DMA at all but purely torturing the
  swap device.

Maybe changing MAP_PRIVATE to MAP_SHARED can emulate better on what we want
to measure, but I'm also not 100% sure on whether it could be accurate..

Thanks,

> 
> > 
> > Thanks
> > 
> > > [copy Jason too]
> > > 
> > > --
> > > Peter Xu
> > > 
> #include 
> #include 
> #include 
> #include 
> #include 
> #include 
> #include 
> #include 
> 
> #define PAGE_SIZE 4096
> #define GB (1024 * 1024 * 1024)
> 
> int main()
> {
> char *buff;
> size_t size;
> struct stat stat;
> // Take file of size atleast double of RAM size to
> // achieve max dirty rate possible.
> const char * file_name = "file_10_gb";
> int fd;
> size_t i = 0, count = 0;
> struct timespec ts1, ts0;
> double time_diff;
> 
> fd = open(file_name, O_RDONLY);
> if (fd == -1) {
>perror("Error opening file");
>exit(1);
> }
> 
> fstat (fd, &stat);
> size = stat.st_size;
> printf("File size %ld\n", (long)size);
> 
> buff = (char *)mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0);
> if (buff == MAP_FAILED) {
>perror("Mmap Error");
>exit(1);
> }
> 
> (void)clock_gettime(CLOCK_MONOTONIC, &ts0);
> 
> while(1) {
>char c;
> 
>i = (i + PAGE_SIZE) % size;
>c = buff[i];
>count++;
>  

Re: [PATCH v3 1/1] Fix the coredump when memory backend id conflicts with default_ram_id

2022-06-13 Thread Li Zhang
On Mon, Jun 13, 2022 at 4:19 PM Igor Mammedov  wrote:
>
> On Mon, 13 Jun 2022 12:44:02 +0200
> Li Zhang  wrote:
>
> > When no memory backend is specified in machine options,
> > a default memory device will be added with default_ram_id.
> > However, if a memory backend object is added in QEMU options
> > and id is the same as default_ram_id, a coredump happens.
> >
> > Command line:
> > qemu-system-x86_64 -name guest=vmtest,debug-threads=on \
> > -machine pc-q35-6.0,accel=kvm,usb=off,vmport=off \
> > -smp 16,sockets=16,cores=1,threads=1 \
> > -m 4G \
> > -object memory-backend-ram,id=pc.ram,size=4G \
> > -no-user-config -nodefaults -nographic
> >
> > Stack trace of thread 16903:
> > #0  0x7fb109a9318b raise (libc.so.6 + 0x3a18b)
> > #1  0x7fb109a94585 abort (libc.so.6 + 0x3b585)
> > #2  0x558c34bc89be error_handle_fatal (qemu-system-x86_64 + 
> > 0x9c89be)
> > #3  0x558c34bc8aee error_setv (qemu-system-x86_64 + 0x9c8aee)
> > #4  0x558c34bc8ccf error_setg_internal (qemu-system-x86_64 + 
> > 0x9c8ccf)
> > #5  0x558c349f6899 object_property_try_add (qemu-system-x86_64 + 
> > 0x7f6899)
> > #6  0x558c349f7df8 object_property_try_add_child 
> > (qemu-system-x86_64 + 0x7f7df8)
> > #7  0x558c349f7e91 object_property_add_child (qemu-system-x86_64 + 
> > 0x7f7e91)
> > #8  0x558c3454686d create_default_memdev (qemu-system-x86_64 + 
> > 0x34686d)
> > #9  0x558c34546f58 qemu_init_board (qemu-system-x86_64 + 0x346f58)
> > #10 0x558c345471b9 qmp_x_exit_preconfig (qemu-system-x86_64 + 
> > 0x3471b9)
> > #11 0x558c345497d9 qemu_init (qemu-system-x86_64 + 0x3497d9)
> > #12 0x558c344e54c2 main (qemu-system-x86_64 + 0x2e54c2)
> > #13 0x7fb109a7e34d __libc_start_main (libc.so.6 + 0x2534d)
> > #14 0x558c344e53ba _start (qemu-system-x86_64 + 0x2e53ba)
> >
> > Signed-off-by: Li Zhang 
>
> Acked-by: Igor Mammedov 
>
>
> CCing David as he probably would be the one to merge it
>

Thanks for your review.

> > ---
> >  hw/core/machine.c | 12 
> >  1 file changed, 12 insertions(+)
> >
> > diff --git a/hw/core/machine.c b/hw/core/machine.c
> > index a673302cce..9ede63b01c 100644
> > --- a/hw/core/machine.c
> > +++ b/hw/core/machine.c
> > @@ -1265,9 +1265,21 @@ MemoryRegion *machine_consume_memdev(MachineState 
> > *machine,
> >  static bool create_default_memdev(MachineState *ms, const char *path, 
> > Error **errp)
> >  {
> >  Object *obj;
> > +ObjectProperty *prop;
> >  MachineClass *mc = MACHINE_GET_CLASS(ms);
> >  bool r = false;
> >
> > +prop = object_property_find(object_get_objects_root(), 
> > mc->default_ram_id);
> > +if (prop) {
> > +error_report("A memory backend with id '%s' already exists, "
> > + "cannot create default RAM backend with the same id. "
> > + "Either change id of the offending backend or "
> > + "provide system RAM backend explicitly using "
> > + "'-machine memory-backend' option. " ,
> > + mc->default_ram_id);
> > +exit(EXIT_FAILURE);
> > +}
> > +
> >  obj = object_new(path ? TYPE_MEMORY_BACKEND_FILE : 
> > TYPE_MEMORY_BACKEND_RAM);
> >  if (path) {
> >  if (!object_property_set_str(obj, "mem-path", path, errp)) {
>


-- 

Best Regards
-Li



Re: [PATCH v14 5/8] qmp: decode feature & status bits in virtio-status

2022-06-13 Thread Jonah Palmer


On 6/10/22 01:41, Michael S. Tsirkin wrote:

On Thu, May 19, 2022 at 02:30:43AM -0400, Jonah Palmer wrote:

On 5/16/22 16:26, Michael S. Tsirkin wrote:

 On Fri, Apr 01, 2022 at 09:23:22AM -0400, Jonah Palmer wrote:

 From: Laurent Vivier

 Display feature names instead of bitmaps for host, guest, and
 backend for VirtIODevices.

 Display status names instead of bitmaps for VirtIODevices.

 Display feature names instead of bitmaps for backend, protocol,
 acked, and features (hdev->features) for vhost devices.

 Decode features according to device ID. Decode statuses
 according to configuration status bitmap (config_status_map).
 Decode vhost user protocol features according to vhost user
 protocol bitmap (vhost_user_protocol_map).

 Transport features are on the first line. Undecoded bits (if
 any) are stored in a separate field.

 Signed-off-by: Jonah Palmer


 So this has several problems that I missed previously.
 First, sign off from poster is missing.

My apologies, will add missing Laurent's SOB in correct order for
patches 3-8.


Were you going to repost?


Yes, and sorry for the delay. Trying to get these out ASAP.

Jonah







 ---
  hw/block/virtio-blk.c  |  29 
  hw/char/virtio-serial-bus.c|  11 ++
  hw/display/virtio-gpu.c|  18 ++
  hw/input/virtio-input.c|  10 ++
  hw/net/virtio-net.c|  47 +
  hw/scsi/virtio-scsi.c  |  17 ++
  hw/virtio/vhost-user-fs.c  |  10 ++
  hw/virtio/vhost-user-i2c.c |  14 ++
  hw/virtio/vhost-vsock-common.c |  10 ++
  hw/virtio/virtio-balloon.c |  14 ++
  hw/virtio/virtio-crypto.c  |  10 ++
  hw/virtio/virtio-iommu.c   |  14 ++
  hw/virtio/virtio-mem.c |  11 ++
  hw/virtio/virtio.c | 302 -
  include/hw/virtio/vhost.h  |   3 +
  include/hw/virtio/virtio.h |  19 +++
  qapi/virtio.json   | 156 ++---
  17 files changed, 667 insertions(+), 28 deletions(-)

 diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
 index 27c71ad316..f104603040 100644
 --- a/hw/block/virtio-blk.c
 +++ b/hw/block/virtio-blk.c
 @@ -13,6 +13,7 @@

  #include "qemu/osdep.h"
  #include "qapi/error.h"
 +#include "qapi/qapi-visit-virtio.h"
  #include "qemu/iov.h"
  #include "qemu/module.h"
  #include "qemu/error-report.h"
 @@ -33,10 +34,38 @@
  #include "migration/qemu-file-types.h"
  #include "hw/virtio/virtio-access.h"
  #include "qemu/coroutine.h"
 +#include "standard-headers/linux/vhost_types.h"

  /* Config size before the discard support (hide associated config 
fields) */
  #define VIRTIO_BLK_CFG_SIZE offsetof(struct virtio_blk_config, \
   max_discard_sectors)
 +
 +qmp_virtio_feature_map_t blk_map[] = {
 +#define FEATURE_ENTRY(name) \
 +{ VIRTIO_BLK_F_##name, #name }
 +FEATURE_ENTRY(SIZE_MAX),
 +FEATURE_ENTRY(SEG_MAX),
 +FEATURE_ENTRY(GEOMETRY),
 +FEATURE_ENTRY(RO),
 +FEATURE_ENTRY(BLK_SIZE),
 +FEATURE_ENTRY(TOPOLOGY),
 +FEATURE_ENTRY(MQ),
 +FEATURE_ENTRY(DISCARD),
 +FEATURE_ENTRY(WRITE_ZEROES),
 +#ifndef VIRTIO_BLK_NO_LEGACY
 +FEATURE_ENTRY(BARRIER),
 +FEATURE_ENTRY(SCSI),
 +FEATURE_ENTRY(FLUSH),
 +FEATURE_ENTRY(CONFIG_WCE),
 +#endif /* !VIRTIO_BLK_NO_LEGACY */
 +#undef FEATURE_ENTRY
 +#define FEATURE_ENTRY(name) \
 +{ VHOST_F_##name, #name }
 +FEATURE_ENTRY(LOG_ALL),
 +#undef FEATURE_ENTRY
 +{ -1, "" }
 +};
 +
  /*
   * Starting from the discard feature, we can use this array to 
properly
   * set the config size depending on the features enabled.
 diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
 index 7d4601cb5d..fbb31a2b16 100644
 --- a/hw/char/virtio-serial-bus.c
 +++ b/hw/char/virtio-serial-bus.c
 @@ -20,6 +20,7 @@

  #include "qemu/osdep.h"
  #include "qapi/error.h"
 +#include "qapi/qapi-visit-virtio.h"
  #include "qemu/iov.h"
  #include "qemu/main-loop.h"
  #include "qemu/module.h"
 @@ -32,6 +33,16 @@
  #include "hw/virtio/virtio-serial.h"
  #include "hw/virtio/virtio-access.h"

 +qmp_virtio_feature_map_t serial_map[] = {
 +#define FEATURE_ENTRY(name) \
 +{ VIRTIO_CONSOLE_F_##name, #name }
 +FEATURE_E

[RFC PATCH] tcg/ppc: implement rem[u]_i{32,64} with mod[su][wd]

2022-06-13 Thread Matheus Kowalczuk Ferst
Power ISA v3.0 introduced mod[su][wd] insns that can be used to
implement rem[u]_i{32,64}.

Signed-off-by: Matheus Ferst 
---
 tcg/ppc/tcg-target.c.inc | 22 ++
 tcg/ppc/tcg-target.h |  4 ++--
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
index de4483e43b..1cbd047ab3 100644
--- a/tcg/ppc/tcg-target.c.inc
+++ b/tcg/ppc/tcg-target.c.inc
@@ -371,6 +371,8 @@ static bool tcg_target_const_match(int64_t val, TCGType 
type, int ct)
 #define MULHWU XO31( 11)
 #define DIVW   XO31(491)
 #define DIVWU  XO31(459)
+#define MODSW  XO31(779)
+#define MODUW  XO31(267)
 #define CMPXO31(  0)
 #define CMPL   XO31( 32)
 #define LHBRX  XO31(790)
@@ -403,6 +405,8 @@ static bool tcg_target_const_match(int64_t val, TCGType 
type, int ct)
 #define MULHDU XO31(  9)
 #define DIVD   XO31(489)
 #define DIVDU  XO31(457)
+#define MODSD  XO31(777)
+#define MODUD  XO31(265)
 
 #define LBZX   XO31( 87)
 #define LHZX   XO31(279)
@@ -2806,6 +2810,14 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 tcg_out32(s, DIVWU | TAB(args[0], args[1], args[2]));
 break;
 
+case INDEX_op_rem_i32:
+tcg_out32(s, MODSW | TAB(args[0], args[1], args[2]));
+break;
+
+case INDEX_op_remu_i32:
+tcg_out32(s, MODUW | TAB(args[0], args[1], args[2]));
+break;
+
 case INDEX_op_shl_i32:
 if (const_args[2]) {
 /* Limit immediate shift count lest we create an illegal insn.  */
@@ -2947,6 +2959,12 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 case INDEX_op_divu_i64:
 tcg_out32(s, DIVDU | TAB(args[0], args[1], args[2]));
 break;
+case INDEX_op_rem_i64:
+tcg_out32(s, MODSD | TAB(args[0], args[1], args[2]));
+break;
+case INDEX_op_remu_i64:
+tcg_out32(s, MODUD | TAB(args[0], args[1], args[2]));
+break;
 
 case INDEX_op_qemu_ld_i32:
 tcg_out_qemu_ld(s, args, false);
@@ -3722,6 +3740,8 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 
 case INDEX_op_div_i32:
 case INDEX_op_divu_i32:
+case INDEX_op_rem_i32:
+case INDEX_op_remu_i32:
 case INDEX_op_nand_i32:
 case INDEX_op_nor_i32:
 case INDEX_op_muluh_i32:
@@ -3732,6 +3752,8 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_nor_i64:
 case INDEX_op_div_i64:
 case INDEX_op_divu_i64:
+case INDEX_op_rem_i64:
+case INDEX_op_remu_i64:
 case INDEX_op_mulsh_i64:
 case INDEX_op_muluh_i64:
 return C_O1_I2(r, r, r);
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index e6cf72503f..b5cd225cfa 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -83,7 +83,7 @@ extern bool have_vsx;
 
 /* optional instructions */
 #define TCG_TARGET_HAS_div_i32  1
-#define TCG_TARGET_HAS_rem_i32  0
+#define TCG_TARGET_HAS_rem_i32  have_isa_3_00
 #define TCG_TARGET_HAS_rot_i32  1
 #define TCG_TARGET_HAS_ext8s_i321
 #define TCG_TARGET_HAS_ext16s_i32   1
@@ -117,7 +117,7 @@ extern bool have_vsx;
 #define TCG_TARGET_HAS_extrl_i64_i320
 #define TCG_TARGET_HAS_extrh_i64_i320
 #define TCG_TARGET_HAS_div_i64  1
-#define TCG_TARGET_HAS_rem_i64  0
+#define TCG_TARGET_HAS_rem_i64  have_isa_3_00
 #define TCG_TARGET_HAS_rot_i64  1
 #define TCG_TARGET_HAS_ext8s_i641
 #define TCG_TARGET_HAS_ext16s_i64   1
-- 
2.25.1



Re: [PATCH] hw/mem/nvdimm: fix error message for 'unarmed' flag

2022-06-13 Thread Julia Suvorova
On Tue, May 31, 2022 at 5:32 PM Stefan Hajnoczi  wrote:
>
> On Tue, May 31, 2022 at 04:51:47PM +0200, Julia Suvorova wrote:
> > In the ACPI specification [1], the 'unarmed' bit is set when a device
> > cannot accept a persistent write. This means that when a memdev is
> > read-only, the 'unarmed' flag must be turned on. The logic is correct,
> > just changing the error message.
> >
> > [1] ACPI NFIT NVDIMM Region Mapping Structure "NVDIMM State Flags" Bit 3
> >
> > Signed-off-by: Julia Suvorova 
> > ---
> >  hw/mem/nvdimm.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
>
> Reviewed-by: Stefan Hajnoczi 

It seems like Xiao is not active, whose tree should this patch go to?

Best regards, Julia Suvorova.




Re: [PATCH] hw/mem/nvdimm: fix error message for 'unarmed' flag

2022-06-13 Thread Stefan Hajnoczi
On Mon, Jun 13, 2022 at 05:01:10PM +0200, Julia Suvorova wrote:
> On Tue, May 31, 2022 at 5:32 PM Stefan Hajnoczi  wrote:
> >
> > On Tue, May 31, 2022 at 04:51:47PM +0200, Julia Suvorova wrote:
> > > In the ACPI specification [1], the 'unarmed' bit is set when a device
> > > cannot accept a persistent write. This means that when a memdev is
> > > read-only, the 'unarmed' flag must be turned on. The logic is correct,
> > > just changing the error message.
> > >
> > > [1] ACPI NFIT NVDIMM Region Mapping Structure "NVDIMM State Flags" Bit 3
> > >
> > > Signed-off-by: Julia Suvorova 
> > > ---
> > >  hw/mem/nvdimm.c | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > Reviewed-by: Stefan Hajnoczi 
> 
> It seems like Xiao is not active, whose tree should this patch go to?

Michael or Igor can merge it:

  $ scripts/get_maintainer.pl -f hw/mem/nvdimm.c
  Xiao Guangrong  (maintainer:NVDIMM)
  "Michael S. Tsirkin"  (supporter:ACPI/SMBIOS)
  Igor Mammedov  (supporter:ACPI/SMBIOS)
  Ani Sinha  (reviewer:ACPI/SMBIOS)
  qemu-devel@nongnu.org (open list:All patches CC here)

Stefan


signature.asc
Description: PGP signature


Re: [PATCH v11 13/14] vfio-user: handle device interrupts

2022-06-13 Thread Stefan Hajnoczi
On Fri, Jun 10, 2022 at 03:50:40PM -0400, Jagannathan Raman wrote:
> @@ -307,6 +315,38 @@ bool msi_is_masked(const PCIDevice *dev, unsigned int 
> vector)
>  return mask & (1U << vector);
>  }
>  
> +void msi_set_irq_state(PCIDevice *dev, int vector, bool mask, Error **errp)

The function name is non-obvious. This function masks or unmasks an MSI
vector. Maybe call it msi_set_mask()?

> +{
> +ERRP_GUARD();
> +uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
> +bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
> +uint32_t irq_state, vector_mask, pending;
> +
> +if (vector > PCI_MSI_VECTORS_MAX) {
> +error_setg(errp, "msi: vector %d not allocated. max vector is %d",
> +   vector, PCI_MSI_VECTORS_MAX);
> +}

Missing return statement?

> @@ -131,6 +136,31 @@ static void msix_handle_mask_update(PCIDevice *dev, int 
> vector, bool was_masked)
>  }
>  }
>  
> +void msix_set_irq_state(PCIDevice *dev, int vector, bool mask, Error **errp)

Same naming question here.


signature.asc
Description: PGP signature


Re: [PATCH v3 1/1] Fix the coredump when memory backend id conflicts with default_ram_id

2022-06-13 Thread David Hildenbrand
On 13.06.22 16:37, Li Zhang wrote:
> On Mon, Jun 13, 2022 at 4:19 PM Igor Mammedov  wrote:
>>
>> On Mon, 13 Jun 2022 12:44:02 +0200
>> Li Zhang  wrote:
>>
>>> When no memory backend is specified in machine options,
>>> a default memory device will be added with default_ram_id.
>>> However, if a memory backend object is added in QEMU options
>>> and id is the same as default_ram_id, a coredump happens.
>>>
>>> Command line:
>>> qemu-system-x86_64 -name guest=vmtest,debug-threads=on \
>>> -machine pc-q35-6.0,accel=kvm,usb=off,vmport=off \
>>> -smp 16,sockets=16,cores=1,threads=1 \
>>> -m 4G \
>>> -object memory-backend-ram,id=pc.ram,size=4G \
>>> -no-user-config -nodefaults -nographic
>>>
>>> Stack trace of thread 16903:
>>> #0  0x7fb109a9318b raise (libc.so.6 + 0x3a18b)
>>> #1  0x7fb109a94585 abort (libc.so.6 + 0x3b585)
>>> #2  0x558c34bc89be error_handle_fatal (qemu-system-x86_64 + 
>>> 0x9c89be)
>>> #3  0x558c34bc8aee error_setv (qemu-system-x86_64 + 0x9c8aee)
>>> #4  0x558c34bc8ccf error_setg_internal (qemu-system-x86_64 + 
>>> 0x9c8ccf)
>>> #5  0x558c349f6899 object_property_try_add (qemu-system-x86_64 + 
>>> 0x7f6899)
>>> #6  0x558c349f7df8 object_property_try_add_child 
>>> (qemu-system-x86_64 + 0x7f7df8)
>>> #7  0x558c349f7e91 object_property_add_child (qemu-system-x86_64 + 
>>> 0x7f7e91)
>>> #8  0x558c3454686d create_default_memdev (qemu-system-x86_64 + 
>>> 0x34686d)
>>> #9  0x558c34546f58 qemu_init_board (qemu-system-x86_64 + 0x346f58)
>>> #10 0x558c345471b9 qmp_x_exit_preconfig (qemu-system-x86_64 + 
>>> 0x3471b9)
>>> #11 0x558c345497d9 qemu_init (qemu-system-x86_64 + 0x3497d9)
>>> #12 0x558c344e54c2 main (qemu-system-x86_64 + 0x2e54c2)
>>> #13 0x7fb109a7e34d __libc_start_main (libc.so.6 + 0x2534d)
>>> #14 0x558c344e53ba _start (qemu-system-x86_64 + 0x2e53ba)
>>>
>>> Signed-off-by: Li Zhang 
>>
>> Acked-by: Igor Mammedov 
>>
>>
>> CCing David as he probably would be the one to merge it
>>
> 
> Thanks for your review.


Acked-by: David Hildenbrand 


Paolo, can you queue this?

https://lore.kernel.org/qemu-devel/20220613104402.10279-1-lizh...@suse.de/

-- 
Thanks,

David / dhildenb




Re: [PATCH v17 6/8] softmmu/dirtylimit: Implement virtual CPU throttle

2022-06-13 Thread manish.mishra



On 13/06/22 8:03 pm, Peter Xu wrote:

On Mon, Jun 13, 2022 at 03:28:34PM +0530, manish.mishra wrote:

On 26/05/22 8:21 am, Jason Wang wrote:

On Wed, May 25, 2022 at 11:56 PM Peter Xu  wrote:

On Wed, May 25, 2022 at 11:38:26PM +0800, Hyman Huang wrote:

2. Also this algorithm only control or limits dirty rate by guest
writes. There can be some memory dirtying done by virtio based devices
which is accounted only at qemu level so may not be accounted through
dirty rings so do we have plan for that in future? Those are not issue
for auto-converge as it slows full VM but dirty rate limit only slows
guest writes.


  From the migration point of view, time spent on migrating memory is far
greater than migrating devices emulated by qemu. I think we can do that when
migrating device costs the same magnitude time as migrating memory.

As to auto-converge, it throttle vcpu by kicking it and force it to sleep
periodically. The two seems has no much difference from the perspective of
internal method but the auto-converge is kind of "offensive" when doing
restraint. I'll read the auto-converge implementation code and figure out
the problem you point out.

This seems to be not virtio-specific, but can be applied to any device DMA
writting to guest mem (if not including vfio).  But indeed virtio can be
normally faster.

I'm also curious how fast a device DMA could dirty memories.  This could be
a question to answer to all vcpu-based throttling approaches (including the
quota based approach that was proposed on KVM list).  Maybe for kernel
virtio drivers we can have some easier estimation?

As you said below, it really depends on the speed of the backend.


   My guess is it'll be
much harder for DPDK-in-guest (aka userspace drivers) because IIUC that
could use a large chunk of guest mem.

Probably, for vhost-user backend, it could be ~20Mpps or even higher.

Sorry for late response on this. We did experiment with IO on virtio-scsi based 
disk.

Thanks for trying this and sharing it out.


We could see dirty rate of ~500MBps on my system and most of that was not 
tracked

as kvm_dirty_log. Also for reference i am attaching test we used to avoid 
tacking

in KVM. (as attached file).

The number looks sane as it seems to be the sequential bandwidth for a
disk, though I'm not 100% sure it'll work as expected since you mmap()ed
the region with private pages rather than shared, so after you did I'm
wondering whether below will happen (also based on the fact that you mapped
twice the size of guest mem as you mentioned in the comment):

   (1) Swap out will start to trigger after you read a lot of data into the
   mem already, then old-read pages will be swapped out to disk (and
   hopefully the swap device does not reside on the same virtio-scsi
   disk or it'll be even more complicated scenario of mixture IOs..),
   meanwhile when you finish reading a round and start to read from
   offset 0 swap-in will start to happen too.  Swapping can slow down
   things already, and I'm wondering whether the 500MB/s was really
   caused by the swapout rather than backend disk reads.  More below.

   (2) Another attribute of private pages AFAICT is after you read it once
   it does not need to be read again from the virtio-scsi disks.  In
   other words, I'm thinking whether starting from the 2nd iteration
   your program won't trigger any DMA at all but purely torturing the
   swap device.

Maybe changing MAP_PRIVATE to MAP_SHARED can emulate better on what we want
to measure, but I'm also not 100% sure on whether it could be accurate..

Thanks,


Thanks Peter, Yes agree MAP_SHARED should be used here, sorry i missed that 😁.

Yes, my purpose of taking file size larger than RAM_SIZE was to cause

frequent page cache flush and re-populating page-cache pages, not to

trigger swaps. I checked on my VM i had swapping disabled, may be

MAP_PRIVATE did not make difference because it was read-only.

I tested again with MAP_SHARED it comes around ~500MBps.

Thanks

Manish Mishra


Thanks


[copy Jason too]

--
Peter Xu


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define PAGE_SIZE 4096
#define GB (1024 * 1024 * 1024)

int main()
{
 char *buff;
 size_t size;
 struct stat stat;
 // Take file of size atleast double of RAM size to
 // achieve max dirty rate possible.
 const char * file_name = "file_10_gb";
 int fd;
 size_t i = 0, count = 0;
 struct timespec ts1, ts0;
 double time_diff;

 fd = open(file_name, O_RDONLY);
 if (fd == -1) {
perror("Error opening file");
exit(1);
 }

 fstat (fd, &stat);
 size = stat.st_size;
 printf("File size %ld\n", (long)size);

 buff = (char *)mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0);
 if (buff == MAP_FAILED) {
perror("Mmap Error");
exit(1);
 }

 (void)clock_gettime(CLOCK_MONOTONIC, &ts0);

 while(1) {
char c;

[PATCH 01/11] ppc/pnv: move root port attach to pnv_phb4_realize()

2022-06-13 Thread Daniel Henrique Barboza
Creating a root port is something related to the PHB, not the PEC. It
also makes the logic more in line with what pnv-phb3 does.

Signed-off-by: Daniel Henrique Barboza 
---
 hw/pci-host/pnv_phb4.c | 4 
 hw/pci-host/pnv_phb4_pec.c | 3 ---
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index 6594016121..23ad8de7ee 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -1547,6 +1547,7 @@ static void pnv_phb4_instance_init(Object *obj)
 static void pnv_phb4_realize(DeviceState *dev, Error **errp)
 {
 PnvPHB4 *phb = PNV_PHB4(dev);
+PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(phb->pec);
 PCIHostState *pci = PCI_HOST_BRIDGE(dev);
 XiveSource *xsrc = &phb->xsrc;
 int nr_irqs;
@@ -1583,6 +1584,9 @@ static void pnv_phb4_realize(DeviceState *dev, Error 
**errp)
 pci_setup_iommu(pci->bus, pnv_phb4_dma_iommu, phb);
 pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
 
+/* Add a single Root port if running with defaults */
+pnv_phb_attach_root_port(pci, pecc->rp_model);
+
 /* Setup XIVE Source */
 if (phb->big_phb) {
 nr_irqs = PNV_PHB4_MAX_INTs;
diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c
index 8b7e823fa5..c9aaf1c28e 100644
--- a/hw/pci-host/pnv_phb4_pec.c
+++ b/hw/pci-host/pnv_phb4_pec.c
@@ -130,9 +130,6 @@ static void pnv_pec_default_phb_realize(PnvPhb4PecState 
*pec,
 if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
 return;
 }
-
-/* Add a single Root port if running with defaults */
-pnv_phb_attach_root_port(PCI_HOST_BRIDGE(phb), pecc->rp_model);
 }
 
 static void pnv_pec_realize(DeviceState *dev, Error **errp)
-- 
2.36.1




[PATCH 02/11] ppc/pnv: attach phb3/phb4 root ports in QOM tree

2022-06-13 Thread Daniel Henrique Barboza
At this moment we leave the pnv-phb3(4)-root-port unattached in QOM:

  /unattached (container)
(...)
/device[2] (pnv-phb3-root-port)
  /bus master container[0] (memory-region)
  /bus master[0] (memory-region)
  /pci_bridge_io[0] (memory-region)
  /pci_bridge_io[1] (memory-region)
  /pci_bridge_mem[0] (memory-region)
  /pci_bridge_pci[0] (memory-region)
  /pci_bridge_pref_mem[0] (memory-region)
  /pci_bridge_vga_io_hi[0] (memory-region)
  /pci_bridge_vga_io_lo[0] (memory-region)
  /pci_bridge_vga_mem[0] (memory-region)
  /pcie.0 (PCIE)

Let's make changes in pnv_phb_attach_root_port() to attach the created
root ports to its corresponding PHB.

This is the result afterwards:

/pnv-phb3[0] (pnv-phb3)
  /lsi (ics)
  /msi (phb3-msi)
  /msi32[0] (memory-region)
  /msi64[0] (memory-region)
  /pbcq (pnv-pbcq)
(...)
  /phb3_iommu[0] (pnv-phb3-iommu-memory-region)
  /pnv-phb3-root.0 (pnv-phb3-root)
/pnv-phb3-root-port[0] (pnv-phb3-root-port)
  /bus master container[0] (memory-region)
  /bus master[0] (memory-region)
  /pci_bridge_io[0] (memory-region)
  /pci_bridge_io[1] (memory-region)
  /pci_bridge_mem[0] (memory-region)
  /pci_bridge_pci[0] (memory-region)
  /pci_bridge_pref_mem[0] (memory-region)
  /pci_bridge_vga_io_hi[0] (memory-region)
  /pci_bridge_vga_io_lo[0] (memory-region)
  /pci_bridge_vga_mem[0] (memory-region)
  /pcie.0 (PCIE)

Signed-off-by: Daniel Henrique Barboza 
---
 hw/pci-host/pnv_phb3.c | 2 +-
 hw/pci-host/pnv_phb4.c | 2 +-
 hw/ppc/pnv.c   | 7 ++-
 include/hw/ppc/pnv.h   | 2 +-
 4 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c
index 26ac9b7123..4ba660f8b9 100644
--- a/hw/pci-host/pnv_phb3.c
+++ b/hw/pci-host/pnv_phb3.c
@@ -1052,7 +1052,7 @@ static void pnv_phb3_realize(DeviceState *dev, Error 
**errp)
 
 pci_setup_iommu(pci->bus, pnv_phb3_dma_iommu, phb);
 
-pnv_phb_attach_root_port(PCI_HOST_BRIDGE(phb), TYPE_PNV_PHB3_ROOT_PORT);
+pnv_phb_attach_root_port(pci, TYPE_PNV_PHB3_ROOT_PORT, phb->phb_id);
 }
 
 void pnv_phb3_update_regions(PnvPHB3 *phb)
diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index 23ad8de7ee..ffd9d8a947 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -1585,7 +1585,7 @@ static void pnv_phb4_realize(DeviceState *dev, Error 
**errp)
 pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
 
 /* Add a single Root port if running with defaults */
-pnv_phb_attach_root_port(pci, pecc->rp_model);
+pnv_phb_attach_root_port(pci, pecc->rp_model, phb->phb_id);
 
 /* Setup XIVE Source */
 if (phb->big_phb) {
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 7c08a78d6c..40e0cbd84d 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -1190,9 +1190,14 @@ static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error 
**errp)
 }
 
 /* Attach a root port device */
-void pnv_phb_attach_root_port(PCIHostState *pci, const char *name)
+void pnv_phb_attach_root_port(PCIHostState *pci, const char *name, int index)
 {
 PCIDevice *root = pci_new(PCI_DEVFN(0, 0), name);
+g_autofree char *default_id = g_strdup_printf("%s[%d]", name, index);
+const char *dev_id = DEVICE(root)->id;
+
+object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id,
+  OBJECT(root));
 
 pci_realize_and_unref(root, pci->bus, &error_fatal);
 }
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index 86cb7d7f97..033890a23f 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -189,7 +189,7 @@ DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER10,
  TYPE_PNV_CHIP_POWER10)
 
 PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir);
-void pnv_phb_attach_root_port(PCIHostState *pci, const char *name);
+void pnv_phb_attach_root_port(PCIHostState *pci, const char *name, int index);
 
 #define TYPE_PNV_MACHINE   MACHINE_TYPE_NAME("powernv")
 typedef struct PnvMachineClass PnvMachineClass;
-- 
2.36.1




[PATCH 03/11] ppc/pnv: use dev->parent_bus->parent to get the PHB

2022-06-13 Thread Daniel Henrique Barboza
It is not advisable to execute an object_dynamic_cast() to poke into
bus->qbus.parent and follow it up with a C cast into the PnvPHB type we
think we got.

A better way is to access the PnvPHB object via a QOM macro accessing
the existing parent links of the DeviceState. For a given
pnv-phb3/4-root-port 'dev', dev->parent_bus will give us the PHB bus,
and dev->parent_bus->parent is the PHB. Use the adequate QOM macro to
assert the type, and keep the NULL check in case we didn't get the
object we were expecting.

Signed-off-by: Daniel Henrique Barboza 
---
 hw/pci-host/pnv_phb3.c | 10 +++---
 hw/pci-host/pnv_phb4.c | 10 +++---
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c
index 4ba660f8b9..7901d8172c 100644
--- a/hw/pci-host/pnv_phb3.c
+++ b/hw/pci-host/pnv_phb3.c
@@ -1139,12 +1139,16 @@ static void pnv_phb3_root_port_realize(DeviceState 
*dev, Error **errp)
 {
 PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev);
 PCIDevice *pci = PCI_DEVICE(dev);
-PCIBus *bus = pci_get_bus(pci);
 PnvPHB3 *phb = NULL;
 Error *local_err = NULL;
 
-phb = (PnvPHB3 *) object_dynamic_cast(OBJECT(bus->qbus.parent),
-  TYPE_PNV_PHB3);
+/*
+ * dev->parent_bus gives access to the pnv-phb-root bus.
+ * The PnvPHB3 is the owner (parent) of the bus.
+ */
+if (dev && dev->parent_bus) {
+phb = PNV_PHB3(dev->parent_bus->parent);
+}
 
 if (!phb) {
 error_setg(errp,
diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index ffd9d8a947..bae9398d86 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -1782,12 +1782,16 @@ static void pnv_phb4_root_port_realize(DeviceState 
*dev, Error **errp)
 {
 PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev);
 PCIDevice *pci = PCI_DEVICE(dev);
-PCIBus *bus = pci_get_bus(pci);
 PnvPHB4 *phb = NULL;
 Error *local_err = NULL;
 
-phb = (PnvPHB4 *) object_dynamic_cast(OBJECT(bus->qbus.parent),
-  TYPE_PNV_PHB4);
+/*
+ * dev->parent_bus gives access to the pnv-phb-root bus.
+ * The PnvPHB4 is the owner (parent) of the bus.
+ */
+if (dev && dev->parent_bus) {
+phb = PNV_PHB4(dev->parent_bus->parent);
+}
 
 if (!phb) {
 error_setg(errp, "%s must be connected to pnv-phb4 buses", dev->id);
-- 
2.36.1




[PATCH 00/11] pnv-phb related cleanups

2022-06-13 Thread Daniel Henrique Barboza
Hi,

I decided to make some cleanups/fixes after the feedback received in the
v2 of the pnv-phb proxy series [1]. A lot of the reviews and comment were
related to the current state of the code instead of what was being done
there.

With this series we want to:

- provide a better base for proxy pnv-phb series, fixing and changing code
that is already in place;
- make a common logic that applies to both default and user created devices.
There's no reason to make distinctions between them aside from what we will
already have to deal with.


After these cleanups we'll be able to simplify the work required in [1].

[1] https://lists.gnu.org/archive/html/qemu-devel/2022-05/msg06254.html

Daniel Henrique Barboza (11):
  ppc/pnv: move root port attach to pnv_phb4_realize()
  ppc/pnv: attach phb3/phb4 root ports in QOM tree
  ppc/pnv: use dev->parent_bus->parent to get the PHB
  ppc/pnv: use dev instead of pci->qdev in root_port_realize()
  ppc/pnv: make pnv_ics_get() use the chip8->phbs[] array
  ppc/pnv: make pnv_ics_resend() use chip8->phbs[]
  ppc/pnv: make pnv_chip_power8_pic_print_info() use chip8->phbs[]
  ppc/pnv: turn chip8->phbs[] into a PnvPHB3* array
  ppc/pnv: add PHB object/bus parenting helpers
  ppc/pnv: move PHB3 initialization to realize time
  ppc/pnv: move PHB4 parent fixup to phb4_realize()

 hw/pci-host/pnv_phb3.c |  30 +++--
 hw/pci-host/pnv_phb4.c |  31 +++--
 hw/pci-host/pnv_phb4_pec.c |   4 --
 hw/ppc/pnv.c   | 127 +
 include/hw/ppc/pnv.h   |  10 ++-
 5 files changed, 128 insertions(+), 74 deletions(-)

-- 
2.36.1




[PATCH 06/11] ppc/pnv: make pnv_ics_resend() use chip8->phbs[]

2022-06-13 Thread Daniel Henrique Barboza
pnv_ics_resend() is scrolling through all the child objects of the chip
to search for the PHBs. It's faster and simpler to just use the phbs[]
array.

pnv_ics_resend_child() was folded into pnv_ics_resend() since it's too
simple to justify its own function.

Signed-off-by: Daniel Henrique Barboza 
---
 hw/ppc/pnv.c | 22 +++---
 1 file changed, 7 insertions(+), 15 deletions(-)

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 05a8d5034f..d70deffa1d 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -1993,28 +1993,20 @@ PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t 
chip_id)
 return NULL;
 }
 
-static int pnv_ics_resend_child(Object *child, void *opaque)
-{
-PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3);
-
-if (phb3) {
-ics_resend(&phb3->lsis);
-ics_resend(ICS(&phb3->msis));
-}
-return 0;
-}
-
 static void pnv_ics_resend(XICSFabric *xi)
 {
 PnvMachineState *pnv = PNV_MACHINE(xi);
-int i;
+int i, j;
 
 for (i = 0; i < pnv->num_chips; i++) {
-PnvChip *chip = pnv->chips[i];
 Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
 
-ics_resend(&chip8->psi.ics);
-object_child_foreach(OBJECT(chip), pnv_ics_resend_child, NULL);
+for (j = 0; j < chip8->num_phbs; j++) {
+PnvPHB3 *phb3 = &chip8->phbs[j];
+
+ics_resend(&phb3->lsis);
+ics_resend(ICS(&phb3->msis));
+}
 }
 }
 
-- 
2.36.1




[PATCH 08/11] ppc/pnv: turn chip8->phbs[] into a PnvPHB3* array

2022-06-13 Thread Daniel Henrique Barboza
When enabling user created PHBs (a change reverted by commit 9c10d86fee)
we were handling PHBs created by default versus by the user in different
manners. The only difference between these PHBs is that one will have a
valid phb3->chip that is assigned during pnv_chip_power8_realize(),
while the user created needs to search which chip it belongs to.

Aside from that there shouldn't be any difference. Making the default
PHBs behave in line with the user created ones will make it easier to
re-introduce them later on. It will also make the code easier to follow
since we are dealing with them in equal manner.

The first step is to turn chip8->phbs[] into a PnvPHB3 pointer array.
This will allow us to assign user created PHBs into it later on. The way
we initilize the default case is now more in line with that would happen
with the user created case: the object is created, parented by the chip
because pnv_xscom_dt() relies on it, and then assigned to the array.

Signed-off-by: Daniel Henrique Barboza 
---
 hw/ppc/pnv.c | 19 ++-
 include/hw/ppc/pnv.h |  6 +-
 2 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 5e3323e950..6ce9e94e05 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -660,7 +660,7 @@ static void pnv_chip_power8_pic_print_info(PnvChip *chip, 
Monitor *mon)
 ics_pic_print_info(&chip8->psi.ics, mon);
 
 for (i = 0; i < chip8->num_phbs; i++) {
-PnvPHB3 *phb3 = &chip8->phbs[i];
+PnvPHB3 *phb3 = chip8->phbs[i];
 
 pnv_phb3_msi_pic_print_info(&phb3->msis, mon);
 ics_pic_print_info(&phb3->lsis, mon);
@@ -1149,7 +1149,16 @@ static void pnv_chip_power8_instance_init(Object *obj)
 chip8->num_phbs = pcc->num_phbs;
 
 for (i = 0; i < chip8->num_phbs; i++) {
-object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB3);
+PnvPHB3 *phb3 = PNV_PHB3(object_new(TYPE_PNV_PHB3));
+
+/*
+ * We need the chip to parent the PHB to allow the DT
+ * to build correctly (via pnv_xscom_dt()).
+ *
+ * TODO: the PHB should be parented by a PEC device.
+ */
+object_property_add_child(obj, "phb[*]", OBJECT(phb3));
+chip8->phbs[i] = phb3;
 }
 
 }
@@ -1278,7 +1287,7 @@ static void pnv_chip_power8_realize(DeviceState *dev, 
Error **errp)
 
 /* PHB3 controllers */
 for (i = 0; i < chip8->num_phbs; i++) {
-PnvPHB3 *phb = &chip8->phbs[i];
+PnvPHB3 *phb = chip8->phbs[i];
 
 object_property_set_int(OBJECT(phb), "index", i, &error_fatal);
 object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id,
@@ -1963,7 +1972,7 @@ static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
 }
 
 for (j = 0; j < chip8->num_phbs; j++) {
-pnv_ics_get_phb_ics(&chip8->phbs[j], &args);
+pnv_ics_get_phb_ics(chip8->phbs[j], &args);
 
 if (args.ics) {
 return args.ics;
@@ -1996,7 +2005,7 @@ static void pnv_ics_resend(XICSFabric *xi)
 Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
 
 for (j = 0; j < chip8->num_phbs; j++) {
-PnvPHB3 *phb3 = &chip8->phbs[j];
+PnvPHB3 *phb3 = chip8->phbs[j];
 
 ics_resend(&phb3->lsis);
 ics_resend(ICS(&phb3->msis));
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index 033890a23f..11f1089289 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -80,7 +80,11 @@ struct Pnv8Chip {
 PnvHomer homer;
 
 #define PNV8_CHIP_PHB3_MAX 4
-PnvPHB3  phbs[PNV8_CHIP_PHB3_MAX];
+/*
+ * The array is used to allow quick access to the phbs by
+ * pnv_ics_get_child() and pnv_ics_resend_child().
+ */
+PnvPHB3  *phbs[PNV8_CHIP_PHB3_MAX];
 uint32_t num_phbs;
 
 XICSFabric*xics;
-- 
2.36.1




  1   2   3   >