Re: [PATCH v6 2/2] i386: Add notify VM exit support

2022-09-18 Thread Chenyi Qiang




On 9/17/2022 5:57 AM, Peter Xu wrote:

On Thu, Sep 15, 2022 at 05:28:39PM +0800, Chenyi Qiang wrote:

There are cases that malicious virtual machine can cause CPU stuck (due
to event windows don't open up), e.g., infinite loop in microcode when
nested #AC (CVE-2015-5307). No event window means no event (NMI, SMI and
IRQ) can be delivered. It leads the CPU to be unavailable to host or
other VMs. Notify VM exit is introduced to mitigate such kind of
attacks, which will generate a VM exit if no event window occurs in VM
non-root mode for a specified amount of time (notify window).

A new KVM capability KVM_CAP_X86_NOTIFY_VMEXIT is exposed to user space
so that the user can query the capability and set the expected notify
window when creating VMs. The format of the argument when enabling this
capability is as follows:
   Bit 63:32 - notify window specified in qemu command
   Bit 31:0  - some flags (e.g. KVM_X86_NOTIFY_VMEXIT_ENABLED is set to
   enable the feature.)

Because there are some concerns, e.g. a notify VM exit may happen with
VM_CONTEXT_INVALID set in exit qualification (no cases are anticipated
that would set this bit), which means VM context is corrupted. To avoid
the false positive and a well-behaved guest gets killed, make this
feature disabled by default. Users can enable the feature by a new
machine property:
 qemu -machine notify_vmexit=on,notify_window=0 ...

Note that notify_window is only valid when notify_vmexit is on. The valid
range of notify_window is non-negative. It is even safe to set it to zero
since there's an internal hardware threshold to be added to ensure no false
positive.

A new KVM exit reason KVM_EXIT_NOTIFY is defined for notify VM exit. If
it happens with VM_INVALID_CONTEXT, hypervisor exits to user space to
inform the fatal case. Then user space can inject a SHUTDOWN event to
the target vcpu. This is implemented by injecting a sythesized triple
fault event.

Signed-off-by: Chenyi Qiang 
---
  hw/i386/x86.c | 45 +++
  include/hw/i386/x86.h |  5 +
  qemu-options.hx   | 10 +-
  target/i386/kvm/kvm.c | 28 +++
  4 files changed, 87 insertions(+), 1 deletion(-)

diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index 050eedc0c8..1eccbd3deb 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -1379,6 +1379,37 @@ static void machine_set_sgx_epc(Object *obj, Visitor *v, 
const char *name,
  qapi_free_SgxEPCList(list);
  }
  
+static bool x86_machine_get_notify_vmexit(Object *obj, Error **errp)

+{
+X86MachineState *x86ms = X86_MACHINE(obj);
+
+return x86ms->notify_vmexit;
+}
+
+static void x86_machine_set_notify_vmexit(Object *obj, bool value, Error 
**errp)
+{
+X86MachineState *x86ms = X86_MACHINE(obj);
+
+x86ms->notify_vmexit = value;
+}
+
+static void x86_machine_get_notify_window(Object *obj, Visitor *v,
+const char *name, void *opaque, Error **errp)
+{
+X86MachineState *x86ms = X86_MACHINE(obj);
+uint32_t notify_window = x86ms->notify_window;
+
+visit_type_uint32(v, name, _window, errp);
+}
+
+static void x86_machine_set_notify_window(Object *obj, Visitor *v,
+   const char *name, void *opaque, Error **errp)
+{
+X86MachineState *x86ms = X86_MACHINE(obj);
+
+visit_type_uint32(v, name, >notify_window, errp);
+}
+
  static void x86_machine_initfn(Object *obj)
  {
  X86MachineState *x86ms = X86_MACHINE(obj);
@@ -1392,6 +1423,8 @@ static void x86_machine_initfn(Object *obj)
  x86ms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8);
  x86ms->bus_lock_ratelimit = 0;
  x86ms->above_4g_mem_start = 4 * GiB;
+x86ms->notify_vmexit = false;
+x86ms->notify_window = 0;
  }
  
  static void x86_machine_class_init(ObjectClass *oc, void *data)

@@ -1461,6 +1494,18 @@ static void x86_machine_class_init(ObjectClass *oc, void 
*data)
  NULL, NULL);
  object_class_property_set_description(oc, "sgx-epc",
  "SGX EPC device");
+
+object_class_property_add(oc, X86_MACHINE_NOTIFY_WINDOW, "uint32_t",
+  x86_machine_get_notify_window,
+  x86_machine_set_notify_window, NULL, NULL);
+object_class_property_set_description(oc, X86_MACHINE_NOTIFY_WINDOW,
+"Set the notify window required by notify VM exit");
+
+object_class_property_add_bool(oc, X86_MACHINE_NOTIFY_VMEXIT,
+   x86_machine_get_notify_vmexit,
+   x86_machine_set_notify_vmexit);
+object_class_property_set_description(oc, X86_MACHINE_NOTIFY_VMEXIT,
+"Enable notify VM exit");
  }
  
  static const TypeInfo x86_machine_info = {

diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
index 62fa5774f8..5707329fa7 100644
--- a/include/hw/i386/x86.h
+++ b/include/hw/i386/x86.h
@@ -85,6 +85,9 @@ struct X86MachineState {
   * which means no limitation 

[PATCH 3/4] crypto: Support export akcipher to pkcs8

2022-09-18 Thread Lei He
crypto: support export RSA private keys with PKCS#8 standard.
So that users can upload this private key to linux kernel.

Signed-off-by: lei he 
---
 crypto/akcipher.c | 17 +
 crypto/rsakey.c   | 42 ++
 crypto/rsakey.h   | 11 ++-
 include/crypto/akcipher.h | 21 +
 4 files changed, 90 insertions(+), 1 deletion(-)

diff --git a/crypto/akcipher.c b/crypto/akcipher.c
index ad88379c1e..fc9d4b2a6d 100644
--- a/crypto/akcipher.c
+++ b/crypto/akcipher.c
@@ -22,6 +22,7 @@
 #include "qemu/osdep.h"
 #include "crypto/akcipher.h"
 #include "akcipherpriv.h"
+#include "der.h"
 
 #if defined(CONFIG_GCRYPT)
 #include "akcipher-gcrypt.c.inc"
@@ -106,3 +107,19 @@ void qcrypto_akcipher_free(QCryptoAkCipher *akcipher)
 
 drv->free(akcipher);
 }
+
+int qcrypto_akcipher_export_p8info(const QCryptoAkCipherOptions *opts,
+   uint8_t *key, size_t keylen,
+   uint8_t **dst, size_t *dst_len,
+   Error **errp)
+{
+switch (opts->alg) {
+case QCRYPTO_AKCIPHER_ALG_RSA:
+qcrypto_akcipher_rsakey_export_p8info(key, keylen, dst, dst_len);
+return 0;
+
+default:
+error_setg(errp, "Unsupported algorithm: %u", opts->alg);
+return -1;
+}
+}
diff --git a/crypto/rsakey.c b/crypto/rsakey.c
index cc40e072f0..7d6f273aef 100644
--- a/crypto/rsakey.c
+++ b/crypto/rsakey.c
@@ -19,6 +19,8 @@
  *
  */
 
+#include "qemu/osdep.h"
+#include "der.h"
 #include "rsakey.h"
 
 void qcrypto_akcipher_rsakey_free(QCryptoAkCipherRSAKey *rsa_key)
@@ -37,6 +39,46 @@ void qcrypto_akcipher_rsakey_free(QCryptoAkCipherRSAKey 
*rsa_key)
 g_free(rsa_key);
 }
 
+/**
+ * PKCS#8 private key info for RSA
+ *
+ * PrivateKeyInfo ::= SEQUENCE {
+ * version INTEGER,
+ * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
+ * privateKey  OCTET STRING,
+ * attributes  [0] IMPLICIT Attributes OPTIONAL
+ * }
+ */
+void qcrypto_akcipher_rsakey_export_p8info(const uint8_t *key,
+   size_t keylen,
+   uint8_t **dst,
+   size_t *dlen)
+{
+QCryptoEncodeContext *ctx = qcrypto_der_encode_ctx_new();
+uint8_t version = 0;
+
+qcrypto_der_encode_seq_begin(ctx);
+
+/* version */
+qcrypto_der_encode_int(ctx, , sizeof(version));
+
+/* algorithm identifier */
+qcrypto_der_encode_seq_begin(ctx);
+qcrypto_der_encode_oid(ctx, (uint8_t *)QCRYPTO_OID_rsaEncryption,
+   sizeof(QCRYPTO_OID_rsaEncryption) - 1);
+qcrypto_der_encode_null(ctx);
+qcrypto_der_encode_seq_end(ctx);
+
+/* RSA private key */
+qcrypto_der_encode_octet_str(ctx, key, keylen);
+
+qcrypto_der_encode_seq_end(ctx);
+
+*dlen = qcrypto_der_encode_ctx_buffer_len(ctx);
+*dst = g_malloc(*dlen);
+qcrypto_der_encode_ctx_flush_and_free(ctx, *dst);
+}
+
 #if defined(CONFIG_NETTLE) && defined(CONFIG_HOGWEED)
 #include "rsakey-nettle.c.inc"
 #else
diff --git a/crypto/rsakey.h b/crypto/rsakey.h
index 974b76f659..00b3eccec7 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"
 
@@ -84,6 +83,16 @@ QCryptoAkCipherRSAKey *qcrypto_akcipher_rsakey_parse(
 QCryptoAkCipherKeyType type,
 const uint8_t *key, size_t keylen, Error **errp);
 
+/**
+ * qcrypto_akcipher_rsakey_export_as_p8info:
+ *
+ * Export RSA private key to PKCS#8 private key info.
+ */
+void qcrypto_akcipher_rsakey_export_p8info(const uint8_t *key,
+   size_t keylen,
+   uint8_t **dst,
+   size_t *dlen);
+
 void qcrypto_akcipher_rsakey_free(QCryptoAkCipherRSAKey *key);
 
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoAkCipherRSAKey,
diff --git a/include/crypto/akcipher.h b/include/crypto/akcipher.h
index 51f5fa2774..214e58ca47 100644
--- a/include/crypto/akcipher.h
+++ b/include/crypto/akcipher.h
@@ -153,6 +153,27 @@ int qcrypto_akcipher_max_dgst_len(QCryptoAkCipher 
*akcipher);
  */
 void qcrypto_akcipher_free(QCryptoAkCipher *akcipher);
 
+/**
+ * qcrypto_akcipher_export_p8info:
+ * @opts: the options of the akcipher to be exported.
+ * @key: the original key of the akcipher to be exported.
+ * @keylen: length of the 'key'
+ * @dst: output parameter, if export succeed, *dst is set to the
+ * PKCS#8 encoded private key, caller MUST free this key with
+ * g_free after use.
+ * @dst_len: output parameter, indicates the length of PKCS#8 encoded
+ * key.
+ *
+ * Export the akcipher into DER encoded pkcs#8 private key info, expects
+ * |key| stores a valid asymmetric PRIVATE key.
+ *
+ * Returns: 0 for succeed, otherwise -1 is returned.
+ */
+int 

[PATCH 4/4] cryptodev: Add a lkcf-backend for cryptodev

2022-09-18 Thread Lei He
cryptodev: Added a new type of backend named lkcf-backend for
cryptodev. This backend upload asymmetric keys to linux kernel,
and let kernel do the accelerations if possible.
The lkcf stands for Linux Kernel Cryptography Framework.

Signed-off-by: lei he 
---
 backends/cryptodev-lkcf.c  | 640 +
 backends/meson.build   |   3 +
 include/sysemu/cryptodev.h |   1 +
 qapi/qom.json  |   2 +
 4 files changed, 646 insertions(+)
 create mode 100644 backends/cryptodev-lkcf.c

diff --git a/backends/cryptodev-lkcf.c b/backends/cryptodev-lkcf.c
new file mode 100644
index 00..61aef5074e
--- /dev/null
+++ b/backends/cryptodev-lkcf.c
@@ -0,0 +1,640 @@
+/*
+ * QEMU Cryptodev backend for QEMU cipher APIs
+ *
+ * Copyright (c) 2022 Bytedance.Inc
+ *
+ * Authors:
+ *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 "qemu/osdep.h"
+#include "crypto/cipher.h"
+#include "crypto/akcipher.h"
+#include "qapi/error.h"
+#include "qemu/main-loop.h"
+#include "qemu/thread.h"
+#include "qemu/error-report.h"
+#include "qemu/queue.h"
+#include "qom/object.h"
+#include "sysemu/cryptodev.h"
+#include "standard-headers/linux/virtio_crypto.h"
+
+#include 
+#include 
+
+/**
+ * @TYPE_CRYPTODEV_BACKEND_LKCF:
+ * name of backend that uses linux kernel crypto framework
+ */
+#define TYPE_CRYPTODEV_BACKEND_LKCF "cryptodev-backend-lkcf"
+
+OBJECT_DECLARE_SIMPLE_TYPE(CryptoDevBackendLKCF, CRYPTODEV_BACKEND_LKCF)
+
+#define INVALID_KEY_ID -1
+#define MAX_SESSIONS 256
+#define NR_WORKER_THREAD 64
+
+#define KCTL_KEY_TYPE_PKEY "asymmetric"
+/**
+ * Here the key is uploaded to the thread-keyring of worker thread, at least
+ * util linux-6.0:
+ * 1. process keyring seems to behave unexpectedly if main-thread does not
+ * create the keyring before creating any other thread.
+ * 2. at present, the guest kernel never perform multiple operations on a
+ * session.
+ * 3. it can reduce the load of the main-loop because the key passed by the
+ * guest kernel has been already checked.
+ */
+#define KCTL_KEY_RING KEY_SPEC_THREAD_KEYRING
+
+typedef struct CryptoDevBackendLKCFSession {
+uint8_t *key;
+size_t keylen;
+QCryptoAkCipherKeyType keytype;
+QCryptoAkCipherOptions akcipher_opts;
+} CryptoDevBackendLKCFSession;
+
+typedef struct CryptoDevBackendLKCF CryptoDevBackendLKCF;
+typedef struct CryptoDevLKCFTask CryptoDevLKCFTask;
+struct CryptoDevLKCFTask {
+CryptoDevBackendLKCFSession *sess;
+CryptoDevBackendOpInfo *op_info;
+CryptoDevCompletionFunc cb;
+void *opaque;
+int status;
+CryptoDevBackendLKCF *lkcf;
+QSIMPLEQ_ENTRY(CryptoDevLKCFTask) queue;
+};
+
+typedef struct CryptoDevBackendLKCF {
+CryptoDevBackend parent_obj;
+CryptoDevBackendLKCFSession *sess[MAX_SESSIONS];
+QSIMPLEQ_HEAD(, CryptoDevLKCFTask) requests;
+QSIMPLEQ_HEAD(, CryptoDevLKCFTask) responses;
+QemuMutex mutex;
+QemuCond cond;
+QemuMutex rsp_mutex;
+
+/**
+ * There is no async interface for asymmetric keys like AF_ALG sockets,
+ * we don't seem to have better way than create a lots of thread.
+ */
+QemuThread worker_threads[NR_WORKER_THREAD];
+bool running;
+int eventfd;
+} CryptoDevBackendLKCF;
+
+static void *cryptodev_lkcf_worker(void *arg);
+static int cryptodev_lkcf_close_session(CryptoDevBackend *backend,
+uint64_t session_id,
+uint32_t queue_index,
+CryptoDevCompletionFunc cb,
+void *opaque);
+
+static void cryptodev_lkcf_handle_response(void *opaque)
+{
+CryptoDevBackendLKCF *lkcf = (CryptoDevBackendLKCF *)opaque;
+QSIMPLEQ_HEAD(, CryptoDevLKCFTask) responses;
+CryptoDevLKCFTask *task, *next;
+eventfd_t nevent;
+
+QSIMPLEQ_INIT();
+eventfd_read(lkcf->eventfd, );
+
+qemu_mutex_lock(>rsp_mutex);
+QSIMPLEQ_PREPEND(, >responses);
+qemu_mutex_unlock(>rsp_mutex);
+
+QSIMPLEQ_FOREACH_SAFE(task, , queue, next) {
+if (task->cb) {
+task->cb(task->opaque, task->status);
+}
+g_free(task);
+}
+}
+
+static int cryptodev_lkcf_set_op_desc(QCryptoAkCipherOptions *opts,
+  char *key_desc,
+

[PATCH 1/4] virtio-crypto: Support asynchronous mode

2022-09-18 Thread Lei He
virtio-crypto: Modify the current interface of virtio-crypto
device to support asynchronous mode.

Signed-off-by: lei he 
---
 backends/cryptodev-builtin.c|  69 ++---
 backends/cryptodev-vhost-user.c |  51 +--
 backends/cryptodev.c|  44 +++---
 hw/virtio/virtio-crypto.c   | 324 ++--
 include/sysemu/cryptodev.h  |  60 +---
 5 files changed, 336 insertions(+), 212 deletions(-)

diff --git a/backends/cryptodev-builtin.c b/backends/cryptodev-builtin.c
index 125cbad1d3..cda6ca3b71 100644
--- a/backends/cryptodev-builtin.c
+++ b/backends/cryptodev-builtin.c
@@ -355,42 +355,62 @@ static int cryptodev_builtin_create_akcipher_session(
 return index;
 }
 
-static int64_t cryptodev_builtin_create_session(
+static int cryptodev_builtin_create_session(
CryptoDevBackend *backend,
CryptoDevBackendSessionInfo *sess_info,
-   uint32_t queue_index, Error **errp)
+   uint32_t queue_index,
+   CryptoDevCompletionFunc cb,
+   void *opaque)
 {
 CryptoDevBackendBuiltin *builtin =
   CRYPTODEV_BACKEND_BUILTIN(backend);
 CryptoDevBackendSymSessionInfo *sym_sess_info;
 CryptoDevBackendAsymSessionInfo *asym_sess_info;
+int ret, status;
+Error *local_error = NULL;
 
 switch (sess_info->op_code) {
 case VIRTIO_CRYPTO_CIPHER_CREATE_SESSION:
 sym_sess_info = _info->u.sym_sess_info;
-return cryptodev_builtin_create_cipher_session(
-   builtin, sym_sess_info, errp);
+ret = cryptodev_builtin_create_cipher_session(
+builtin, sym_sess_info, _error);
+break;
 
 case VIRTIO_CRYPTO_AKCIPHER_CREATE_SESSION:
 asym_sess_info = _info->u.asym_sess_info;
-return cryptodev_builtin_create_akcipher_session(
-   builtin, asym_sess_info, errp);
+ret = cryptodev_builtin_create_akcipher_session(
+   builtin, asym_sess_info, _error);
+break;
 
 case VIRTIO_CRYPTO_HASH_CREATE_SESSION:
 case VIRTIO_CRYPTO_MAC_CREATE_SESSION:
 default:
-error_setg(errp, "Unsupported opcode :%" PRIu32 "",
+error_setg(_error, "Unsupported opcode :%" PRIu32 "",
sess_info->op_code);
-return -1;
+return -VIRTIO_CRYPTO_NOTSUPP;
 }
 
-return -1;
+if (local_error) {
+error_report_err(local_error);
+}
+if (ret < 0) {
+status = -VIRTIO_CRYPTO_ERR;
+} else {
+sess_info->session_id = ret;
+status = VIRTIO_CRYPTO_OK;
+}
+if (cb) {
+cb(opaque, status);
+}
+return 0;
 }
 
 static int cryptodev_builtin_close_session(
CryptoDevBackend *backend,
uint64_t session_id,
-   uint32_t queue_index, Error **errp)
+   uint32_t queue_index,
+   CryptoDevCompletionFunc cb,
+   void *opaque)
 {
 CryptoDevBackendBuiltin *builtin =
   CRYPTODEV_BACKEND_BUILTIN(backend);
@@ -407,6 +427,9 @@ static int cryptodev_builtin_close_session(
 
 g_free(session);
 builtin->sessions[session_id] = NULL;
+if (cb) {
+cb(opaque, VIRTIO_CRYPTO_OK);
+}
 return 0;
 }
 
@@ -506,7 +529,9 @@ static int cryptodev_builtin_asym_operation(
 static int cryptodev_builtin_operation(
  CryptoDevBackend *backend,
  CryptoDevBackendOpInfo *op_info,
- uint32_t queue_index, Error **errp)
+ uint32_t queue_index,
+ CryptoDevCompletionFunc cb,
+ void *opaque)
 {
 CryptoDevBackendBuiltin *builtin =
   CRYPTODEV_BACKEND_BUILTIN(backend);
@@ -514,11 +539,12 @@ static int cryptodev_builtin_operation(
 CryptoDevBackendSymOpInfo *sym_op_info;
 CryptoDevBackendAsymOpInfo *asym_op_info;
 enum CryptoDevBackendAlgType algtype = op_info->algtype;
-int ret = -VIRTIO_CRYPTO_ERR;
+int status = -VIRTIO_CRYPTO_ERR;
+Error *local_error = NULL;
 
 if (op_info->session_id >= MAX_NUM_SESSIONS ||
   builtin->sessions[op_info->session_id] == NULL) {
-error_setg(errp, "Cannot find a valid session id: %" PRIu64 "",
+error_setg(_error, "Cannot find a valid session id: %" PRIu64 "",
op_info->session_id);
 return -VIRTIO_CRYPTO_INVSESS;
 }
@@ -526,14 +552,21 @@ static int cryptodev_builtin_operation(
 sess = builtin->sessions[op_info->session_id];
 if (algtype == CRYPTODEV_BACKEND_ALG_SYM) {
 sym_op_info = op_info->u.sym_op_info;
-ret = cryptodev_builtin_sym_operation(sess, sym_op_info, errp);
+status = cryptodev_builtin_sym_operation(sess, sym_op_info,
+ _error);
 } else if (algtype == CRYPTODEV_BACKEND_ALG_ASYM) {
 asym_op_info = op_info->u.asym_op_info;
-ret = 

[PATCH 2/4] crypto: Support DER encodings

2022-09-18 Thread Lei He
Add encoding interfaces for DER encoding:
1. support decoding of 'bit string', 'octet string', 'object id'
and 'context specific tag' for DER encoder.
2. implemented a simple DER encoder.
3. add more testsuits for DER encoder.

Signed-off-by: lei he 
---
 crypto/der.c | 307 +++
 crypto/der.h | 211 -
 tests/unit/test-crypto-der.c | 126 ++
 3 files changed, 597 insertions(+), 47 deletions(-)

diff --git a/crypto/der.c b/crypto/der.c
index f877390bbb..dab3fe4f24 100644
--- a/crypto/der.c
+++ b/crypto/der.c
@@ -22,20 +22,93 @@
 #include "qemu/osdep.h"
 #include "crypto/der.h"
 
+typedef struct QCryptoDerEncodeNode {
+uint8_t tag;
+struct QCryptoDerEncodeNode *parent;
+struct QCryptoDerEncodeNode *next;
+/* for constructed type, data is null */
+const uint8_t *data;
+size_t dlen;
+} QCryptoDerEncodeNode;
+
+typedef struct QCryptoEncodeContext {
+QCryptoDerEncodeNode root;
+QCryptoDerEncodeNode *current_parent;
+QCryptoDerEncodeNode *tail;
+} QCryptoEncodeContext;
+
 enum QCryptoDERTypeTag {
 QCRYPTO_DER_TYPE_TAG_BOOL = 0x1,
 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))
+
+/**
+ * qcrypto_der_encode_length:
+ * @src_len: the length of source data
+ * @dst: distination to save the encoded 'length', if dst is NULL, only compute
+ * the expected buffer size in bytes.
+ * @dst_len: output parameter, indicates how many bytes wrote.
+ *
+ * Encode the 'length' part of TLV tuple.
+ */
+static void qcrypto_der_encode_length(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 = 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 = length_bytes + 1;
+}
+if (!dst) {
+return;
+}
+*dst++ = header_byte;
+/* Bigendian length bytes */
+for (; length_bytes > 0; length_bytes--) {
+*dst++ = ((src_len >> (length_bytes - 1) * 8) & 0xFF);
+}
+}
+
 static uint8_t qcrypto_der_peek_byte(const uint8_t **data, size_t *dlen)
 {
 return **data;
@@ -150,40 +223,230 @@ 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;
 
-return qcrypto_der_extract_data(data, dlen, cb, ctx, errp);
+error:
+*data = saved_data;
+*dlen = saved_dlen;
+return -1;
+}
+

[PATCH 0/4] Add a new backend for cryptodev

2022-09-18 Thread Lei He
This patch adds a new backend called LKCF to cryptodev, LKCF stands
for Linux Kernel Cryptography Framework. If a cryptographic
accelerator that supports LKCF is installed on the the host (you can
see which algorithms are supported in host's LKCF by executing
'cat /proc/crypto'), then RSA operations can be offloaded.
More background info can refer to: https://lwn.net/Articles/895399/,
'keyctl[5]' in the picture.

This patch:
1. Modified some interfaces of cryptodev and cryptodev-backend to
support asynchronous requests.
2. Extended the DER encoder in crypto, so that we can export the
RSA private key into PKCS#8 format and upload it to host kernel.
3. Added a new backend for cryptodev.

I tested the backend with a QAT card, the qps of RSA-2048-decryption
is about 25k/s, and the main-loop becomes the bottleneck. The qps
using OpenSSL directly is about 6k/s (with 6 vCPUs). We will support 
IO-thread for cryptodev in another series later.

Lei He (4):
  virtio-crypto: Support asynchronous mode
  crypto: Support DER encodings
  crypto: Support export akcipher to pkcs8
  cryptodev: Add a lkcf-backend for cryptodev

 backends/cryptodev-builtin.c|  69 +++--
 backends/cryptodev-lkcf.c   | 620 
 backends/cryptodev-vhost-user.c |  51 +++-
 backends/cryptodev.c|  44 +--
 backends/meson.build|   3 +
 crypto/akcipher.c   |  17 ++
 crypto/der.c| 307 ++--
 crypto/der.h| 211 +-
 crypto/rsakey.c |  42 +++
 crypto/rsakey.h |  11 +-
 hw/virtio/virtio-crypto.c   | 324 -
 include/crypto/akcipher.h   |  21 ++
 include/sysemu/cryptodev.h  |  61 ++--
 qapi/qom.json   |   2 +
 tests/unit/test-crypto-der.c| 126 ++--
 15 files changed, 1649 insertions(+), 260 deletions(-)
 create mode 100644 backends/cryptodev-lkcf.c

--
2.11.0




Re: [PATCH v9 1/7] include: add zoned device structs

2022-09-18 Thread Sam Li
Stefan Hajnoczi  于2022年9月18日周日 04:17写道:
>
> On Thu, Sep 15, 2022 at 06:06:38PM +0800, Sam Li wrote:
> > Eric Blake  于2022年9月15日周四 16:05写道:
> > >
> > > On Sat, Sep 10, 2022 at 01:27:53PM +0800, Sam Li wrote:
> > > > Signed-off-by: Sam Li 
> > > > Reviewed-by: Stefan Hajnoczi 
> > > > Reviewed-by: Damien Le Moal 
> > > > ---
> > > >  include/block/block-common.h | 43 
> > > >  1 file changed, 43 insertions(+)
> > > >
> > > > diff --git a/include/block/block-common.h b/include/block/block-common.h
> > > > index fdb7306e78..36bd0e480e 100644
> > > > --- a/include/block/block-common.h
> > > > +++ b/include/block/block-common.h
> > > > @@ -49,6 +49,49 @@ typedef struct BlockDriver BlockDriver;
> > > >  typedef struct BdrvChild BdrvChild;
> > > >  typedef struct BdrvChildClass BdrvChildClass;
> > > >
> > > > +typedef enum BlockZoneOp {
> > > > +BLK_ZO_OPEN,
> > > > +BLK_ZO_CLOSE,
> > > > +BLK_ZO_FINISH,
> > > > +BLK_ZO_RESET,
> > > > +} BlockZoneOp;
> > > > +
> > > > +typedef enum BlockZoneModel {
> > > > +BLK_Z_NONE = 0x0, /* Regular block device */
> > > > +BLK_Z_HM = 0x1, /* Host-managed zoned block device */
> > > > +BLK_Z_HA = 0x2, /* Host-aware zoned block device */
> > > > +} BlockZoneModel;
> > > > +
> > > > +typedef enum BlockZoneCondition {
> > > > +BLK_ZS_NOT_WP = 0x0,
> > > > +BLK_ZS_EMPTY = 0x1,
> > > > +BLK_ZS_IOPEN = 0x2,
> > > > +BLK_ZS_EOPEN = 0x3,
> > > > +BLK_ZS_CLOSED = 0x4,
> > > > +BLK_ZS_RDONLY = 0xD,
> > > > +BLK_ZS_FULL = 0xE,
> > > > +BLK_ZS_OFFLINE = 0xF,
> > > > +} BlockZoneCondition;
> > > > +
> > > > +typedef enum BlockZoneType {
> > > > +BLK_ZT_CONV = 0x1, /* Conventional random writes supported */
> > > > +BLK_ZT_SWR = 0x2, /* Sequential writes required */
> > > > +BLK_ZT_SWP = 0x3, /* Sequential writes preferred */
> > > > +} BlockZoneType;
> > > > +
> > > > +/*
> > > > + * Zone descriptor data structure.
> > > > + * Provides information on a zone with all position and size values in 
> > > > bytes.
> > >
> > > I'm glad that you chose bytes here for use in qemu.  But since the
> > > kernel struct blk_zone uses sectors instead of bytes, is it worth
> > > adding a sentence that we intentionally use bytes here, different from
> > > Linux, to make it easier for reviewers to realize that scaling when
> > > translating between qemu and kernel is necessary?
> >
> > Sorry about the unit mistake. The zone information is in sectors which
> > is the same as kernel struct blk_zone. I think adding a sentence to
> > inform the sector unit makes it clear what the zone descriptor is.
>
> I'd make the units bytes for consistency with the rest of the QEMU block
> layer. For example, the MapEntry structure that "qemu-img map" reports
> has names with similar fields and they are in bytes:
>
>   struct MapEntry {
>   int64_t start;
>   int64_t length;
>

I think the zone descriptor uses sector units because ioctl() will
report zones in sector units. Making blk_zone.offset =
zone_descriptor.offset is more convenient than using byte units where
it needs make conversions twice(sector -> byte -> sector in zone
descriptors and offset argument in bdrv_co_zone_report). The MapEntry
uses byte units because lseek() in bdrv_co_block_status suggests the
file offset is set to bytes and I think it may be why the rest of the
block layer uses bytes(not sure).

I do not object to using bytes here but it would require some
compromises. If I was wrong about anything, please let me know.


Sam



Re: [PATCH 00/42] Consolidate PIIX south bridges

2022-09-18 Thread Bernhard Beschow
Am 18. September 2022 20:22:55 UTC schrieb Mark Cave-Ayland 
:
>On 01/09/2022 17:25, Bernhard Beschow wrote:
>
>> This series consolidates the implementations of the PIIX3 and PIIX4 south
>> bridges and is an extended version of [1]. The motivation is to share as much
>> code as possible and to bring both device models to feature parity such that
>> perhaps PIIX4 can become a drop-in-replacement for PIIX3 in the pc machine. 
>> This
>> could resolve the "Frankenstein" PIIX4-PM problem in PIIX3 discussed on this
>> list before.
>> 
>> The series is structured as follows: First, PIIX3 is changed to instantiate
>> internal devices itself, like PIIX4 does already. Second, PIIX3 gets prepared
>> for the merge with PIIX4 which includes some fixes, cleanups, and renamings.
>> Third, the same is done for PIIX4. In step four the implementations are 
>> merged.
>> Since some consolidations could be done easier with merged implementations, 
>> the
>> consolidation continues in step five which concludes the series.
>> 
>> One particular challenge in this series was that the PIC of PIIX3 used to be
>> instantiated outside of the south bridge while some sub functions require a 
>> PIC
>> with populated qemu_irqs. This has been solved by introducing a proxy PIC 
>> which
>> furthermore allows PIIX3 to be agnostic towards the virtualization technology
>> used (KVM, TCG, Xen). Due to consolidation PIIX4 gained the PIC as well,
>> possibly allowing the Malta board to gain KVM capabilities in the future.
>> 
>> Another challenge was dealing with optional devices where Peter already gave
>> advice in [1] which this series implements.
>> 
>> An unsolved problem still is PCI interrupt handling. The first function
>> passed to pci_bus_irqs() is device-specific while the second one seems
>> board-specific. This causes both PIIX device models to be coupled to a
>> particular board. Any advice how to resolve this would be highly 
>> appreaciated.
>
>Could you explain this in a bit more detail?

Sure!

Even after the consolidation there are piix3_pci_slot_get_pirq() and 
piix4_pci_slot_get_pirq() which seem board-specific rather than south 
bridge-specific. So they seem to belong into board code (pc_piix and Malta). 
piix_set_irq(), OTOH, seems appropriate in piix.c and is even shared between 3 
and 4. However, pci_bus_irqs() assigns both piix_set_irq() and 
piix{3,4}_pci_slot_get_pirq() in one go. So it is unclear to me how to pass the 
board-specific piix{3,4}_pci_slot_get_pirq() into the south bridge for 
pci_bus_irqs() if this call is performed there.

I'm really curious about an answer. Let me know if I was still unclear.

>
>> Last but not least there might be some opportunity to consolidate VM state
>> handling, probably by reusing the one from PIIX3. Since I'm not very familiar
>> with the requirements I didn't touch it so far.
>> 
>> Testing done:
>> * make check
>> * Boot live CD:
>>* `qemu-system-x86_64 -M pc -m 2G -accel kvm -cpu host -cdrom
>> manjaro-kde-21.3.2-220704-linux515.iso`
>>* `qemu-system-x86_64 -M q35 -m 2G -accel kvm -cpu host -cdrom
>> manjaro-kde-21.3.2-220704-linux515.iso`
>> 
>> [1] https://lists.nongnu.org/archive/html/qemu-devel/2022-07/msg02348.html
>> 
>> Bernhard Beschow (42):
>>hw/i386/pc: Create DMA controllers in south bridges
>>hw/i386/pc: Create RTC controllers in south bridges
>>hw/i386/pc: No need for rtc_state to be an out-parameter
>>hw/i386/pc_piix: Allow for setting properties before realizing PIIX3
>>  south bridge
>>hw/isa/piix3: Create USB controller in host device
>>hw/isa/piix3: Create power management controller in host device
>>hw/intc/i8259: Introduce i8259 proxy "isa-pic"
>>hw/isa/piix3: Create ISA PIC in host device
>>hw/isa/piix3: Create IDE controller in host device
>>hw/isa/piix3: Wire up ACPI interrupt internally
>>hw/isa/piix3: Remove extra ';' outside of functions
>>hw/isa/piix3: Remove unused include
>>hw/isa/piix3: Add size constraints to rcr_ops
>>hw/isa/piix3: Modernize reset handling
>>hw/isa/piix3: Prefer pci_address_space() over get_system_memory()
>>hw/isa/piix3: Allow board to provide PCI interrupt routes
>>hw/isa/piix3: Resolve redundant PIIX_NUM_PIC_IRQS
>>hw/isa/piix3: Rename pci_piix3_props for sharing with PIIX4
>>hw/isa/piix3: Rename piix3_reset() for sharing with PIIX4
>>hw/isa/piix3: Prefix pci_slot_get_pirq() with "piix3_"
>>hw/isa/piix3: Rename typedef PIIX3State to PIIXState
>>hw/mips/malta: Reuse dev variable
>>meson: Fix dependencies of piix4 southbridge
>>hw/isa/piix4: Add missing initialization
>>hw/isa/piix4: Move pci_ide_create_devs() call to board code
>>hw/isa/piix4: Make PIIX4's ACPI and USB functions optional
>>hw/isa/piix4: Allow board to provide PCI interrupt routes
>>hw/isa/piix4: Remove unused code
>>hw/isa/piix4: Use ISA PIC device
>>hw/isa/piix4: Reuse struct PIIXState from PIIX3
>>hw/isa/piix4: Rename 

Re: [PATCH 26/42] hw/isa/piix4: Make PIIX4's ACPI and USB functions optional

2022-09-18 Thread Bernhard Beschow
Am 18. September 2022 20:10:51 UTC schrieb Mark Cave-Ayland 
:
>On 01/09/2022 17:25, Bernhard Beschow wrote:
>
>> This aligns PIIX4 with PIIX3.
>> 
>> Signed-off-by: Bernhard Beschow 
>> ---
>>   hw/isa/piix4.c  | 44 
>>   hw/mips/malta.c |  6 --
>>   2 files changed, 36 insertions(+), 14 deletions(-)
>> 
>> diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c
>> index 67881e3a75..ed9eca715f 100644
>> --- a/hw/isa/piix4.c
>> +++ b/hw/isa/piix4.c
>> @@ -50,9 +50,16 @@ struct PIIX4State {
>>   PCIIDEState ide;
>>   UHCIState uhci;
>>   PIIX4PMState pm;
>> +
>> +uint32_t smb_io_base;
>> +
>>   /* Reset Control Register */
>>   MemoryRegion rcr_mem;
>>   uint8_t rcr;
>> +
>> +bool has_acpi;
>> +bool has_usb;
>> +bool smm_enabled;
>>   };
>> OBJECT_DECLARE_SIMPLE_TYPE(PIIX4State, PIIX4_PCI_DEVICE)
>> @@ -258,17 +265,26 @@ static void piix4_realize(PCIDevice *dev, Error **errp)
>>   }
>> /* USB */
>> -qdev_prop_set_int32(DEVICE(>uhci), "addr", dev->devfn + 2);
>> -if (!qdev_realize(DEVICE(>uhci), BUS(pci_bus), errp)) {
>> -return;
>> +if (s->has_usb) {
>> +object_initialize_child(OBJECT(dev), "uhci", >uhci,
>> +"piix4-usb-uhci");
>
>Can you use the relevant TYPE_ macro here for the USB-UHCI device?
>
>> +qdev_prop_set_int32(DEVICE(>uhci), "addr", dev->devfn + 2);
>> +if (!qdev_realize(DEVICE(>uhci), BUS(pci_bus), errp)) {
>> +return;
>> +}
>>   }
>> /* ACPI controller */
>> -qdev_prop_set_int32(DEVICE(>pm), "addr", dev->devfn + 3);
>> -if (!qdev_realize(DEVICE(>pm), BUS(pci_bus), errp)) {
>> -return;
>> +if (s->has_acpi) {
>> +object_initialize_child(OBJECT(s), "pm", >pm, TYPE_PIIX4_PM);
>> +qdev_prop_set_int32(DEVICE(>pm), "addr", dev->devfn + 3);
>> +qdev_prop_set_uint32(DEVICE(>pm), "smb_io_base", s->smb_io_base);
>> +qdev_prop_set_bit(DEVICE(>pm), "smm-enabled", s->smm_enabled);
>> +if (!qdev_realize(DEVICE(>pm), BUS(pci_bus), errp)) {
>> +return;
>> +}
>> +qdev_connect_gpio_out(DEVICE(>pm), 0, s->isa[9]);
>>   }
>> -qdev_connect_gpio_out(DEVICE(>pm), 0, s->isa[9]);
>> pci_bus_irqs(pci_bus, piix4_set_irq, pci_slot_get_pirq, s, 
>> PIIX_NUM_PIRQS);
>>   }
>> @@ -279,13 +295,16 @@ static void piix4_init(Object *obj)
>> object_initialize_child(obj, "rtc", >rtc, TYPE_MC146818_RTC);
>>   object_initialize_child(obj, "ide", >ide, "piix4-ide");
>
>... and same here for IDE?

Sure!

Best regards,
Bernhard
>
>> -object_initialize_child(obj, "uhci", >uhci, "piix4-usb-uhci");
>> -
>> -object_initialize_child(obj, "pm", >pm, TYPE_PIIX4_PM);
>> -qdev_prop_set_uint32(DEVICE(>pm), "smb_io_base", 0x1100);
>> -qdev_prop_set_bit(DEVICE(>pm), "smm-enabled", 0);
>>   }
>>   +static Property piix4_props[] = {
>> +DEFINE_PROP_UINT32("smb_io_base", PIIX4State, smb_io_base, 0),
>> +DEFINE_PROP_BOOL("has-acpi", PIIX4State, has_acpi, true),
>> +DEFINE_PROP_BOOL("has-usb", PIIX4State, has_usb, true),
>> +DEFINE_PROP_BOOL("smm-enabled", PIIX4State, smm_enabled, false),
>> +DEFINE_PROP_END_OF_LIST(),
>> +};
>> +
>>   static void piix4_class_init(ObjectClass *klass, void *data)
>>   {
>>   DeviceClass *dc = DEVICE_CLASS(klass);
>> @@ -304,6 +323,7 @@ static void piix4_class_init(ObjectClass *klass, void 
>> *data)
>>*/
>>   dc->user_creatable = false;
>>   dc->hotpluggable = false;
>> +device_class_set_props(dc, piix4_props);
>>   }
>> static const TypeInfo piix4_info = {
>> diff --git a/hw/mips/malta.c b/hw/mips/malta.c
>> index a4b866a2cf..6339b0d66c 100644
>> --- a/hw/mips/malta.c
>> +++ b/hw/mips/malta.c
>> @@ -1400,8 +1400,10 @@ void mips_malta_init(MachineState *machine)
>>   empty_slot_init("GT64120", 0, 0x2000);
>> /* Southbridge */
>> -piix4 = pci_create_simple_multifunction(pci_bus, PCI_DEVFN(10, 0), true,
>> -TYPE_PIIX4_PCI_DEVICE);
>> +piix4 = pci_new_multifunction(PCI_DEVFN(10, 0), true,
>> +  TYPE_PIIX4_PCI_DEVICE);
>> +qdev_prop_set_uint32(DEVICE(piix4), "smb_io_base", 0x1100);
>> +pci_realize_and_unref(piix4, pci_bus, _fatal);
>>   isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix4), "isa.0"));
>> dev = DEVICE(object_resolve_path_component(OBJECT(piix4), "ide"));
>
>
>ATB,
>
>Mark.




Re: [PATCH 05/42] hw/isa/piix3: Create USB controller in host device

2022-09-18 Thread Bernhard Beschow
Am 1. September 2022 19:13:22 UTC schrieb "Philippe Mathieu-Daudé" 
:
>On 1/9/22 18:25, Bernhard Beschow wrote:
>> The USB controller is an integral part of PIIX3 (function 2). So create
>> it as part of the south bridge.
>> 
>> Note that the USB function is optional in QEMU. This is why it gets
>> object_initialize_child()'ed in realize rather than in instance_init.
>> 
>> Signed-off-by: Bernhard Beschow 
>> ---
>>   hw/i386/pc_piix.c |  6 ++
>>   hw/isa/Kconfig|  1 +
>>   hw/isa/piix3.c| 17 +
>>   include/hw/southbridge/piix.h |  4 
>>   4 files changed, 24 insertions(+), 4 deletions(-)
>> 
>> diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
>> index b08d946992..76ac8b2035 100644
>> --- a/hw/i386/pc_piix.c
>> +++ b/hw/i386/pc_piix.c
>> @@ -219,6 +219,8 @@ static void pc_init1(MachineState *machine,
>>   pcms->bus = pci_bus;
>> pci_dev = pci_new_multifunction(-1, true, type);
>> +object_property_set_bool(OBJECT(pci_dev), "has-usb",
>> + machine_usb(machine), _abort);
>>   pci_realize_and_unref(pci_dev, pci_bus, _fatal);
>>   piix3 = PIIX3_PCI_DEVICE(pci_dev);
>>   piix3->pic = x86ms->gsi;
>> @@ -297,10 +299,6 @@ static void pc_init1(MachineState *machine,
>>   }
>>   #endif
>>   -if (pcmc->pci_enabled && machine_usb(machine)) {
>> -pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci");
>> -}
>> -
>>   if (pcmc->pci_enabled && 
>> x86_machine_is_acpi_enabled(X86_MACHINE(pcms))) {
>>   PCIDevice *piix4_pm;
>>   diff --git a/hw/isa/Kconfig b/hw/isa/Kconfig
>> index 6e8f9cac54..f02eca3c3e 100644
>> --- a/hw/isa/Kconfig
>> +++ b/hw/isa/Kconfig
>> @@ -36,6 +36,7 @@ config PIIX3
>>   select I8257
>>   select ISA_BUS
>>   select MC146818RTC
>> +select USB_UHCI
>> config PIIX4
>>   bool
>> diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c
>> index 96ab7107e2..27052a5546 100644
>> --- a/hw/isa/piix3.c
>> +++ b/hw/isa/piix3.c
>> @@ -297,6 +297,7 @@ static const MemoryRegionOps rcr_ops = {
>>   static void pci_piix3_realize(PCIDevice *dev, Error **errp)
>>   {
>>   PIIX3State *d = PIIX3_PCI_DEVICE(dev);
>> +PCIBus *pci_bus = pci_get_bus(dev);
>>   ISABus *isa_bus;
>> isa_bus = isa_bus_new(DEVICE(d), get_system_memory(),
>> @@ -319,6 +320,16 @@ static void pci_piix3_realize(PCIDevice *dev, Error 
>> **errp)
>>   if (!qdev_realize(DEVICE(>rtc), BUS(isa_bus), errp)) {
>>   return;
>>   }
>> +
>> +/* USB */
>> +if (d->has_usb) {
>> +object_initialize_child(OBJECT(dev), "uhci", >uhci,
>> +"piix3-usb-uhci");
>> +qdev_prop_set_int32(DEVICE(>uhci), "addr", dev->devfn + 2);
>> +if (!qdev_realize(DEVICE(>uhci), BUS(pci_bus), errp)) {
>> +return;
>> +}
>> +}
>>   }
>> static void build_pci_isa_aml(AcpiDevAmlIf *adev, Aml *scope)
>> @@ -341,6 +352,11 @@ static void pci_piix3_init(Object *obj)
>>   object_initialize_child(obj, "rtc", >rtc, TYPE_MC146818_RTC);
>>   }
>>   +static Property pci_piix3_props[] = {
>> +DEFINE_PROP_BOOL("has-usb", PIIX3State, has_usb, true),
>
>Maybe s/has-usb/usb-enabled/?

I consisered that. I chose has-foo for now since I took inspiration from the 
board. Also, "enabled" may refer to a device being present but its enable bit 
is cleared in PCI configuration space, c.f. vt82c686. Let me know if you still 
suggest a change here, in which case I'll consult you for naming suggestions 
once I consolidate piix and vt82c686 ;)

Best regards,
Bernhard
>
>> +DEFINE_PROP_END_OF_LIST(),
>> +};
>> +
>>   static void pci_piix3_class_init(ObjectClass *klass, void *data)
>>   {
>>   DeviceClass *dc = DEVICE_CLASS(klass);
>> @@ -359,6 +375,7 @@ static void pci_piix3_class_init(ObjectClass *klass, 
>> void *data)
>>* pc_piix.c's pc_init1()
>>*/
>>   dc->user_creatable = false;
>> +device_class_set_props(dc, pci_piix3_props);
>>   adevc->build_dev_aml = build_pci_isa_aml;
>>   }
>>   diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h
>> index b1fa08dd2b..5367917182 100644
>> --- a/include/hw/southbridge/piix.h
>> +++ b/include/hw/southbridge/piix.h
>> @@ -15,6 +15,7 @@
>>   #include "hw/pci/pci.h"
>>   #include "qom/object.h"
>>   #include "hw/rtc/mc146818rtc.h"
>> +#include "hw/usb/hcd-uhci.h"
>> /* PIRQRC[A:D]: PIRQx Route Control Registers */
>>   #define PIIX_PIRQCA 0x60
>> @@ -54,12 +55,15 @@ struct PIIXState {
>>   int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
>> RTCState rtc;
>> +UHCIState uhci;
>> /* Reset Control Register contents */
>>   uint8_t rcr;
>> /* IO memory region for Reset Control Register (PIIX_RCR_IOPORT) */
>>   MemoryRegion rcr_mem;
>> +
>> +bool has_usb;
>>   };
>>   typedef struct PIIXState PIIX3State;
>>   
>




Re: [PATCH v5 16/21] ppc4xx_sdram: Move ppc4xx DDR and DDR2 SDRAM controller models together

2022-09-18 Thread Philippe Mathieu-Daudé via

On 18/9/22 23:24, BALATON Zoltan wrote:

On Sun, 18 Sep 2022, Philippe Mathieu-Daudé wrote:

Hi Zoltan,

On 18/9/22 22:24, BALATON Zoltan wrote:

Move the PPC4xx DDR and DDR2 SDRAM contrller models into a new file
called ppc4xx_sdram to separate from other device models and put them
in one place allowing sharing some code between them.

Signed-off-by: BALATON Zoltan 
---
  hw/ppc/meson.build  |   3 +-
  hw/ppc/ppc440_uc.c  | 332 -
  hw/ppc/ppc4xx_devs.c    | 414 -
  hw/ppc/ppc4xx_sdram.c   | 771 
  include/hw/ppc/ppc4xx.h |  24 +-
  5 files changed, 785 insertions(+), 759 deletions(-)


This seems a proper cleanup, but even using `git-diff 
--color-moved=dimmed-zebra` I'm having hard time reviewing this single

patch.
Looking at the changes in the ppc4xx_sdram_types[] array, it
seems we can be move one model at a time, right?


I could try to break this patch up some more if absolutely necessary but 
I've already spent a lot of time rebasing this series as every little 
change in earlier patch leads to conflicts later then patches get 
squashed during rebase and I have to redo it again to separate them. So 
if you can't review it looking at it some more I could try a v6 but 
don't want if can be avoided. I'll wait for Cédric's comments too in any 
case to only do as many respins as needed.


Sure, I totally understand. Let see first if someone is willing to
review it as it.



Re: [PATCH v3 03/20] ppc4xx_sdram: Get rid of the init RAM hack

2022-09-18 Thread BALATON Zoltan

On Sun, 18 Sep 2022, Cédric Le Goater wrote:

On 9/14/22 20:25, BALATON Zoltan wrote:

On Wed, 14 Sep 2022, Cédric Le Goater wrote:

On 9/14/22 13:44, BALATON Zoltan wrote:

On Wed, 14 Sep 2022, Cédric Le Goater wrote:

On 9/13/22 21:52, BALATON Zoltan wrote:

The do_init parameter of ppc4xx_sdram_init() is used to map memory
regions that is normally done by the firmware by programming the SDRAM
controller. This is needed when booting a kernel directly from -kernel
without a firmware. Do this from board code accesing normal SDRAM


accessing


Fixed, also two ofhers in another patch you haven't noticed.


controller registers the same way as firmware would do, so we can get
rid of this hack.

Signed-off-by: BALATON Zoltan 
---
v2: Fix ref405ep boot with -kernel and U-Boot

  hw/ppc/ppc405.h |  1 -
  hw/ppc/ppc405_boards.c  | 12 ++--
  hw/ppc/ppc405_uc.c  |  4 +---
  hw/ppc/ppc440_bamboo.c  |  8 +++-
  hw/ppc/ppc440_uc.c  |  2 --
  hw/ppc/ppc4xx_devs.c    | 11 +--
  include/hw/ppc/ppc4xx.h |  8 ++--
  7 files changed, 25 insertions(+), 21 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 1e558c7831..756865621b 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -169,7 +169,6 @@ struct Ppc405SoCState {
  /* Public */
  MemoryRegion ram_banks[2];
  hwaddr ram_bases[2], ram_sizes[2];
-    bool do_dram_init;
    MemoryRegion *dram_mr;
  hwaddr ram_size;
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 083f12b23e..bf02a71c6d 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -274,6 +274,7 @@ static void ppc405_init(MachineState *machine)
  MachineClass *mc = MACHINE_GET_CLASS(machine);
  const char *kernel_filename = machine->kernel_filename;
  MemoryRegion *sysmem = get_system_memory();
+    CPUPPCState *env;
    if (machine->ram_size != mc->default_ram_size) {
  char *sz = size_to_str(mc->default_ram_size);
@@ -288,12 +289,19 @@ static void ppc405_init(MachineState *machine)
   machine->ram_size, _fatal);
  object_property_set_link(OBJECT(>soc), "dram",
   OBJECT(machine->ram), _abort);
-    object_property_set_bool(OBJECT(>soc), "dram-init",
- kernel_filename != NULL, _abort);
  object_property_set_uint(OBJECT(>soc), "sys-clk", 
,

   _abort);
  qdev_realize(DEVICE(>soc), NULL, _fatal);
  +    /* Enable SDRAM memory regions */
+    /* FIXME This shouldn't be needed with firmware but we lack SPD 
data */


what do you mean ?


U-Boot detects the available RAM by reading the SPD info of the RAM 
modules but that probably also needs i2c emulation. See sam460ex.



+    env = >soc.cpu.env;
+    if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x20) ||
+    ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x8000)) {



I am not in favor of these ppc_drc_write calls and this is still a hack.


It's not. Normally this is done by firmware to enable memory controller 
but the board code has to do it if not using firmware (e.g. booting with 
-kernel) the same way it provides bootinfo or device tree mods the 
firmware would normally do or in this case maybe the emulation is 
incomplete so the part of firmware that configures the SDRAM controller 
does not run.


Exactly, and what the above proposal does is mimicking execution of CPU
instructions before the CPU is even fully initiated. Reset has not been
called at that stage.


I don't get this. We're not calling any CPU instructions, ppc_dcr_write 
just calls the write callback the device has registered for the dcr so it 
just does the same as the hack did at the end just doing it the same way 
the firmware should do.


The "dram-init" property is a cleaner solution. It takes care of doing 
the

pre-mapping of RAM banks in the realize routine of the sdram model (when
available).


I disagree, the hardware does not have such feature, it proviesd DCRs as 
the way to configure it. Adding a special property for it deviates from 
hardware and clutters qtree. 



In this machine, running QEMU with -kernel deviates from HW. That's


In all machines booting with -kernel likely deviates and all machines 
probably have additinal code in this case to do some things normally done 
by the firmware. Look at pegasos2_machine_reset() for example. All that is 
not needed when we boot with firmware as then the firmware will do all that 
and provide the device tree, etc. bur we need to do these when booting 
without firmware. In thes case QEMU also emulates the firmware and has to 
do thinigs like enabling the memory controller.



the whole purpose of this option. It assumes that the SDRAM device
is pre-initialized (and much more should be done) by the QEMU machine
and the simplest way to acheive this goal is to inform the SDRAM model
to take care of the pre-initialization.


In my opinion the SDRAM controller model 

Re: [PATCH 39/42] hw/isa/piix: Unexport PIIXState

2022-09-18 Thread Bernhard Beschow
Am 18. September 2022 20:21:09 UTC schrieb Mark Cave-Ayland 
:
>On 01/09/2022 17:26, Bernhard Beschow wrote:
>
>> The - deliberately exported - components can still be accessed
>> via QOM properties.
>> 
>> Signed-off-by: Bernhard Beschow 
>> ---
>>   hw/isa/piix.c | 52 +
>>   include/hw/southbridge/piix.h | 54 ---
>>   2 files changed, 52 insertions(+), 54 deletions(-)
>> 
>> diff --git a/hw/isa/piix.c b/hw/isa/piix.c
>> index e413d7e792..c503a6e836 100644
>> --- a/hw/isa/piix.c
>> +++ b/hw/isa/piix.c
>> @@ -26,20 +26,72 @@
>>   #include "qemu/osdep.h"
>>   #include "qemu/range.h"
>>   #include "qapi/error.h"
>> +#include "qom/object.h"
>> +#include "hw/acpi/piix4.h"
>>   #include "hw/dma/i8257.h"
>> +#include "hw/ide/pci.h"
>>   #include "hw/intc/i8259.h"
>>   #include "hw/southbridge/piix.h"
>>   #include "hw/timer/i8254.h"
>>   #include "hw/irq.h"
>>   #include "hw/qdev-properties.h"
>>   #include "hw/isa/isa.h"
>> +#include "hw/pci/pci.h"
>> +#include "hw/qdev-properties.h"
>> +#include "hw/rtc/mc146818rtc.h"
>> +#include "hw/usb/hcd-uhci.h"
>>   #include "hw/xen/xen.h"
>>   #include "sysemu/runstate.h"
>>   #include "migration/vmstate.h"
>>   #include "hw/acpi/acpi_aml_interface.h"
>>   +#define PIIX_NUM_PIRQS  4ULL/* PIRQ[A-D] */
>>   #define XEN_PIIX_NUM_PIRQS  128ULL
>>   +struct PIIXState {
>> +PCIDevice dev;
>> +
>> +/*
>> + * bitmap to track pic levels.
>> + * The pic level is the logical OR of all the PCI irqs mapped to it
>> + * So one PIC level is tracked by PIIX_NUM_PIRQS bits.
>> + *
>> + * PIRQ is mapped to PIC pins, we track it by
>> + * PIIX_NUM_PIRQS * ISA_NUM_IRQS = 64 bits with
>> + * pic_irq * PIIX_NUM_PIRQS + pirq
>> + */
>> +#if ISA_NUM_IRQS * PIIX_NUM_PIRQS > 64
>> +#error "unable to encode pic state in 64bit in pic_levels."
>> +#endif
>> +uint64_t pic_levels;
>> +
>> +/* This member isn't used. Just for save/load compatibility */
>> +int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
>> +uint8_t pci_irq_reset_mappings[PIIX_NUM_PIRQS];
>> +
>> +ISAPICState pic;
>> +RTCState rtc;
>> +PCIIDEState ide;
>> +UHCIState uhci;
>> +PIIX4PMState pm;
>> +
>> +uint32_t smb_io_base;
>> +
>> +/* Reset Control Register contents */
>> +uint8_t rcr;
>> +
>> +/* IO memory region for Reset Control Register (PIIX_RCR_IOPORT) */
>> +MemoryRegion rcr_mem;
>> +
>> +bool has_acpi;
>> +bool has_usb;
>> +bool smm_enabled;
>> +};
>> +typedef struct PIIXState PIIXState;
>> +
>> +DECLARE_INSTANCE_CHECKER(PIIXState, PIIX_PCI_DEVICE,
>> + TYPE_PIIX3_PCI_DEVICE)
>> +
>>   static void piix_set_irq_pic(PIIXState *piix, int pic_irq)
>>   {
>>   qemu_set_irq(piix->pic.in_irqs[pic_irq],
>> diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h
>> index c9fa0f1aa6..0edc23710c 100644
>> --- a/include/hw/southbridge/piix.h
>> +++ b/include/hw/southbridge/piix.h
>> @@ -12,14 +12,6 @@
>>   #ifndef HW_SOUTHBRIDGE_PIIX_H
>>   #define HW_SOUTHBRIDGE_PIIX_H
>>   -#include "hw/pci/pci.h"
>> -#include "qom/object.h"
>> -#include "hw/acpi/piix4.h"
>> -#include "hw/ide/pci.h"
>> -#include "hw/intc/i8259.h"
>> -#include "hw/rtc/mc146818rtc.h"
>> -#include "hw/usb/hcd-uhci.h"
>> -
>>   /* PIRQRC[A:D]: PIRQx Route Control Registers */
>>   #define PIIX_PIRQCA 0x60
>>   #define PIIX_PIRQCB 0x61
>> @@ -32,53 +24,7 @@
>>*/
>>   #define PIIX_RCR_IOPORT 0xcf9
>>   -#define PIIX_NUM_PIRQS  4ULL/* PIRQ[A-D] */
>> -
>> -struct PIIXState {
>> -PCIDevice dev;
>> -
>> -/*
>> - * bitmap to track pic levels.
>> - * The pic level is the logical OR of all the PCI irqs mapped to it
>> - * So one PIC level is tracked by PIIX_NUM_PIRQS bits.
>> - *
>> - * PIRQ is mapped to PIC pins, we track it by
>> - * PIIX_NUM_PIRQS * ISA_NUM_IRQS = 64 bits with
>> - * pic_irq * PIIX_NUM_PIRQS + pirq
>> - */
>> -#if ISA_NUM_IRQS * PIIX_NUM_PIRQS > 64
>> -#error "unable to encode pic state in 64bit in pic_levels."
>> -#endif
>> -uint64_t pic_levels;
>> -
>> -/* This member isn't used. Just for save/load compatibility */
>> -int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
>> -uint8_t pci_irq_reset_mappings[PIIX_NUM_PIRQS];
>> -
>> -ISAPICState pic;
>> -RTCState rtc;
>> -PCIIDEState ide;
>> -UHCIState uhci;
>> -PIIX4PMState pm;
>> -
>> -uint32_t smb_io_base;
>> -
>> -/* Reset Control Register contents */
>> -uint8_t rcr;
>> -
>> -/* IO memory region for Reset Control Register (PIIX_RCR_IOPORT) */
>> -MemoryRegion rcr_mem;
>> -
>> -bool has_acpi;
>> -bool has_usb;
>> -bool smm_enabled;
>> -};
>> -typedef struct PIIXState PIIXState;
>> -
>>   #define TYPE_PIIX3_PCI_DEVICE "pci-piix3"
>> -DECLARE_INSTANCE_CHECKER(PIIXState, PIIX_PCI_DEVICE,
>> - TYPE_PIIX3_PCI_DEVICE)
>> -
>>   

Re: [PATCH v5 16/21] ppc4xx_sdram: Move ppc4xx DDR and DDR2 SDRAM controller models together

2022-09-18 Thread BALATON Zoltan

On Sun, 18 Sep 2022, Philippe Mathieu-Daudé wrote:

Hi Zoltan,

On 18/9/22 22:24, BALATON Zoltan wrote:

Move the PPC4xx DDR and DDR2 SDRAM contrller models into a new file
called ppc4xx_sdram to separate from other device models and put them
in one place allowing sharing some code between them.

Signed-off-by: BALATON Zoltan 
---
  hw/ppc/meson.build  |   3 +-
  hw/ppc/ppc440_uc.c  | 332 -
  hw/ppc/ppc4xx_devs.c| 414 -
  hw/ppc/ppc4xx_sdram.c   | 771 
  include/hw/ppc/ppc4xx.h |  24 +-
  5 files changed, 785 insertions(+), 759 deletions(-)


This seems a proper cleanup, but even using `git-diff 
--color-moved=dimmed-zebra` I'm having hard time reviewing this single

patch.
Looking at the changes in the ppc4xx_sdram_types[] array, it
seems we can be move one model at a time, right?


I could try to break this patch up some more if absolutely necessary but 
I've already spent a lot of time rebasing this series as every little 
change in earlier patch leads to conflicts later then patches get squashed 
during rebase and I have to redo it again to separate them. So if you 
can't review it looking at it some more I could try a v6 but don't want if 
can be avoided. I'll wait for Cédric's comments too in any case to only do 
as many respins as needed.


Regards,
BALATON Zoltan


[...]

+static const TypeInfo ppc4xx_sdram_types[] = {
+{
+.name   = TYPE_PPC4xx_SDRAM_DDR,
+.parent = TYPE_PPC4xx_DCR_DEVICE,
+.instance_size  = sizeof(Ppc4xxSdramDdrState),
+.class_init = ppc4xx_sdram_ddr_class_init,
+}, {
+.name   = TYPE_PPC4xx_SDRAM_DDR2,
+.parent = TYPE_PPC4xx_DCR_DEVICE,
+.instance_size  = sizeof(Ppc4xxSdramDdr2State),
+.class_init = ppc4xx_sdram_ddr2_class_init,
+}
+};
+
+DEFINE_TYPES(ppc4xx_sdram_types)

[...]



Re: [PATCH v5 16/21] ppc4xx_sdram: Move ppc4xx DDR and DDR2 SDRAM controller models together

2022-09-18 Thread Philippe Mathieu-Daudé via

Hi Zoltan,

On 18/9/22 22:24, BALATON Zoltan wrote:

Move the PPC4xx DDR and DDR2 SDRAM contrller models into a new file
called ppc4xx_sdram to separate from other device models and put them
in one place allowing sharing some code between them.

Signed-off-by: BALATON Zoltan 
---
  hw/ppc/meson.build  |   3 +-
  hw/ppc/ppc440_uc.c  | 332 -
  hw/ppc/ppc4xx_devs.c| 414 -
  hw/ppc/ppc4xx_sdram.c   | 771 
  include/hw/ppc/ppc4xx.h |  24 +-
  5 files changed, 785 insertions(+), 759 deletions(-)


This seems a proper cleanup, but even using `git-diff 
--color-moved=dimmed-zebra` I'm having hard time reviewing this single

patch.
Looking at the changes in the ppc4xx_sdram_types[] array, it
seems we can be move one model at a time, right?

[...]

+static const TypeInfo ppc4xx_sdram_types[] = {
+{
+.name   = TYPE_PPC4xx_SDRAM_DDR,
+.parent = TYPE_PPC4xx_DCR_DEVICE,
+.instance_size  = sizeof(Ppc4xxSdramDdrState),
+.class_init = ppc4xx_sdram_ddr_class_init,
+}, {
+.name   = TYPE_PPC4xx_SDRAM_DDR2,
+.parent = TYPE_PPC4xx_DCR_DEVICE,
+.instance_size  = sizeof(Ppc4xxSdramDdr2State),
+.class_init = ppc4xx_sdram_ddr2_class_init,
+}
+};
+
+DEFINE_TYPES(ppc4xx_sdram_types)

[...]



Re: [PATCH v5 18/21] ppc4xx_sdram: Rename local state variable for brevity

2022-09-18 Thread Philippe Mathieu-Daudé via

On 18/9/22 22:24, BALATON Zoltan wrote:

Rename the sdram local state variable to s in dcr read/write functions
and reset methods for better readability and to match realize methods.
Other places not converted will be changed or removed in subsequent
patches.

Signed-off-by: BALATON Zoltan 
---
  hw/ppc/ppc4xx_sdram.c | 158 +-
  1 file changed, 79 insertions(+), 79 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 



Re: [PATCH v3 07/12] linux-user: Fix strace of chmod() if mode == 0

2022-09-18 Thread Philippe Mathieu-Daudé via

On 18/9/22 21:45, Helge Deller wrote:

If the mode parameter of chmod() is zero, this value isn't shown
when stracing a program:
 chmod("filename",)
This patch fixes it up to show the zero-value as well:
 chmod("filename",000)

Signed-off-by: Helge Deller 
---
  linux-user/strace.c | 5 +
  1 file changed, 5 insertions(+)

diff --git a/linux-user/strace.c b/linux-user/strace.c
index 5ac64df02b..2f539845bb 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1505,6 +1505,11 @@ print_file_mode(abi_long mode, int last)
  const char *sep = "";
  const struct flags *m;

+if (mode == 0) {
+qemu_log("000%s", get_comma(last));


I'd use either 0 or , not 000...

Preferably using a single 0:
Reviewed-by: Philippe Mathieu-Daudé 



+return;
+}
+
  for (m = _flags[0]; m->f_string != NULL; m++) {
  if ((m->f_value & mode) == m->f_value) {
  qemu_log("%s%s", m->f_string, sep);
--
2.37.3







Re: [PATCH v3 12/12] linux-user: Add parameters of getrandom() syscall for strace

2022-09-18 Thread Philippe Mathieu-Daudé via

On 18/9/22 21:45, Helge Deller wrote:

Signed-off-by: Helge Deller 
---
  linux-user/strace.list | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linux-user/strace.list b/linux-user/strace.list
index ad9ef94689..97d8ccadac 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -355,7 +355,7 @@
  { TARGET_NR_getpriority, "getpriority", "%s(%#x,%#x)", NULL, NULL },
  #endif
  #ifdef TARGET_NR_getrandom
-{ TARGET_NR_getrandom, "getrandom", NULL, NULL, NULL },
+{ TARGET_NR_getrandom, "getrandom", "%s(%p,%u,%d)", NULL, NULL },


The last argument is unsigned.

Conditional to using "%s(%p,%u,%u)":
Reviewed-by: Philippe Mathieu-Daudé 


  #endif
  #ifdef TARGET_NR_getresgid
  { TARGET_NR_getresgid, "getresgid" , NULL, NULL, NULL },
--
2.37.3







Re: [PATCH v3 04/12] linux-user: Log failing executable in EXCP_DUMP()

2022-09-18 Thread Philippe Mathieu-Daudé via

On 18/9/22 21:45, Helge Deller wrote:

Enhance the EXCP_DUMP() macro to print out the failing program too.
During debugging it's sometimes hard to track down the actual failing
program if you are e.g. building a whole debian package.

Signed-off-by: Helge Deller 
---
  linux-user/cpu_loop-common.h | 2 ++
  1 file changed, 2 insertions(+)


Reviewed-by: Philippe Mathieu-Daudé 



Re: [PATCH v5 09/21] ppc440_sdram: Split off map/unmap of sdram banks for later reuse

2022-09-18 Thread Philippe Mathieu-Daudé via

On 18/9/22 22:24, BALATON Zoltan wrote:

Signed-off-by: BALATON Zoltan 
---
  hw/ppc/ppc440_uc.c | 33 +
  1 file changed, 21 insertions(+), 12 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 



[PATCH v5 20/21] ppc4xx_sdram: Convert DDR SDRAM controller to new bank handling

2022-09-18 Thread BALATON Zoltan
Use the generic bank handling introduced in previous patch in the DDR
SDRAM controller too. This also fixes previously broken region unmap
due to sdram_ddr_unmap_bcr() ignoring container region so it crashed
with an assert when the guest tried to disable the controller.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/ppc4xx_sdram.c | 98 ---
 1 file changed, 37 insertions(+), 61 deletions(-)

diff --git a/hw/ppc/ppc4xx_sdram.c b/hw/ppc/ppc4xx_sdram.c
index 0d4b4f398f..2ef363d5e6 100644
--- a/hw/ppc/ppc4xx_sdram.c
+++ b/hw/ppc/ppc4xx_sdram.c
@@ -142,6 +142,8 @@ enum {
 
 /*/
 /* DDR SDRAM controller */
+#define SDRAM_DDR_BCR_MASK 0xFFDEE001
+
 static uint32_t sdram_ddr_bcr(hwaddr ram_base, hwaddr ram_size)
 {
 uint32_t bcr;
@@ -200,58 +202,6 @@ static hwaddr sdram_ddr_size(uint32_t bcr)
 return size;
 }
 
-static void sdram_ddr_set_bcr(Ppc4xxSdramDdrState *sdram, int i,
-  uint32_t bcr, int enabled)
-{
-if (sdram->bank[i].bcr & 1) {
-/* Unmap RAM */
-trace_ppc4xx_sdram_unmap(sdram_ddr_base(sdram->bank[i].bcr),
- sdram_ddr_size(sdram->bank[i].bcr));
-memory_region_del_subregion(get_system_memory(),
->bank[i].container);
-memory_region_del_subregion(>bank[i].container,
->bank[i].ram);
-object_unparent(OBJECT(>bank[i].container));
-}
-sdram->bank[i].bcr = bcr & 0xFFDEE001;
-if (enabled && (bcr & 1)) {
-trace_ppc4xx_sdram_map(sdram_ddr_base(bcr), sdram_ddr_size(bcr));
-memory_region_init(>bank[i].container, NULL, "sdram-container",
-   sdram_ddr_size(bcr));
-memory_region_add_subregion(>bank[i].container, 0,
->bank[i].ram);
-memory_region_add_subregion(get_system_memory(),
-sdram_ddr_base(bcr),
->bank[i].container);
-}
-}
-
-static void sdram_ddr_map_bcr(Ppc4xxSdramDdrState *sdram)
-{
-int i;
-
-for (i = 0; i < sdram->nbanks; i++) {
-if (sdram->bank[i].size != 0) {
-sdram_ddr_set_bcr(sdram, i, sdram_ddr_bcr(sdram->bank[i].base,
-  sdram->bank[i].size), 1);
-} else {
-sdram_ddr_set_bcr(sdram, i, 0, 0);
-}
-}
-}
-
-static void sdram_ddr_unmap_bcr(Ppc4xxSdramDdrState *sdram)
-{
-int i;
-
-for (i = 0; i < sdram->nbanks; i++) {
-trace_ppc4xx_sdram_unmap(sdram_ddr_base(sdram->bank[i].bcr),
- sdram_ddr_size(sdram->bank[i].bcr));
-memory_region_del_subregion(get_system_memory(),
->bank[i].ram);
-}
-}
-
 static uint32_t sdram_ddr_dcr_read(void *opaque, int dcrn)
 {
 Ppc4xxSdramDdrState *s = opaque;
@@ -322,6 +272,7 @@ static uint32_t sdram_ddr_dcr_read(void *opaque, int dcrn)
 static void sdram_ddr_dcr_write(void *opaque, int dcrn, uint32_t val)
 {
 Ppc4xxSdramDdrState *s = opaque;
+int i;
 
 switch (dcrn) {
 case SDRAM0_CFGADDR:
@@ -343,12 +294,24 @@ static void sdram_ddr_dcr_write(void *opaque, int dcrn, 
uint32_t val)
 if (!(s->cfg & 0x8000) && (val & 0x8000)) {
 trace_ppc4xx_sdram_enable("enable");
 /* validate all RAM mappings */
-sdram_ddr_map_bcr(s);
+for (i = 0; i < s->nbanks; i++) {
+if (s->bank[i].size) {
+sdram_bank_set_bcr(>bank[i], s->bank[i].bcr,
+   s->bank[i].base, s->bank[i].size,
+   1);
+}
+}
 s->status &= ~0x8000;
 } else if ((s->cfg & 0x8000) && !(val & 0x8000)) {
 trace_ppc4xx_sdram_enable("disable");
 /* invalidate all RAM mappings */
-sdram_ddr_unmap_bcr(s);
+for (i = 0; i < s->nbanks; i++) {
+if (s->bank[i].size) {
+sdram_bank_set_bcr(>bank[i], s->bank[i].bcr,
+   s->bank[i].base, s->bank[i].size,
+   0);
+}
+}
 s->status |= 0x8000;
 }
 if (!(s->cfg & 0x4000) && (val & 0x4000)) {
@@ -368,16 +331,16 @@ static void sdram_ddr_dcr_write(void *opaque, int dcrn, 
uint32_t val)
 s->pmit = (val & 0xF800) | 0x07C0;
 break;
 case 0x40: /* SDRAM_B0CR */
-sdram_ddr_set_bcr(s, 0, val, s->cfg & 0x8000);
-break;
 case 0x44: /* SDRAM_B1CR */
-sdram_ddr_set_bcr(s, 1, val, s->cfg & 

Re: [PATCH v5 00/21] ppc4xx_sdram QOMify and clean ups

2022-09-18 Thread Philippe Mathieu-Daudé via

On 18/9/22 22:24, BALATON Zoltan wrote:

This is the end of the QOMify series started by Cédric. This series
handles the SDRAM controller models to clean them up, QOMify and unify
them and at least partially clean up the mess that has accumulated
around these in the past. This includes the not yet merged patches
from the last series and new ones that change the DDR2 version used by
sam460ex.

v5: Add functions the enable sdram controller and call it from boards
v4: address more review comments
v3: Fix patches that got squashed during rebase
v2: address some review comments and try to avoid compile problem with
gcc 12.2 (untested)


When respining a large series with various patches already ready, you
could mention "missing review: patches F, L, N..." in the cover letter
so we directly go look at those.



[PATCH v5 15/21] ppc440_sdram: QOM'ify

2022-09-18 Thread BALATON Zoltan
Change the ppc440_sdram model to a QOM class derived from the
PPC4xx-dcr-device and name it ppc4xx-sdram-ddr2. This is mostly
modelling the DDR2 SDRAM controller found in the 460EX (used on the
sam460ex board). Newer SoCs (regardless of their PPC core, e.g. 405EX)
may have this controller but we only emulate enough of it for the
sam460ex u-boot firmware.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Cédric Le Goater 
---
 hw/ppc/ppc440.h |   2 -
 hw/ppc/ppc440_uc.c  | 121 
 hw/ppc/sam460ex.c   |   9 ++-
 include/hw/ppc/ppc4xx.h |  18 +-
 4 files changed, 97 insertions(+), 53 deletions(-)

diff --git a/hw/ppc/ppc440.h b/hw/ppc/ppc440.h
index 29f6f14ed7..7c24db8504 100644
--- a/hw/ppc/ppc440.h
+++ b/hw/ppc/ppc440.h
@@ -16,8 +16,6 @@
 void ppc4xx_l2sram_init(CPUPPCState *env);
 void ppc4xx_cpr_init(CPUPPCState *env);
 void ppc4xx_sdr_init(CPUPPCState *env);
-void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-   MemoryRegion *ram);
 void ppc4xx_ahb_init(CPUPPCState *env);
 void ppc4xx_dma_init(CPUPPCState *env, int dcr_base);
 void ppc460ex_pcie_init(CPUPPCState *env);
diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 2b9d666b71..46daecab19 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -484,13 +484,6 @@ void ppc4xx_sdr_init(CPUPPCState *env)
 
 /*/
 /* SDRAM controller */
-typedef struct ppc440_sdram_t {
-uint32_t addr;
-uint32_t mcopt2;
-int nbanks; /* Banks to use from the 4, e.g. when board has less slots */
-Ppc4xxSdramBank bank[4];
-} ppc440_sdram_t;
-
 enum {
 SDRAM0_CFGADDR = 0x10,
 SDRAM0_CFGDATA,
@@ -581,7 +574,7 @@ static void sdram_bank_unmap(Ppc4xxSdramBank *bank)
 object_unparent(OBJECT(>container));
 }
 
-static void sdram_ddr2_set_bcr(ppc440_sdram_t *sdram, int i,
+static void sdram_ddr2_set_bcr(Ppc4xxSdramDdr2State *sdram, int i,
uint32_t bcr, int enabled)
 {
 if (sdram->bank[i].bcr & 1) {
@@ -597,7 +590,7 @@ static void sdram_ddr2_set_bcr(ppc440_sdram_t *sdram, int i,
 }
 }
 
-static void sdram_ddr2_map_bcr(ppc440_sdram_t *sdram)
+static void sdram_ddr2_map_bcr(Ppc4xxSdramDdr2State *sdram)
 {
 int i;
 
@@ -612,7 +605,7 @@ static void sdram_ddr2_map_bcr(ppc440_sdram_t *sdram)
 }
 }
 
-static void sdram_ddr2_unmap_bcr(ppc440_sdram_t *sdram)
+static void sdram_ddr2_unmap_bcr(Ppc4xxSdramDdr2State *sdram)
 {
 int i;
 
@@ -625,7 +618,7 @@ static void sdram_ddr2_unmap_bcr(ppc440_sdram_t *sdram)
 
 static uint32_t sdram_ddr2_dcr_read(void *opaque, int dcrn)
 {
-ppc440_sdram_t *sdram = opaque;
+Ppc4xxSdramDdr2State *sdram = opaque;
 uint32_t ret = 0;
 
 switch (dcrn) {
@@ -680,7 +673,7 @@ static uint32_t sdram_ddr2_dcr_read(void *opaque, int dcrn)
 
 static void sdram_ddr2_dcr_write(void *opaque, int dcrn, uint32_t val)
 {
-ppc440_sdram_t *sdram = opaque;
+Ppc4xxSdramDdr2State *sdram = opaque;
 
 switch (dcrn) {
 case SDRAM_R0BAS:
@@ -724,58 +717,92 @@ static void sdram_ddr2_dcr_write(void *opaque, int dcrn, 
uint32_t val)
 }
 }
 
-static void sdram_ddr2_reset(void *opaque)
+static void ppc4xx_sdram_ddr2_reset(DeviceState *dev)
 {
-ppc440_sdram_t *sdram = opaque;
+Ppc4xxSdramDdr2State *sdram = PPC4xx_SDRAM_DDR2(dev);
 
 sdram->addr = 0;
 sdram->mcopt2 = 0;
 }
 
-void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-   MemoryRegion *ram)
+static void ppc4xx_sdram_ddr2_realize(DeviceState *dev, Error **errp)
 {
-ppc440_sdram_t *s;
+Ppc4xxSdramDdr2State *s = PPC4xx_SDRAM_DDR2(dev);
+Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev);
 const ram_addr_t valid_bank_sizes[] = {
 4 * GiB, 2 * GiB, 1 * GiB, 512 * MiB, 256 * MiB, 128 * MiB, 64 * MiB,
 32 * MiB, 16 * MiB, 8 * MiB, 0
 };
 
-s = g_malloc0(sizeof(*s));
-s->nbanks = nbanks;
-ppc4xx_sdram_banks(ram, s->nbanks, s->bank, valid_bank_sizes);
-qemu_register_reset(_ddr2_reset, s);
-ppc_dcr_register(env, SDRAM0_CFGADDR,
- s, _ddr2_dcr_read, _ddr2_dcr_write);
-ppc_dcr_register(env, SDRAM0_CFGDATA,
- s, _ddr2_dcr_read, _ddr2_dcr_write);
-
-ppc_dcr_register(env, SDRAM_R0BAS,
- s, _ddr2_dcr_read, _ddr2_dcr_write);
-ppc_dcr_register(env, SDRAM_R1BAS,
- s, _ddr2_dcr_read, _ddr2_dcr_write);
-ppc_dcr_register(env, SDRAM_R2BAS,
- s, _ddr2_dcr_read, _ddr2_dcr_write);
-ppc_dcr_register(env, SDRAM_R3BAS,
- s, _ddr2_dcr_read, _ddr2_dcr_write);
-ppc_dcr_register(env, SDRAM_CONF1HB,
- s, _ddr2_dcr_read, _ddr2_dcr_write);
-ppc_dcr_register(env, SDRAM_PLBADDULL,
- s, _ddr2_dcr_read, _ddr2_dcr_write);
-ppc_dcr_register(env, SDRAM_CONF1LL,
- s, _ddr2_dcr_read, _ddr2_dcr_write);
-

[PATCH v5 19/21] ppc4xx_sdram: Generalise bank setup

2022-09-18 Thread BALATON Zoltan
Currently only base and size are set on initial bank creation and bcr
value is computed on mapping the region. Set bcr at init so the bcr
encoding method becomes local to the controller model and mapping and
unmapping can operate on the bank so it can be shared between
different controller models. This patch converts the DDR2 controller.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/ppc4xx_sdram.c | 91 ++-
 hw/ppc/trace-events   |  1 +
 2 files changed, 48 insertions(+), 44 deletions(-)

diff --git a/hw/ppc/ppc4xx_sdram.c b/hw/ppc/ppc4xx_sdram.c
index 3b2d01a144..0d4b4f398f 100644
--- a/hw/ppc/ppc4xx_sdram.c
+++ b/hw/ppc/ppc4xx_sdram.c
@@ -106,6 +106,7 @@ static void ppc4xx_sdram_banks(MemoryRegion *ram, int 
nr_banks,
 
 static void sdram_bank_map(Ppc4xxSdramBank *bank)
 {
+trace_ppc4xx_sdram_map(bank->base, bank->size);
 memory_region_init(>container, NULL, "sdram-container", bank->size);
 memory_region_add_subregion(>container, 0, >ram);
 memory_region_add_subregion(get_system_memory(), bank->base,
@@ -114,11 +115,26 @@ static void sdram_bank_map(Ppc4xxSdramBank *bank)
 
 static void sdram_bank_unmap(Ppc4xxSdramBank *bank)
 {
+trace_ppc4xx_sdram_unmap(bank->base, bank->size);
 memory_region_del_subregion(get_system_memory(), >container);
 memory_region_del_subregion(>container, >ram);
 object_unparent(OBJECT(>container));
 }
 
+static void sdram_bank_set_bcr(Ppc4xxSdramBank *bank, uint32_t bcr,
+   hwaddr base, hwaddr size, int enabled)
+{
+if (memory_region_is_mapped(>container)) {
+sdram_bank_unmap(bank);
+}
+bank->bcr = bcr;
+bank->base = base;
+bank->size = size;
+if (enabled && (bcr & 1)) {
+sdram_bank_map(bank);
+}
+}
+
 enum {
 SDRAM0_CFGADDR = 0x010,
 SDRAM0_CFGDATA = 0x011,
@@ -456,6 +472,8 @@ void ppc4xx_sdram_ddr_enable(Ppc4xxSdramDdrState *s)
 
 /*/
 /* DDR2 SDRAM controller */
+#define SDRAM_DDR2_BCR_MASK 0xffe0ffc1
+
 enum {
 SDRAM_R0BAS = 0x40,
 SDRAM_R1BAS,
@@ -529,48 +547,6 @@ static hwaddr sdram_ddr2_size(uint32_t bcr)
 return size;
 }
 
-static void sdram_ddr2_set_bcr(Ppc4xxSdramDdr2State *sdram, int i,
-   uint32_t bcr, int enabled)
-{
-if (sdram->bank[i].bcr & 1) {
-/* First unmap RAM if enabled */
-trace_ppc4xx_sdram_unmap(sdram_ddr2_base(sdram->bank[i].bcr),
- sdram_ddr2_size(sdram->bank[i].bcr));
-sdram_bank_unmap(>bank[i]);
-}
-sdram->bank[i].bcr = bcr & 0xffe0ffc1;
-if (enabled && (bcr & 1)) {
-trace_ppc4xx_sdram_map(sdram_ddr2_base(bcr), sdram_ddr2_size(bcr));
-sdram_bank_map(>bank[i]);
-}
-}
-
-static void sdram_ddr2_map_bcr(Ppc4xxSdramDdr2State *sdram)
-{
-int i;
-
-for (i = 0; i < sdram->nbanks; i++) {
-if (sdram->bank[i].size) {
-sdram_ddr2_set_bcr(sdram, i,
-   sdram_ddr2_bcr(sdram->bank[i].base,
-  sdram->bank[i].size), 1);
-} else {
-sdram_ddr2_set_bcr(sdram, i, 0, 0);
-}
-}
-}
-
-static void sdram_ddr2_unmap_bcr(Ppc4xxSdramDdr2State *sdram)
-{
-int i;
-
-for (i = 0; i < sdram->nbanks; i++) {
-if (sdram->bank[i].size) {
-sdram_ddr2_set_bcr(sdram, i, sdram->bank[i].bcr & ~1, 0);
-}
-}
-}
-
 static uint32_t sdram_ddr2_dcr_read(void *opaque, int dcrn)
 {
 Ppc4xxSdramDdr2State *s = opaque;
@@ -629,6 +605,7 @@ static uint32_t sdram_ddr2_dcr_read(void *opaque, int dcrn)
 static void sdram_ddr2_dcr_write(void *opaque, int dcrn, uint32_t val)
 {
 Ppc4xxSdramDdr2State *s = opaque;
+int i;
 
 switch (dcrn) {
 case SDRAM_R0BAS:
@@ -653,13 +630,25 @@ static void sdram_ddr2_dcr_write(void *opaque, int dcrn, 
uint32_t val)
 (val & SDRAM_DDR2_MCOPT2_DCEN)) {
 trace_ppc4xx_sdram_enable("enable");
 /* validate all RAM mappings */
-sdram_ddr2_map_bcr(s);
+for (i = 0; i < s->nbanks; i++) {
+if (s->bank[i].size) {
+sdram_bank_set_bcr(>bank[i], s->bank[i].bcr,
+   s->bank[i].base, s->bank[i].size,
+   1);
+}
+}
 s->mcopt2 |= SDRAM_DDR2_MCOPT2_DCEN;
 } else if ((s->mcopt2 & SDRAM_DDR2_MCOPT2_DCEN) &&
!(val & SDRAM_DDR2_MCOPT2_DCEN)) {
 trace_ppc4xx_sdram_enable("disable");
 /* invalidate all RAM mappings */
-sdram_ddr2_unmap_bcr(s);
+for (i = 0; i < s->nbanks; i++) {
+if (s->bank[i].size) {
+sdram_bank_set_bcr(>bank[i], s->bank[i].bcr,
+   

Re: [PATCH v3 06/12] linux-user/hppa: Dump IIR on register dump

2022-09-18 Thread Philippe Mathieu-Daudé via

On 18/9/22 21:45, Helge Deller wrote:

Include the IIR register (which holds the opcode of the failing
instruction) when dumping the hppa registers.

Signed-off-by: Helge Deller 
---
  target/hppa/helper.c | 6 --
  1 file changed, 4 insertions(+), 2 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 



[PATCH v5 18/21] ppc4xx_sdram: Rename local state variable for brevity

2022-09-18 Thread BALATON Zoltan
Rename the sdram local state variable to s in dcr read/write functions
and reset methods for better readability and to match realize methods.
Other places not converted will be changed or removed in subsequent
patches.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/ppc4xx_sdram.c | 158 +-
 1 file changed, 79 insertions(+), 79 deletions(-)

diff --git a/hw/ppc/ppc4xx_sdram.c b/hw/ppc/ppc4xx_sdram.c
index 3ec2edeb17..3b2d01a144 100644
--- a/hw/ppc/ppc4xx_sdram.c
+++ b/hw/ppc/ppc4xx_sdram.c
@@ -238,56 +238,56 @@ static void sdram_ddr_unmap_bcr(Ppc4xxSdramDdrState 
*sdram)
 
 static uint32_t sdram_ddr_dcr_read(void *opaque, int dcrn)
 {
-Ppc4xxSdramDdrState *sdram = opaque;
+Ppc4xxSdramDdrState *s = opaque;
 uint32_t ret;
 
 switch (dcrn) {
 case SDRAM0_CFGADDR:
-ret = sdram->addr;
+ret = s->addr;
 break;
 case SDRAM0_CFGDATA:
-switch (sdram->addr) {
+switch (s->addr) {
 case 0x00: /* SDRAM_BESR0 */
-ret = sdram->besr0;
+ret = s->besr0;
 break;
 case 0x08: /* SDRAM_BESR1 */
-ret = sdram->besr1;
+ret = s->besr1;
 break;
 case 0x10: /* SDRAM_BEAR */
-ret = sdram->bear;
+ret = s->bear;
 break;
 case 0x20: /* SDRAM_CFG */
-ret = sdram->cfg;
+ret = s->cfg;
 break;
 case 0x24: /* SDRAM_STATUS */
-ret = sdram->status;
+ret = s->status;
 break;
 case 0x30: /* SDRAM_RTR */
-ret = sdram->rtr;
+ret = s->rtr;
 break;
 case 0x34: /* SDRAM_PMIT */
-ret = sdram->pmit;
+ret = s->pmit;
 break;
 case 0x40: /* SDRAM_B0CR */
-ret = sdram->bank[0].bcr;
+ret = s->bank[0].bcr;
 break;
 case 0x44: /* SDRAM_B1CR */
-ret = sdram->bank[1].bcr;
+ret = s->bank[1].bcr;
 break;
 case 0x48: /* SDRAM_B2CR */
-ret = sdram->bank[2].bcr;
+ret = s->bank[2].bcr;
 break;
 case 0x4C: /* SDRAM_B3CR */
-ret = sdram->bank[3].bcr;
+ret = s->bank[3].bcr;
 break;
 case 0x80: /* SDRAM_TR */
 ret = -1; /* ? */
 break;
 case 0x94: /* SDRAM_ECCCFG */
-ret = sdram->ecccfg;
+ret = s->ecccfg;
 break;
 case 0x98: /* SDRAM_ECCESR */
-ret = sdram->eccesr;
+ret = s->eccesr;
 break;
 default: /* Error */
 ret = -1;
@@ -305,78 +305,78 @@ static uint32_t sdram_ddr_dcr_read(void *opaque, int dcrn)
 
 static void sdram_ddr_dcr_write(void *opaque, int dcrn, uint32_t val)
 {
-Ppc4xxSdramDdrState *sdram = opaque;
+Ppc4xxSdramDdrState *s = opaque;
 
 switch (dcrn) {
 case SDRAM0_CFGADDR:
-sdram->addr = val;
+s->addr = val;
 break;
 case SDRAM0_CFGDATA:
-switch (sdram->addr) {
+switch (s->addr) {
 case 0x00: /* SDRAM_BESR0 */
-sdram->besr0 &= ~val;
+s->besr0 &= ~val;
 break;
 case 0x08: /* SDRAM_BESR1 */
-sdram->besr1 &= ~val;
+s->besr1 &= ~val;
 break;
 case 0x10: /* SDRAM_BEAR */
-sdram->bear = val;
+s->bear = val;
 break;
 case 0x20: /* SDRAM_CFG */
 val &= 0xFFE0;
-if (!(sdram->cfg & 0x8000) && (val & 0x8000)) {
+if (!(s->cfg & 0x8000) && (val & 0x8000)) {
 trace_ppc4xx_sdram_enable("enable");
 /* validate all RAM mappings */
-sdram_ddr_map_bcr(sdram);
-sdram->status &= ~0x8000;
-} else if ((sdram->cfg & 0x8000) && !(val & 0x8000)) {
+sdram_ddr_map_bcr(s);
+s->status &= ~0x8000;
+} else if ((s->cfg & 0x8000) && !(val & 0x8000)) {
 trace_ppc4xx_sdram_enable("disable");
 /* invalidate all RAM mappings */
-sdram_ddr_unmap_bcr(sdram);
-sdram->status |= 0x8000;
+sdram_ddr_unmap_bcr(s);
+s->status |= 0x8000;
 }
-if (!(sdram->cfg & 0x4000) && (val & 0x4000)) {
-sdram->status |= 0x4000;
-} else if ((sdram->cfg & 0x4000) && !(val & 0x4000)) {
-sdram->status &= ~0x4000;
+if (!(s->cfg & 0x4000) && (val & 0x4000)) {
+s->status |= 0x4000;
+} else if ((s->cfg & 0x4000) && !(val & 0x4000)) {
+s->status &= ~0x4000;
 }
-sdram->cfg = val;
+s->cfg = val;
 break;
   

[PATCH v5 14/21] ppc440_sdram: Move RAM size check to ppc440_sdram_init

2022-09-18 Thread BALATON Zoltan
Move the check for valid memory sizes from board to sdram controller
init. This adds the missing valid memory sizes of 4 GiB, 16 and 8 MiB
to the DoC and the board now only checks for additional restrictions
imposed by its firmware then sdram init checks for valid sizes for SoC.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/ppc440.h|  4 ++--
 hw/ppc/ppc440_uc.c | 15 +++
 hw/ppc/sam460ex.c  | 32 +---
 3 files changed, 26 insertions(+), 25 deletions(-)

diff --git a/hw/ppc/ppc440.h b/hw/ppc/ppc440.h
index 01d76b8000..29f6f14ed7 100644
--- a/hw/ppc/ppc440.h
+++ b/hw/ppc/ppc440.h
@@ -11,13 +11,13 @@
 #ifndef PPC440_H
 #define PPC440_H
 
-#include "hw/ppc/ppc4xx.h"
+#include "hw/ppc/ppc.h"
 
 void ppc4xx_l2sram_init(CPUPPCState *env);
 void ppc4xx_cpr_init(CPUPPCState *env);
 void ppc4xx_sdr_init(CPUPPCState *env);
 void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-   Ppc4xxSdramBank *ram_banks);
+   MemoryRegion *ram);
 void ppc4xx_ahb_init(CPUPPCState *env);
 void ppc4xx_dma_init(CPUPPCState *env, int dcr_base);
 void ppc460ex_pcie_init(CPUPPCState *env);
diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index edd0781eb7..2b9d666b71 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -487,7 +487,7 @@ void ppc4xx_sdr_init(CPUPPCState *env)
 typedef struct ppc440_sdram_t {
 uint32_t addr;
 uint32_t mcopt2;
-int nbanks;
+int nbanks; /* Banks to use from the 4, e.g. when board has less slots */
 Ppc4xxSdramBank bank[4];
 } ppc440_sdram_t;
 
@@ -733,18 +733,17 @@ static void sdram_ddr2_reset(void *opaque)
 }
 
 void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-   Ppc4xxSdramBank *ram_banks)
+   MemoryRegion *ram)
 {
 ppc440_sdram_t *s;
-int i;
+const ram_addr_t valid_bank_sizes[] = {
+4 * GiB, 2 * GiB, 1 * GiB, 512 * MiB, 256 * MiB, 128 * MiB, 64 * MiB,
+32 * MiB, 16 * MiB, 8 * MiB, 0
+};
 
 s = g_malloc0(sizeof(*s));
 s->nbanks = nbanks;
-for (i = 0; i < nbanks; i++) {
-s->bank[i].ram = ram_banks[i].ram;
-s->bank[i].base = ram_banks[i].base;
-s->bank[i].size = ram_banks[i].size;
-}
+ppc4xx_sdram_banks(ram, s->nbanks, s->bank, valid_bank_sizes);
 qemu_register_reset(_ddr2_reset, s);
 ppc_dcr_register(env, SDRAM0_CFGADDR,
  s, _ddr2_dcr_read, _ddr2_dcr_write);
diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
index b318521b01..13055a8916 100644
--- a/hw/ppc/sam460ex.c
+++ b/hw/ppc/sam460ex.c
@@ -74,13 +74,6 @@
 #define EBC_FREQ 11500
 #define UART_FREQ 11059200
 
-/* The SoC could also handle 4 GiB but firmware does not work with that. */
-/* Maybe it overflows a signed 32 bit number somewhere? */
-static const ram_addr_t ppc460ex_sdram_bank_sizes[] = {
-2 * GiB, 1 * GiB, 512 * MiB, 256 * MiB, 128 * MiB, 64 * MiB,
-32 * MiB, 0
-};
-
 struct boot_info {
 uint32_t dt_base;
 uint32_t dt_size;
@@ -273,7 +266,6 @@ static void sam460ex_init(MachineState *machine)
 {
 MemoryRegion *address_space_mem = get_system_memory();
 MemoryRegion *isa = g_new(MemoryRegion, 1);
-Ppc4xxSdramBank *ram_banks = g_new0(Ppc4xxSdramBank, 1);
 MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1);
 DeviceState *uic[4];
 int i;
@@ -340,12 +332,22 @@ static void sam460ex_init(MachineState *machine)
 }
 
 /* SDRAM controller */
-/* put all RAM on first bank because board has one slot
- * and firmware only checks that */
-ppc4xx_sdram_banks(machine->ram, 1, ram_banks, ppc460ex_sdram_bank_sizes);
-
+/* The SoC could also handle 4 GiB but firmware does not work with that. */
+if (machine->ram_size > 2 * GiB) {
+error_report("Memory over 2 GiB is not supported");
+exit(1);
+}
+/* Firmware needs at least 64 MiB */
+if (machine->ram_size < 64 * MiB) {
+error_report("Memory below 64 MiB is not supported");
+exit(1);
+}
+/*
+ * Put all RAM on first bank because board has one slot
+ * and firmware only checks that
+ */
+ppc440_sdram_init(env, 1, machine->ram);
 /* FIXME: does 460EX have ECC interrupts? */
-ppc440_sdram_init(env, 1, ram_banks);
 /* Enable SDRAM memory regions as we may boot without firmware */
 ppc4xx_sdram_ddr2_enable(env);
 
@@ -354,8 +356,8 @@ static void sam460ex_init(MachineState *machine)
qdev_get_gpio_in(uic[0], 2));
 i2c = PPC4xx_I2C(dev)->bus;
 /* SPD EEPROM on RAM module */
-spd_data = spd_data_generate(ram_banks->size < 128 * MiB ? DDR : DDR2,
- ram_banks->size);
+spd_data = spd_data_generate(machine->ram_size < 128 * MiB ? DDR : DDR2,
+ machine->ram_size);
 spd_data[20] = 4; /* SO-DIMM module */
 smbus_eeprom_init_one(i2c, 0x50, spd_data);
 /* RTC */
-- 
2.30.4




[PATCH v5 13/21] ppc4xx_sdram: Rename functions to prevent name clashes

2022-09-18 Thread BALATON Zoltan
Rename functions to avoid name clashes when moving the DDR2 controller
model currently called ppc440_sdram to ppc4xx_devs. This also more
clearly shows which function belongs to which model.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/ppc/ppc405_boards.c  |  2 +-
 hw/ppc/ppc440_bamboo.c  |  2 +-
 hw/ppc/ppc440_uc.c  | 67 +
 hw/ppc/ppc4xx_devs.c| 46 ++--
 hw/ppc/sam460ex.c   |  2 +-
 include/hw/ppc/ppc4xx.h |  4 +--
 6 files changed, 62 insertions(+), 61 deletions(-)

diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index b59393d4bd..4092ebc1ab 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -337,7 +337,7 @@ static void ppc405_init(MachineState *machine)
 
 /* Load ELF kernel and rootfs.cpio */
 } else if (kernel_filename && !machine->firmware) {
-ppc4xx_sdram_enable(>soc.sdram);
+ppc4xx_sdram_ddr_enable(>soc.sdram);
 boot_from_kernel(machine, >soc.cpu);
 }
 }
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index 5c35ba6086..56f47e7509 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -204,7 +204,7 @@ static void bamboo_init(MachineState *machine)
 /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
 sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(uicdev, 14));
 /* Enable SDRAM memory regions, this should be done by the firmware */
-ppc4xx_sdram_enable(PPC4xx_SDRAM_DDR(dev));
+ppc4xx_sdram_ddr_enable(PPC4xx_SDRAM_DDR(dev));
 
 /* PCI */
 dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST_BRIDGE,
diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 97e6d5f5b2..edd0781eb7 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -505,7 +505,7 @@ enum {
 SDRAM_PLBADDUHB = 0x50,
 };
 
-static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size)
+static uint32_t sdram_ddr2_bcr(hwaddr ram_base, hwaddr ram_size)
 {
 uint32_t bcr;
 
@@ -550,12 +550,12 @@ static uint32_t sdram_bcr(hwaddr ram_base, hwaddr 
ram_size)
 return bcr;
 }
 
-static inline hwaddr sdram_base(uint32_t bcr)
+static inline hwaddr sdram_ddr2_base(uint32_t bcr)
 {
 return (bcr & 0xffe0) << 2;
 }
 
-static uint64_t sdram_size(uint32_t bcr)
+static uint64_t sdram_ddr2_size(uint32_t bcr)
 {
 uint64_t size;
 int sh;
@@ -581,48 +581,49 @@ static void sdram_bank_unmap(Ppc4xxSdramBank *bank)
 object_unparent(OBJECT(>container));
 }
 
-static void sdram_set_bcr(ppc440_sdram_t *sdram, int i,
-  uint32_t bcr, int enabled)
+static void sdram_ddr2_set_bcr(ppc440_sdram_t *sdram, int i,
+   uint32_t bcr, int enabled)
 {
 if (sdram->bank[i].bcr & 1) {
 /* First unmap RAM if enabled */
-trace_ppc4xx_sdram_unmap(sdram_base(sdram->bank[i].bcr),
- sdram_size(sdram->bank[i].bcr));
+trace_ppc4xx_sdram_unmap(sdram_ddr2_base(sdram->bank[i].bcr),
+ sdram_ddr2_size(sdram->bank[i].bcr));
 sdram_bank_unmap(>bank[i]);
 }
 sdram->bank[i].bcr = bcr & 0xffe0ffc1;
 if (enabled && (bcr & 1)) {
-trace_ppc4xx_sdram_map(sdram_base(bcr), sdram_size(bcr));
+trace_ppc4xx_sdram_map(sdram_ddr2_base(bcr), sdram_ddr2_size(bcr));
 sdram_bank_map(>bank[i]);
 }
 }
 
-static void sdram_map_bcr(ppc440_sdram_t *sdram)
+static void sdram_ddr2_map_bcr(ppc440_sdram_t *sdram)
 {
 int i;
 
 for (i = 0; i < sdram->nbanks; i++) {
 if (sdram->bank[i].size) {
-sdram_set_bcr(sdram, i, sdram_bcr(sdram->bank[i].base,
+sdram_ddr2_set_bcr(sdram, i,
+   sdram_ddr2_bcr(sdram->bank[i].base,
   sdram->bank[i].size), 1);
 } else {
-sdram_set_bcr(sdram, i, 0, 0);
+sdram_ddr2_set_bcr(sdram, i, 0, 0);
 }
 }
 }
 
-static void sdram_unmap_bcr(ppc440_sdram_t *sdram)
+static void sdram_ddr2_unmap_bcr(ppc440_sdram_t *sdram)
 {
 int i;
 
 for (i = 0; i < sdram->nbanks; i++) {
 if (sdram->bank[i].size) {
-sdram_set_bcr(sdram, i, sdram->bank[i].bcr & ~1, 0);
+sdram_ddr2_set_bcr(sdram, i, sdram->bank[i].bcr & ~1, 0);
 }
 }
 }
 
-static uint32_t dcr_read_sdram(void *opaque, int dcrn)
+static uint32_t sdram_ddr2_dcr_read(void *opaque, int dcrn)
 {
 ppc440_sdram_t *sdram = opaque;
 uint32_t ret = 0;
@@ -633,8 +634,8 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
 case SDRAM_R2BAS:
 case SDRAM_R3BAS:
 if (sdram->bank[dcrn - SDRAM_R0BAS].size) {
-ret = sdram_bcr(sdram->bank[dcrn - SDRAM_R0BAS].base,
-sdram->bank[dcrn - SDRAM_R0BAS].size);
+ret = sdram_ddr2_bcr(sdram->bank[dcrn - SDRAM_R0BAS].base,
+ sdram->bank[dcrn - 

[PATCH v5 21/21] ppc4xx_sdram: Add errp parameter to ppc4xx_sdram_banks()

2022-09-18 Thread BALATON Zoltan
Do not exit from ppc4xx_sdram_banks() but report error via an errp
parameter instead.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/ppc/ppc4xx_sdram.c | 28 +++-
 1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/hw/ppc/ppc4xx_sdram.c b/hw/ppc/ppc4xx_sdram.c
index 2ef363d5e6..543d47aec3 100644
--- a/hw/ppc/ppc4xx_sdram.c
+++ b/hw/ppc/ppc4xx_sdram.c
@@ -53,10 +53,12 @@
  * must be one of a small set of sizes. The number of banks and the supported
  * sizes varies by SoC.
  */
-static void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
+static bool ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
Ppc4xxSdramBank ram_banks[],
-   const ram_addr_t sdram_bank_sizes[])
+   const ram_addr_t sdram_bank_sizes[],
+   Error **errp)
 {
+ERRP_GUARD();
 ram_addr_t size_left = memory_region_size(ram);
 ram_addr_t base = 0;
 ram_addr_t bank_size;
@@ -94,14 +96,16 @@ static void ppc4xx_sdram_banks(MemoryRegion *ram, int 
nr_banks,
sdram_bank_sizes[i] / MiB,
sdram_bank_sizes[i + 1] ? ", " : "");
 }
-error_report("at most %d bank%s of %s MiB each supported",
- nr_banks, nr_banks == 1 ? "" : "s", s->str);
-error_printf("Possible valid RAM size: %" PRIi64 " MiB\n",
-used_size ? used_size / MiB : sdram_bank_sizes[i - 1] / MiB);
+error_setg(errp, "Invalid SDRAM banks");
+error_append_hint(errp, "at most %d bank%s of %s MiB each supported\n",
+  nr_banks, nr_banks == 1 ? "" : "s", s->str);
+error_append_hint(errp, "Possible valid RAM size: %" PRIi64 " MiB\n",
+  used_size ? used_size / MiB : sdram_bank_sizes[i - 1] / MiB);
 
 g_string_free(s, true);
-exit(EXIT_FAILURE);
+return false;
 }
+return true;
 }
 
 static void sdram_bank_map(Ppc4xxSdramBank *bank)
@@ -400,7 +404,10 @@ static void ppc4xx_sdram_ddr_realize(DeviceState *dev, 
Error **errp)
 error_setg(errp, "Missing dram memory region");
 return;
 }
-ppc4xx_sdram_banks(s->dram_mr, s->nbanks, s->bank, valid_bank_sizes);
+if (!ppc4xx_sdram_banks(s->dram_mr, s->nbanks, s->bank,
+valid_bank_sizes, errp)) {
+return;
+}
 for (i = 0; i < s->nbanks; i++) {
 if (s->bank[i].size) {
 s->bank[i].bcr = sdram_ddr_bcr(s->bank[i].base, s->bank[i].size);
@@ -663,7 +670,10 @@ static void ppc4xx_sdram_ddr2_realize(DeviceState *dev, 
Error **errp)
 error_setg(errp, "Missing dram memory region");
 return;
 }
-ppc4xx_sdram_banks(s->dram_mr, s->nbanks, s->bank, valid_bank_sizes);
+if (!ppc4xx_sdram_banks(s->dram_mr, s->nbanks, s->bank,
+valid_bank_sizes, errp)) {
+return;
+}
 for (i = 0; i < s->nbanks; i++) {
 if (s->bank[i].size) {
 s->bank[i].bcr = sdram_ddr2_bcr(s->bank[i].base, s->bank[i].size);
-- 
2.30.4




[PATCH v5 16/21] ppc4xx_sdram: Move ppc4xx DDR and DDR2 SDRAM controller models together

2022-09-18 Thread BALATON Zoltan
Move the PPC4xx DDR and DDR2 SDRAM contrller models into a new file
called ppc4xx_sdram to separate from other device models and put them
in one place allowing sharing some code between them.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/meson.build  |   3 +-
 hw/ppc/ppc440_uc.c  | 332 -
 hw/ppc/ppc4xx_devs.c| 414 -
 hw/ppc/ppc4xx_sdram.c   | 771 
 include/hw/ppc/ppc4xx.h |  24 +-
 5 files changed, 785 insertions(+), 759 deletions(-)
 create mode 100644 hw/ppc/ppc4xx_sdram.c

diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build
index 62801923f3..74720dd1e1 100644
--- a/hw/ppc/meson.build
+++ b/hw/ppc/meson.build
@@ -59,8 +59,9 @@ ppc_ss.add(when: 'CONFIG_PPC440', if_true: files(
   'ppc440_bamboo.c',
   'ppc440_pcix.c', 'ppc440_uc.c'))
 ppc_ss.add(when: 'CONFIG_PPC4XX', if_true: files(
+  'ppc4xx_devs.c',
   'ppc4xx_pci.c',
-  'ppc4xx_devs.c'))
+  'ppc4xx_sdram.c'))
 ppc_ss.add(when: 'CONFIG_SAM460EX', if_true: files('sam460ex.c'))
 # PReP
 ppc_ss.add(when: 'CONFIG_PREP', if_true: files('prep.c'))
diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 46daecab19..651263926e 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -10,21 +10,14 @@
 
 #include "qemu/osdep.h"
 #include "qemu/units.h"
-#include "qemu/error-report.h"
 #include "qapi/error.h"
 #include "qemu/log.h"
-#include "qemu/module.h"
 #include "hw/irq.h"
-#include "exec/memory.h"
-#include "cpu.h"
 #include "hw/ppc/ppc4xx.h"
 #include "hw/qdev-properties.h"
 #include "hw/pci/pci.h"
-#include "sysemu/block-backend.h"
 #include "sysemu/reset.h"
 #include "ppc440.h"
-#include "qom/object.h"
-#include "trace.h"
 
 /*/
 /* L2 Cache as SRAM */
@@ -380,10 +373,6 @@ enum {
 PESDR1_RSTSTA = 0x365,
 };
 
-#define SDR0_DDR0_DDRM_ENCODE(n)  unsigned long)(n)) & 0x03) << 29)
-#define SDR0_DDR0_DDRM_DDR1   0x2000
-#define SDR0_DDR0_DDRM_DDR2   0x4000
-
 static uint32_t dcr_read_sdr(void *opaque, int dcrn)
 {
 ppc4xx_sdr_t *sdr = opaque;
@@ -482,327 +471,6 @@ void ppc4xx_sdr_init(CPUPPCState *env)
  sdr, _read_sdr, _write_sdr);
 }
 
-/*/
-/* SDRAM controller */
-enum {
-SDRAM0_CFGADDR = 0x10,
-SDRAM0_CFGDATA,
-SDRAM_R0BAS = 0x40,
-SDRAM_R1BAS,
-SDRAM_R2BAS,
-SDRAM_R3BAS,
-SDRAM_CONF1HB = 0x45,
-SDRAM_PLBADDULL = 0x4a,
-SDRAM_CONF1LL = 0x4b,
-SDRAM_CONFPATHB = 0x4f,
-SDRAM_PLBADDUHB = 0x50,
-};
-
-static uint32_t sdram_ddr2_bcr(hwaddr ram_base, hwaddr ram_size)
-{
-uint32_t bcr;
-
-switch (ram_size) {
-case (8 * MiB):
-bcr = 0xffc0;
-break;
-case (16 * MiB):
-bcr = 0xff80;
-break;
-case (32 * MiB):
-bcr = 0xff00;
-break;
-case (64 * MiB):
-bcr = 0xfe00;
-break;
-case (128 * MiB):
-bcr = 0xfc00;
-break;
-case (256 * MiB):
-bcr = 0xf800;
-break;
-case (512 * MiB):
-bcr = 0xf000;
-break;
-case (1 * GiB):
-bcr = 0xe000;
-break;
-case (2 * GiB):
-bcr = 0xc000;
-break;
-case (4 * GiB):
-bcr = 0x8000;
-break;
-default:
-error_report("invalid RAM size " TARGET_FMT_plx, ram_size);
-return 0;
-}
-bcr |= ram_base >> 2 & 0xffe0;
-bcr |= 1;
-
-return bcr;
-}
-
-static inline hwaddr sdram_ddr2_base(uint32_t bcr)
-{
-return (bcr & 0xffe0) << 2;
-}
-
-static uint64_t sdram_ddr2_size(uint32_t bcr)
-{
-uint64_t size;
-int sh;
-
-sh = 1024 - ((bcr >> 6) & 0x3ff);
-size = 8 * MiB * sh;
-
-return size;
-}
-
-static void sdram_bank_map(Ppc4xxSdramBank *bank)
-{
-memory_region_init(>container, NULL, "sdram-container", bank->size);
-memory_region_add_subregion(>container, 0, >ram);
-memory_region_add_subregion(get_system_memory(), bank->base,
->container);
-}
-
-static void sdram_bank_unmap(Ppc4xxSdramBank *bank)
-{
-memory_region_del_subregion(get_system_memory(), >container);
-memory_region_del_subregion(>container, >ram);
-object_unparent(OBJECT(>container));
-}
-
-static void sdram_ddr2_set_bcr(Ppc4xxSdramDdr2State *sdram, int i,
-   uint32_t bcr, int enabled)
-{
-if (sdram->bank[i].bcr & 1) {
-/* First unmap RAM if enabled */
-trace_ppc4xx_sdram_unmap(sdram_ddr2_base(sdram->bank[i].bcr),
- sdram_ddr2_size(sdram->bank[i].bcr));
-sdram_bank_unmap(>bank[i]);
-}
-sdram->bank[i].bcr = bcr & 0xffe0ffc1;
-if (enabled && (bcr & 1)) {
-trace_ppc4xx_sdram_map(sdram_ddr2_base(bcr), sdram_ddr2_size(bcr));
-sdram_bank_map(>bank[i]);
-}
-}
-
-static void sdram_ddr2_map_bcr(Ppc4xxSdramDdr2State *sdram)
-{
-

[PATCH v5 10/21] ppc440_sdram: Implement enable bit in the DDR2 SDRAM

2022-09-18 Thread BALATON Zoltan
To allow removing the do_init hack we need to improve the DDR2 SDRAM
controller model to handle the enable/disable bit that it ignored so
far.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/ppc440_uc.c | 34 --
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 900b7ab998..3fbfe4ad13 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -485,6 +485,7 @@ void ppc4xx_sdr_init(CPUPPCState *env)
 /* SDRAM controller */
 typedef struct ppc440_sdram_t {
 uint32_t addr;
+uint32_t mcopt2;
 int nbanks;
 Ppc4xxSdramBank bank[4];
 } ppc440_sdram_t;
@@ -600,7 +601,7 @@ static void sdram_map_bcr(ppc440_sdram_t *sdram)
 int i;
 
 for (i = 0; i < sdram->nbanks; i++) {
-if (sdram->bank[i].size != 0) {
+if (sdram->bank[i].size) {
 sdram_set_bcr(sdram, i, sdram_bcr(sdram->bank[i].base,
   sdram->bank[i].size), 1);
 } else {
@@ -609,6 +610,17 @@ static void sdram_map_bcr(ppc440_sdram_t *sdram)
 }
 }
 
+static void sdram_unmap_bcr(ppc440_sdram_t *sdram)
+{
+int i;
+
+for (i = 0; i < sdram->nbanks; i++) {
+if (sdram->bank[i].size) {
+sdram_set_bcr(sdram, i, sdram->bank[i].bcr & ~1, 0);
+}
+}
+}
+
 static uint32_t dcr_read_sdram(void *opaque, int dcrn)
 {
 ppc440_sdram_t *sdram = opaque;
@@ -640,7 +652,7 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
 ret = 0x8000;
 break;
 case 0x21: /* SDRAM_MCOPT2 */
-ret = 0x0800;
+ret = sdram->mcopt2;
 break;
 case 0x40: /* SDRAM_MB0CF */
 ret = 0x8001;
@@ -662,6 +674,8 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
 return ret;
 }
 
+#define SDRAM_DDR2_MCOPT2_DCEN BIT(27)
+
 static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
 {
 ppc440_sdram_t *sdram = opaque;
@@ -684,6 +698,21 @@ static void dcr_write_sdram(void *opaque, int dcrn, 
uint32_t val)
 switch (sdram->addr) {
 case 0x00: /* B0CR */
 break;
+case 0x21: /* SDRAM_MCOPT2 */
+if (!(sdram->mcopt2 & SDRAM_DDR2_MCOPT2_DCEN) &&
+(val & SDRAM_DDR2_MCOPT2_DCEN)) {
+trace_ppc4xx_sdram_enable("enable");
+/* validate all RAM mappings */
+sdram_map_bcr(sdram);
+sdram->mcopt2 |= SDRAM_DDR2_MCOPT2_DCEN;
+} else if ((sdram->mcopt2 & SDRAM_DDR2_MCOPT2_DCEN) &&
+   !(val & SDRAM_DDR2_MCOPT2_DCEN)) {
+trace_ppc4xx_sdram_enable("disable");
+/* invalidate all RAM mappings */
+sdram_unmap_bcr(sdram);
+sdram->mcopt2 &= ~SDRAM_DDR2_MCOPT2_DCEN;
+}
+break;
 default:
 break;
 }
@@ -698,6 +727,7 @@ static void sdram_reset(void *opaque)
 ppc440_sdram_t *sdram = opaque;
 
 sdram->addr = 0;
+sdram->mcopt2 = SDRAM_DDR2_MCOPT2_DCEN;
 }
 
 void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-- 
2.30.4




[PATCH v5 12/21] ppc440_sdram: Rename local variable for readability

2022-09-18 Thread BALATON Zoltan
Rename local sdram variable in ppc440_sdram_init to s for readability.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Cédric Le Goater 
---
 hw/ppc/ppc440_uc.c | 36 ++--
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index e8bc088c8f..97e6d5f5b2 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -734,40 +734,40 @@ static void sdram_reset(void *opaque)
 void ppc440_sdram_init(CPUPPCState *env, int nbanks,
Ppc4xxSdramBank *ram_banks)
 {
-ppc440_sdram_t *sdram;
+ppc440_sdram_t *s;
 int i;
 
-sdram = g_malloc0(sizeof(*sdram));
-sdram->nbanks = nbanks;
+s = g_malloc0(sizeof(*s));
+s->nbanks = nbanks;
 for (i = 0; i < nbanks; i++) {
-sdram->bank[i].ram = ram_banks[i].ram;
-sdram->bank[i].base = ram_banks[i].base;
-sdram->bank[i].size = ram_banks[i].size;
+s->bank[i].ram = ram_banks[i].ram;
+s->bank[i].base = ram_banks[i].base;
+s->bank[i].size = ram_banks[i].size;
 }
-qemu_register_reset(_reset, sdram);
+qemu_register_reset(_reset, s);
 ppc_dcr_register(env, SDRAM0_CFGADDR,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM0_CFGDATA,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 
 ppc_dcr_register(env, SDRAM_R0BAS,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM_R1BAS,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM_R2BAS,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM_R3BAS,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM_CONF1HB,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM_PLBADDULL,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM_CONF1LL,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM_CONFPATHB,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM_PLBADDUHB,
- sdram, _read_sdram, _write_sdram);
+ s, _read_sdram, _write_sdram);
 }
 
 void ppc440_sdram_enable(CPUPPCState *env)
-- 
2.30.4




[PATCH v5 17/21] ppc4xx_sdram: Use hwaddr for memory bank size

2022-09-18 Thread BALATON Zoltan
This resolves the target_ulong dependency that's clearly wrong and was
also noted in a fixme comment.

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

diff --git a/hw/ppc/ppc4xx_sdram.c b/hw/ppc/ppc4xx_sdram.c
index fe91b0ca82..3ec2edeb17 100644
--- a/hw/ppc/ppc4xx_sdram.c
+++ b/hw/ppc/ppc4xx_sdram.c
@@ -34,7 +34,6 @@
 #include "qapi/error.h"
 #include "qemu/log.h"
 #include "exec/address-spaces.h" /* get_system_memory() */
-#include "exec/cpu-defs.h" /* target_ulong */
 #include "hw/irq.h"
 #include "hw/qdev-properties.h"
 #include "qapi/error.h"
@@ -127,11 +126,6 @@ enum {
 
 /*/
 /* DDR SDRAM controller */
-/*
- * XXX: TOFIX: some patches have made this code become inconsistent:
- *  there are type inconsistencies, mixing hwaddr, target_ulong
- *  and uint32_t
- */
 static uint32_t sdram_ddr_bcr(hwaddr ram_base, hwaddr ram_size)
 {
 uint32_t bcr;
@@ -175,9 +169,9 @@ static inline hwaddr sdram_ddr_base(uint32_t bcr)
 return bcr & 0xFF80;
 }
 
-static target_ulong sdram_ddr_size(uint32_t bcr)
+static hwaddr sdram_ddr_size(uint32_t bcr)
 {
-target_ulong size;
+hwaddr size;
 int sh;
 
 sh = (bcr >> 17) & 0x7;
@@ -524,9 +518,9 @@ static inline hwaddr sdram_ddr2_base(uint32_t bcr)
 return (bcr & 0xffe0) << 2;
 }
 
-static uint64_t sdram_ddr2_size(uint32_t bcr)
+static hwaddr sdram_ddr2_size(uint32_t bcr)
 {
-uint64_t size;
+hwaddr size;
 int sh;
 
 sh = 1024 - ((bcr >> 6) & 0x3ff);
-- 
2.30.4




[PATCH v5 06/21] ppc4xx_sdram: Move size check to ppc4xx_sdram_init()

2022-09-18 Thread BALATON Zoltan
Instead of checking if memory size is valid in board code move this
check to ppc4xx_sdram_init() as this is a restriction imposed by the
SDRAM controller.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/ppc/ppc405.h |  2 --
 hw/ppc/ppc405_boards.c  | 10 --
 hw/ppc/ppc405_uc.c  | 11 ++-
 hw/ppc/ppc440_bamboo.c  | 10 +-
 hw/ppc/ppc4xx_devs.c| 14 ++
 include/hw/ppc/ppc4xx.h |  2 +-
 6 files changed, 10 insertions(+), 39 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index ca0972b88b..ad54dff542 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -167,9 +167,7 @@ struct Ppc405SoCState {
 DeviceState parent_obj;
 
 /* Public */
-Ppc4xxSdramBank ram_banks[2];
 MemoryRegion *dram_mr;
-hwaddr ram_size;
 
 PowerPCCPU cpu;
 PPCUIC uic;
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 1eaeca8806..824acf7a80 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -271,21 +271,11 @@ static void boot_from_kernel(MachineState *machine, 
PowerPCCPU *cpu)
 static void ppc405_init(MachineState *machine)
 {
 Ppc405MachineState *ppc405 = PPC405_MACHINE(machine);
-MachineClass *mc = MACHINE_GET_CLASS(machine);
 const char *kernel_filename = machine->kernel_filename;
 MemoryRegion *sysmem = get_system_memory();
 
-if (machine->ram_size != mc->default_ram_size) {
-char *sz = size_to_str(mc->default_ram_size);
-error_report("Invalid RAM size, should be %s", sz);
-g_free(sz);
-exit(EXIT_FAILURE);
-}
-
 object_initialize_child(OBJECT(machine), "soc", >soc,
 TYPE_PPC405_SOC);
-object_property_set_uint(OBJECT(>soc), "ram-size",
- machine->ram_size, _fatal);
 object_property_set_link(OBJECT(>soc), "dram",
  OBJECT(machine->ram), _abort);
 object_property_set_uint(OBJECT(>soc), "sys-clk", ,
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index bcbf35bc14..e1c7188e61 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1073,15 +1073,9 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
qdev_get_gpio_in(DEVICE(>cpu), PPC40x_INPUT_CINT));
 
 /* SDRAM controller */
-/* XXX 405EP has no ECC interrupt */
-s->ram_banks[0].base = 0;
-s->ram_banks[0].size = s->ram_size;
-memory_region_init_alias(>ram_banks[0].ram, OBJECT(s),
- "ppc405.sdram0", s->dram_mr,
- s->ram_banks[0].base, s->ram_banks[0].size);
-
+/* XXX 405EP has no ECC interrupt */
 ppc4xx_sdram_init(env, qdev_get_gpio_in(DEVICE(>uic), 17), 1,
-  s->ram_banks);
+  s->dram_mr);
 
 /* External bus controller */
 if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(>ebc), >cpu, errp)) {
@@ -1159,7 +1153,6 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 static Property ppc405_soc_properties[] = {
 DEFINE_PROP_LINK("dram", Ppc405SoCState, dram_mr, TYPE_MEMORY_REGION,
  MemoryRegion *),
-DEFINE_PROP_UINT64("ram-size", Ppc405SoCState, ram_size, 0),
 DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index 7ec7c7c43d..91d9a4eef3 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -50,10 +50,6 @@
 
 #define PPC440EP_SDRAM_NR_BANKS 4
 
-static const ram_addr_t ppc440ep_sdram_bank_sizes[] = {
-256 * MiB, 128 * MiB, 64 * MiB, 32 * MiB, 16 * MiB, 8 * MiB, 4 * MiB, 0
-};
-
 static hwaddr entry;
 
 static int bamboo_load_device_tree(hwaddr addr,
@@ -168,8 +164,6 @@ static void bamboo_init(MachineState *machine)
 unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
 MemoryRegion *address_space_mem = get_system_memory();
 MemoryRegion *isa = g_new(MemoryRegion, 1);
-Ppc4xxSdramBank *ram_banks = g_new0(Ppc4xxSdramBank,
-PPC440EP_SDRAM_NR_BANKS);
 PCIBus *pcibus;
 PowerPCCPU *cpu;
 CPUPPCState *env;
@@ -204,11 +198,9 @@ static void bamboo_init(MachineState *machine)
qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_CINT));
 
 /* SDRAM controller */
-ppc4xx_sdram_banks(machine->ram, PPC440EP_SDRAM_NR_BANKS, ram_banks,
-   ppc440ep_sdram_bank_sizes);
 /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
 ppc4xx_sdram_init(env, qdev_get_gpio_in(uicdev, 14),
-  PPC440EP_SDRAM_NR_BANKS, ram_banks);
+  PPC440EP_SDRAM_NR_BANKS, machine->ram);
 /* Enable SDRAM memory regions, this should be done by the firmware */
 ppc4xx_sdram_enable(env);
 
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index fcbda57c55..2e0343970f 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -41,7 +41,7 @@
 typedef struct 

[PATCH v5 09/21] ppc440_sdram: Split off map/unmap of sdram banks for later reuse

2022-09-18 Thread BALATON Zoltan
Signed-off-by: BALATON Zoltan 
---
 hw/ppc/ppc440_uc.c | 33 +
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 8eae4ad9f0..900b7ab998 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -23,6 +23,7 @@
 #include "sysemu/reset.h"
 #include "ppc440.h"
 #include "qom/object.h"
+#include "trace.h"
 
 /*/
 /* L2 Cache as SRAM */
@@ -563,26 +564,34 @@ static uint64_t sdram_size(uint32_t bcr)
 return size;
 }
 
+static void sdram_bank_map(Ppc4xxSdramBank *bank)
+{
+memory_region_init(>container, NULL, "sdram-container", bank->size);
+memory_region_add_subregion(>container, 0, >ram);
+memory_region_add_subregion(get_system_memory(), bank->base,
+>container);
+}
+
+static void sdram_bank_unmap(Ppc4xxSdramBank *bank)
+{
+memory_region_del_subregion(get_system_memory(), >container);
+memory_region_del_subregion(>container, >ram);
+object_unparent(OBJECT(>container));
+}
+
 static void sdram_set_bcr(ppc440_sdram_t *sdram, int i,
   uint32_t bcr, int enabled)
 {
 if (sdram->bank[i].bcr & 1) {
 /* First unmap RAM if enabled */
-memory_region_del_subregion(get_system_memory(),
->bank[i].container);
-memory_region_del_subregion(>bank[i].container,
->bank[i].ram);
-object_unparent(OBJECT(>bank[i].container));
+trace_ppc4xx_sdram_unmap(sdram_base(sdram->bank[i].bcr),
+ sdram_size(sdram->bank[i].bcr));
+sdram_bank_unmap(>bank[i]);
 }
 sdram->bank[i].bcr = bcr & 0xffe0ffc1;
 if (enabled && (bcr & 1)) {
-memory_region_init(>bank[i].container, NULL, "sdram-container",
-   sdram_size(bcr));
-memory_region_add_subregion(>bank[i].container, 0,
->bank[i].ram);
-memory_region_add_subregion(get_system_memory(),
-sdram_base(bcr),
->bank[i].container);
+trace_ppc4xx_sdram_map(sdram_base(bcr), sdram_size(bcr));
+sdram_bank_map(>bank[i]);
 }
 }
 
-- 
2.30.4




[PATCH v5 08/21] ppc4xx_sdram: Drop extra zeros for readability

2022-09-18 Thread BALATON Zoltan
Constants that are written zero padded for no good reason are hard to
read, it's easier to see what is meant if it's just 0 or 1 instead.

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

diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 3d700e5c85..02ac8ff335 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -54,31 +54,31 @@ static uint32_t sdram_ddr_bcr(hwaddr ram_base, hwaddr 
ram_size)
 
 switch (ram_size) {
 case 4 * MiB:
-bcr = 0x;
+bcr = 0;
 break;
 case 8 * MiB:
-bcr = 0x0002;
+bcr = 0x2;
 break;
 case 16 * MiB:
-bcr = 0x0004;
+bcr = 0x4;
 break;
 case 32 * MiB:
-bcr = 0x0006;
+bcr = 0x6;
 break;
 case 64 * MiB:
-bcr = 0x0008;
+bcr = 0x8;
 break;
 case 128 * MiB:
-bcr = 0x000A;
+bcr = 0xA;
 break;
 case 256 * MiB:
-bcr = 0x000C;
+bcr = 0xC;
 break;
 default:
 qemu_log_mask(LOG_GUEST_ERROR,
   "%s: invalid RAM size 0x%" HWADDR_PRIx "\n", __func__,
   ram_size);
-return 0x;
+return 0;
 }
 bcr |= ram_base & 0xFF80;
 bcr |= 1;
@@ -109,7 +109,7 @@ static target_ulong sdram_size(uint32_t bcr)
 static void sdram_set_bcr(Ppc4xxSdramDdrState *sdram, int i,
   uint32_t bcr, int enabled)
 {
-if (sdram->bank[i].bcr & 0x0001) {
+if (sdram->bank[i].bcr & 1) {
 /* Unmap RAM */
 trace_ppc4xx_sdram_unmap(sdram_base(sdram->bank[i].bcr),
  sdram_size(sdram->bank[i].bcr));
@@ -120,7 +120,7 @@ static void sdram_set_bcr(Ppc4xxSdramDdrState *sdram, int i,
 object_unparent(OBJECT(>bank[i].container));
 }
 sdram->bank[i].bcr = bcr & 0xFFDEE001;
-if (enabled && (bcr & 0x0001)) {
+if (enabled && (bcr & 1)) {
 trace_ppc4xx_sdram_map(sdram_base(bcr), sdram_size(bcr));
 memory_region_init(>bank[i].container, NULL, "sdram-container",
sdram_size(bcr));
@@ -141,7 +141,7 @@ static void sdram_map_bcr(Ppc4xxSdramDdrState *sdram)
 sdram_set_bcr(sdram, i, sdram_ddr_bcr(sdram->bank[i].base,
   sdram->bank[i].size), 1);
 } else {
-sdram_set_bcr(sdram, i, 0x, 0);
+sdram_set_bcr(sdram, i, 0, 0);
 }
 }
 }
@@ -218,7 +218,7 @@ static uint32_t sdram_ddr_dcr_read(void *opaque, int dcrn)
 break;
 default:
 /* Avoid gcc warning */
-ret = 0x;
+ret = 0;
 break;
 }
 
@@ -311,18 +311,18 @@ static void ppc4xx_sdram_ddr_reset(DeviceState *dev)
 {
 Ppc4xxSdramDdrState *sdram = PPC4xx_SDRAM_DDR(dev);
 
-sdram->addr = 0x;
-sdram->bear = 0x;
-sdram->besr0 = 0x; /* No error */
-sdram->besr1 = 0x; /* No error */
-sdram->cfg = 0x;
-sdram->ecccfg = 0x; /* No ECC */
-sdram->eccesr = 0x; /* No error */
+sdram->addr = 0;
+sdram->bear = 0;
+sdram->besr0 = 0; /* No error */
+sdram->besr1 = 0; /* No error */
+sdram->cfg = 0;
+sdram->ecccfg = 0; /* No ECC */
+sdram->eccesr = 0; /* No error */
 sdram->pmit = 0x07C0;
 sdram->rtr = 0x05F0;
 sdram->tr = 0x00854009;
 /* We pre-initialize RAM banks */
-sdram->status = 0x;
+sdram->status = 0;
 sdram->cfg = 0x0080;
 }
 
-- 
2.30.4




[PATCH v5 11/21] ppc440_sdram: Get rid of the init RAM hack

2022-09-18 Thread BALATON Zoltan
Remove the do_init parameter of ppc440_sdram_init and enable SDRAM
controller from the board. Firmware does this so it may only be needed
when booting with -kernel without firmware but we enable SDRAM
unconditionally to preserve previous behaviour.

Signed-off-by: BALATON Zoltan 
---
v5: Add function to enable sdram controller

 hw/ppc/ppc440.h |  3 +--
 hw/ppc/ppc440_uc.c  | 15 +--
 hw/ppc/sam460ex.c   |  4 +++-
 include/hw/ppc/ppc4xx.h |  2 ++
 4 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/hw/ppc/ppc440.h b/hw/ppc/ppc440.h
index e6c905b7d6..01d76b8000 100644
--- a/hw/ppc/ppc440.h
+++ b/hw/ppc/ppc440.h
@@ -17,8 +17,7 @@ void ppc4xx_l2sram_init(CPUPPCState *env);
 void ppc4xx_cpr_init(CPUPPCState *env);
 void ppc4xx_sdr_init(CPUPPCState *env);
 void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-   Ppc4xxSdramBank *ram_banks,
-   int do_init);
+   Ppc4xxSdramBank *ram_banks);
 void ppc4xx_ahb_init(CPUPPCState *env);
 void ppc4xx_dma_init(CPUPPCState *env, int dcr_base);
 void ppc460ex_pcie_init(CPUPPCState *env);
diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 3fbfe4ad13..e8bc088c8f 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -16,6 +16,7 @@
 #include "qemu/module.h"
 #include "hw/irq.h"
 #include "exec/memory.h"
+#include "cpu.h"
 #include "hw/ppc/ppc4xx.h"
 #include "hw/qdev-properties.h"
 #include "hw/pci/pci.h"
@@ -727,12 +728,11 @@ static void sdram_reset(void *opaque)
 ppc440_sdram_t *sdram = opaque;
 
 sdram->addr = 0;
-sdram->mcopt2 = SDRAM_DDR2_MCOPT2_DCEN;
+sdram->mcopt2 = 0;
 }
 
 void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-   Ppc4xxSdramBank *ram_banks,
-   int do_init)
+   Ppc4xxSdramBank *ram_banks)
 {
 ppc440_sdram_t *sdram;
 int i;
@@ -749,9 +749,6 @@ void ppc440_sdram_init(CPUPPCState *env, int nbanks,
  sdram, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM0_CFGDATA,
  sdram, _read_sdram, _write_sdram);
-if (do_init) {
-sdram_map_bcr(sdram);
-}
 
 ppc_dcr_register(env, SDRAM_R0BAS,
  sdram, _read_sdram, _write_sdram);
@@ -773,6 +770,12 @@ void ppc440_sdram_init(CPUPPCState *env, int nbanks,
  sdram, _read_sdram, _write_sdram);
 }
 
+void ppc440_sdram_enable(CPUPPCState *env)
+{
+ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x21);
+ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x0800);
+}
+
 /*/
 /* PLB to AHB bridge */
 enum {
diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
index f4c2a693fb..9c01211b20 100644
--- a/hw/ppc/sam460ex.c
+++ b/hw/ppc/sam460ex.c
@@ -345,7 +345,9 @@ static void sam460ex_init(MachineState *machine)
 ppc4xx_sdram_banks(machine->ram, 1, ram_banks, ppc460ex_sdram_bank_sizes);
 
 /* FIXME: does 460EX have ECC interrupts? */
-ppc440_sdram_init(env, 1, ram_banks, 1);
+ppc440_sdram_init(env, 1, ram_banks);
+/* Enable SDRAM memory regions as we may boot without firmware */
+ppc440_sdram_enable(env);
 
 /* IIC controllers and devices */
 dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700,
diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h
index 558500fb97..78a845399e 100644
--- a/include/hw/ppc/ppc4xx.h
+++ b/include/hw/ppc/ppc4xx.h
@@ -37,6 +37,8 @@ typedef struct {
 uint32_t bcr;
 } Ppc4xxSdramBank;
 
+void ppc440_sdram_enable(CPUPPCState *env);
+
 void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
 Ppc4xxSdramBank ram_banks[],
 const ram_addr_t sdram_bank_sizes[]);
-- 
2.30.4




[PATCH v5 05/21] ppc440_bamboo: Add missing 4 MiB valid memory size

2022-09-18 Thread BALATON Zoltan
Signed-off-by: BALATON Zoltan 
Reviewed-by: Cédric Le Goater 
---
 hw/ppc/ppc440_bamboo.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index edfb8c9709..7ec7c7c43d 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -51,7 +51,7 @@
 #define PPC440EP_SDRAM_NR_BANKS 4
 
 static const ram_addr_t ppc440ep_sdram_bank_sizes[] = {
-256 * MiB, 128 * MiB, 64 * MiB, 32 * MiB, 16 * MiB, 8 * MiB, 0
+256 * MiB, 128 * MiB, 64 * MiB, 32 * MiB, 16 * MiB, 8 * MiB, 4 * MiB, 0
 };
 
 static hwaddr entry;
-- 
2.30.4




[PATCH v5 07/21] ppc4xx_sdram: QOM'ify

2022-09-18 Thread BALATON Zoltan
Change the ppc4xx_sdram model to a QOM class derived from the
PPC4xx-dcr-device and name it ppc4xx-sdram-ddr. This is mostly
modelling the DDR SDRAM controller found in the 440EP (used on the
bamboo board) but also backward compatible with the older DDR
controllers on some 405 SoCs so we also use it for those now. This
likely does not cause problems for guests we run as the new features
are just not accessed but to model 405 SoC accurately some features
may have to be disabled or the model split between 440 and older.

Newer SoCs (regardless of their PPC core, e.g. 405EX) may have an
updated DDR2 SDRAM controller implemented by the ppc440_sdram model
(only partially, enough for the 460EX on the sam460ex) that is not yet
QOM'ified in this patch. That is intended to become ppc4xx-sdram-ddr2
when QOM'ified later.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Cédric Le Goater 
---
 hw/ppc/ppc405.h |   3 +-
 hw/ppc/ppc405_boards.c  |   2 +-
 hw/ppc/ppc405_uc.c  |  22 +
 hw/ppc/ppc440_bamboo.c  |  12 +++--
 hw/ppc/ppc4xx_devs.c| 105 ++--
 include/hw/ppc/ppc4xx.h |  31 ++--
 6 files changed, 105 insertions(+), 70 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index ad54dff542..9a4312691e 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -167,8 +167,6 @@ struct Ppc405SoCState {
 DeviceState parent_obj;
 
 /* Public */
-MemoryRegion *dram_mr;
-
 PowerPCCPU cpu;
 PPCUIC uic;
 Ppc405CpcState cpc;
@@ -182,6 +180,7 @@ struct Ppc405SoCState {
 Ppc405PobState pob;
 Ppc4xxPlbState plb;
 Ppc4xxMalState mal;
+Ppc4xxSdramDdrState sdram;
 };
 
 #endif /* PPC405_H */
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 824acf7a80..b59393d4bd 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -337,7 +337,7 @@ static void ppc405_init(MachineState *machine)
 
 /* Load ELF kernel and rootfs.cpio */
 } else if (kernel_filename && !machine->firmware) {
-ppc4xx_sdram_enable(>soc.cpu.env);
+ppc4xx_sdram_enable(>soc.sdram);
 boot_from_kernel(machine, >soc.cpu);
 }
 }
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index e1c7188e61..c973cfb04e 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1016,6 +1016,9 @@ static void ppc405_soc_instance_init(Object *obj)
 object_initialize_child(obj, "plb", >plb, TYPE_PPC4xx_PLB);
 
 object_initialize_child(obj, "mal", >mal, TYPE_PPC4xx_MAL);
+
+object_initialize_child(obj, "sdram", >sdram, TYPE_PPC4xx_SDRAM_DDR);
+object_property_add_alias(obj, "dram", OBJECT(>sdram), "dram");
 }
 
 static void ppc405_reset(void *opaque)
@@ -1073,9 +1076,17 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
qdev_get_gpio_in(DEVICE(>cpu), PPC40x_INPUT_CINT));
 
 /* SDRAM controller */
+/*
+ * We use the 440 DDR SDRAM controller which has more regs and features
+ * but it's compatible enough for now
+ */
+object_property_set_int(OBJECT(>sdram), "nbanks", 2, _abort);
+if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(>sdram), >cpu, errp)) {
+return;
+}
 /* XXX 405EP has no ECC interrupt */
-ppc4xx_sdram_init(env, qdev_get_gpio_in(DEVICE(>uic), 17), 1,
-  s->dram_mr);
+sysbus_connect_irq(SYS_BUS_DEVICE(>sdram), 0,
+   qdev_get_gpio_in(DEVICE(>uic), 17));
 
 /* External bus controller */
 if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(>ebc), >cpu, errp)) {
@@ -1150,12 +1161,6 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 /* Uses UIC IRQs 9, 15, 17 */
 }
 
-static Property ppc405_soc_properties[] = {
-DEFINE_PROP_LINK("dram", Ppc405SoCState, dram_mr, TYPE_MEMORY_REGION,
- MemoryRegion *),
-DEFINE_PROP_END_OF_LIST(),
-};
-
 static void ppc405_soc_class_init(ObjectClass *oc, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(oc);
@@ -1163,7 +1168,6 @@ static void ppc405_soc_class_init(ObjectClass *oc, void 
*data)
 dc->realize = ppc405_soc_realize;
 /* Reason: only works as part of a ppc405 board/machine */
 dc->user_creatable = false;
-device_class_set_props(dc, ppc405_soc_properties);
 }
 
 static const TypeInfo ppc405_types[] = {
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index 91d9a4eef3..5c35ba6086 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -48,8 +48,6 @@
 #define PPC440EP_PCI_IO 0xe800
 #define PPC440EP_PCI_IOLEN  0x0001
 
-#define PPC440EP_SDRAM_NR_BANKS 4
-
 static hwaddr entry;
 
 static int bamboo_load_device_tree(hwaddr addr,
@@ -198,11 +196,15 @@ static void bamboo_init(MachineState *machine)
qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_CINT));
 
 /* SDRAM controller */
+dev = qdev_new(TYPE_PPC4xx_SDRAM_DDR);
+object_property_set_link(OBJECT(dev), "dram", OBJECT(machine->ram),
+

[PATCH v5 03/21] ppc4xx_sdram: Get rid of the init RAM hack

2022-09-18 Thread BALATON Zoltan
The do_init parameter of ppc4xx_sdram_init() is used to map memory
regions that is normally done by the firmware by programming the SDRAM
controller. Do this from board code emulating what firmware would do
when booting a kernel directly from -kernel without a firmware so we
can get rid of this do_init hack.

Signed-off-by: BALATON Zoltan 
---
v5: Add function to enable sdram controller
v2: Fix ref405ep boot with -kernel and U-Boot

 hw/ppc/ppc405.h |  1 -
 hw/ppc/ppc405_boards.c  |  3 +--
 hw/ppc/ppc405_uc.c  |  4 +---
 hw/ppc/ppc440_bamboo.c  |  4 +++-
 hw/ppc/ppc4xx_devs.c| 12 +++-
 include/hw/ppc/ppc4xx.h |  5 +++--
 6 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 1e558c7831..756865621b 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -169,7 +169,6 @@ struct Ppc405SoCState {
 /* Public */
 MemoryRegion ram_banks[2];
 hwaddr ram_bases[2], ram_sizes[2];
-bool do_dram_init;
 
 MemoryRegion *dram_mr;
 hwaddr ram_size;
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 083f12b23e..1eaeca8806 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -288,8 +288,6 @@ static void ppc405_init(MachineState *machine)
  machine->ram_size, _fatal);
 object_property_set_link(OBJECT(>soc), "dram",
  OBJECT(machine->ram), _abort);
-object_property_set_bool(OBJECT(>soc), "dram-init",
- kernel_filename != NULL, _abort);
 object_property_set_uint(OBJECT(>soc), "sys-clk", ,
  _abort);
 qdev_realize(DEVICE(>soc), NULL, _fatal);
@@ -349,6 +347,7 @@ static void ppc405_init(MachineState *machine)
 
 /* Load ELF kernel and rootfs.cpio */
 } else if (kernel_filename && !machine->firmware) {
+ppc4xx_sdram_enable(>soc.cpu.env);
 boot_from_kernel(machine, >soc.cpu);
 }
 }
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 2ca42fdef6..1e02347e57 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1081,8 +1081,7 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
  s->ram_bases[0], s->ram_sizes[0]);
 
 ppc4xx_sdram_init(env, qdev_get_gpio_in(DEVICE(>uic), 17), 1,
-  s->ram_banks, s->ram_bases, s->ram_sizes,
-  s->do_dram_init);
+  s->ram_banks, s->ram_bases, s->ram_sizes);
 
 /* External bus controller */
 if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(>ebc), >cpu, errp)) {
@@ -1160,7 +1159,6 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 static Property ppc405_soc_properties[] = {
 DEFINE_PROP_LINK("dram", Ppc405SoCState, dram_mr, TYPE_MEMORY_REGION,
  MemoryRegion *),
-DEFINE_PROP_BOOL("dram-init", Ppc405SoCState, do_dram_init, 0),
 DEFINE_PROP_UINT64("ram-size", Ppc405SoCState, ram_size, 0),
 DEFINE_PROP_END_OF_LIST(),
 };
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index 5ec82fa8c2..409a8840da 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -211,7 +211,9 @@ static void bamboo_init(MachineState *machine)
 ppc4xx_sdram_init(env,
   qdev_get_gpio_in(uicdev, 14),
   PPC440EP_SDRAM_NR_BANKS, ram_memories,
-  ram_bases, ram_sizes, 1);
+  ram_bases, ram_sizes);
+/* Enable SDRAM memory regions, this should be done by the firmware */
+ppc4xx_sdram_enable(env);
 
 /* PCI */
 dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST_BRIDGE,
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 1226ec4aa9..3475589679 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -350,8 +350,7 @@ static void sdram_reset(void *opaque)
 void ppc4xx_sdram_init(CPUPPCState *env, qemu_irq irq, int nbanks,
MemoryRegion *ram_memories,
hwaddr *ram_bases,
-   hwaddr *ram_sizes,
-   int do_init)
+   hwaddr *ram_sizes)
 {
 ppc4xx_sdram_t *sdram;
 int i;
@@ -369,9 +368,12 @@ void ppc4xx_sdram_init(CPUPPCState *env, qemu_irq irq, int 
nbanks,
  sdram, _read_sdram, _write_sdram);
 ppc_dcr_register(env, SDRAM0_CFGDATA,
  sdram, _read_sdram, _write_sdram);
-if (do_init) {
-sdram_map_bcr(sdram);
-}
+}
+
+void ppc4xx_sdram_enable(CPUPPCState *env)
+{
+ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x20);
+ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x8000);
 }
 
 /*
diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h
index 2af0d60577..13b3229851 100644
--- a/include/hw/ppc/ppc4xx.h
+++ b/include/hw/ppc/ppc4xx.h
@@ -37,6 +37,8 @@ typedef struct {
 uint32_t bcr;
 } Ppc4xxSdramBank;
 
+void ppc4xx_sdram_enable(CPUPPCState *env);
+
 void 

[PATCH v5 02/21] ppc4xx: Introduce Ppc4xxSdramBank struct

2022-09-18 Thread BALATON Zoltan
Instead of storing sdram bank parameters in unrelated arrays put them
in a struct so it's clear they belong to the same bank and simplify
the state struct using this bank type.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/ppc/ppc440_uc.c  | 49 +-
 hw/ppc/ppc4xx_devs.c| 59 -
 include/hw/ppc/ppc4xx.h |  8 ++
 3 files changed, 61 insertions(+), 55 deletions(-)

diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 53e981ddf4..db4e29 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -16,7 +16,7 @@
 #include "qemu/module.h"
 #include "hw/irq.h"
 #include "exec/memory.h"
-#include "hw/ppc/ppc.h"
+#include "hw/ppc/ppc4xx.h"
 #include "hw/qdev-properties.h"
 #include "hw/pci/pci.h"
 #include "sysemu/block-backend.h"
@@ -485,11 +485,7 @@ void ppc4xx_sdr_init(CPUPPCState *env)
 typedef struct ppc440_sdram_t {
 uint32_t addr;
 int nbanks;
-MemoryRegion containers[4]; /* used for clipping */
-MemoryRegion *ram_memories;
-hwaddr ram_bases[4];
-hwaddr ram_sizes[4];
-uint32_t bcr[4];
+Ppc4xxSdramBank bank[4];
 } ppc440_sdram_t;
 
 enum {
@@ -570,23 +566,23 @@ static uint64_t sdram_size(uint32_t bcr)
 static void sdram_set_bcr(ppc440_sdram_t *sdram, int i,
   uint32_t bcr, int enabled)
 {
-if (sdram->bcr[i] & 1) {
+if (sdram->bank[i].bcr & 1) {
 /* First unmap RAM if enabled */
 memory_region_del_subregion(get_system_memory(),
->containers[i]);
-memory_region_del_subregion(>containers[i],
->ram_memories[i]);
-object_unparent(OBJECT(>containers[i]));
+>bank[i].container);
+memory_region_del_subregion(>bank[i].container,
+>bank[i].ram);
+object_unparent(OBJECT(>bank[i].container));
 }
-sdram->bcr[i] = bcr & 0xffe0ffc1;
+sdram->bank[i].bcr = bcr & 0xffe0ffc1;
 if (enabled && (bcr & 1)) {
-memory_region_init(>containers[i], NULL, "sdram-containers",
+memory_region_init(>bank[i].container, NULL, "sdram-container",
sdram_size(bcr));
-memory_region_add_subregion(>containers[i], 0,
->ram_memories[i]);
+memory_region_add_subregion(>bank[i].container, 0,
+>bank[i].ram);
 memory_region_add_subregion(get_system_memory(),
 sdram_base(bcr),
->containers[i]);
+>bank[i].container);
 }
 }
 
@@ -595,9 +591,9 @@ static void sdram_map_bcr(ppc440_sdram_t *sdram)
 int i;
 
 for (i = 0; i < sdram->nbanks; i++) {
-if (sdram->ram_sizes[i] != 0) {
-sdram_set_bcr(sdram, i, sdram_bcr(sdram->ram_bases[i],
-  sdram->ram_sizes[i]), 1);
+if (sdram->bank[i].size != 0) {
+sdram_set_bcr(sdram, i, sdram_bcr(sdram->bank[i].base,
+  sdram->bank[i].size), 1);
 } else {
 sdram_set_bcr(sdram, i, 0, 0);
 }
@@ -614,9 +610,9 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
 case SDRAM_R1BAS:
 case SDRAM_R2BAS:
 case SDRAM_R3BAS:
-if (sdram->ram_sizes[dcrn - SDRAM_R0BAS]) {
-ret = sdram_bcr(sdram->ram_bases[dcrn - SDRAM_R0BAS],
-sdram->ram_sizes[dcrn - SDRAM_R0BAS]);
+if (sdram->bank[dcrn - SDRAM_R0BAS].size) {
+ret = sdram_bcr(sdram->bank[dcrn - SDRAM_R0BAS].base,
+sdram->bank[dcrn - SDRAM_R0BAS].size);
 }
 break;
 case SDRAM_CONF1HB:
@@ -701,12 +697,15 @@ void ppc440_sdram_init(CPUPPCState *env, int nbanks,
int do_init)
 {
 ppc440_sdram_t *sdram;
+int i;
 
 sdram = g_malloc0(sizeof(*sdram));
 sdram->nbanks = nbanks;
-sdram->ram_memories = ram_memories;
-memcpy(sdram->ram_bases, ram_bases, nbanks * sizeof(hwaddr));
-memcpy(sdram->ram_sizes, ram_sizes, nbanks * sizeof(hwaddr));
+for (i = 0; i < nbanks; i++) {
+sdram->bank[i].ram = ram_memories[i];
+sdram->bank[i].base = ram_bases[i];
+sdram->bank[i].size = ram_sizes[i];
+}
 qemu_register_reset(_reset, sdram);
 ppc_dcr_register(env, SDRAM0_CFGADDR,
  sdram, _read_sdram, _write_sdram);
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index b4cd10f735..1226ec4aa9 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -42,10 +42,7 @@ typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
 struct ppc4xx_sdram_t {
 uint32_t addr;
 int nbanks;
-MemoryRegion containers[4]; /* used for clipping */
-MemoryRegion *ram_memories;
-hwaddr 

[PATCH v5 00/21] ppc4xx_sdram QOMify and clean ups

2022-09-18 Thread BALATON Zoltan
This is the end of the QOMify series started by Cédric. This series
handles the SDRAM controller models to clean them up, QOMify and unify
them and at least partially clean up the mess that has accumulated
around these in the past. This includes the not yet merged patches
from the last series and new ones that change the DDR2 version used by
sam460ex.

v5: Add functions the enable sdram controller and call it from boards
v4: address more review comments
v3: Fix patches that got squashed during rebase
v2: address some review comments and try to avoid compile problem with
gcc 12.2 (untested)

BALATON Zoltan (21):
  ppc440_bamboo: Remove unnecessary memsets
  ppc4xx: Introduce Ppc4xxSdramBank struct
  ppc4xx_sdram: Get rid of the init RAM hack
  ppc4xx: Use Ppc4xxSdramBank in ppc4xx_sdram_banks()
  ppc440_bamboo: Add missing 4 MiB valid memory size
  ppc4xx_sdram: Move size check to ppc4xx_sdram_init()
  ppc4xx_sdram: QOM'ify
  ppc4xx_sdram: Drop extra zeros for readability
  ppc440_sdram: Split off map/unmap of sdram banks for later reuse
  ppc440_sdram: Implement enable bit in the DDR2 SDRAM
  ppc440_sdram: Get rid of the init RAM hack
  ppc440_sdram: Rename local variable for readability
  ppc4xx_sdram: Rename functions to prevent name clashes
  ppc440_sdram: Move RAM size check to ppc440_sdram_init
  ppc440_sdram: QOM'ify
  ppc4xx_sdram: Move ppc4xx DDR and DDR2 SDRAM controller models
together
  ppc4xx_sdram: Use hwaddr for memory bank size
  ppc4xx_sdram: Rename local state variable for brevity
  ppc4xx_sdram: Generalise bank setup
  ppc4xx_sdram: Convert DDR SDRAM controller to new bank handling
  ppc4xx_sdram: Add errp parameter to ppc4xx_sdram_banks()

 hw/ppc/meson.build  |   3 +-
 hw/ppc/ppc405.h |   8 +-
 hw/ppc/ppc405_boards.c  |  13 +-
 hw/ppc/ppc405_uc.c  |  33 +-
 hw/ppc/ppc440.h |   4 -
 hw/ppc/ppc440_bamboo.c  |  25 +-
 hw/ppc/ppc440_uc.c  | 267 +-
 hw/ppc/ppc4xx_devs.c| 413 --
 hw/ppc/ppc4xx_sdram.c   | 754 
 hw/ppc/sam460ex.c   |  44 +--
 hw/ppc/trace-events |   1 +
 include/hw/ppc/ppc4xx.h |  65 +++-
 12 files changed, 860 insertions(+), 770 deletions(-)
 create mode 100644 hw/ppc/ppc4xx_sdram.c

-- 
2.30.4




[PATCH v5 01/21] ppc440_bamboo: Remove unnecessary memsets

2022-09-18 Thread BALATON Zoltan
In ppc4xx_sdram_init() the struct is allocated with g_new0() so no
need to clear its elements. In the bamboo machine init memset can be
replaced with array initialiser which is shorter.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/ppc440_bamboo.c | 6 ++
 hw/ppc/ppc4xx_devs.c   | 8 ++--
 2 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index ea945a1c99..5ec82fa8c2 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -169,8 +169,8 @@ static void bamboo_init(MachineState *machine)
 MemoryRegion *address_space_mem = get_system_memory();
 MemoryRegion *isa = g_new(MemoryRegion, 1);
 MemoryRegion *ram_memories = g_new(MemoryRegion, PPC440EP_SDRAM_NR_BANKS);
-hwaddr ram_bases[PPC440EP_SDRAM_NR_BANKS];
-hwaddr ram_sizes[PPC440EP_SDRAM_NR_BANKS];
+hwaddr ram_bases[PPC440EP_SDRAM_NR_BANKS] = {0};
+hwaddr ram_sizes[PPC440EP_SDRAM_NR_BANKS] = {0};
 PCIBus *pcibus;
 PowerPCCPU *cpu;
 CPUPPCState *env;
@@ -205,8 +205,6 @@ static void bamboo_init(MachineState *machine)
qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_CINT));
 
 /* SDRAM controller */
-memset(ram_bases, 0, sizeof(ram_bases));
-memset(ram_sizes, 0, sizeof(ram_sizes));
 ppc4xx_sdram_banks(machine->ram, PPC440EP_SDRAM_NR_BANKS, ram_memories,
ram_bases, ram_sizes, ppc440ep_sdram_bank_sizes);
 /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index ce38ae65e6..b4cd10f735 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -363,12 +363,8 @@ void ppc4xx_sdram_init(CPUPPCState *env, qemu_irq irq, int 
nbanks,
 sdram->irq = irq;
 sdram->nbanks = nbanks;
 sdram->ram_memories = ram_memories;
-memset(sdram->ram_bases, 0, 4 * sizeof(hwaddr));
-memcpy(sdram->ram_bases, ram_bases,
-   nbanks * sizeof(hwaddr));
-memset(sdram->ram_sizes, 0, 4 * sizeof(hwaddr));
-memcpy(sdram->ram_sizes, ram_sizes,
-   nbanks * sizeof(hwaddr));
+memcpy(sdram->ram_bases, ram_bases, nbanks * sizeof(hwaddr));
+memcpy(sdram->ram_sizes, ram_sizes, nbanks * sizeof(hwaddr));
 qemu_register_reset(_reset, sdram);
 ppc_dcr_register(env, SDRAM0_CFGADDR,
  sdram, _read_sdram, _write_sdram);
-- 
2.30.4




[PATCH v5 04/21] ppc4xx: Use Ppc4xxSdramBank in ppc4xx_sdram_banks()

2022-09-18 Thread BALATON Zoltan
Change ppc4xx_sdram_banks() to take one Ppc4xxSdramBank array instead
of the separate arrays and adjust ppc4xx_sdram_init() and
ppc440_sdram_init() accordingly as well as machines using these.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Cédric Le Goater 
---
v2: Use pointer for ram_banks in the prototype of the init funcs as
an array of struct seems to confuse gcc 12.2.1 and provoke a warning

 hw/ppc/ppc405.h |  4 +---
 hw/ppc/ppc405_uc.c  | 10 +-
 hw/ppc/ppc440.h |  5 ++---
 hw/ppc/ppc440_bamboo.c  | 15 ++-
 hw/ppc/ppc440_uc.c  |  9 -
 hw/ppc/ppc4xx_devs.c| 21 +
 hw/ppc/sam460ex.c   | 15 +--
 include/hw/ppc/ppc4xx.h |  9 +++--
 8 files changed, 35 insertions(+), 53 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 756865621b..ca0972b88b 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -167,9 +167,7 @@ struct Ppc405SoCState {
 DeviceState parent_obj;
 
 /* Public */
-MemoryRegion ram_banks[2];
-hwaddr ram_bases[2], ram_sizes[2];
-
+Ppc4xxSdramBank ram_banks[2];
 MemoryRegion *dram_mr;
 hwaddr ram_size;
 
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 1e02347e57..bcbf35bc14 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1074,14 +1074,14 @@ static void ppc405_soc_realize(DeviceState *dev, Error 
**errp)
 
 /* SDRAM controller */
 /* XXX 405EP has no ECC interrupt */
-s->ram_bases[0] = 0;
-s->ram_sizes[0] = s->ram_size;
-memory_region_init_alias(>ram_banks[0], OBJECT(s),
+s->ram_banks[0].base = 0;
+s->ram_banks[0].size = s->ram_size;
+memory_region_init_alias(>ram_banks[0].ram, OBJECT(s),
  "ppc405.sdram0", s->dram_mr,
- s->ram_bases[0], s->ram_sizes[0]);
+ s->ram_banks[0].base, s->ram_banks[0].size);
 
 ppc4xx_sdram_init(env, qdev_get_gpio_in(DEVICE(>uic), 17), 1,
-  s->ram_banks, s->ram_bases, s->ram_sizes);
+  s->ram_banks);
 
 /* External bus controller */
 if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(>ebc), >cpu, errp)) {
diff --git a/hw/ppc/ppc440.h b/hw/ppc/ppc440.h
index 7cef936125..e6c905b7d6 100644
--- a/hw/ppc/ppc440.h
+++ b/hw/ppc/ppc440.h
@@ -11,14 +11,13 @@
 #ifndef PPC440_H
 #define PPC440_H
 
-#include "hw/ppc/ppc.h"
+#include "hw/ppc/ppc4xx.h"
 
 void ppc4xx_l2sram_init(CPUPPCState *env);
 void ppc4xx_cpr_init(CPUPPCState *env);
 void ppc4xx_sdr_init(CPUPPCState *env);
 void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-   MemoryRegion *ram_memories,
-   hwaddr *ram_bases, hwaddr *ram_sizes,
+   Ppc4xxSdramBank *ram_banks,
int do_init);
 void ppc4xx_ahb_init(CPUPPCState *env);
 void ppc4xx_dma_init(CPUPPCState *env, int dcr_base);
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index 409a8840da..edfb8c9709 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -168,9 +168,8 @@ static void bamboo_init(MachineState *machine)
 unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
 MemoryRegion *address_space_mem = get_system_memory();
 MemoryRegion *isa = g_new(MemoryRegion, 1);
-MemoryRegion *ram_memories = g_new(MemoryRegion, PPC440EP_SDRAM_NR_BANKS);
-hwaddr ram_bases[PPC440EP_SDRAM_NR_BANKS] = {0};
-hwaddr ram_sizes[PPC440EP_SDRAM_NR_BANKS] = {0};
+Ppc4xxSdramBank *ram_banks = g_new0(Ppc4xxSdramBank,
+PPC440EP_SDRAM_NR_BANKS);
 PCIBus *pcibus;
 PowerPCCPU *cpu;
 CPUPPCState *env;
@@ -205,13 +204,11 @@ static void bamboo_init(MachineState *machine)
qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_CINT));
 
 /* SDRAM controller */
-ppc4xx_sdram_banks(machine->ram, PPC440EP_SDRAM_NR_BANKS, ram_memories,
-   ram_bases, ram_sizes, ppc440ep_sdram_bank_sizes);
+ppc4xx_sdram_banks(machine->ram, PPC440EP_SDRAM_NR_BANKS, ram_banks,
+   ppc440ep_sdram_bank_sizes);
 /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
-ppc4xx_sdram_init(env,
-  qdev_get_gpio_in(uicdev, 14),
-  PPC440EP_SDRAM_NR_BANKS, ram_memories,
-  ram_bases, ram_sizes);
+ppc4xx_sdram_init(env, qdev_get_gpio_in(uicdev, 14),
+  PPC440EP_SDRAM_NR_BANKS, ram_banks);
 /* Enable SDRAM memory regions, this should be done by the firmware */
 ppc4xx_sdram_enable(env);
 
diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index db4e29..8eae4ad9f0 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -692,8 +692,7 @@ static void sdram_reset(void *opaque)
 }
 
 void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-   MemoryRegion *ram_memories,
-   hwaddr *ram_bases, hwaddr 

Re: [PATCH 00/42] Consolidate PIIX south bridges

2022-09-18 Thread Mark Cave-Ayland

On 01/09/2022 17:25, Bernhard Beschow wrote:


This series consolidates the implementations of the PIIX3 and PIIX4 south
bridges and is an extended version of [1]. The motivation is to share as much
code as possible and to bring both device models to feature parity such that
perhaps PIIX4 can become a drop-in-replacement for PIIX3 in the pc machine. This
could resolve the "Frankenstein" PIIX4-PM problem in PIIX3 discussed on this
list before.

The series is structured as follows: First, PIIX3 is changed to instantiate
internal devices itself, like PIIX4 does already. Second, PIIX3 gets prepared
for the merge with PIIX4 which includes some fixes, cleanups, and renamings.
Third, the same is done for PIIX4. In step four the implementations are merged.
Since some consolidations could be done easier with merged implementations, the
consolidation continues in step five which concludes the series.

One particular challenge in this series was that the PIC of PIIX3 used to be
instantiated outside of the south bridge while some sub functions require a PIC
with populated qemu_irqs. This has been solved by introducing a proxy PIC which
furthermore allows PIIX3 to be agnostic towards the virtualization technology
used (KVM, TCG, Xen). Due to consolidation PIIX4 gained the PIC as well,
possibly allowing the Malta board to gain KVM capabilities in the future.

Another challenge was dealing with optional devices where Peter already gave
advice in [1] which this series implements.

An unsolved problem still is PCI interrupt handling. The first function
passed to pci_bus_irqs() is device-specific while the second one seems
board-specific. This causes both PIIX device models to be coupled to a
particular board. Any advice how to resolve this would be highly appreaciated.


Could you explain this in a bit more detail?


Last but not least there might be some opportunity to consolidate VM state
handling, probably by reusing the one from PIIX3. Since I'm not very familiar
with the requirements I didn't touch it so far.

Testing done:
* make check
* Boot live CD:
   * `qemu-system-x86_64 -M pc -m 2G -accel kvm -cpu host -cdrom
manjaro-kde-21.3.2-220704-linux515.iso`
   * `qemu-system-x86_64 -M q35 -m 2G -accel kvm -cpu host -cdrom
manjaro-kde-21.3.2-220704-linux515.iso`

[1] https://lists.nongnu.org/archive/html/qemu-devel/2022-07/msg02348.html

Bernhard Beschow (42):
   hw/i386/pc: Create DMA controllers in south bridges
   hw/i386/pc: Create RTC controllers in south bridges
   hw/i386/pc: No need for rtc_state to be an out-parameter
   hw/i386/pc_piix: Allow for setting properties before realizing PIIX3
 south bridge
   hw/isa/piix3: Create USB controller in host device
   hw/isa/piix3: Create power management controller in host device
   hw/intc/i8259: Introduce i8259 proxy "isa-pic"
   hw/isa/piix3: Create ISA PIC in host device
   hw/isa/piix3: Create IDE controller in host device
   hw/isa/piix3: Wire up ACPI interrupt internally
   hw/isa/piix3: Remove extra ';' outside of functions
   hw/isa/piix3: Remove unused include
   hw/isa/piix3: Add size constraints to rcr_ops
   hw/isa/piix3: Modernize reset handling
   hw/isa/piix3: Prefer pci_address_space() over get_system_memory()
   hw/isa/piix3: Allow board to provide PCI interrupt routes
   hw/isa/piix3: Resolve redundant PIIX_NUM_PIC_IRQS
   hw/isa/piix3: Rename pci_piix3_props for sharing with PIIX4
   hw/isa/piix3: Rename piix3_reset() for sharing with PIIX4
   hw/isa/piix3: Prefix pci_slot_get_pirq() with "piix3_"
   hw/isa/piix3: Rename typedef PIIX3State to PIIXState
   hw/mips/malta: Reuse dev variable
   meson: Fix dependencies of piix4 southbridge
   hw/isa/piix4: Add missing initialization
   hw/isa/piix4: Move pci_ide_create_devs() call to board code
   hw/isa/piix4: Make PIIX4's ACPI and USB functions optional
   hw/isa/piix4: Allow board to provide PCI interrupt routes
   hw/isa/piix4: Remove unused code
   hw/isa/piix4: Use ISA PIC device
   hw/isa/piix4: Reuse struct PIIXState from PIIX3
   hw/isa/piix4: Rename reset control operations to match PIIX3
   hw/isa/piix4: Rename wrongly named method
   hw/isa/piix4: Prefix pci_slot_get_pirq() with "piix4_"
   hw/isa/piix3: Merge hw/isa/piix4.c
   hw/isa/piix: Harmonize names of reset control memory regions
   hw/isa/piix: Reuse PIIX3 base class' realize method in PIIX4
   hw/isa/piix: Rename functions to be shared for interrupt triggering
   hw/isa/piix: Consolidate IRQ triggering
   hw/isa/piix: Unexport PIIXState
   hw/isa/piix: Share PIIX3 base class with PIIX4
   hw/isa/piix: Drop the "3" from the PIIX base class
   hw/i386/acpi-build: Resolve PIIX ISA bridge rather than ACPI
 controller

  MAINTAINERS |   6 +-
  configs/devices/mips-softmmu/common.mak |   3 +-
  hw/i386/Kconfig |   3 +-
  hw/i386/acpi-build.c|   4 +-
  hw/i386/pc.c|  19 +-
  hw/i386/pc_piix.c   |  72 +--
  

Re: [PATCH 39/42] hw/isa/piix: Unexport PIIXState

2022-09-18 Thread Mark Cave-Ayland

On 01/09/2022 17:26, Bernhard Beschow wrote:


The - deliberately exported - components can still be accessed
via QOM properties.

Signed-off-by: Bernhard Beschow 
---
  hw/isa/piix.c | 52 +
  include/hw/southbridge/piix.h | 54 ---
  2 files changed, 52 insertions(+), 54 deletions(-)

diff --git a/hw/isa/piix.c b/hw/isa/piix.c
index e413d7e792..c503a6e836 100644
--- a/hw/isa/piix.c
+++ b/hw/isa/piix.c
@@ -26,20 +26,72 @@
  #include "qemu/osdep.h"
  #include "qemu/range.h"
  #include "qapi/error.h"
+#include "qom/object.h"
+#include "hw/acpi/piix4.h"
  #include "hw/dma/i8257.h"
+#include "hw/ide/pci.h"
  #include "hw/intc/i8259.h"
  #include "hw/southbridge/piix.h"
  #include "hw/timer/i8254.h"
  #include "hw/irq.h"
  #include "hw/qdev-properties.h"
  #include "hw/isa/isa.h"
+#include "hw/pci/pci.h"
+#include "hw/qdev-properties.h"
+#include "hw/rtc/mc146818rtc.h"
+#include "hw/usb/hcd-uhci.h"
  #include "hw/xen/xen.h"
  #include "sysemu/runstate.h"
  #include "migration/vmstate.h"
  #include "hw/acpi/acpi_aml_interface.h"
  
+#define PIIX_NUM_PIRQS  4ULL/* PIRQ[A-D] */

  #define XEN_PIIX_NUM_PIRQS  128ULL
  
+struct PIIXState {

+PCIDevice dev;
+
+/*
+ * bitmap to track pic levels.
+ * The pic level is the logical OR of all the PCI irqs mapped to it
+ * So one PIC level is tracked by PIIX_NUM_PIRQS bits.
+ *
+ * PIRQ is mapped to PIC pins, we track it by
+ * PIIX_NUM_PIRQS * ISA_NUM_IRQS = 64 bits with
+ * pic_irq * PIIX_NUM_PIRQS + pirq
+ */
+#if ISA_NUM_IRQS * PIIX_NUM_PIRQS > 64
+#error "unable to encode pic state in 64bit in pic_levels."
+#endif
+uint64_t pic_levels;
+
+/* This member isn't used. Just for save/load compatibility */
+int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
+uint8_t pci_irq_reset_mappings[PIIX_NUM_PIRQS];
+
+ISAPICState pic;
+RTCState rtc;
+PCIIDEState ide;
+UHCIState uhci;
+PIIX4PMState pm;
+
+uint32_t smb_io_base;
+
+/* Reset Control Register contents */
+uint8_t rcr;
+
+/* IO memory region for Reset Control Register (PIIX_RCR_IOPORT) */
+MemoryRegion rcr_mem;
+
+bool has_acpi;
+bool has_usb;
+bool smm_enabled;
+};
+typedef struct PIIXState PIIXState;
+
+DECLARE_INSTANCE_CHECKER(PIIXState, PIIX_PCI_DEVICE,
+ TYPE_PIIX3_PCI_DEVICE)
+
  static void piix_set_irq_pic(PIIXState *piix, int pic_irq)
  {
  qemu_set_irq(piix->pic.in_irqs[pic_irq],
diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h
index c9fa0f1aa6..0edc23710c 100644
--- a/include/hw/southbridge/piix.h
+++ b/include/hw/southbridge/piix.h
@@ -12,14 +12,6 @@
  #ifndef HW_SOUTHBRIDGE_PIIX_H
  #define HW_SOUTHBRIDGE_PIIX_H
  
-#include "hw/pci/pci.h"

-#include "qom/object.h"
-#include "hw/acpi/piix4.h"
-#include "hw/ide/pci.h"
-#include "hw/intc/i8259.h"
-#include "hw/rtc/mc146818rtc.h"
-#include "hw/usb/hcd-uhci.h"
-
  /* PIRQRC[A:D]: PIRQx Route Control Registers */
  #define PIIX_PIRQCA 0x60
  #define PIIX_PIRQCB 0x61
@@ -32,53 +24,7 @@
   */
  #define PIIX_RCR_IOPORT 0xcf9
  
-#define PIIX_NUM_PIRQS  4ULL/* PIRQ[A-D] */

-
-struct PIIXState {
-PCIDevice dev;
-
-/*
- * bitmap to track pic levels.
- * The pic level is the logical OR of all the PCI irqs mapped to it
- * So one PIC level is tracked by PIIX_NUM_PIRQS bits.
- *
- * PIRQ is mapped to PIC pins, we track it by
- * PIIX_NUM_PIRQS * ISA_NUM_IRQS = 64 bits with
- * pic_irq * PIIX_NUM_PIRQS + pirq
- */
-#if ISA_NUM_IRQS * PIIX_NUM_PIRQS > 64
-#error "unable to encode pic state in 64bit in pic_levels."
-#endif
-uint64_t pic_levels;
-
-/* This member isn't used. Just for save/load compatibility */
-int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
-uint8_t pci_irq_reset_mappings[PIIX_NUM_PIRQS];
-
-ISAPICState pic;
-RTCState rtc;
-PCIIDEState ide;
-UHCIState uhci;
-PIIX4PMState pm;
-
-uint32_t smb_io_base;
-
-/* Reset Control Register contents */
-uint8_t rcr;
-
-/* IO memory region for Reset Control Register (PIIX_RCR_IOPORT) */
-MemoryRegion rcr_mem;
-
-bool has_acpi;
-bool has_usb;
-bool smm_enabled;
-};
-typedef struct PIIXState PIIXState;
-
  #define TYPE_PIIX3_PCI_DEVICE "pci-piix3"
-DECLARE_INSTANCE_CHECKER(PIIXState, PIIX_PCI_DEVICE,
- TYPE_PIIX3_PCI_DEVICE)
-
  #define TYPE_PIIX3_DEVICE "PIIX3"
  #define TYPE_PIIX3_XEN_DEVICE "PIIX3-xen"
  #define TYPE_PIIX4_PCI_DEVICE "piix4-isa"


I don't think that this is the right way to go here - whilst the definition of public 
and private can be a little vague, the general aim should be for the QOM type struct 
and macros to be in the corresponding .h file and the implementation in the .c file. 
In effect this ensures that anyone who wants to use a TYPE_FOO will include foo.h 
which helps make it easier to keep track of 

Re: [PATCH 26/42] hw/isa/piix4: Make PIIX4's ACPI and USB functions optional

2022-09-18 Thread Mark Cave-Ayland

On 01/09/2022 17:25, Bernhard Beschow wrote:


This aligns PIIX4 with PIIX3.

Signed-off-by: Bernhard Beschow 
---
  hw/isa/piix4.c  | 44 
  hw/mips/malta.c |  6 --
  2 files changed, 36 insertions(+), 14 deletions(-)

diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c
index 67881e3a75..ed9eca715f 100644
--- a/hw/isa/piix4.c
+++ b/hw/isa/piix4.c
@@ -50,9 +50,16 @@ struct PIIX4State {
  PCIIDEState ide;
  UHCIState uhci;
  PIIX4PMState pm;
+
+uint32_t smb_io_base;
+
  /* Reset Control Register */
  MemoryRegion rcr_mem;
  uint8_t rcr;
+
+bool has_acpi;
+bool has_usb;
+bool smm_enabled;
  };
  
  OBJECT_DECLARE_SIMPLE_TYPE(PIIX4State, PIIX4_PCI_DEVICE)

@@ -258,17 +265,26 @@ static void piix4_realize(PCIDevice *dev, Error **errp)
  }
  
  /* USB */

-qdev_prop_set_int32(DEVICE(>uhci), "addr", dev->devfn + 2);
-if (!qdev_realize(DEVICE(>uhci), BUS(pci_bus), errp)) {
-return;
+if (s->has_usb) {
+object_initialize_child(OBJECT(dev), "uhci", >uhci,
+"piix4-usb-uhci");


Can you use the relevant TYPE_ macro here for the USB-UHCI device?


+qdev_prop_set_int32(DEVICE(>uhci), "addr", dev->devfn + 2);
+if (!qdev_realize(DEVICE(>uhci), BUS(pci_bus), errp)) {
+return;
+}
  }
  
  /* ACPI controller */

-qdev_prop_set_int32(DEVICE(>pm), "addr", dev->devfn + 3);
-if (!qdev_realize(DEVICE(>pm), BUS(pci_bus), errp)) {
-return;
+if (s->has_acpi) {
+object_initialize_child(OBJECT(s), "pm", >pm, TYPE_PIIX4_PM);
+qdev_prop_set_int32(DEVICE(>pm), "addr", dev->devfn + 3);
+qdev_prop_set_uint32(DEVICE(>pm), "smb_io_base", s->smb_io_base);
+qdev_prop_set_bit(DEVICE(>pm), "smm-enabled", s->smm_enabled);
+if (!qdev_realize(DEVICE(>pm), BUS(pci_bus), errp)) {
+return;
+}
+qdev_connect_gpio_out(DEVICE(>pm), 0, s->isa[9]);
  }
-qdev_connect_gpio_out(DEVICE(>pm), 0, s->isa[9]);
  
  pci_bus_irqs(pci_bus, piix4_set_irq, pci_slot_get_pirq, s, PIIX_NUM_PIRQS);

  }
@@ -279,13 +295,16 @@ static void piix4_init(Object *obj)
  
  object_initialize_child(obj, "rtc", >rtc, TYPE_MC146818_RTC);

  object_initialize_child(obj, "ide", >ide, "piix4-ide");


... and same here for IDE?


-object_initialize_child(obj, "uhci", >uhci, "piix4-usb-uhci");
-
-object_initialize_child(obj, "pm", >pm, TYPE_PIIX4_PM);
-qdev_prop_set_uint32(DEVICE(>pm), "smb_io_base", 0x1100);
-qdev_prop_set_bit(DEVICE(>pm), "smm-enabled", 0);
  }
  
+static Property piix4_props[] = {

+DEFINE_PROP_UINT32("smb_io_base", PIIX4State, smb_io_base, 0),
+DEFINE_PROP_BOOL("has-acpi", PIIX4State, has_acpi, true),
+DEFINE_PROP_BOOL("has-usb", PIIX4State, has_usb, true),
+DEFINE_PROP_BOOL("smm-enabled", PIIX4State, smm_enabled, false),
+DEFINE_PROP_END_OF_LIST(),
+};
+
  static void piix4_class_init(ObjectClass *klass, void *data)
  {
  DeviceClass *dc = DEVICE_CLASS(klass);
@@ -304,6 +323,7 @@ static void piix4_class_init(ObjectClass *klass, void *data)
   */
  dc->user_creatable = false;
  dc->hotpluggable = false;
+device_class_set_props(dc, piix4_props);
  }
  
  static const TypeInfo piix4_info = {

diff --git a/hw/mips/malta.c b/hw/mips/malta.c
index a4b866a2cf..6339b0d66c 100644
--- a/hw/mips/malta.c
+++ b/hw/mips/malta.c
@@ -1400,8 +1400,10 @@ void mips_malta_init(MachineState *machine)
  empty_slot_init("GT64120", 0, 0x2000);
  
  /* Southbridge */

-piix4 = pci_create_simple_multifunction(pci_bus, PCI_DEVFN(10, 0), true,
-TYPE_PIIX4_PCI_DEVICE);
+piix4 = pci_new_multifunction(PCI_DEVFN(10, 0), true,
+  TYPE_PIIX4_PCI_DEVICE);
+qdev_prop_set_uint32(DEVICE(piix4), "smb_io_base", 0x1100);
+pci_realize_and_unref(piix4, pci_bus, _fatal);
  isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix4), "isa.0"));
  
  dev = DEVICE(object_resolve_path_component(OBJECT(piix4), "ide"));



ATB,

Mark.



[PATCH v3 07/12] linux-user: Fix strace of chmod() if mode == 0

2022-09-18 Thread Helge Deller
If the mode parameter of chmod() is zero, this value isn't shown
when stracing a program:
chmod("filename",)
This patch fixes it up to show the zero-value as well:
chmod("filename",000)

Signed-off-by: Helge Deller 
---
 linux-user/strace.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/linux-user/strace.c b/linux-user/strace.c
index 5ac64df02b..2f539845bb 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1505,6 +1505,11 @@ print_file_mode(abi_long mode, int last)
 const char *sep = "";
 const struct flags *m;

+if (mode == 0) {
+qemu_log("000%s", get_comma(last));
+return;
+}
+
 for (m = _flags[0]; m->f_string != NULL; m++) {
 if ((m->f_value & mode) == m->f_value) {
 qemu_log("%s%s", m->f_string, sep);
--
2.37.3




[PATCH v3 06/12] linux-user/hppa: Dump IIR on register dump

2022-09-18 Thread Helge Deller
Include the IIR register (which holds the opcode of the failing
instruction) when dumping the hppa registers.

Signed-off-by: Helge Deller 
---
 target/hppa/helper.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/target/hppa/helper.c b/target/hppa/helper.c
index e2758d8df3..74b8747083 100644
--- a/target/hppa/helper.c
+++ b/target/hppa/helper.c
@@ -85,9 +85,11 @@ void hppa_cpu_dump_state(CPUState *cs, FILE *f, int flags)
 char psw_c[20];
 int i;

-qemu_fprintf(f, "IA_F " TARGET_FMT_lx " IA_B " TARGET_FMT_lx "\n",
+qemu_fprintf(f, "IA_F " TARGET_FMT_lx " IA_B " TARGET_FMT_lx
+ " IIR " TREG_FMT_lx  "\n",
  hppa_form_gva_psw(psw, env->iasq_f, env->iaoq_f),
- hppa_form_gva_psw(psw, env->iasq_b, env->iaoq_b));
+ hppa_form_gva_psw(psw, env->iasq_b, env->iaoq_b),
+ env->cr[CR_IIR]);

 psw_c[0]  = (psw & PSW_W ? 'W' : '-');
 psw_c[1]  = (psw & PSW_E ? 'E' : '-');
--
2.37.3




[PATCH v3 05/12] linux-user/hppa: Use EXCP_DUMP() to show enhanced debug info

2022-09-18 Thread Helge Deller
Enhance the hppa linux-user cpu_loop() to show more debugging info
on hard errors.

Signed-off-by: Helge Deller 
---
 linux-user/hppa/cpu_loop.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/linux-user/hppa/cpu_loop.c b/linux-user/hppa/cpu_loop.c
index 64263c3dc4..1ef3b46191 100644
--- a/linux-user/hppa/cpu_loop.c
+++ b/linux-user/hppa/cpu_loop.c
@@ -147,12 +147,15 @@ void cpu_loop(CPUHPPAState *env)
 force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, env->iaoq_f);
 break;
 case EXCP_ILL:
+EXCP_DUMP(env, "qemu: got CPU exception 0x%x - aborting\n", 
trapnr);
 force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->iaoq_f);
 break;
 case EXCP_PRIV_OPR:
+EXCP_DUMP(env, "qemu: got CPU exception 0x%x - aborting\n", 
trapnr);
 force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->iaoq_f);
 break;
 case EXCP_PRIV_REG:
+EXCP_DUMP(env, "qemu: got CPU exception 0x%x - aborting\n", 
trapnr);
 force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVREG, env->iaoq_f);
 break;
 case EXCP_OVERFLOW:
@@ -171,7 +174,8 @@ void cpu_loop(CPUHPPAState *env)
 /* just indicate that signals should be handled asap */
 break;
 default:
-g_assert_not_reached();
+EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", 
trapnr);
+abort();
 }
 process_pending_signals(env);
 }
--
2.37.3




[PATCH v3 04/12] linux-user: Log failing executable in EXCP_DUMP()

2022-09-18 Thread Helge Deller
Enhance the EXCP_DUMP() macro to print out the failing program too.
During debugging it's sometimes hard to track down the actual failing
program if you are e.g. building a whole debian package.

Signed-off-by: Helge Deller 
---
 linux-user/cpu_loop-common.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/linux-user/cpu_loop-common.h b/linux-user/cpu_loop-common.h
index dc0042e4de..36ff5b14f2 100644
--- a/linux-user/cpu_loop-common.h
+++ b/linux-user/cpu_loop-common.h
@@ -27,9 +27,11 @@
 do {\
 CPUState *cs = env_cpu(env);\
 fprintf(stderr, fmt , ## __VA_ARGS__);  \
+fprintf(stderr, "Failing executable: %s\n", exec_path); \
 cpu_dump_state(cs, stderr, 0);  \
 if (qemu_log_separate()) {  \
 qemu_log(fmt, ## __VA_ARGS__);  \
+qemu_log("Failing executable: %s\n", exec_path);\
 log_cpu_state(cs, 0);   \
 }   \
 } while (0)
--
2.37.3




[PATCH v3 08/12] linux-user/hppa: Set TASK_UNMAPPED_BASE to 0xfa000000 for hppa arch

2022-09-18 Thread Helge Deller
On the parisc architecture the stack grows upwards.
Move the TASK_UNMAPPED_BASE to high memory area as it's done by the
kernel on physical machines.

Signed-off-by: Helge Deller 
---
 linux-user/mmap.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 048c4135af..dba6823668 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -251,8 +251,12 @@ static int mmap_frag(abi_ulong real_start,
 # define TASK_UNMAPPED_BASE  (1ul << 38)
 #endif
 #else
+#ifdef TARGET_HPPA
+# define TASK_UNMAPPED_BASE  0xfa00
+#else
 # define TASK_UNMAPPED_BASE  0x4000
 #endif
+#endif
 abi_ulong mmap_next_start = TASK_UNMAPPED_BASE;

 unsigned long last_brk;
--
2.37.3




[PATCH v3 12/12] linux-user: Add parameters of getrandom() syscall for strace

2022-09-18 Thread Helge Deller
Signed-off-by: Helge Deller 
---
 linux-user/strace.list | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linux-user/strace.list b/linux-user/strace.list
index ad9ef94689..97d8ccadac 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -355,7 +355,7 @@
 { TARGET_NR_getpriority, "getpriority", "%s(%#x,%#x)", NULL, NULL },
 #endif
 #ifdef TARGET_NR_getrandom
-{ TARGET_NR_getrandom, "getrandom", NULL, NULL, NULL },
+{ TARGET_NR_getrandom, "getrandom", "%s(%p,%u,%d)", NULL, NULL },
 #endif
 #ifdef TARGET_NR_getresgid
 { TARGET_NR_getresgid, "getresgid" , NULL, NULL, NULL },
--
2.37.3




[PATCH v3 10/12] linux-user: Show timespec on strace for futex()

2022-09-18 Thread Helge Deller
Signed-off-by: Helge Deller 
---
 linux-user/strace.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/linux-user/strace.c b/linux-user/strace.c
index 6f818212d5..b6b9abaea4 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -3714,11 +3714,20 @@ print_futex(CPUArchState *cpu_env, const struct 
syscallname *name,
 abi_long arg0, abi_long arg1, abi_long arg2,
 abi_long arg3, abi_long arg4, abi_long arg5)
 {
+abi_long op = arg1 & FUTEX_CMD_MASK;
 print_syscall_prologue(name);
 print_pointer(arg0, 0);
 print_futex_op(arg1, 0);
 print_raw_param(",%d", arg2, 0);
-print_pointer(arg3, 0); /* struct timespec */
+switch (op) {
+case FUTEX_WAIT:
+case FUTEX_WAIT_BITSET:
+print_timespec(arg3, 0);
+break;
+default:
+print_pointer(arg3, 0);
+break;
+}
 print_pointer(arg4, 0);
 print_raw_param("%d", arg4, 1);
 print_syscall_epilogue(name);
--
2.37.3




[PATCH v3 01/12] linux-user: Add missing signals in strace output

2022-09-18 Thread Helge Deller
Some of the guest signal numbers are currently not converted to
their representative names in the strace output, e.g. SIGVTALRM.

This patch introduces a smart way to generate and keep in sync the
host-to-guest and guest-to-host signal conversion tables for usage in
the qemu signal and strace code. This ensures that any signals
will now show up in both tables.

There is no functional change in this patch - with the exception that yet
missing signal names now show up in the strace code too.

Signed-off-by: Helge Deller 
---
 linux-user/signal-common.h | 46 ++
 linux-user/signal.c| 37 +++---
 linux-user/strace.c| 30 +
 3 files changed, 60 insertions(+), 53 deletions(-)

diff --git a/linux-user/signal-common.h b/linux-user/signal-common.h
index 6a7e4a93fc..3e2dc604c2 100644
--- a/linux-user/signal-common.h
+++ b/linux-user/signal-common.h
@@ -118,4 +118,50 @@ static inline void finish_sigsuspend_mask(int ret)
 }
 }

+#if defined(SIGSTKFLT) && defined(TARGET_SIGSTKFLT)
+#define MAKE_SIG_ENTRY_SIGSTKFLTMAKE_SIG_ENTRY(SIGSTKFLT)
+#else
+#define MAKE_SIG_ENTRY_SIGSTKFLT
+#endif
+
+#if defined(SIGIOT) && defined(TARGET_SIGIOT)
+#define MAKE_SIG_ENTRY_SIGIOT   MAKE_SIG_ENTRY(SIGIOT)
+#else
+#define MAKE_SIG_ENTRY_SIGIOT
+#endif
+
+#define MAKE_SIGNAL_LIST \
+MAKE_SIG_ENTRY(SIGHUP) \
+MAKE_SIG_ENTRY(SIGINT) \
+MAKE_SIG_ENTRY(SIGQUIT) \
+MAKE_SIG_ENTRY(SIGILL) \
+MAKE_SIG_ENTRY(SIGTRAP) \
+MAKE_SIG_ENTRY(SIGABRT) \
+MAKE_SIG_ENTRY(SIGBUS) \
+MAKE_SIG_ENTRY(SIGFPE) \
+MAKE_SIG_ENTRY(SIGKILL) \
+MAKE_SIG_ENTRY(SIGUSR1) \
+MAKE_SIG_ENTRY(SIGSEGV) \
+MAKE_SIG_ENTRY(SIGUSR2) \
+MAKE_SIG_ENTRY(SIGPIPE) \
+MAKE_SIG_ENTRY(SIGALRM) \
+MAKE_SIG_ENTRY(SIGTERM) \
+MAKE_SIG_ENTRY(SIGCHLD) \
+MAKE_SIG_ENTRY(SIGCONT) \
+MAKE_SIG_ENTRY(SIGSTOP) \
+MAKE_SIG_ENTRY(SIGTSTP) \
+MAKE_SIG_ENTRY(SIGTTIN) \
+MAKE_SIG_ENTRY(SIGTTOU) \
+MAKE_SIG_ENTRY(SIGURG) \
+MAKE_SIG_ENTRY(SIGXCPU) \
+MAKE_SIG_ENTRY(SIGXFSZ) \
+MAKE_SIG_ENTRY(SIGVTALRM) \
+MAKE_SIG_ENTRY(SIGPROF) \
+MAKE_SIG_ENTRY(SIGWINCH) \
+MAKE_SIG_ENTRY(SIGIO) \
+MAKE_SIG_ENTRY(SIGPWR) \
+MAKE_SIG_ENTRY(SIGSYS) \
+MAKE_SIG_ENTRY_SIGSTKFLT \
+MAKE_SIG_ENTRY_SIGIOT
+
 #endif
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 8d29bfaa6b..61c6fa3fcf 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -53,40 +53,9 @@ abi_ulong default_rt_sigreturn;
 QEMU_BUILD_BUG_ON(__SIGRTMAX + 1 != _NSIG);
 #endif
 static uint8_t host_to_target_signal_table[_NSIG] = {
-[SIGHUP] = TARGET_SIGHUP,
-[SIGINT] = TARGET_SIGINT,
-[SIGQUIT] = TARGET_SIGQUIT,
-[SIGILL] = TARGET_SIGILL,
-[SIGTRAP] = TARGET_SIGTRAP,
-[SIGABRT] = TARGET_SIGABRT,
-/*[SIGIOT] = TARGET_SIGIOT,*/
-[SIGBUS] = TARGET_SIGBUS,
-[SIGFPE] = TARGET_SIGFPE,
-[SIGKILL] = TARGET_SIGKILL,
-[SIGUSR1] = TARGET_SIGUSR1,
-[SIGSEGV] = TARGET_SIGSEGV,
-[SIGUSR2] = TARGET_SIGUSR2,
-[SIGPIPE] = TARGET_SIGPIPE,
-[SIGALRM] = TARGET_SIGALRM,
-[SIGTERM] = TARGET_SIGTERM,
-#ifdef SIGSTKFLT
-[SIGSTKFLT] = TARGET_SIGSTKFLT,
-#endif
-[SIGCHLD] = TARGET_SIGCHLD,
-[SIGCONT] = TARGET_SIGCONT,
-[SIGSTOP] = TARGET_SIGSTOP,
-[SIGTSTP] = TARGET_SIGTSTP,
-[SIGTTIN] = TARGET_SIGTTIN,
-[SIGTTOU] = TARGET_SIGTTOU,
-[SIGURG] = TARGET_SIGURG,
-[SIGXCPU] = TARGET_SIGXCPU,
-[SIGXFSZ] = TARGET_SIGXFSZ,
-[SIGVTALRM] = TARGET_SIGVTALRM,
-[SIGPROF] = TARGET_SIGPROF,
-[SIGWINCH] = TARGET_SIGWINCH,
-[SIGIO] = TARGET_SIGIO,
-[SIGPWR] = TARGET_SIGPWR,
-[SIGSYS] = TARGET_SIGSYS,
+#define MAKE_SIG_ENTRY(sig) [sig] = TARGET_##sig,
+MAKE_SIGNAL_LIST
+#undef MAKE_SIG_ENTRY
 /* next signals stay the same */
 };

diff --git a/linux-user/strace.c b/linux-user/strace.c
index 7d882526da..a4eeef7ae1 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -17,6 +17,7 @@
 #include "qemu.h"
 #include "user-internals.h"
 #include "strace.h"
+#include "signal-common.h"

 struct syscallname {
 int nr;
@@ -141,30 +142,21 @@ if( cmd == val ) { \
 qemu_log("%d", cmd);
 }

+static const char * const target_signal_name[] = {
+#define MAKE_SIG_ENTRY(sig) [TARGET_##sig] = #sig,
+MAKE_SIGNAL_LIST
+#undef MAKE_SIG_ENTRY
+};
+
 static void
 print_signal(abi_ulong arg, int last)
 {
 const char *signal_name = NULL;
-switch(arg) {
-case TARGET_SIGHUP: signal_name = "SIGHUP"; break;
-case TARGET_SIGINT: signal_name = "SIGINT"; break;
-case TARGET_SIGQUIT: signal_name = "SIGQUIT"; break;
-case TARGET_SIGILL: signal_name = "SIGILL"; break;
-case TARGET_SIGABRT: signal_name = "SIGABRT"; break;
-case TARGET_SIGFPE: signal_name = 

[PATCH v3 11/12] linux-user: Add close_range() syscall

2022-09-18 Thread Helge Deller
Signed-off-by: Helge Deller 
---
 linux-user/strace.list |  3 +++
 linux-user/syscall.c   | 16 
 2 files changed, 19 insertions(+)

diff --git a/linux-user/strace.list b/linux-user/strace.list
index 215d971b2a..ad9ef94689 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -103,6 +103,9 @@
 #ifdef TARGET_NR_close
 { TARGET_NR_close, "close" , "%s(%d)", NULL, NULL },
 #endif
+#ifdef TARGET_NR_close_range
+{ TARGET_NR_close_range, "close_range" , "%s(%d,%d,%d)", NULL, NULL },
+#endif
 #ifdef TARGET_NR_connect
 { TARGET_NR_connect, "connect" , "%s(%d,%#x,%d)", NULL, NULL },
 #endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index ca39acfceb..2e0e974562 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -338,6 +338,10 @@ _syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
 #ifdef __NR_exit_group
 _syscall1(int,exit_group,int,error_code)
 #endif
+#if defined(__NR_close_range) && defined(TARGET_NR_close_range)
+#define __NR_sys_close_range __NR_close_range
+_syscall3(int,sys_close_range,int,first,int,last,int,flags)
+#endif
 #if defined(__NR_futex)
 _syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
   const struct timespec *,timeout,int *,uaddr2,int,val3)
@@ -8721,6 +8725,18 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int 
num, abi_long arg1,
 case TARGET_NR_close:
 fd_trans_unregister(arg1);
 return get_errno(close(arg1));
+#if defined(__NR_close_range) && defined(TARGET_NR_close_range)
+case TARGET_NR_close_range:
+{
+abi_long fd;
+abi_long maxfd = (arg2 == (abi_long)-1) ? target_fd_max : arg2;
+
+for (fd = arg1; fd <= maxfd; fd++) {
+fd_trans_unregister(fd);
+}
+}
+return get_errno(sys_close_range(arg1, arg2, arg3));
+#endif

 case TARGET_NR_brk:
 return do_brk(arg1);
--
2.37.3




[PATCH v3 03/12] linux-user: Add pidfd_open(), pidfd_send_signal() and pidfd_getfd() syscalls

2022-09-18 Thread Helge Deller
I noticed those were missing when running the glib2.0 testsuite.
Add the syscalls including the strace output.

Signed-off-by: Helge Deller 
---
 linux-user/strace.c| 28 
 linux-user/strace.list |  9 +
 linux-user/syscall.c   | 34 ++
 3 files changed, 71 insertions(+)

diff --git a/linux-user/strace.c b/linux-user/strace.c
index 816e679995..5ac64df02b 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -3317,6 +3317,34 @@ print_openat(CPUArchState *cpu_env, const struct 
syscallname *name,
 }
 #endif

+#ifdef TARGET_NR_pidfd_send_signal
+static void
+print_pidfd_send_signal(CPUArchState *cpu_env, const struct syscallname *name,
+abi_long arg0, abi_long arg1, abi_long arg2,
+abi_long arg3, abi_long arg4, abi_long arg5)
+{
+void *p;
+target_siginfo_t uinfo;
+
+print_syscall_prologue(name);
+print_raw_param("%d", arg0, 0);
+print_signal(arg1, 0);
+
+p = lock_user(VERIFY_READ, arg2, sizeof(target_siginfo_t), 1);
+if (p) {
+get_target_siginfo(, p);
+print_siginfo();
+
+unlock_user(p, arg2, 0);
+} else {
+print_pointer(arg2, 1);
+}
+
+print_raw_param("%u", arg3, 0);
+print_syscall_epilogue(name);
+}
+#endif
+
 #ifdef TARGET_NR_mq_unlink
 static void
 print_mq_unlink(CPUArchState *cpu_env, const struct syscallname *name,
diff --git a/linux-user/strace.list b/linux-user/strace.list
index a78cdf3cdf..4d8b7f6a5e 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1664,6 +1664,15 @@
 #ifdef TARGET_NR_pipe2
 { TARGET_NR_pipe2, "pipe2", NULL, NULL, NULL },
 #endif
+#ifdef TARGET_NR_pidfd_open
+{ TARGET_NR_pidfd_open, "pidfd_open", "%s(%d,%u)", NULL, NULL },
+#endif
+#ifdef TARGET_NR_pidfd_send_signal
+{ TARGET_NR_pidfd_send_signal, "pidfd_send_signal", NULL, 
print_pidfd_send_signal, NULL },
+#endif
+#ifdef TARGET_NR_pidfd_getfd
+{ TARGET_NR_pidfd_getfd, "pidfd_getfd", "%s(%d,%d,%u)", NULL, NULL },
+#endif
 #ifdef TARGET_NR_atomic_cmpxchg_32
 { TARGET_NR_atomic_cmpxchg_32, "atomic_cmpxchg_32", NULL, NULL, NULL },
 #endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f409121202..ca39acfceb 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -346,6 +346,16 @@ _syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
 _syscall6(int,sys_futex_time64,int *,uaddr,int,op,int,val,
   const struct timespec *,timeout,int *,uaddr2,int,val3)
 #endif
+#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open)
+_syscall2(int, pidfd_open, pid_t, pid, unsigned int, flags);
+#endif
+#if defined(__NR_pidfd_send_signal) && defined(TARGET_NR_pidfd_send_signal)
+_syscall4(int, pidfd_send_signal, int, pidfd, int, sig, siginfo_t *, info,
+ unsigned int, flags);
+#endif
+#if defined(__NR_pidfd_getfd) && defined(TARGET_NR_pidfd_getfd)
+_syscall3(int, pidfd_getfd, int, pidfd, int, targetfd, unsigned int, flags);
+#endif
 #define __NR_sys_sched_getaffinity __NR_sched_getaffinity
 _syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
   unsigned long *, user_mask_ptr);
@@ -8683,6 +8693,30 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int 
num, abi_long arg1,
 ret = do_open_by_handle_at(arg1, arg2, arg3);
 fd_trans_unregister(ret);
 return ret;
+#endif
+#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open)
+case TARGET_NR_pidfd_open:
+return get_errno(pidfd_open(arg1, arg2));
+#endif
+#if defined(__NR_pidfd_send_signal) && defined(TARGET_NR_pidfd_send_signal)
+case TARGET_NR_pidfd_send_signal:
+{
+siginfo_t uinfo;
+
+p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
+if (!p) {
+return -TARGET_EFAULT;
+}
+target_to_host_siginfo(, p);
+unlock_user(p, arg3, 0);
+ret = get_errno(pidfd_send_signal(arg1, 
target_to_host_signal(arg2),
+, arg4));
+}
+return ret;
+#endif
+#if defined(__NR_pidfd_getfd) && defined(TARGET_NR_pidfd_getfd)
+case TARGET_NR_pidfd_getfd:
+return get_errno(pidfd_getfd(arg1, arg2, arg3));
 #endif
 case TARGET_NR_close:
 fd_trans_unregister(arg1);
--
2.37.3




[PATCH v3 02/12] linux-user: Add missing clock_gettime64() syscall strace

2022-09-18 Thread Helge Deller
Allow linux-user to strace the clock_gettime64() syscall.
This syscall is used a lot on 32-bit guest architectures which use newer
glibc versions.

Signed-off-by: Helge Deller 
---
 linux-user/strace.c| 53 ++
 linux-user/strace.list |  4 
 2 files changed, 57 insertions(+)

diff --git a/linux-user/strace.c b/linux-user/strace.c
index a4eeef7ae1..816e679995 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -82,6 +82,7 @@ UNUSED static void print_buf(abi_long addr, abi_long len, int 
last);
 UNUSED static void print_raw_param(const char *, abi_long, int);
 UNUSED static void print_timeval(abi_ulong, int);
 UNUSED static void print_timespec(abi_ulong, int);
+UNUSED static void print_timespec64(abi_ulong, int);
 UNUSED static void print_timezone(abi_ulong, int);
 UNUSED static void print_itimerval(abi_ulong, int);
 UNUSED static void print_number(abi_long, int);
@@ -795,6 +796,24 @@ print_syscall_ret_clock_gettime(CPUArchState *cpu_env, 
const struct syscallname
 #define print_syscall_ret_clock_getres print_syscall_ret_clock_gettime
 #endif

+#if defined(TARGET_NR_clock_gettime64)
+static void
+print_syscall_ret_clock_gettime64(CPUArchState *cpu_env, const struct 
syscallname *name,
+abi_long ret, abi_long arg0, abi_long arg1,
+abi_long arg2, abi_long arg3, abi_long arg4,
+abi_long arg5)
+{
+if (!print_syscall_err(ret)) {
+qemu_log(TARGET_ABI_FMT_ld, ret);
+qemu_log(" (");
+print_timespec64(arg1, 1);
+qemu_log(")");
+}
+
+qemu_log("\n");
+}
+#endif
+
 #ifdef TARGET_NR_gettimeofday
 static void
 print_syscall_ret_gettimeofday(CPUArchState *cpu_env, const struct syscallname 
*name,
@@ -1652,6 +1671,27 @@ print_timespec(abi_ulong ts_addr, int last)
 }
 }

+static void
+print_timespec64(abi_ulong ts_addr, int last)
+{
+if (ts_addr) {
+struct target__kernel_timespec *ts;
+
+ts = lock_user(VERIFY_READ, ts_addr, sizeof(*ts), 1);
+if (!ts) {
+print_pointer(ts_addr, last);
+return;
+}
+qemu_log("{tv_sec = %lld"
+ ",tv_nsec = %lld}%s",
+ (long long)tswap64(ts->tv_sec), (long 
long)tswap64(ts->tv_nsec),
+ get_comma(last));
+unlock_user(ts, ts_addr, 0);
+} else {
+qemu_log("NULL%s", get_comma(last));
+}
+}
+
 static void
 print_timezone(abi_ulong tz_addr, int last)
 {
@@ -2267,6 +2307,19 @@ print_clock_gettime(CPUArchState *cpu_env, const struct 
syscallname *name,
 #define print_clock_getres print_clock_gettime
 #endif

+#if defined(TARGET_NR_clock_gettime64)
+static void
+print_clock_gettime64(CPUArchState *cpu_env, const struct syscallname *name,
+abi_long arg0, abi_long arg1, abi_long arg2,
+abi_long arg3, abi_long arg4, abi_long arg5)
+{
+print_syscall_prologue(name);
+print_enums(clockids, arg0, 0);
+print_pointer(arg1, 1);
+print_syscall_epilogue(name);
+}
+#endif
+
 #ifdef TARGET_NR_clock_settime
 static void
 print_clock_settime(CPUArchState *cpu_env, const struct syscallname *name,
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 72e17b1acf..a78cdf3cdf 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1676,3 +1676,7 @@
 #ifdef TARGET_NR_copy_file_range
 { TARGET_NR_copy_file_range, "copy_file_range", 
"%s(%d,%p,%d,%p,"TARGET_ABI_FMT_lu",%u)", NULL, NULL },
 #endif
+#ifdef TARGET_NR_clock_gettime64
+{ TARGET_NR_clock_gettime64, "clock_gettime64" , NULL, print_clock_gettime64,
+   print_syscall_ret_clock_gettime64 },
+#endif
--
2.37.3




[PATCH v3 09/12] linux-user: Add strace for clock_nanosleep()

2022-09-18 Thread Helge Deller
Signed-off-by: Helge Deller 
---
 linux-user/strace.c| 15 +++
 linux-user/strace.list |  3 ++-
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/linux-user/strace.c b/linux-user/strace.c
index 2f539845bb..6f818212d5 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -3567,6 +3567,21 @@ print_unshare(CPUArchState *cpu_env, const struct 
syscallname *name,
 }
 #endif

+#ifdef TARGET_NR_clock_nanosleep
+static void
+print_clock_nanosleep(CPUArchState *cpu_env, const struct syscallname *name,
+abi_long arg0, abi_long arg1, abi_long arg2,
+abi_long arg3, abi_long arg4, abi_long arg5)
+{
+print_syscall_prologue(name);
+print_enums(clockids, arg0, 0);
+print_raw_param("%d", arg1, 0);
+print_timespec(arg2, 0);
+print_timespec(arg3, 1);
+print_syscall_epilogue(name);
+}
+#endif
+
 #ifdef TARGET_NR_utime
 static void
 print_utime(CPUArchState *cpu_env, const struct syscallname *name,
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 4d8b7f6a5e..215d971b2a 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -91,7 +91,8 @@
print_syscall_ret_clock_gettime },
 #endif
 #ifdef TARGET_NR_clock_nanosleep
-{ TARGET_NR_clock_nanosleep, "clock_nanosleep" , NULL, NULL, NULL },
+{ TARGET_NR_clock_nanosleep, "clock_nanosleep" , NULL, print_clock_nanosleep,
+NULL },
 #endif
 #ifdef TARGET_NR_clock_settime
 { TARGET_NR_clock_settime, "clock_settime" , NULL, print_clock_settime, NULL },
--
2.37.3




[PATCH v3 00/12] linux-user: Add more syscalls, enhance tracing & logging enhancements

2022-09-18 Thread Helge Deller
Here is a bunch of patches for linux-user.

Most of them add missing syscalls and enhance the tracing/logging.
Some of the patches are target-hppa specific.
I've tested those on productive hppa debian buildd servers (running qemu-user).

Thanks!
Helge

Changes to v2:
- Fix build of close_range() and pidfd_*() patches on older Linux
  distributions (noticed by Stefan Hajnoczi)

Changes to v1:
- Dropped the faccessat2() syscall patch in favour of Richard's patch
- Various changes to the "missing signals in strace output" patch based on
  Richard's feedback, e.g. static arrays, fixed usage of _NSIG, fix build when
  TARGET_SIGIOT does not exist
- Use FUTEX_CMD_MASK in "Show timespec on strace for futex" patch
  unconditionally and turn into a switch statement - as suggested by Richard

Helge Deller (12):
  linux-user: Add missing signals in strace output
  linux-user: Add missing clock_gettime64() syscall strace
  linux-user: Add pidfd_open(), pidfd_send_signal() and pidfd_getfd()
syscalls
  linux-user: Log failing executable in EXCP_DUMP()
  linux-user/hppa: Use EXCP_DUMP() to show enhanced debug info
  linux-user/hppa: Dump IIR on register dump
  linux-user: Fix strace of chmod() if mode == 0
  linux-user/hppa: Set TASK_UNMAPPED_BASE to 0xfa00 for hppa arch
  linux-user: Add strace for clock_nanosleep()
  linux-user: Show timespec on strace for futex()
  linux-user: Add close_range() syscall
  linux-user: Add parameters of getrandom() syscall for strace

 linux-user/cpu_loop-common.h |   2 +
 linux-user/hppa/cpu_loop.c   |   6 +-
 linux-user/mmap.c|   4 +
 linux-user/signal-common.h   |  46 
 linux-user/signal.c  |  37 +
 linux-user/strace.c  | 142 ++-
 linux-user/strace.list   |  21 +-
 linux-user/syscall.c |  50 
 target/hppa/helper.c |   6 +-
 9 files changed, 255 insertions(+), 59 deletions(-)

--
2.37.3




Re: [PATCH 14/42] hw/isa/piix3: Modernize reset handling

2022-09-18 Thread Mark Cave-Ayland

On 01/09/2022 17:25, Bernhard Beschow wrote:


Rather than registering the reset handler via a function which
appends the handler to a global list, prefer to implement it as
a virtual method - PIIX4 does the same already.

Signed-off-by: Bernhard Beschow 
---
  hw/isa/piix3.c | 8 +++-
  1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c
index c8c2dd6048..0350f70706 100644
--- a/hw/isa/piix3.c
+++ b/hw/isa/piix3.c
@@ -31,7 +31,6 @@
  #include "hw/qdev-properties.h"
  #include "hw/isa/isa.h"
  #include "hw/xen/xen.h"
-#include "sysemu/reset.h"
  #include "sysemu/runstate.h"
  #include "migration/vmstate.h"
  #include "hw/acpi/acpi_aml_interface.h"
@@ -156,9 +155,9 @@ static void piix3_write_config_xen(PCIDevice *dev,
  piix3_write_config(dev, address, val, len);
  }
  
-static void piix3_reset(void *opaque)

+static void piix3_reset(DeviceState *dev)
  {
-PIIX3State *d = opaque;
+PIIX3State *d = PIIX3_PCI_DEVICE(dev);
  uint8_t *pci_conf = d->dev.config;
  
  pci_conf[0x04] = 0x07; /* master, memory and I/O */

@@ -321,8 +320,6 @@ static void pci_piix3_realize(PCIDevice *dev, Error **errp)
  memory_region_add_subregion_overlap(pci_address_space_io(dev),
  PIIX_RCR_IOPORT, >rcr_mem, 1);
  
-qemu_register_reset(piix3_reset, d);

-
  i8257_dma_init(isa_bus, 0);
  
  /* RTC */

@@ -397,6 +394,7 @@ static void pci_piix3_class_init(ObjectClass *klass, void 
*data)
  PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
  AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
  
+dc->reset   = piix3_reset;

  dc->desc= "ISA bridge";
  dc->vmsd= _piix3;
  dc->hotpluggable   = false;


One minor point to be aware of here is that qdev reset is a PCI bus level reset 
compared with the existing qemu_register_reset() which is a machine level reset. What 
this means is that dc->reset can also be called writing to the relevant configuration 
space register on a PCI bridge - it may not be an issue here, but worth a mention.



ATB,

Mark.



Re: [PATCH 07/42] hw/intc/i8259: Introduce i8259 proxy "isa-pic"

2022-09-18 Thread Mark Cave-Ayland

On 01/09/2022 17:25, Bernhard Beschow wrote:


Having an i8259 proxy allows for ISA PICs to be created and wired up in
southbridges. This is especially interesting for PIIX3 for two reasons:
First, the southbridge doesn't need to care about the virtualization
technology used (KVM, TCG, Xen) due to in-IRQs (where devices get
attached) and out-IRQs (which will trigger the IRQs of the respective
virtzalization technology) are separated. Second, since the in-IRQs are
populated with fully initialized qemu_irq's, they can already be wired
up inside PIIX3.

Signed-off-by: Bernhard Beschow 
---
  hw/intc/i8259.c | 27 +++
  include/hw/intc/i8259.h | 14 ++
  2 files changed, 41 insertions(+)

diff --git a/hw/intc/i8259.c b/hw/intc/i8259.c
index cc4e21ffec..531f6cca53 100644
--- a/hw/intc/i8259.c
+++ b/hw/intc/i8259.c
@@ -458,9 +458,36 @@ static const TypeInfo i8259_info = {
  .class_size = sizeof(PICClass),
  };
  
+static void isapic_set_irq(void *opaque, int irq, int level)

+{
+ISAPICState *s = opaque;
+
+qemu_set_irq(s->out_irqs[irq], level);
+}
+
+static void isapic_init(Object *obj)
+{
+ISAPICState *s = ISA_PIC(obj);
+
+qdev_init_gpio_in(DEVICE(s), isapic_set_irq, ISA_NUM_IRQS);
+qdev_init_gpio_out(DEVICE(s), s->out_irqs, ISA_NUM_IRQS);
+
+for (int i = 0; i < ISA_NUM_IRQS; ++i) {
+s->in_irqs[i] = qdev_get_gpio_in(DEVICE(s), i);
+}
+}
+
+static const TypeInfo isapic_info = {
+.name  = TYPE_ISA_PIC,
+.parent= TYPE_ISA_DEVICE,
+.instance_size = sizeof(ISAPICState),
+.instance_init = isapic_init,
+};
+
  static void pic_register_types(void)
  {
  type_register_static(_info);
+type_register_static(_info);
  }
  
  type_init(pic_register_types)

diff --git a/include/hw/intc/i8259.h b/include/hw/intc/i8259.h
index e2b1e8c59a..0246ab6ac6 100644
--- a/include/hw/intc/i8259.h
+++ b/include/hw/intc/i8259.h
@@ -1,6 +1,20 @@
  #ifndef HW_I8259_H
  #define HW_I8259_H
  
+#include "qom/object.h"

+#include "hw/isa/isa.h"
+#include "qemu/typedefs.h"
+
+#define TYPE_ISA_PIC "isa-pic"
+OBJECT_DECLARE_SIMPLE_TYPE(ISAPICState, ISA_PIC)
+
+struct ISAPICState {
+ISADevice parent_obj;
+
+qemu_irq in_irqs[ISA_NUM_IRQS];
+qemu_irq out_irqs[ISA_NUM_IRQS];
+};
+
  /* i8259.c */
  
  extern DeviceState *isa_pic;


So effectively this proxy device is working around the issue that we don't yet have a 
qdev-ified PIC that can be used to wire up ISA bus IRQs via qdev_connect_gpio_out(). 
Whilst ultimately this is the goal, I think having the proxy is a nice intermediate 
step as long as we can ensure that the device is not user-visible (i.e. it won't be 
exposed via the command line) so that this can be improved later.



ATB,

Mark.



Re: [PULL 00/12] linux-user patches

2022-09-18 Thread Helge Deller

On 9/17/22 22:11, Stefan Hajnoczi wrote:

On Sat, 17 Sept 2022 at 15:31, Philippe Mathieu-Daudé  wrote:


On 17/9/22 16:26, Stefan Hajnoczi wrote:

The close_range(2) man page says:
close_range() first appeared in Linux 5.9.  Library support was added
in glibc in version 2.34.

The qemu-user GitLab CI jobs are failing. For example, see
https://gitlab.com/qemu-project/qemu/-/jobs/3043629417:

../linux-user/syscall.c:8734:26: error: implicit declaration of
function 'close_range' is invalid in C99
[-Werror,-Wimplicit-function-declaration]
return get_errno(close_range(arg1, arg2, arg3));
 ^

There is a second issue with this pull request:
../linux-user/syscall.c:357:16: error: ‘pidfd_getfd’ defined but not
used [-Werror=unused-function]
357 | _syscall3(int, pidfd_getfd, int, pidfd, int, targetfd, unsigned
int, flags);
 | ^~~
../linux-user/syscall.c:251:13: note: in definition of macro ‘_syscall3’

See https://gitlab.com/qemu-project/qemu/-/jobs/3043629434.


Stefan, Thanks for testing those patches!
I'll send a new series with those issues fixed soon.



Hmm apparently this PR hasn't been reviewed (although the patches were
on the list for 2 weeks).

The 'check DCO' job - looking for S-o-b tags -  is green:
https://gitlab.com/qemu-project/qemu/-/jobs/3043629425.
Should we complete it by a R-b/A-b check over the commit range?


In some areas there will be no R-b/A-b, so I don't think we can
require those checks.

Was this pull request supposed to go through Laurent instead of being
applied directly by me?


I'm fine with either way :-)

Thanks!
Helge

Btw, I have a whole bunch of additional patches on top of this
series so it would be good to get this series in first...



Re: [PATCH] ui/console: fix three double frees in png_save()

2022-09-18 Thread Philippe Mathieu-Daudé via
+Kshitij

On Sun, Sep 18, 2022 at 6:24 PM Volker Rümelin  wrote:
>
> The png_destroy_write_struct() function frees all memory used by
> libpng. Don't use the glib auto cleanup mechanism to free the
> memory allocated by libpng again. For the pixman image, use only the
> auto cleanup mechanism and remove the qemu_pixman_image_unref()
> function call to prevent another double free.
>
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1210
> Signed-off-by: Volker Rümelin 
> ---
>  ui/console.c | 5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/ui/console.c b/ui/console.c
> index 765892f84f..030e75bc71 100644
> --- a/ui/console.c
> +++ b/ui/console.c
> @@ -304,8 +304,8 @@ static bool png_save(int fd, pixman_image_t *image, Error 
> **errp)
>  {
>  int width = pixman_image_get_width(image);
>  int height = pixman_image_get_height(image);
> -g_autofree png_struct *png_ptr = NULL;
> -g_autofree png_info *info_ptr = NULL;
> +png_struct *png_ptr;
> +png_info *info_ptr = NULL;

No need to NULL-initialize.

Fixes: 9a0a119a38 ("Added parameter to take screenshot with screendump as PNG")
Tested-by: Philippe Mathieu-Daudé 
Reviewed-by: Philippe Mathieu-Daudé 

>  g_autoptr(pixman_image_t) linebuf =
>  qemu_pixman_linebuf_create(PIXMAN_a8r8g8b8, 
> width);
>  uint8_t *buf = (uint8_t *)pixman_image_get_data(linebuf);
> @@ -346,7 +346,6 @@ static bool png_save(int fd, pixman_image_t *image, Error 
> **errp)
>  qemu_pixman_linebuf_fill(linebuf, image, width, 0, y);
>  png_write_row(png_ptr, buf);
>  }
> -qemu_pixman_image_unref(linebuf);
>
>  png_write_end(png_ptr, NULL);
>
> --
> 2.35.3
>
>



Re: [PATCH v11 21/21] job: remove unused functions

2022-09-18 Thread Emanuele Giuseppe Esposito



Am 14/09/2022 um 16:28 schrieb Vladimir Sementsov-Ogievskiy:
> On 8/26/22 16:21, Emanuele Giuseppe Esposito wrote:
>> These public functions are not used anywhere, thus can be dropped.
>> Also, since this is the final job API that doesn't use AioContext
>> lock and replaces it with job_lock, adjust all remaining function
>> documentation to clearly specify if the job lock is taken or not.
>>
>> Also document the locking requirements for a few functions
>> where the second version is not removed.
>>
>> Signed-off-by: Emanuele Giuseppe Esposito 
>> Reviewed-by: Stefan Hajnoczi 
>> Reviewed-by: Kevin Wolf 
>> ---
>>   include/qemu/job.h |  96 ++
>>   job.c  | 101 ++---
>>   2 files changed, 34 insertions(+), 163 deletions(-)
>>
>> diff --git a/include/qemu/job.h b/include/qemu/job.h
>> index ad8b32b4ba..762d6a98a7 100644
>> --- a/include/qemu/job.h
>> +++ b/include/qemu/job.h
>> @@ -384,6 +384,8 @@ JobTxn *job_txn_new(void);
>>   /**
>>    * Release a reference that was previously acquired with
>> job_txn_add_job or
> 
> [..]
> 
>> +/**
>> + * Returns true if the job is user-paused.
>> + * Called with job lock held.
>> + */
>>   bool job_user_paused_locked(Job *job);
>>     /**
>>    * Resume the specified @job.
>>    * Must be paired with a preceding job_user_pause.
> 
> in comment: job_user_puase_locked
> 
> 
> Please also fix other removed function mentioning in comments, for
> example I see in comments mentioning of removed job_ref, job_unref,
> job_user_pause...

Ok

>> @@ -725,9 +703,6 @@ void job_cancel_sync_all(void);
>>    * Returns the return value from the job.
>>    * Called with job_lock *not* held.
> 
> in comment: with lock held.
> 

No idea what you mean here.

Thank you,
Emanuele




Re: [PATCH v11 18/21] job.c: enable job lock/unlock and remove Aiocontext locks

2022-09-18 Thread Emanuele Giuseppe Esposito



Am 15/09/2022 um 16:52 schrieb Vladimir Sementsov-Ogievskiy:
> On 8/26/22 16:21, Emanuele Giuseppe Esposito wrote:
>> Change the job_{lock/unlock} and macros to use job_mutex.
>>
>> Now that they are not nop anymore, remove the aiocontext
>> to avoid deadlocks.
>>
>> Therefore:
>> - when possible, remove completely the aiocontext lock/unlock pair
>> - if it is used by some other function too, reduce the locking
>>    section as much as possible, leaving the job API outside.
>> - change AIO_WAIT_WHILE in AIO_WAIT_WHILE_UNLOCKED, since we
>>    are not using the aiocontext lock anymore
>>
>> The only functions that still need the aiocontext lock are the JobDriver
>> callbacks, already documented in job.h. Reduce the locking section to
>> only cover the callback invocation and document the functions that
>> take the AioContext lock, to avoid taking it twice.
>>
>> Also remove real_job_{lock/unlock}, as they are replaced by the
>> public functions.
>>
>> Signed-off-by: Emanuele Giuseppe Esposito 
>> Reviewed-by: Stefan Hajnoczi 
>> ---
> 
> [..]
> 
>> --- a/qemu-img.c
>> +++ b/qemu-img.c
>> @@ -911,7 +911,6 @@ static void run_block_job(BlockJob *job, Error
>> **errp)
>>   AioContext *aio_context = block_job_get_aio_context(job);
>>   int ret = 0;
>>   -    aio_context_acquire(aio_context);
>>   job_lock();
>>   job_ref_locked(>job);
>>   do {
> 
> aio_poll() call here, doesn't require aio_context to be acquired?

On the contrary I think, if you see in AIO_WAIT_WHILE we explicitly
release it because we don't want to allow something else to run with the
aiocontext acquired.

> 
>> @@ -936,7 +935,6 @@ static void run_block_job(BlockJob *job, Error
>> **errp)
>>   }
>>   job_unref_locked(>job);
>>   job_unlock();
>> -    aio_context_release(aio_context);
>>     /* publish completion progress only when success */
>>   if (!ret) {
> 
> [..]
> 
> In replication_stop, we call job_cancel_sync() inside
> aio_context_acquire - aio_context_release section. Should it be fixed?

I don't think it breaks anything. The question is: what is the
aiocontext there protecting? Do we need it? I have no idea.
> 
> Another question, sometimes you move job_start out of
> aio-context-acquire critical section, sometimes not. As I understand,
> it's of for job_start to be called both with acquired aio-context or not
> acquired?
> 
Same as above, job_start does not need the aiocontext to be taken
(otherwise job_lock would be useless).

> 
> Otherwise looks good to me!
> 

Thank you,
Emanuele




Re: [PATCH v11 13/21] jobs: protect job.aio_context with BQL and job_mutex

2022-09-18 Thread Emanuele Giuseppe Esposito



Am 14/09/2022 um 15:25 schrieb Vladimir Sementsov-Ogievskiy:
> On 8/26/22 16:20, Emanuele Giuseppe Esposito wrote:
>> In order to make it thread safe, implement a "fake rwlock",
>> where we allow reads under BQL *or* job_mutex held, but
>> writes only under BQL *and* job_mutex.
>>
>> The only write we have is in child_job_set_aio_ctx, which always
>> happens under drain (so the job is paused).
>> For this reason, introduce job_set_aio_context and make sure that
>> the context is set under BQL, job_mutex and drain.
>> Also make sure all other places where the aiocontext is read
>> are protected.
>>
>> The reads in commit.c and mirror.c are actually safe, because always
>> done under BQL.
>>
>> Note: at this stage, job_{lock/unlock} and job lock guard macros
>> are *nop*.
>>
>> Suggested-by: Paolo Bonzini 
>> Signed-off-by: Emanuele Giuseppe Esposito 
>> ---
>>   block/replication.c |  7 +--
>>   blockjob.c  |  3 ++-
>>   include/qemu/job.h  | 23 ---
>>   job.c   | 12 
>>   4 files changed, 39 insertions(+), 6 deletions(-)
>>
>> diff --git a/block/replication.c b/block/replication.c
>> index 55c8f894aa..6e02d98126 100644
>> --- a/block/replication.c
>> +++ b/block/replication.c
>> @@ -142,14 +142,17 @@ static void replication_close(BlockDriverState *bs)
>>   {
>>   BDRVReplicationState *s = bs->opaque;
>>   Job *commit_job;
>> +    GLOBAL_STATE_CODE();
>>     if (s->stage == BLOCK_REPLICATION_RUNNING) {
>>   replication_stop(s->rs, false, NULL);
>>   }
>>   if (s->stage == BLOCK_REPLICATION_FAILOVER) {
>>   commit_job = >commit_job->job;
>> -    assert(commit_job->aio_context ==
>> qemu_get_current_aio_context());
>> -    job_cancel_sync(commit_job, false);
>> +    WITH_JOB_LOCK_GUARD() {
>> +    assert(commit_job->aio_context ==
>> qemu_get_current_aio_context());
>> +    job_cancel_sync_locked(commit_job, false);
>> +    }
> 
> As Kevin said, this hunk seems not needed.. Why to add locking for
> reading aio_context, when we have GLOBAL_STATE_CODE()?

Ok, getting rid of it.
> 
>>   }
>>     if (s->mode == REPLICATION_MODE_SECONDARY) {
>> diff --git a/blockjob.c b/blockjob.c
>> index 96fb9d9f73..c8919cef9b 100644
>> --- a/blockjob.c
>> +++ b/blockjob.c
>> @@ -162,12 +162,13 @@ static void child_job_set_aio_ctx(BdrvChild *c,
>> AioContext *ctx,
>>   bdrv_set_aio_context_ignore(sibling->bs, ctx, ignore);
>>   }
>>   -    job->job.aio_context = ctx;
>> +    job_set_aio_context(>job, ctx);
>>   }
>>     static AioContext *child_job_get_parent_aio_context(BdrvChild *c)
>>   {
>>   BlockJob *job = c->opaque;
>> +    GLOBAL_STATE_CODE();
>>     return job->job.aio_context;
>>   }
>> diff --git a/include/qemu/job.h b/include/qemu/job.h
>> index 5709e8d4a8..cede227e67 100644
>> --- a/include/qemu/job.h
>> +++ b/include/qemu/job.h
>> @@ -74,11 +74,17 @@ typedef struct Job {
>>   /* ProgressMeter API is thread-safe */
>>   ProgressMeter progress;
>>   +    /**
>> + * AioContext to run the job coroutine in.
>> + * The job Aiocontext can be read when holding *either*
>> + * the BQL (so we are in the main loop) or the job_mutex.
>> + * It can only be written when we hold *both* BQL
>> + * and the job_mutex.
>> + */
>> +    AioContext *aio_context;
>>   -    /** Protected by AioContext lock */
>>   -    /** AioContext to run the job coroutine in */
>> -    AioContext *aio_context;
>> +    /** Protected by AioContext lock */
>>     /** Reference count of the block job */
>>   int refcnt;
>> @@ -741,4 +747,15 @@ int job_finish_sync(Job *job, void (*finish)(Job
>> *, Error **errp),
>>   int job_finish_sync_locked(Job *job, void (*finish)(Job *, Error
>> **errp),
>>  Error **errp);
>>   +/**
>> + * Sets the @job->aio_context.
>> + * Called with job_mutex *not* held.
>> + *
>> + * This function must run in the main thread to protect against
>> + * concurrent read in job_finish_sync_locked(), takes the job_mutex
>> + * lock to protect against the read in job_do_yield_locked(), and must
>> + * be called when the coroutine is quiescent.
> 
> May be "job is quiscent" or "job is doing nothing", "no in-flight io
> operations in job".
> 
> For example, backup has several running coroutines in contest of
> block_copy process, and main coroutine of the job
> is almost always "quescent"..

"job is quiescent" seems ok

> 
>> + */
>> +void job_set_aio_context(Job *job, AioContext *ctx);
>> +
>>   #endif
>> diff --git a/job.c b/job.c
>> index 85ae843f03..9f2fb2e73b 100644
>> --- a/job.c
>> +++ b/job.c
>> @@ -396,6 +396,17 @@ Job *job_get(const char *id)
>>   return job_get_locked(id);
>>   }
>>   +void job_set_aio_context(Job *job, AioContext *ctx)
>> +{
>> +    /* protect against read in job_finish_sync_locked and job_start */
>> +    GLOBAL_STATE_CODE();
>> +    /* protect against read in job_do_yield_locked */
>> 

Re: [PATCH v11 11/21] jobs: group together API calls under the same job lock

2022-09-18 Thread Emanuele Giuseppe Esposito



Am 14/09/2022 um 14:36 schrieb Vladimir Sementsov-Ogievskiy:
> On 8/26/22 16:20, Emanuele Giuseppe Esposito wrote:
>> Now that the API offers also _locked() functions, take advantage
>> of it and give also the caller control to take the lock and call
>> _locked functions.
>>
>> This makes sense especially when we have for loops, because it
>> makes no sense to have:
>>
>> for(job = job_next(); ...)
>>
>> where each job_next() takes the lock internally.
>> Instead we want
>>
>> JOB_LOCK_GUARD();
>> for(job = job_next_locked(); ...)
>>
>> In addition, protect also direct field accesses, by either creating a
>> new critical section or widening the existing ones.
>>
>> Note: at this stage, job_{lock/unlock} and job lock guard macros
>> are *nop*.
>>
>> Signed-off-by: Emanuele Giuseppe Esposito 
>> Reviewed-by: Vladimir Sementsov-Ogievskiy 
>> ---
>>   block.c    | 17 ++---
>>   blockdev.c | 14 ++
>>   blockjob.c | 35 ++-
>>   job-qmp.c  |  9 ++---
>>   job.c  |  7 +--
>>   monitor/qmp-cmds.c |  7 +--
>>   qemu-img.c | 17 +++--
>>   7 files changed, 69 insertions(+), 37 deletions(-)
>>
> 
> [..]
> 
>> diff --git a/job.c b/job.c
>> index dcd561fd46..e336af0c1c 100644
>> --- a/job.c
>> +++ b/job.c
> 
> job.c hunks are unrelated in this patch, they should go to patch 05.
> 
>> @@ -672,7 +672,7 @@ void coroutine_fn job_pause_point(Job *job)
>>   job_pause_point_locked(job);
>>   }
>>   -void job_yield_locked(Job *job)
>> +static void job_yield_locked(Job *job)
>>   {
>>   assert(job->busy);
>>   @@ -1046,11 +1046,14 @@ static void
>> job_completed_txn_abort_locked(Job *job)
>>   /* Called with job_mutex held, but releases it temporarily */
>>   static int job_prepare_locked(Job *job)
>>   {
>> +    int ret;
>> +
>>   GLOBAL_STATE_CODE();
>>   if (job->ret == 0 && job->driver->prepare) {
>>   job_unlock();
>> -    job->ret = job->driver->prepare(job);
>> +    ret = job->driver->prepare(job);
>>   job_lock();
>> +    job->ret = ret;
>>   job_update_rc_locked(job);
>>   }
>>   return job->ret;
>> diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
>> index 7314cd813d..81c8fdadf8 100644
>> --- a/monitor/qmp-cmds.c
>> +++ b/monitor/qmp-cmds.c
>> @@ -135,8 +135,11 @@ void qmp_cont(Error **errp)
>>   blk_iostatus_reset(blk);
>>   }
>>   -    for (job = block_job_next(NULL); job; job = block_job_next(job)) {
>> -    block_job_iostatus_reset(job);
>> +    WITH_JOB_LOCK_GUARD() {
>> +    for (job = block_job_next_locked(NULL); job;
>> + job = block_job_next_locked(job)) {
>> +    block_job_iostatus_reset_locked(job);
>> +    }
>>   }
>>     /* Continuing after completed migration. Images have been
>> inactivated to
>> diff --git a/qemu-img.c b/qemu-img.c
>> index 7d4b33b3da..c8ae704166 100644
>> --- a/qemu-img.c
>> +++ b/qemu-img.c
>> @@ -912,25 +912,30 @@ static void run_block_job(BlockJob *job, Error
>> **errp)
>>   int ret = 0;
>>     aio_context_acquire(aio_context);
>> -    job_ref(>job);
>> +    job_lock();
>> +    job_ref_locked(>job);
>>   do {
>>   float progress = 0.0f;
>> +    job_unlock();
>>   aio_poll(aio_context, true);
>>     progress_get_snapshot(>job.progress, _current,
>> -  _total);
>> +    _total);
> 
> broken indentation
> 
>>   if (progress_total) {
>>   progress = (float)progress_current / progress_total *
>> 100.f;
>>   }
>>   qemu_progress_print(progress, 0);
>> -    } while (!job_is_ready(>job) && !job_is_completed(>job));
>> +    job_lock();
>> +    } while (!job_is_ready_locked(>job) &&
>> +    !job_is_completed_locked(>job));
> 
> and here

Makes sense, I'll fix it.

Thank you,
Emanuele
> 
>>   -    if (!job_is_completed(>job)) {
>> -    ret = job_complete_sync(>job, errp);
>> +    if (!job_is_completed_locked(>job)) {
>> +    ret = job_complete_sync_locked(>job, errp);
>>   } else {
>>   ret = job->job.ret;
>>   }
>> -    job_unref(>job);
>> +    job_unref_locked(>job);
>> +    job_unlock();
>>   aio_context_release(aio_context);
>>     /* publish completion progress only when success */
> 
> 




[PATCH 8/8] Ping : hw/gpio Fix license statements in avr_gpio

2022-09-18 Thread Heecheol Yang
I send this patch to continue our works discussed about two years ago.
Due to my personal issue, I couldn't noticed that there were some issues
in license statements in the code. 

I am very sorry for my late response and politely  request to check this patch.

Signed-off-by: Heecheol Yang 
---
 hw/gpio/avr_gpio.c | 16 
 include/hw/gpio/avr_gpio.h | 15 +++
 2 files changed, 7 insertions(+), 24 deletions(-)

diff --git a/hw/gpio/avr_gpio.c b/hw/gpio/avr_gpio.c
index 29252d6ccf..7613ca6493 100644
--- a/hw/gpio/avr_gpio.c
+++ b/hw/gpio/avr_gpio.c
@@ -4,19 +4,11 @@
  * Copyright (C) 2020 Heecheol Yang 
  * Copyright (C) 2021 Niteesh Babu G S 
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see .
+ * This work is licensed under the terms of the GNU GPLv2 or later.
+ * See the COPYING file in the top-level directory.
+ * SPDX-License-Identifier: GPL-2.0-or-later
  */
+ 
 #include "qemu/osdep.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
diff --git a/include/hw/gpio/avr_gpio.h b/include/hw/gpio/avr_gpio.h
index e982f627ea..e4bfef0def 100644
--- a/include/hw/gpio/avr_gpio.h
+++ b/include/hw/gpio/avr_gpio.h
@@ -3,18 +3,9 @@
  *
  * Copyright (C) 2020 Heecheol Yang 
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see .
+ * This work is licensed under the terms of the GNU GPLv2 or later.
+ * See the COPYING file in the top-level directory.
+ * SPDX-License-Identifier: GPL-2.0-or-later
  */
 
 #ifndef AVR_GPIO_H
-- 
2.34.1




[PATCH] ui/console: fix three double frees in png_save()

2022-09-18 Thread Volker Rümelin
The png_destroy_write_struct() function frees all memory used by
libpng. Don't use the glib auto cleanup mechanism to free the
memory allocated by libpng again. For the pixman image, use only the
auto cleanup mechanism and remove the qemu_pixman_image_unref()
function call to prevent another double free.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1210
Signed-off-by: Volker Rümelin 
---
 ui/console.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/ui/console.c b/ui/console.c
index 765892f84f..030e75bc71 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -304,8 +304,8 @@ static bool png_save(int fd, pixman_image_t *image, Error 
**errp)
 {
 int width = pixman_image_get_width(image);
 int height = pixman_image_get_height(image);
-g_autofree png_struct *png_ptr = NULL;
-g_autofree png_info *info_ptr = NULL;
+png_struct *png_ptr;
+png_info *info_ptr = NULL;
 g_autoptr(pixman_image_t) linebuf =
 qemu_pixman_linebuf_create(PIXMAN_a8r8g8b8, width);
 uint8_t *buf = (uint8_t *)pixman_image_get_data(linebuf);
@@ -346,7 +346,6 @@ static bool png_save(int fd, pixman_image_t *image, Error 
**errp)
 qemu_pixman_linebuf_fill(linebuf, image, width, 0, y);
 png_write_row(png_ptr, buf);
 }
-qemu_pixman_image_unref(linebuf);
 
 png_write_end(png_ptr, NULL);
 
-- 
2.35.3




Re: [PATCH 00/11] ppc/e500: Add support for two types of flash, cleanup

2022-09-18 Thread Philippe Mathieu-Daudé via

On 15/9/22 17:25, Bernhard Beschow wrote:

This series adds support for -pflash and direct SD card access to the
PPC e500 boards. The idea is to increase compatibility with "real" firmware
images where only the bare minimum of drivers is compiled in.

The series is structured as follows:

Patches 1-3 perform some general cleanup which paves the way for the rest of
the series.

Patches 4-7 add -pflash handling where memory-mapped flash can be added on
user's behalf. That is, the flash memory region is only added if the -pflash
argument is supplied. Note that the cfi01 device model becomes stricter in
checking the size of the emulated flash space.

Patches 8-11 add a new device model - the Freescale eSDHC - to the e500
boards which was missing so far.

User documentation is also added as the new features become available.


Future possible cleanup: Looking at the e500 component, the MPC8544 GUTS
added in commit b0fb84236d ("PPC: E500: Implement reboot controller")
was used in hw/ppce500_mpc8544ds.c board, but in a later refactor
(commit 4a18e7c92a "PPC: e500: rename mpc8544ds into generic file")
this file got renamed as hw/ppc/e500.c; having a MPC8544 specific piece
in the common e500 seems odd.



Re: [PATCH 08/11] hw/sd/sdhci-internal: Unexport ESDHC defines

2022-09-18 Thread Philippe Mathieu-Daudé via

On 15/9/22 17:25, Bernhard Beschow wrote:

These defines aren't used outside of sdhci.c, so can be defined there.

Signed-off-by: Bernhard Beschow 
---
  hw/sd/sdhci-internal.h | 20 
  hw/sd/sdhci.c  | 19 +++
  2 files changed, 19 insertions(+), 20 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 



Re: [PATCH 05/11] hw/ppc/e500: Remove if statement which is now always true

2022-09-18 Thread Philippe Mathieu-Daudé via

On 15/9/22 17:25, Bernhard Beschow wrote:

Now that the MPC8544DS board also has a platform bus, the if statement
was always true.


s/was/is/.

Reviewed-by: Philippe Mathieu-Daudé 



Signed-off-by: Bernhard Beschow 
---
  hw/ppc/e500.c  | 30 ++
  hw/ppc/e500.h  |  1 -
  hw/ppc/e500plat.c  |  1 -
  hw/ppc/mpc8544ds.c |  1 -
  4 files changed, 14 insertions(+), 19 deletions(-)




Re: [PATCH 03/11] docs/system/ppc/ppce500: Add heading for networking chapter

2022-09-18 Thread Philippe Mathieu-Daudé

On 15/9/22 17:25, Bernhard Beschow wrote:

The sudden change of topics is slightly confusing and makes the
networking information less visible. So separate the networking chapter
to improve comprehensibility.

Signed-off-by: Bernhard Beschow 
---
  docs/system/ppc/ppce500.rst | 3 +++
  1 file changed, 3 insertions(+)


Reviewed-by: Philippe Mathieu-Daudé 




Re: [PATCH 02/11] hw/gpio/meson: Introduce dedicated config switch for hw/gpio/mpc8xxx

2022-09-18 Thread Philippe Mathieu-Daudé via

On 15/9/22 17:25, Bernhard Beschow wrote:

Having a dedicated config switch makes dependency handling cleaner.

Signed-off-by: Bernhard Beschow 
---
  hw/gpio/Kconfig | 3 +++
  hw/gpio/meson.build | 2 +-
  hw/ppc/Kconfig  | 1 +
  3 files changed, 5 insertions(+), 1 deletion(-)


Reviewed-by: Philippe Mathieu-Daudé 



Re: [PATCH 01/11] hw/ppc/meson: Allow e500 boards to be enabled separately

2022-09-18 Thread Philippe Mathieu-Daudé via

On 15/9/22 17:25, Bernhard Beschow wrote:

Gives users more fine-grained control over what should be compiled into
QEMU.

Signed-off-by: Bernhard Beschow 
---
  configs/devices/ppc-softmmu/default.mak | 3 ++-
  hw/ppc/Kconfig  | 8 
  hw/ppc/meson.build  | 6 ++
  3 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/configs/devices/ppc-softmmu/default.mak 
b/configs/devices/ppc-softmmu/default.mak
index 658a454426..a887f5438b 100644
--- a/configs/devices/ppc-softmmu/default.mak
+++ b/configs/devices/ppc-softmmu/default.mak
@@ -1,7 +1,8 @@
  # Default configuration for ppc-softmmu
  
  # For embedded PPCs:

-CONFIG_E500=y
+CONFIG_E500PLAT=y
+CONFIG_MPC8544DS=y
  CONFIG_PPC405=y
  CONFIG_PPC440=y
  CONFIG_VIRTEX=y
diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig
index 3a4418a69e..22a64745d4 100644
--- a/hw/ppc/Kconfig
+++ b/hw/ppc/Kconfig
@@ -132,6 +132,14 @@ config E500
  select FDT_PPC
  select DS1338
  
+config E500PLAT

+bool
+select E500
+
+config MPC8544DS
+bool
+select E500
+
  config VIRTEX
  bool
  select PPC4XX
diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build
index 62801923f3..32babc9b48 100644
--- a/hw/ppc/meson.build
+++ b/hw/ppc/meson.build
@@ -71,12 +71,10 @@ ppc_ss.add(when: 'CONFIG_MAC_OLDWORLD', if_true: 
files('mac_oldworld.c'))
  # NewWorld PowerMac
  ppc_ss.add(when: 'CONFIG_MAC_NEWWORLD', if_true: files('mac_newworld.c'))
  # e500
+ppc_ss.add(when: 'CONFIG_E500PLAT', if_true: files('e500plat.c'))
+ppc_ss.add(when: 'CONFIG_MPC8544DS', if_true: files('mpc8544ds.c'))
  ppc_ss.add(when: 'CONFIG_E500', if_true: files(
'e500.c',
-  'mpc8544ds.c',
-  'e500plat.c'
-))
-ppc_ss.add(when: 'CONFIG_E500', if_true: files(
'mpc8544_guts.c',


Reviewed-by: Philippe Mathieu-Daudé 


'ppce500_spin.c'
  ))





Re: [Bug 1772165] Re: arm raspi2/raspi3 emulation has no USB support

2022-09-18 Thread Philippe Mathieu-Daudé via
On Tue, Feb 22, 2022 at 3:15 PM Carlo Bramini
<1772...@bugs.launchpad.net> wrote:
>
> I'm also trying to run QEMU for emulating Raspberry PI, but I'm still unable 
> to make working external USB devices like keyboard and mouse.
> Unlike previous users, I'm not using a linux distro but Microsoft Windows 10 
> instead.
> I'm using the precompiled 64bit executables downloaded from 
> https://qemu.weilnetz.de/w64/ as suggested from the download page at qemu.org 
> for Windows targets.

> The emulator starts, the desktop of the OS appears, but still no keyboard and 
> no mouse support.
> However, I can still login by using the terminal provided by the emulated 
> serial terminal.
>
> Is the feature expected to work also on the port of QEMU for Windows?

Yes.

However upstream QEMU bugs are now tracked on https://gitlab.com/qemu-
project/qemu/-/issues - so if you can reproduce it with the latest
version from upstream QEMU, please report it there.

Regards,

Phil.



Re: [PATCH v3 03/20] ppc4xx_sdram: Get rid of the init RAM hack

2022-09-18 Thread BALATON Zoltan

On Sun, 18 Sep 2022, BALATON Zoltan wrote:

On Sun, 18 Sep 2022, Cédric Le Goater wrote:

On 9/14/22 20:32, BALATON Zoltan wrote:

On Wed, 14 Sep 2022, BALATON Zoltan wrote:

On Wed, 14 Sep 2022, Cédric Le Goater wrote:

On 9/14/22 13:44, BALATON Zoltan wrote:

On Wed, 14 Sep 2022, Cédric Le Goater wrote:

On 9/13/22 21:52, BALATON Zoltan wrote:

The do_init parameter of ppc4xx_sdram_init() is used to map memory
regions that is normally done by the firmware by programming the 
SDRAM
controller. This is needed when booting a kernel directly from 
-kernel

without a firmware. Do this from board code accesing normal SDRAM


accessing


Fixed, also two ofhers in another patch you haven't noticed.


controller registers the same way as firmware would do, so we can get
rid of this hack.

Signed-off-by: BALATON Zoltan 
---
v2: Fix ref405ep boot with -kernel and U-Boot

  hw/ppc/ppc405.h |  1 -
  hw/ppc/ppc405_boards.c  | 12 ++--
  hw/ppc/ppc405_uc.c  |  4 +---
  hw/ppc/ppc440_bamboo.c  |  8 +++-
  hw/ppc/ppc440_uc.c  |  2 --
  hw/ppc/ppc4xx_devs.c    | 11 +--
  include/hw/ppc/ppc4xx.h |  8 ++--
  7 files changed, 25 insertions(+), 21 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 1e558c7831..756865621b 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -169,7 +169,6 @@ struct Ppc405SoCState {
  /* Public */
  MemoryRegion ram_banks[2];
  hwaddr ram_bases[2], ram_sizes[2];
-    bool do_dram_init;
    MemoryRegion *dram_mr;
  hwaddr ram_size;
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 083f12b23e..bf02a71c6d 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -274,6 +274,7 @@ static void ppc405_init(MachineState *machine)
  MachineClass *mc = MACHINE_GET_CLASS(machine);
  const char *kernel_filename = machine->kernel_filename;
  MemoryRegion *sysmem = get_system_memory();
+    CPUPPCState *env;
    if (machine->ram_size != mc->default_ram_size) {
  char *sz = size_to_str(mc->default_ram_size);
@@ -288,12 +289,19 @@ static void ppc405_init(MachineState *machine)
   machine->ram_size, _fatal);
  object_property_set_link(OBJECT(>soc), "dram",
   OBJECT(machine->ram), _abort);
-    object_property_set_bool(OBJECT(>soc), "dram-init",
- kernel_filename != NULL, _abort);
  object_property_set_uint(OBJECT(>soc), "sys-clk", 
,

   _abort);
  qdev_realize(DEVICE(>soc), NULL, _fatal);
  +    /* Enable SDRAM memory regions */
+    /* FIXME This shouldn't be needed with firmware but we lack SPD 
data */


what do you mean ?


U-Boot detects the available RAM by reading the SPD info of the RAM 
modules but that probably also needs i2c emulation. See sam460ex.



+    env = >soc.cpu.env;
+    if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x20) ||
+    ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x8000)) {



I am not in favor of these ppc_drc_write calls and this is still a 
hack.


It's not. Normally this is done by firmware to enable memory controller 
but the board code has to do it if not using firmware (e.g. booting 
with -kernel) the same way it provides bootinfo or device tree mods the 
firmware would normally do or in this case maybe the emulation is 
incomplete so the part of firmware that configures the SDRAM controller 
does not run.


Exactly, and what the above proposal does is mimicking execution of CPU
instructions before the CPU is even fully initiated. Reset has not been
called at that stage.


I don't get this. We're not calling any CPU instructions, ppc_dcr_write 
just calls the write callback the device has registered for the dcr so it 
just does the same as the hack did at the end just doing it the same way 
the firmware should do.


The "dram-init" property is a cleaner solution. It takes care of doing 
the
pre-mapping of RAM banks in the realize routine of the sdram model 
(when

available).


I disagree, the hardware does not have such feature, it proviesd DCRs 
as the way to configure it. Adding a special property for it deviates 
from hardware and clutters qtree. 



In this machine, running QEMU with -kernel deviates from HW. That's


In all machines booting with -kernel likely deviates and all machines 
probably have additinal code in this case to do some things normally done 
by the firmware. Look at pegasos2_machine_reset() for example. All that 
is not needed when we boot with firmware as then the firmware will do all 
that and provide the device tree, etc. bur we need to do these when 
booting without firmware. In thes case QEMU also emulates the firmware 
and has to do thinigs like enabling the memory controller.



the whole purpose of this option. It assumes that the SDRAM device
is pre-initialized (and much more should be done) by the QEMU machine
and the simplest way to acheive this goal is to inform the 

Re: [PATCH v3 03/20] ppc4xx_sdram: Get rid of the init RAM hack

2022-09-18 Thread BALATON Zoltan

On Sun, 18 Sep 2022, Cédric Le Goater wrote:

On 9/14/22 20:32, BALATON Zoltan wrote:

On Wed, 14 Sep 2022, BALATON Zoltan wrote:

On Wed, 14 Sep 2022, Cédric Le Goater wrote:

On 9/14/22 13:44, BALATON Zoltan wrote:

On Wed, 14 Sep 2022, Cédric Le Goater wrote:

On 9/13/22 21:52, BALATON Zoltan wrote:

The do_init parameter of ppc4xx_sdram_init() is used to map memory
regions that is normally done by the firmware by programming the SDRAM
controller. This is needed when booting a kernel directly from -kernel
without a firmware. Do this from board code accesing normal SDRAM


accessing


Fixed, also two ofhers in another patch you haven't noticed.


controller registers the same way as firmware would do, so we can get
rid of this hack.

Signed-off-by: BALATON Zoltan 
---
v2: Fix ref405ep boot with -kernel and U-Boot

  hw/ppc/ppc405.h |  1 -
  hw/ppc/ppc405_boards.c  | 12 ++--
  hw/ppc/ppc405_uc.c  |  4 +---
  hw/ppc/ppc440_bamboo.c  |  8 +++-
  hw/ppc/ppc440_uc.c  |  2 --
  hw/ppc/ppc4xx_devs.c    | 11 +--
  include/hw/ppc/ppc4xx.h |  8 ++--
  7 files changed, 25 insertions(+), 21 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 1e558c7831..756865621b 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -169,7 +169,6 @@ struct Ppc405SoCState {
  /* Public */
  MemoryRegion ram_banks[2];
  hwaddr ram_bases[2], ram_sizes[2];
-    bool do_dram_init;
    MemoryRegion *dram_mr;
  hwaddr ram_size;
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 083f12b23e..bf02a71c6d 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -274,6 +274,7 @@ static void ppc405_init(MachineState *machine)
  MachineClass *mc = MACHINE_GET_CLASS(machine);
  const char *kernel_filename = machine->kernel_filename;
  MemoryRegion *sysmem = get_system_memory();
+    CPUPPCState *env;
    if (machine->ram_size != mc->default_ram_size) {
  char *sz = size_to_str(mc->default_ram_size);
@@ -288,12 +289,19 @@ static void ppc405_init(MachineState *machine)
   machine->ram_size, _fatal);
  object_property_set_link(OBJECT(>soc), "dram",
   OBJECT(machine->ram), _abort);
-    object_property_set_bool(OBJECT(>soc), "dram-init",
- kernel_filename != NULL, _abort);
  object_property_set_uint(OBJECT(>soc), "sys-clk", 
,

   _abort);
  qdev_realize(DEVICE(>soc), NULL, _fatal);
  +    /* Enable SDRAM memory regions */
+    /* FIXME This shouldn't be needed with firmware but we lack SPD 
data */


what do you mean ?


U-Boot detects the available RAM by reading the SPD info of the RAM 
modules but that probably also needs i2c emulation. See sam460ex.



+    env = >soc.cpu.env;
+    if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x20) ||
+    ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x8000)) {



I am not in favor of these ppc_drc_write calls and this is still a 
hack.


It's not. Normally this is done by firmware to enable memory controller 
but the board code has to do it if not using firmware (e.g. booting with 
-kernel) the same way it provides bootinfo or device tree mods the 
firmware would normally do or in this case maybe the emulation is 
incomplete so the part of firmware that configures the SDRAM controller 
does not run.


Exactly, and what the above proposal does is mimicking execution of CPU
instructions before the CPU is even fully initiated. Reset has not been
called at that stage.


I don't get this. We're not calling any CPU instructions, ppc_dcr_write 
just calls the write callback the device has registered for the dcr so it 
just does the same as the hack did at the end just doing it the same way 
the firmware should do.


The "dram-init" property is a cleaner solution. It takes care of doing 
the
pre-mapping of RAM banks in the realize routine of the sdram model 
(when

available).


I disagree, the hardware does not have such feature, it proviesd DCRs as 
the way to configure it. Adding a special property for it deviates from 
hardware and clutters qtree. 



In this machine, running QEMU with -kernel deviates from HW. That's


In all machines booting with -kernel likely deviates and all machines 
probably have additinal code in this case to do some things normally done 
by the firmware. Look at pegasos2_machine_reset() for example. All that is 
not needed when we boot with firmware as then the firmware will do all 
that and provide the device tree, etc. bur we need to do these when 
booting without firmware. In thes case QEMU also emulates the firmware and 
has to do thinigs like enabling the memory controller.



the whole purpose of this option. It assumes that the SDRAM device
is pre-initialized (and much more should be done) by the QEMU machine
and the simplest way to acheive this goal is to inform the SDRAM model
to take care of the pre-initialization.

Re: [PATCH v4 14/21] ppc440_sdram: Move RAM size check to ppc440_sdram_init

2022-09-18 Thread BALATON Zoltan

On Sun, 18 Sep 2022, Philippe Mathieu-Daudé wrote:

On 14/9/22 13:34, BALATON Zoltan wrote:

Move the check for valid memory sizes from board to sdram controller
init. Board now only checks for additional restrictions imposed by
firmware then sdram init checks for valid sizes for SoC.

Signed-off-by: BALATON Zoltan 
---
  hw/ppc/ppc440.h|  4 ++--
  hw/ppc/ppc440_uc.c | 15 +++
  hw/ppc/sam460ex.c  | 32 +---
  3 files changed, 26 insertions(+), 25 deletions(-)

diff --git a/hw/ppc/ppc440.h b/hw/ppc/ppc440.h
index 01d76b8000..29f6f14ed7 100644
--- a/hw/ppc/ppc440.h
+++ b/hw/ppc/ppc440.h
@@ -11,13 +11,13 @@
  #ifndef PPC440_H
  #define PPC440_H
  -#include "hw/ppc/ppc4xx.h"
+#include "hw/ppc/ppc.h"
void ppc4xx_l2sram_init(CPUPPCState *env);
  void ppc4xx_cpr_init(CPUPPCState *env);
  void ppc4xx_sdr_init(CPUPPCState *env);
  void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-   Ppc4xxSdramBank *ram_banks);
+   MemoryRegion *ram);
  void ppc4xx_ahb_init(CPUPPCState *env);
  void ppc4xx_dma_init(CPUPPCState *env, int dcr_base);
  void ppc460ex_pcie_init(CPUPPCState *env);
diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index fa313f979d..bd2a489557 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -486,7 +486,7 @@ void ppc4xx_sdr_init(CPUPPCState *env)
  typedef struct ppc440_sdram_t {
  uint32_t addr;
  uint32_t mcopt2;
-int nbanks;
+int nbanks; /* Banks to use from the 4, e.g. when board has less slots 
*/

  Ppc4xxSdramBank bank[4];
  } ppc440_sdram_t;
  @@ -732,18 +732,17 @@ static void sdram_ddr2_reset(void *opaque)
  }
void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-   Ppc4xxSdramBank *ram_banks)
+   MemoryRegion *ram)
  {
  ppc440_sdram_t *s;
-int i;
+const ram_addr_t valid_bank_sizes[] = {
+4 * GiB, 2 * GiB, 1 * GiB, 512 * MiB, 256 * MiB, 128 * MiB, 64 * 
MiB,

+32 * MiB, 16 * MiB, 8 * MiB, 0


Where 16/8 come from?


From sdram_ddr2_bcr(). This array now has the missing 4 GB, 16 and 8 MB 
the SoC can handle but the board can't and added separate checks for the 
board restrictions in the board code. Probably isn't worth splitting this 
out in a separate patch but I should more explicitly mention it in the 
commit message to make it clearer.


Regards,
BALATON Zoltan


+};
s = g_malloc0(sizeof(*s));
  s->nbanks = nbanks;
-for (i = 0; i < nbanks; i++) {
-s->bank[i].ram = ram_banks[i].ram;
-s->bank[i].base = ram_banks[i].base;
-s->bank[i].size = ram_banks[i].size;
-}
+ppc4xx_sdram_banks(ram, s->nbanks, s->bank, valid_bank_sizes);
  qemu_register_reset(_ddr2_reset, s);
  ppc_dcr_register(env, SDRAM0_CFGADDR,
   s, _ddr2_dcr_read, _ddr2_dcr_write);
diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
index dac329d482..9b850808a3 100644
--- a/hw/ppc/sam460ex.c
+++ b/hw/ppc/sam460ex.c
@@ -74,13 +74,6 @@
  #define EBC_FREQ 11500
  #define UART_FREQ 11059200
  -/* The SoC could also handle 4 GiB but firmware does not work with that. 
*/

-/* Maybe it overflows a signed 32 bit number somewhere? */
-static const ram_addr_t ppc460ex_sdram_bank_sizes[] = {
-2 * GiB, 1 * GiB, 512 * MiB, 256 * MiB, 128 * MiB, 64 * MiB,
-32 * MiB, 0
-};
-
  struct boot_info {
  uint32_t dt_base;
  uint32_t dt_size;
@@ -273,7 +266,6 @@ static void sam460ex_init(MachineState *machine)
  {
  MemoryRegion *address_space_mem = get_system_memory();
  MemoryRegion *isa = g_new(MemoryRegion, 1);
-Ppc4xxSdramBank *ram_banks = g_new0(Ppc4xxSdramBank, 1);
  MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1);
  DeviceState *uic[4];
  int i;
@@ -340,12 +332,22 @@ static void sam460ex_init(MachineState *machine)
  }
/* SDRAM controller */
-/* put all RAM on first bank because board has one slot
- * and firmware only checks that */
-ppc4xx_sdram_banks(machine->ram, 1, ram_banks, 
ppc460ex_sdram_bank_sizes);

-
+/* The SoC could also handle 4 GiB but firmware does not work with 
that. */

+if (machine->ram_size > 2 * GiB) {
+error_report("Memory over 2 GiB is not supported");
+exit(1);
+}
+/* Firmware needs at least 64 MiB */
+if (machine->ram_size < 64 * MiB) {
+error_report("Memory below 64 MiB is not supported");
+exit(1);
+}
+/*
+ * Put all RAM on first bank because board has one slot
+ * and firmware only checks that
+ */
+ppc440_sdram_init(env, 1, machine->ram);
  /* FIXME: does 460EX have ECC interrupts? */
-ppc440_sdram_init(env, 1, ram_banks);
  /* Enable SDRAM memory regions as we may boot without firmware */
  if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x21) ||
  ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x0800)) {
@@ -358,8 +360,8 @@ static void sam460ex_init(MachineState *machine)
  

Re: [PATCH 0/3] Add qemu-img checksum command using blkhash

2022-09-18 Thread Nir Soffer
ping

Kevin, Hanna, I hope you have time to take a look.

https://lists.nongnu.org/archive/html/qemu-block/2022-09/msg00021.html


On Thu, Sep 1, 2022 at 5:32 PM Nir Soffer  wrote:
>
> Since blkhash is available only via copr now, the new command is added as
> optional feature, built only if blkhash-devel package is installed.
>
> Nir Soffer (3):
>   qemu-img: Add checksum command
>   iotests: Test qemu-img checksum
>   qemu-img: Speed up checksum
>
>  docs/tools/qemu-img.rst   |  22 +
>  meson.build   |  10 +-
>  meson_options.txt |   2 +
>  qemu-img-cmds.hx  |   8 +
>  qemu-img.c| 388 ++
>  tests/qemu-iotests/tests/qemu-img-checksum| 149 +++
>  .../qemu-iotests/tests/qemu-img-checksum.out  |  74 
>  7 files changed, 652 insertions(+), 1 deletion(-)
>  create mode 100755 tests/qemu-iotests/tests/qemu-img-checksum
>  create mode 100644 tests/qemu-iotests/tests/qemu-img-checksum.out
>
> --
> 2.37.2
>




[PATCH] target/riscv: Check the correct exception cause in vector GDB stub

2022-09-18 Thread frank . chang
From: Frank Chang 

After RISCVException enum is introduced, riscv_csrrw_debug() returns
RISCV_EXCP_NONE to indicate there's no error. RISC-V vector GDB stub
should check the result against RISCV_EXCP_NONE instead of value 0.
Otherwise, 'E14' packet would be incorrectly reported for vector CSRs
when using "info reg vector" GDB command.

Signed-off-by: Frank Chang 
Reviewed-by: Jim Shu 
Reviewed-by: Tommy Wu 
---
 target/riscv/gdbstub.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 9ed049c29e..118bd40f10 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -211,7 +211,7 @@ static int riscv_gdb_get_vector(CPURISCVState *env, 
GByteArray *buf, int n)
 target_ulong val = 0;
 int result = riscv_csrrw_debug(env, csrno, , 0, 0);
 
-if (result == 0) {
+if (result == RISCV_EXCP_NONE) {
 return gdb_get_regl(buf, val);
 }
 
@@ -238,7 +238,7 @@ static int riscv_gdb_set_vector(CPURISCVState *env, uint8_t 
*mem_buf, int n)
 target_ulong val = ldtul_p(mem_buf);
 int result = riscv_csrrw_debug(env, csrno, NULL, val, -1);
 
-if (result == 0) {
+if (result == RISCV_EXCP_NONE) {
 return sizeof(target_ulong);
 }
 
-- 
2.36.1




[PATCH] target/i386: fix INSERTQ implementation

2022-09-18 Thread Paolo Bonzini
INSERTQ is defined to not modify any bits in the lower 64 bits of the
destination, other than the ones being replaced with bits from the
source operand.  QEMU instead is using unshifted bits from the source
for those bits.

Signed-off-by: Paolo Bonzini 
---
 target/i386/ops_sse.h| 10 +-
 target/i386/ops_sse_header.h |  2 +-
 target/i386/tcg/translate.c  | 14 --
 3 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index 3504bca36a..7bf8bb967d 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -934,7 +934,7 @@ void helper_extrq_i(CPUX86State *env, ZMMReg *d, int index, 
int length)
 d->ZMM_Q(0) = helper_extrq(d->ZMM_Q(0), index, length);
 }
 
-static inline uint64_t helper_insertq(uint64_t src, int shift, int len)
+static inline uint64_t helper_insertq(uint64_t dest, uint64_t src, int shift, 
int len)
 {
 uint64_t mask;
 
@@ -943,17 +943,17 @@ static inline uint64_t helper_insertq(uint64_t src, int 
shift, int len)
 } else {
 mask = (1ULL << len) - 1;
 }
-return (src & ~(mask << shift)) | ((src & mask) << shift);
+return (dest & ~(mask << shift)) | ((src & mask) << shift);
 }
 
 void helper_insertq_r(CPUX86State *env, ZMMReg *d, ZMMReg *s)
 {
-d->ZMM_Q(0) = helper_insertq(s->ZMM_Q(0), s->ZMM_B(9) & 63, s->ZMM_B(8) & 
63);
+d->ZMM_Q(0) = helper_insertq(d->ZMM_Q(0), s->ZMM_Q(0), s->ZMM_B(9) & 63, 
s->ZMM_B(8) & 63);
 }
 
-void helper_insertq_i(CPUX86State *env, ZMMReg *d, int index, int length)
+void helper_insertq_i(CPUX86State *env, ZMMReg *d, ZMMReg *s, int index, int 
length)
 {
-d->ZMM_Q(0) = helper_insertq(d->ZMM_Q(0), index, length);
+d->ZMM_Q(0) = helper_insertq(d->ZMM_Q(0), s->ZMM_Q(0), index, length);
 }
 #endif
 
diff --git a/target/i386/ops_sse_header.h b/target/i386/ops_sse_header.h
index d99464afb0..400b24c091 100644
--- a/target/i386/ops_sse_header.h
+++ b/target/i386/ops_sse_header.h
@@ -193,7 +193,7 @@ DEF_HELPER_3(rcpss, void, env, ZMMReg, ZMMReg)
 DEF_HELPER_3(extrq_r, void, env, ZMMReg, ZMMReg)
 DEF_HELPER_4(extrq_i, void, env, ZMMReg, int, int)
 DEF_HELPER_3(insertq_r, void, env, ZMMReg, ZMMReg)
-DEF_HELPER_4(insertq_i, void, env, ZMMReg, int, int)
+DEF_HELPER_5(insertq_i, void, env, ZMMReg, ZMMReg, int, int)
 DEF_HELPER_3(glue(haddps, SUFFIX), void, env, ZMMReg, ZMMReg)
 DEF_HELPER_3(glue(haddpd, SUFFIX), void, env, ZMMReg, ZMMReg)
 DEF_HELPER_3(glue(hsubps, SUFFIX), void, env, ZMMReg, ZMMReg)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 8ec91d17af..5f31a59fb8 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -3506,10 +3506,20 @@ static void gen_sse(CPUX86State *env, DisasContext *s, 
int b,
 gen_helper_extrq_i(cpu_env, s->ptr0,
tcg_const_i32(bit_index),
tcg_const_i32(field_length));
-else
-gen_helper_insertq_i(cpu_env, s->ptr0,
+else {
+if (mod != 3) {
+gen_lea_modrm(env, s, modrm);
+op2_offset = offsetof(CPUX86State, xmm_t0);
+gen_ldq_env_A0(s, offsetof(CPUX86State, 
xmm_t0.ZMM_D(0)));
+} else {
+rm = (modrm & 7) | REX_B(s);
+op2_offset = ZMM_OFFSET(rm);
+}
+tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset);
+gen_helper_insertq_i(cpu_env, s->ptr0, s->ptr1,
  tcg_const_i32(bit_index),
  tcg_const_i32(field_length));
+}
 }
 break;
 case 0x7e: /* movd ea, mm */
-- 
2.37.2




Re: [PATCH v3 03/20] ppc4xx_sdram: Get rid of the init RAM hack

2022-09-18 Thread Cédric Le Goater

On 9/14/22 20:32, BALATON Zoltan wrote:

On Wed, 14 Sep 2022, BALATON Zoltan wrote:

On Wed, 14 Sep 2022, Cédric Le Goater wrote:

On 9/14/22 13:44, BALATON Zoltan wrote:

On Wed, 14 Sep 2022, Cédric Le Goater wrote:

On 9/13/22 21:52, BALATON Zoltan wrote:

The do_init parameter of ppc4xx_sdram_init() is used to map memory
regions that is normally done by the firmware by programming the SDRAM
controller. This is needed when booting a kernel directly from -kernel
without a firmware. Do this from board code accesing normal SDRAM


accessing


Fixed, also two ofhers in another patch you haven't noticed.


controller registers the same way as firmware would do, so we can get
rid of this hack.

Signed-off-by: BALATON Zoltan 
---
v2: Fix ref405ep boot with -kernel and U-Boot

  hw/ppc/ppc405.h |  1 -
  hw/ppc/ppc405_boards.c  | 12 ++--
  hw/ppc/ppc405_uc.c  |  4 +---
  hw/ppc/ppc440_bamboo.c  |  8 +++-
  hw/ppc/ppc440_uc.c  |  2 --
  hw/ppc/ppc4xx_devs.c    | 11 +--
  include/hw/ppc/ppc4xx.h |  8 ++--
  7 files changed, 25 insertions(+), 21 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 1e558c7831..756865621b 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -169,7 +169,6 @@ struct Ppc405SoCState {
  /* Public */
  MemoryRegion ram_banks[2];
  hwaddr ram_bases[2], ram_sizes[2];
-    bool do_dram_init;
    MemoryRegion *dram_mr;
  hwaddr ram_size;
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 083f12b23e..bf02a71c6d 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -274,6 +274,7 @@ static void ppc405_init(MachineState *machine)
  MachineClass *mc = MACHINE_GET_CLASS(machine);
  const char *kernel_filename = machine->kernel_filename;
  MemoryRegion *sysmem = get_system_memory();
+    CPUPPCState *env;
    if (machine->ram_size != mc->default_ram_size) {
  char *sz = size_to_str(mc->default_ram_size);
@@ -288,12 +289,19 @@ static void ppc405_init(MachineState *machine)
   machine->ram_size, _fatal);
  object_property_set_link(OBJECT(>soc), "dram",
   OBJECT(machine->ram), _abort);
-    object_property_set_bool(OBJECT(>soc), "dram-init",
- kernel_filename != NULL, _abort);
  object_property_set_uint(OBJECT(>soc), "sys-clk", ,
   _abort);
  qdev_realize(DEVICE(>soc), NULL, _fatal);
  +    /* Enable SDRAM memory regions */
+    /* FIXME This shouldn't be needed with firmware but we lack SPD data */


what do you mean ?


U-Boot detects the available RAM by reading the SPD info of the RAM modules but 
that probably also needs i2c emulation. See sam460ex.


+    env = >soc.cpu.env;
+    if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x20) ||
+    ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x8000)) {



I am not in favor of these ppc_drc_write calls and this is still a hack.


It's not. Normally this is done by firmware to enable memory controller but the 
board code has to do it if not using firmware (e.g. booting with -kernel) the 
same way it provides bootinfo or device tree mods the firmware would normally 
do or in this case maybe the emulation is incomplete so the part of firmware 
that configures the SDRAM controller does not run.


Exactly, and what the above proposal does is mimicking execution of CPU
instructions before the CPU is even fully initiated. Reset has not been
called at that stage.


I don't get this. We're not calling any CPU instructions, ppc_dcr_write just 
calls the write callback the device has registered for the dcr so it just does 
the same as the hack did at the end just doing it the same way the firmware 
should do.


The "dram-init" property is a cleaner solution. It takes care of doing the
pre-mapping of RAM banks in the realize routine of the sdram model (when
available).


I disagree, the hardware does not have such feature, it proviesd DCRs as the way to configure it. Adding a special property for it deviates from hardware and clutters qtree. 



In this machine, running QEMU with -kernel deviates from HW. That's


In all machines booting with -kernel likely deviates and all machines probably 
have additinal code in this case to do some things normally done by the 
firmware. Look at pegasos2_machine_reset() for example. All that is not needed 
when we boot with firmware as then the firmware will do all that and provide 
the device tree, etc. bur we need to do these when booting without firmware. In 
thes case QEMU also emulates the firmware and has to do thinigs like enabling 
the memory controller.


the whole purpose of this option. It assumes that the SDRAM device
is pre-initialized (and much more should be done) by the QEMU machine
and the simplest way to acheive this goal is to inform the SDRAM model
to take care of the pre-initialization.


In my opinion the SDRAM controller model should model 

Re: [PATCH v3 03/20] ppc4xx_sdram: Get rid of the init RAM hack

2022-09-18 Thread Cédric Le Goater

On 9/14/22 20:25, BALATON Zoltan wrote:

On Wed, 14 Sep 2022, Cédric Le Goater wrote:

On 9/14/22 13:44, BALATON Zoltan wrote:

On Wed, 14 Sep 2022, Cédric Le Goater wrote:

On 9/13/22 21:52, BALATON Zoltan wrote:

The do_init parameter of ppc4xx_sdram_init() is used to map memory
regions that is normally done by the firmware by programming the SDRAM
controller. This is needed when booting a kernel directly from -kernel
without a firmware. Do this from board code accesing normal SDRAM


accessing


Fixed, also two ofhers in another patch you haven't noticed.


controller registers the same way as firmware would do, so we can get
rid of this hack.

Signed-off-by: BALATON Zoltan 
---
v2: Fix ref405ep boot with -kernel and U-Boot

  hw/ppc/ppc405.h |  1 -
  hw/ppc/ppc405_boards.c  | 12 ++--
  hw/ppc/ppc405_uc.c  |  4 +---
  hw/ppc/ppc440_bamboo.c  |  8 +++-
  hw/ppc/ppc440_uc.c  |  2 --
  hw/ppc/ppc4xx_devs.c    | 11 +--
  include/hw/ppc/ppc4xx.h |  8 ++--
  7 files changed, 25 insertions(+), 21 deletions(-)

diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h
index 1e558c7831..756865621b 100644
--- a/hw/ppc/ppc405.h
+++ b/hw/ppc/ppc405.h
@@ -169,7 +169,6 @@ struct Ppc405SoCState {
  /* Public */
  MemoryRegion ram_banks[2];
  hwaddr ram_bases[2], ram_sizes[2];
-    bool do_dram_init;
    MemoryRegion *dram_mr;
  hwaddr ram_size;
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 083f12b23e..bf02a71c6d 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -274,6 +274,7 @@ static void ppc405_init(MachineState *machine)
  MachineClass *mc = MACHINE_GET_CLASS(machine);
  const char *kernel_filename = machine->kernel_filename;
  MemoryRegion *sysmem = get_system_memory();
+    CPUPPCState *env;
    if (machine->ram_size != mc->default_ram_size) {
  char *sz = size_to_str(mc->default_ram_size);
@@ -288,12 +289,19 @@ static void ppc405_init(MachineState *machine)
   machine->ram_size, _fatal);
  object_property_set_link(OBJECT(>soc), "dram",
   OBJECT(machine->ram), _abort);
-    object_property_set_bool(OBJECT(>soc), "dram-init",
- kernel_filename != NULL, _abort);
  object_property_set_uint(OBJECT(>soc), "sys-clk", ,
   _abort);
  qdev_realize(DEVICE(>soc), NULL, _fatal);
  +    /* Enable SDRAM memory regions */
+    /* FIXME This shouldn't be needed with firmware but we lack SPD data */


what do you mean ?


U-Boot detects the available RAM by reading the SPD info of the RAM modules but 
that probably also needs i2c emulation. See sam460ex.


+    env = >soc.cpu.env;
+    if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x20) ||
+    ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x8000)) {



I am not in favor of these ppc_drc_write calls and this is still a hack.


It's not. Normally this is done by firmware to enable memory controller but the 
board code has to do it if not using firmware (e.g. booting with -kernel) the 
same way it provides bootinfo or device tree mods the firmware would normally 
do or in this case maybe the emulation is incomplete so the part of firmware 
that configures the SDRAM controller does not run.


Exactly, and what the above proposal does is mimicking execution of CPU
instructions before the CPU is even fully initiated. Reset has not been
called at that stage.


I don't get this. We're not calling any CPU instructions, ppc_dcr_write just 
calls the write callback the device has registered for the dcr so it just does 
the same as the hack did at the end just doing it the same way the firmware 
should do.


The "dram-init" property is a cleaner solution. It takes care of doing the
pre-mapping of RAM banks in the realize routine of the sdram model (when
available).


I disagree, the hardware does not have such feature, it proviesd DCRs as the way to configure it. Adding a special property for it deviates from hardware and clutters qtree. 



In this machine, running QEMU with -kernel deviates from HW. That's


In all machines booting with -kernel likely deviates and all machines probably 
have additinal code in this case to do some things normally done by the 
firmware. Look at pegasos2_machine_reset() for example. All that is not needed 
when we boot with firmware as then the firmware will do all that and provide 
the device tree, etc. bur we need to do these when booting without firmware. In 
thes case QEMU also emulates the firmware and has to do thinigs like enabling 
the memory controller.


the whole purpose of this option. It assumes that the SDRAM device
is pre-initialized (and much more should be done) by the QEMU machine
and the simplest way to acheive this goal is to inform the SDRAM model
to take care of the pre-initialization.


In my opinion the SDRAM controller model should model the hardware and if the 
board uses it 

[PATCH] target/i386: correctly mask SSE4a bit indices in register operands

2022-09-18 Thread Paolo Bonzini
SSE4a instructions EXTRQ and INSERTQ have two bit index operands, that can be
immediates or taken from an XMM register.  In both cases, the fields are
6-bit wide and the top two bits in the byte are ignored.  translate.c is
doing that correctly for the immediate case, but not for the XMM case, so
fix it.

Signed-off-by: Paolo Bonzini 
---
 target/i386/ops_sse.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index c0766de18d..3504bca36a 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -926,7 +926,7 @@ static inline uint64_t helper_extrq(uint64_t src, int 
shift, int len)
 
 void helper_extrq_r(CPUX86State *env, ZMMReg *d, ZMMReg *s)
 {
-d->ZMM_Q(0) = helper_extrq(d->ZMM_Q(0), s->ZMM_B(1), s->ZMM_B(0));
+d->ZMM_Q(0) = helper_extrq(d->ZMM_Q(0), s->ZMM_B(1) & 63, s->ZMM_B(0) & 
63);
 }
 
 void helper_extrq_i(CPUX86State *env, ZMMReg *d, int index, int length)
@@ -948,7 +948,7 @@ static inline uint64_t helper_insertq(uint64_t src, int 
shift, int len)
 
 void helper_insertq_r(CPUX86State *env, ZMMReg *d, ZMMReg *s)
 {
-d->ZMM_Q(0) = helper_insertq(s->ZMM_Q(0), s->ZMM_B(9), s->ZMM_B(8));
+d->ZMM_Q(0) = helper_insertq(s->ZMM_Q(0), s->ZMM_B(9) & 63, s->ZMM_B(8) & 
63);
 }
 
 void helper_insertq_i(CPUX86State *env, ZMMReg *d, int index, int length)
-- 
2.37.2